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界面。