android 开机流程详细分析

来源:互联网 发布:可视化编程软件 编辑:程序博客网 时间:2024/05/19 18:13

arm平台开机的时候,会先跑ic内部的rom code,rom code把flash上的uboot加载到dram中,然后执行uboot。不同的ic厂商uboot实现可能不一样,有些厂商会把uboot拆分为两个部分,第一部分会先加载到ic内部的sram运行起来,然后初始化dram,再把第二部分加载到dram中运行起来。这里我们不再深入探讨,我们只分析common的部分,uboot在跳转到kernel之前,会传递一些参数过来,并且对于arm构架的平台而言,跳转到kernel前,r0寄存器设置为0,r1的值为match type,r2的值为指向参数结构体的指针,所以kernel是通过r2寄存器拿到uboot传递过来的参数。


linux-4.10/arch/arm/kernel/head.S

/*60   * Kernel startup entry point.61   * ---------------------------62   *63   * This is normally called from the decompressor code.  The requirements64   * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,65   * r1 = machine nr, r2 = atags or dtb pointer.66   *67   * This code is mostly position independent, so if you link the kernel at68   * 0xc0008000, you call this at __pa(0xc0008000).69   *70   * See linux/arch/arm/tools/mach-types for the complete list of machine71   * numbers for r1.72   *73   * We're trying to keep crap to a minimum; DO NOT add any machine specific74   * crap here - that's what the boot loader (or in extreme, well justified75   * circumstances, zImage) is for.76   */77  .arm78  79  __HEAD80  ENTRY(stext)   // ...117  /*118   * r1 = machine no, r2 = atags or dtb,119   * r8 = phys_offset, r9 = cpuid, r10 = procinfo120   */121  bl__vet_atags  //...130  /*131   * The following calls CPU specific code in a position independent132   * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of133   * xxx_proc_info structure selected by __lookup_processor_type134   * above.135   *136   * The processor init function will be called with:137   *  r1 - machine type138   *  r2 - boot data (atags/dt) pointer139   *  r4 - translation table base (low word)140   *  r5 - translation table base (high word, if LPAE)141   *  r8 - translation table base 1 (pfn if LPAE)142   *  r9 - cpuid143   *  r13 - virtual address for __enable_mmu -> __turn_mmu_on144   *145   * On return, the CPU will be ready for the MMU to be turned on,146   * r0 will hold the CPU control register value, r1, r2, r4, and147   * r9 will be preserved.  r5 will also be preserved if LPAE.148   */149  ldrr13, =__mmap_switched@ address to jump to after150  @ mmu has been enabled151  badrlr, 1f@ return (PIC) address152  #ifdef CONFIG_ARM_LPAE153  movr5, #0@ high TTBR0154  movr8, r4, lsr #12@ TTBR1 is swapper_pg_dir pfn155  #else156  movr8, r4@ set TTBR1 to swapper_pg_dir157  #endif158  ldrr12, [r10, #PROCINFO_INITFUNC]159  addr12, r12, r10160  retr12161  1:b__enable_mmu162  ENDPROC(stext)

bl      __vet_atags 就是把uboot传递给kernel的参数拷贝到一个位置,ldr        r13, =__mmap_switched  保存后面要执行的指令

/*436   * Setup common bits before finally enabling the MMU.  Essentially437   * this is just loading the page table pointer and domain access438   * registers.  All these registers need to be preserved by the439   * processor setup function (or set in the case of r0)440   *441   *  r0  = cp#15 control register442   *  r1  = machine ID443   *  r2  = atags or dtb pointer444   *  r4  = TTBR pointer (low word)445   *  r5  = TTBR pointer (high word if LPAE)446   *  r9  = processor ID447   *  r13 = *virtual* address to jump to upon completion448   */449  __enable_mmu://...471  b__turn_mmu_on472  ENDPROC(__enable_mmu)
__enable_mmu执行完之后,又跳转到__turn_mmu_on,我们接下来看一下__turn_mmu_on。

490  ENTRY(__turn_mmu_on)491  movr0, r0492  instr_sync493  mcrp15, 0, r0, c1, c0, 0@ write control reg494  mrcp15, 0, r3, c0, c0, 0@ read id reg495  instr_sync496  movr3, r3497  movr3, r13498  retr3   //子程序返回时,执行这条指令,也就是跳到 __mmap_switched499  __turn_mmu_on_end:500  ENDPROC(__turn_mmu_on) 
__turn_mmu_on最后执行r3中的指令,r3从r13来,而r13在上面的赋值是__mmap_switched。

linux-4.10/arch/arm/kernel/head-common.S

15  #define ATAG_CORE 0x5441000116  #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)17  #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)47  __vet_atags:48  tstr2, #0x3@ aligned?49  bne1f50  51  ldrr5, [r2, #0]52  #ifdef CONFIG_OF_FLATTREE53  ldrr6, =OF_DT_MAGIC@ is it a DTB?54  cmpr5, r655  beq2f56  #endif57  cmpr5, #ATAG_CORE_SIZE@ is first tag ATAG_CORE?58  cmpner5, #ATAG_CORE_SIZE_EMPTY59  bne1f60  ldrr5, [r2, #4]61  ldrr6, =ATAG_CORE62  cmpr5, r663  bne1f64  65  2:retlr@ atag/dtb pointer is ok66  67  1:movr2, #068  retlr69  ENDPROC(__vet_atags)

在分析__mmap_switched之前,我们先看一下__vet_atags把参数拷贝到了哪里,下面这两句汇编相当于把uboot传递过来的参数拷贝到了0x54410001这个地址开始的内存中。

ldr    r5, [r2, #4]

ldr    r6, =ATAG_CORE

下面我们接着看__mmap_switched 汇编代码做了什么事。

/*72   * The following fragment of code is executed with the MMU on in MMU mode,73   * and uses absolute addresses; this is not position independent.74   *75   *  r0  = cp#15 control register76   *  r1  = machine ID77   *  r2  = atags/dtb pointer78   *  r9  = processor ID79   */80  __INIT81  __mmap_switched:82  adrr3, __mmap_switched_data83  84  ldmiar3!, {r4, r5, r6, r7}85  cmpr4, r5@ Copy data segment if needed86  1:cmpner5, r687  ldrnefp, [r4], #488  strnefp, [r5], #489  bne1b90  91  movfp, #0@ Clear BSS (and zero fp)92  1:cmpr6, r793  strccfp, [r6],#494  bcc1b95  96   ARM(ldmiar3, {r4, r5, r6, r7, sp})97   THUMB(ldmiar3, {r4, r5, r6, r7})98   THUMB(ldrsp, [r3, #16])99  strr9, [r4]@ Save processor ID100  strr1, [r5]@ Save machine type101  strr2, [r6]@ Save atags pointer102  cmpr7, #0103  strner0, [r7]@ Save control register values104  bstart_kernel105  ENDPROC(__mmap_switched)

前面做了很多初始化的工作,准备好C函数的运行环境,然后跳转到start_kernel()函数中,这里就从汇编跑到了C代码。


linux-4.10/init/main.c

482  asmlinkage __visible void __init start_kernel(void)483  {484  char *command_line;485  char *after_dashes;//...672  /* Do the rest non-__init'ed, we're now alive */673  rest_init();674  }
前面做了一大堆各种各样的初始化,接着跑到rest_init();
384  static noinline void __ref rest_init(void)385  {386  int pid;387  388  rcu_scheduler_starting();389  /*390   * We need to spawn init first so that it obtains pid 1, however391   * the init task will end up wanting to create kthreads, which, if392   * we schedule it before we create kthreadd, will OOPS.393   */394  kernel_thread(kernel_init, NULL, CLONE_FS);395  numa_default_policy();396  pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);397  rcu_read_lock();398  kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);399  rcu_read_unlock();400  complete(&kthreadd_done);401  402  /*403   * The boot idle thread must execute schedule()404   * at least once to get things moving:405   */406  init_idle_bootup_task(current);407  schedule_preempt_disabled();408  /* Call into cpu_idle with preempt disabled */409  cpu_startup_entry(CPUHP_ONLINE);410  }

est_init()里面创建了两个线程(进程),一个是init进程,这里还是内核空间的进程,后面会变成用户空间的init进程;另外一个是kthreadd进程,内核的守护进程。所以我们重点关注内核空间的init进程接下来做了什么事。

static int __ref kernel_init(void *unused)953  {954  int ret;955  956  kernel_init_freeable();//...968  if (ramdisk_execute_command) {969  ret = run_init_process(ramdisk_execute_command);970  if (!ret)971  return 0;972  pr_err("Failed to execute %s (error %d)\n",973         ramdisk_execute_command, ret);974  }975  976  /*977   * We try each of these until one succeeds.978   *979   * The Bourne shell can be used instead of init if we are980   * trying to recover a really broken machine.981   */982  if (execute_command) {983  ret = run_init_process(execute_command);984  if (!ret)985  return 0;986  panic("Requested init %s failed (error %d).",987        execute_command, ret);988  }989  if (!try_to_run_init_process("/sbin/init") ||990      !try_to_run_init_process("/etc/init") ||991      !try_to_run_init_process("/bin/init") ||992      !try_to_run_init_process("/bin/sh"))993  return 0;994  995  panic("No working init found.  Try passing init= option to kernel. "996        "See Linux Documentation/admin-guide/init.rst for guidance.");997  }

我们继续追踪kernel_init_freeable();

static noinline void __init kernel_init_freeable(void)1000  {//...1032  do_basic_setup();//...1062  integrity_load_keys();1063  load_default_modules();1064  }

继续追踪do_basic_setup();


/*867   * Ok, the machine is now initialized. None of the devices868   * have been touched yet, but the CPU subsystem is up and869   * running, and memory and process management works.870   *871   * Now we can finally start doing some real work..872   */873  static void __init do_basic_setup(void)874  {875  cpuset_init_smp();876  shmem_init();877  driver_init();878  init_irq_proc();879  do_ctors();880  usermodehelper_enable();881  do_initcalls();882  random_int_secret_init();883  }

do_initcalls()会调用到每个driver的init(),也就是module_init()传入的函数指针。


858  static void __init do_initcalls(void)859  {860  int level;861  862  for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)863  do_initcall_level(level);864  }
843  static void __init do_initcall_level(int level)844  {845  initcall_t *fn;846  847  strcpy(initcall_command_line, saved_command_line);848  parse_args(initcall_level_names[level],849     initcall_command_line, __start___param,850     __stop___param - __start___param,851     level, level,852     NULL, &repair_env_string);853  854  for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)855  do_one_initcall(*fn);856  }

777  int __init_or_module do_one_initcall(initcall_t fn)778  {779  int count = preempt_count();780  int ret;781  char msgbuf[64];782  783  if (initcall_blacklisted(fn))784  return -EPERM;785  786  if (initcall_debug)787  ret = do_one_initcall_debug(fn);788  else789  ret = fn();  //这里调用了init函数//…804  return ret;805  }

到这里我们就了解了driver的初始化是在这里调用的,到后面调用run_init_process(execute_command); 把init进程加载到内存运行起来。


static int run_init_process(const char *init_filename)905  {906  argv_init[0] = init_filename;907  return do_execve(getname_kernel(init_filename),908  (const char __user *const __user *)argv_init,909  (const char __user *const __user *)envp_init);910  }

为什么这里运行了init进程后,就会变成用户空间的init进程?可以了解一下do_execve()这个系统调用。

system/core/init/init.cpp

int main(int argc, char** argv) {//...603      // Get the basic filesystem setup we need put together in the initramdisk604      // on / and then we'll let the rc file figure out the rest.605      if (is_first_stage) {606          mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");607          mkdir("/dev/pts", 0755);608          mkdir("/dev/socket", 0755);609          mount("devpts", "/dev/pts", "devpts", 0, NULL);610          #define MAKE_STR(x) __STRING(x)611          mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));612          mount("sysfs", "/sys", "sysfs", 0, NULL);613      }//...684      Parser& parser = Parser::GetInstance();685      parser.AddSectionParser("service",std::make_unique<ServiceParser>());686      parser.AddSectionParser("on", std::make_unique<ActionParser>());687      parser.AddSectionParser("import", std::make_unique<ImportParser>());688      parser.ParseConfig("/init.rc");689  690      ActionManager& am = ActionManager::GetInstance();691  692      am.QueueEventTrigger("early-init");//...702      // Trigger all the boot actions to get us started.703      am.QueueEventTrigger("init");//...717      // Run all property triggers based on current state of the properties.718      am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");719  720      while (true) {721          if (!waiting_for_exec) {722              am.ExecuteOneCommand();723              restart_processes();724          }725  726          int timeout = -1;727          if (process_needs_restart) {728              timeout = (process_needs_restart - gettime()) * 1000;729              if (timeout < 0)730                  timeout = 0;731          }732  733          if (am.HasMoreCommands()) {734              timeout = 0;735          }736  737          bootchart_sample(&timeout);738  739          epoll_event ev;740          int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));741          if (nr == -1) {742              ERROR("epoll_wait failed: %s\n", strerror(errno));743          } else if (nr == 1) {744              ((void (*)()) ev.data.ptr)();745          }746      }747  748      return 0;749  }

跑到init的main()函数中,里面做了很多事,包括mount各种文件系统,解析init.rc,执行init.rc里面的各种command,最后进入while循环,等待各种请求。


system/core/rootdir/init.zygote32.rc

1 service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server2     class main3     socket zygote stream 660 root system4     onrestart write /sys/android_power/request_state wake5     onrestart write /sys/power/state on6     onrestart restart audioserver7     onrestart restart cameraserver8     onrestart restart media9     onrestart restart netd10     writepid /dev/cpuset/foreground/tasks

init进程在解析init.rc文件后,会把很多service进程运行起来,其中包括zygote进程。

frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])187  {      //...245      ++i;  // Skip unused "parent dir" argument.246      while (i < argc) {247          const char* arg = argv[i++];248          if (strcmp(arg, "--zygote") == 0) {249              zygote = true;250              niceName = ZYGOTE_NICE_NAME;251          } else if (strcmp(arg, "--start-system-server") == 0) {252              startSystemServer = true;253          } else if (strcmp(arg, "--application") == 0) {254              application = true;255         } else if (strncmp(arg, "--nice-name=", 12) == 0) {256             niceName.setTo(arg + 12);257         } else if (strncmp(arg, "--", 2) != 0) {258             className.setTo(arg);259             break;260         } else {261             --i;262             break;263          }264      }//...279          if (startSystemServer) {280              args.add(String8("start-system-server"));281          }282  //...306      if (zygote) {307          runtime.start("com.android.internal.os.ZygoteInit", args, zygote);308      } else if (className) {309          runtime.start("com.android.internal.os.RuntimeInit", args, zygote);310      } else {311          fprintf(stderr, "Error: no class name or --zygote supplied.\n");312          app_usage();313          LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");314          return 10;315      }316  }

里面做了很多事,包括解析传进来的参数,传进来的参数有--zygote--start-system-server,所以走的是runtime.start("com.android.internal.os.ZygoteInit",args, zygote); args中带有start-system-server字符串。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {//...714          try {//...722              String abiList = null;723              for (int i = 1; i < argv.length; i++) {724                  if ("start-system-server".equals(argv[i])) {725                      startSystemServer = true;726                  } else if (argv[i].startsWith(ABI_LIST_ARG)) {727                      abiList = argv[i].substring(ABI_LIST_ARG.length());728                  } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {729                      socketName = argv[i].substring(SOCKET_NAME_ARG.length());730                  } else {731                      throw new RuntimeException("Unknown command line argument: " + argv[i]);732                  }733              }//...767              if (startSystemServer) {768                  startSystemServer(abiList, socketName);769              }770  771              Log.i(TAG, "Accepting command socket connections");772              runSelectLoop(abiList);773  774              closeServerSocket();775          } catch (MethodAndArgsCaller caller) {776              caller.run();777          } catch (Throwable ex) {778              Log.e(TAG, "Zygote died with exception", ex);779              closeServerSocket();780              throw ex;781          }782      }

为什么跑runtime.start("com.android.internal.os.ZygoteInit",args, zygote) 会跑到ZygoteInit中的main()函数,这里先不讲。在跑这个之前,runtime,也就是虚拟机已经初始化好了,所以可以跑java的代码了。

private static boolean startSystemServer(String abiList, String socketName)634              throws MethodAndArgsCaller, RuntimeException {//...652          /* Hardcoded command line to start the system server */653          String args[] = {654              "--setuid=1000",655              "--setgid=1000",656              "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",657              "--capabilities=" + capabilities + "," + capabilities,658              "--nice-name=system_server",659              "--runtime-args",660              "com.android.server.SystemServer",661          };662          ZygoteConnection.Arguments parsedArgs = null;663  664          int pid;665  666          try {667              parsedArgs = new ZygoteConnection.Arguments(args);668              ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);669              ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);670  671              /* Request to fork the system server process */672              pid = Zygote.forkSystemServer(673                      parsedArgs.uid, parsedArgs.gid,674                      parsedArgs.gids,675                      parsedArgs.debugFlags,676                      null,677                      parsedArgs.permittedCapabilities,678                      parsedArgs.effectiveCapabilities);679          } catch (IllegalArgumentException ex) {680              throw new RuntimeException(ex);681          }682  683          /* For child process */684          if (pid == 0) {685              if (hasSecondZygote(abiList)) {686                  waitForSecondaryZygote(socketName);687              }688  689              handleSystemServerProcess(parsedArgs);690          }691  692          return true;693      }

这里fork出了一个新进程,就是system_server,注意参数里面的com.android.server.SystemServer。如果是子进程才跑handleSystemServerProcess(),如果是父进程就直接返回true了。父进程(zygote)往下跑就会进入runSelectLoop(abiList);循环,等待socket请求,fork出新的子进程。

private static void handleSystemServerProcess(506              ZygoteConnection.Arguments parsedArgs)507              throws ZygoteInit.MethodAndArgsCaller {508  509          closeServerSocket();//...518          final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");519          if (systemServerClasspath != null) {520              performSystemServerDexOpt(systemServerClasspath);521          }//...547              /*548               * Pass the remaining arguments to SystemServer.549               */550              RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);551          }552  553          /* should never reach here */554      }

handleSystemServerProcess() 关闭fork“继承”过来socket,加载systemserver类。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

     public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)281              throws ZygoteInit.MethodAndArgsCaller {282          if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");283  284          Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");285          redirectLogStreams();286  287          commonInit();288          nativeZygoteInit();289          applicationInit(targetSdkVersion, argv, classLoader);290      }

继续往下,跑到applicationInit()。

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)//...336          // Remaining arguments are passed to the start class's static main337          invokeStaticMain(args.startClass, args.startArgs, classLoader);338      }private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)210              throws ZygoteInit.MethodAndArgsCaller {211          Class<?> cl;212  213          try {214              cl = Class.forName(className, true, classLoader);215          } catch (ClassNotFoundException ex) {216              throw new RuntimeException(217                      "Missing class when invoking static main " + className,218                      ex);219          }220  221          Method m;222          try {223              m = cl.getMethod("main", new Class[] { String[].class });224          } catch (NoSuchMethodException ex) {225              throw new RuntimeException(226                      "Missing static main on " + className, ex);227          } catch (SecurityException ex) {228              throw new RuntimeException(229                      "Problem getting static main on " + className, ex);230          }//...244          throw new ZygoteInit.MethodAndArgsCaller(m, argv);245      }

前面有提到过注意传入的参数,所以加载的cl类就是SystemServer类。最后抛出了一个异常,这里应该会有很多人疑惑,这是一个“别有用心”的设计,可以清掉栈中ZygoteInit.main()之后调用的函数。

catch (MethodAndArgsCaller caller) {776              caller.run();777          }

抛出异常后,回到ZygoteInit.main()中捕获异常的模块,执行caller.run();


frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {219          new SystemServer().run();220      }

所以就跑到了SystemServer的main()函数中。

private void run() {//...310              Looper.prepareMainLooper();311  312              // Initialize native services.313              System.loadLibrary("android_servers");//...329          // Start services.330          try {331              Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");332              startBootstrapServices();333              startCoreServices();334              startOtherServices();335          } catch (Throwable ex) {336              Slog.e("System", "******************************************");337              Slog.e("System", "************ Failure starting system services", ex);338              throw ex;339          } finally {340              Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);341          }//...348          // Loop forever.349          Looper.loop();350          throw new RuntimeException("Main thread loop unexpectedly exited");351      }

run()函数里面又做了一大堆的事件,在这里面创建了许多service,比如AMS,PMS等等。

  

     /**514       * Starts a miscellaneous grab bag of stuff that has yet to be refactored515       * and organized.516       */517      private void startOtherServices() {//…1302          mActivityManagerService.systemReady(new Runnable() {1303              @Override1304              public void run() {1305                  Slog.i(TAG, "Making services ready");1306                  mSystemServiceManager.startBootPhase(1307                          SystemService.PHASE_ACTIVITY_MANAGER_READY);//…1433              }1434          });1435      }

在startOtherServices()会call到ActivityManagerService的systemReady()函数。


frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

13217      public void systemReady(final Runnable goingCallback) {13218          synchronized(this) {13219              if (mSystemReady) {13220                  // If we're done calling all the receivers, run the next "boot phase" passed in13221                  // by the SystemServer13222                  if (goingCallback != null) {13223                      goingCallback.run();13224                  }13225                  return;13226              }//…13339              startHomeActivityLocked(currentUserId, "systemReady");//…13386      }    boolean startHomeActivityLocked(int userId, String reason) {//...3927          Intent intent = getHomeIntent();3928          ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);3929          if (aInfo != null) {3930              intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));3931              // Don't do this if the home app is currently being3932              // instrumented.3933              aInfo = new ActivityInfo(aInfo);3934              aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);3935              ProcessRecord app = getProcessRecordLocked(aInfo.processName,3936                      aInfo.applicationInfo.uid, true);3937              if (app == null || app.instrumentationClass == null) {3938                  intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);3939                  mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);3940              }3941          } else {3942              Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());3943          }3944  3945          return true;3946      }


frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

      void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {640          mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);641          startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,642                  null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,643                  null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,644                  0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,645                  0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,646                  false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,647                  null /*container*/, null /*inTask*/);648          if (mSupervisor.inResumeTopActivity) {649              // If we are in resume section already, home activity will be initialized, but not650              // resumed (to avoid recursive resume) and will stay that way until something pokes it651              // again. We need to schedule another resume.652              mSupervisor.scheduleResumeTopActivities();653          }654      }

startHomeActivityLocked()就会把launcher 运行起来,到这里我们就看到了android的home界面。




原创粉丝点击