android 開機流程詳細分析

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 requirements
64   * 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 at
68   * 0xc0008000, you call this at __pa(0xc0008000).
69   *
70   * See linux/arch/arm/tools/mach-types for the complete list of machine
71   * numbers for r1.
72   *
73   * We're trying to keep crap to a minimum; DO NOT add any machine specific
74   * crap here - that's what the boot loader (or in extreme, well justified
75   * circumstances, zImage) is for.
76   */
77  	.arm
78  
79  	__HEAD
80  ENTRY(stext)
   // ...
117  	/*
118  	 * r1 = machine no, r2 = atags or dtb,
119  	 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
120  	 */
121  	bl	__vet_atags
  //...
130  	/*
131  	 * The following calls CPU specific code in a position independent
132  	 * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
133  	 * xxx_proc_info structure selected by __lookup_processor_type
134  	 * above.
135  	 *
136  	 * The processor init function will be called with:
137  	 *  r1 - machine type
138  	 *  r2 - boot data (atags/dt) pointer
139  	 *  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 - cpuid
143  	 *  r13 - virtual address for __enable_mmu -> __turn_mmu_on
144  	 *
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, and
147  	 * r9 will be preserved.  r5 will also be preserved if LPAE.
148  	 */
149  	ldr	r13, =__mmap_switched		@ address to jump to after
150  						@ mmu has been enabled
151  	badr	lr, 1f				@ return (PIC) address
152  #ifdef CONFIG_ARM_LPAE
153  	mov	r5, #0				@ high TTBR0
154  	mov	r8, r4, lsr #12			@ TTBR1 is swapper_pg_dir pfn
155  #else
156  	mov	r8, r4				@ set TTBR1 to swapper_pg_dir
157  #endif
158  	ldr	r12, [r10, #PROCINFO_INITFUNC]
159  	add	r12, r12, r10
160  	ret	r12
161  1:	b	__enable_mmu
162  ENDPROC(stext)

bl      __vet_atags 就是把uboot傳遞給kernel的參數拷貝到一個位置,ldr        r13, =__mmap_switched  保存後面要執行的指令

/*
436   * Setup common bits before finally enabling the MMU.  Essentially
437   * this is just loading the page table pointer and domain access
438   * registers.  All these registers need to be preserved by the
439   * processor setup function (or set in the case of r0)
440   *
441   *  r0  = cp#15 control register
442   *  r1  = machine ID
443   *  r2  = atags or dtb pointer
444   *  r4  = TTBR pointer (low word)
445   *  r5  = TTBR pointer (high word if LPAE)
446   *  r9  = processor ID
447   *  r13 = *virtual* address to jump to upon completion
448   */
449  __enable_mmu:
//...
471  	b	__turn_mmu_on
472  ENDPROC(__enable_mmu)
__enable_mmu執行完之後,又跳轉到__turn_mmu_on,我們接下來看一下__turn_mmu_on。

490  ENTRY(__turn_mmu_on)
491  	mov	r0, r0
492  	instr_sync
493  	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
494  	mrc	p15, 0, r3, c0, c0, 0		@ read id reg
495  	instr_sync
496  	mov	r3, r3
497  	mov	r3, r13
498  	ret	r3   //子程序返回時,執行這條指令,也就是跳到 __mmap_switched
499  __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 0x54410001
16  #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
17  #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)

47  __vet_atags:
48  	tst	r2, #0x3			@ aligned?
49  	bne	1f
50  
51  	ldr	r5, [r2, #0]
52  #ifdef CONFIG_OF_FLATTREE
53  	ldr	r6, =OF_DT_MAGIC		@ is it a DTB?
54  	cmp	r5, r6
55  	beq	2f
56  #endif
57  	cmp	r5, #ATAG_CORE_SIZE		@ is first tag ATAG_CORE?
58  	cmpne	r5, #ATAG_CORE_SIZE_EMPTY
59  	bne	1f
60  	ldr	r5, [r2, #4]
61  	ldr	r6, =ATAG_CORE
62  	cmp	r5, r6
63  	bne	1f
64  
65  2:	ret	lr				@ atag/dtb pointer is ok
66  
67  1:	mov	r2, #0
68  	ret	lr
69  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 register
76   *  r1  = machine ID
77   *  r2  = atags/dtb pointer
78   *  r9  = processor ID
79   */
80  	__INIT
81  __mmap_switched:
82  	adr	r3, __mmap_switched_data
83  
84  	ldmia	r3!, {r4, r5, r6, r7}
85  	cmp	r4, r5				@ Copy data segment if needed
86  1:	cmpne	r5, r6
87  	ldrne	fp, [r4], #4
88  	strne	fp, [r5], #4
89  	bne	1b
90  
91  	mov	fp, #0				@ Clear BSS (and zero fp)
92  1:	cmp	r6, r7
93  	strcc	fp, [r6],#4
94  	bcc	1b
95  
96   ARM(	ldmia	r3, {r4, r5, r6, r7, sp})
97   THUMB(	ldmia	r3, {r4, r5, r6, r7}	)
98   THUMB(	ldr	sp, [r3, #16]		)
99  	str	r9, [r4]			@ Save processor ID
100  	str	r1, [r5]			@ Save machine type
101  	str	r2, [r6]			@ Save atags pointer
102  	cmp	r7, #0
103  	strne	r0, [r7]			@ Save control register values
104  	b	start_kernel
105  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, however
391  	 * the init task will end up wanting to create kthreads, which, if
392  	 * 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 are
980  	 * 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 devices
868   * have been touched yet, but the CPU subsystem is up and
869   * 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  	else
789  		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 initramdisk
604      // 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-server
2     class main
3     socket zygote stream 660 root system
4     onrestart write /sys/android_power/request_state wake
5     onrestart write /sys/power/state on
6     onrestart restart audioserver
7     onrestart restart cameraserver
8     onrestart restart media
9     onrestart restart netd
10     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 main
337          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 refactored
515       * and organized.
516       */
517      private void startOtherServices() {
//…
1302          mActivityManagerService.systemReady(new Runnable() {
1303              @Override
1304              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 in
13221                  // by the SystemServer
13222                  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 being
3932              // 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 not
650              // resumed (to avoid recursive resume) and will stay that way until something pokes it
651              // again. We need to schedule another resume.
652              mSupervisor.scheduleResumeTopActivities();
653          }
654      }

startHomeActivityLocked()就會把launcher 運行起來,到這裏我們就看到了android的home界面。




發佈了62 篇原創文章 · 獲贊 37 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章