Android系统启动流程剖析

Posted by Dorck on April 22, 2023

Android 手机从长按开机到应用的启动阶段都经历了些什么呢?Android 启动过程涉及一系列操作,首先是启动 ROM,接着是引导加载程序、内核启动、init、Zygote 和 SystemServer 创建等过程。整个过程涉及到虚拟机的启动、Binder 线程池的创建以及各项系统服务启动等过程。熟悉 APP 启动过程还可以帮助我们打破性能优化瓶颈,助力于启动性能的提升。下面是启动过程涉及到的关键进程和服务:

android_init_brief

本文基于 Android 13 最新代码来分析 Android 系统及应用启动过程。

Init 进程启动

init 进程在 Android 系统中扮演着非常重要的角色,它不仅仅是系统的第一个用户进程(pid 为 1),还负责整个系统的启动和进程的管理。当 Android 设备启动时,Bootloader 会初始化硬件设备,并在硬件自检之后将控制权交给 Kernel,Kernel 会加载 Android 系统的内核。而 init 进程的启动过程就发生在内核启动后,接着调用 system/core/init/main.cpp 来创建 init 进程,在此期间读取 init.rc 文件,启动 zygote 进程、servicemanager 等,最后完成初始化工作。下面来结合源码具体分析 init 启动后都做了些什么:

system/core/init/main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using namespace android::init;

int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#elif __has_feature(hwaddress_sanitizer)
    __hwasan_set_error_report_callback(AsanReportCallback);
#endif
    // Boost prio which will be restored later
    setpriority(PRIO_PROCESS, 0, -20);
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

            return SubcontextMain(argc, argv, &function_map);
        }

        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }

    return FirstStageMain(argc, argv);
}

内核启动后会调用到这里的 main 函数,主要执行了以下几个操作:

  • ueventd_main:该函数是 ueventd 守护进程的主要函数,通过 netlink scoket 响应内核生成的 uevent 事件。它设置信号处理程序,创建用于侦听传入 uevent 的套接字,然后进入无限循环以处理 uevent 事件。 它其实也算是 init 进程,不过具体细节本文不再深究,后面会单独拎出来讲一讲。
  • SubcontextMain:subcontext 进程的主要处理函数,负责为 init 进程创建和管理子进程,并通过 socket 与 init 进行通信。
  • SetupSelinux:该函数会尝试加载在init.rc文件中定义的SELinux策略文件。如果文件存在,则在系统启动时加载所需的SELinux策略,并执行其他相关的SELinux设置。这些设置包括设置SELinux上下文,为设备中的所有进程和授权的服务分配安全策略和权限等。
  • FirstStageMain:init 执行的第一阶段,主要做一些初始化文件系统、kernel 日志以及为第二阶段设定一些环境变量。
  • SecondStageMain:init 执行的第二阶段,主要负责加载属性文件、启动属性服务、加载 init.rc 文件并创建和启动子进程。

下面我们着重分析一下 init.rc 加载及子进程启动过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int SecondStageMain(int argc, char** argv) {
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
    }
   	......
    // 加载属性文件  
    PropertyInit();
  	......
    // 启动属性服务  
    StartPropertyService(&property_fd);

    // Make the time that init stages started available for bootstat to log.
    RecordStageBoottimes(start_time);

   	......
    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();
		// 加载解析 init.rc
    LoadBootScripts(am, sm);
}

init.rc 文件的解析是在 LoadBootScripts() 中完成的,详见下面的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser = CreateParser(action_manager, service_list);

    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        // late_import is available only in Q and earlier release. As we don't
        // have system_ext in those versions, skip late_import for system_ext.
        parser.ParseConfig("/system_ext/etc/init");
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}

Init 进程依次解析不同路径下谷歌内置 system、SoC 厂商 vendor 以及 odm 厂商的 init.rc 文件并执行启动相关进程。init.rc 本质上只是一个语法文件,至于具体的 Service 和 Action 解析逻辑是在 ServiceParser 和 ActionParser 中处理,至于最终执行逻辑则是由解析处理器将所有 Service 和 Action 封装到 ServiceList 和 ActionList 单例对象中集中处理的。这里以 init.zygote64_32.rc 中一段启动 zygote 的 rc 代码为例:

Note:system/core/rootdir/init.rc 中通过 import 动态引入了基于不同平台的 zygote 进程启动配置,以下仅以常见的 init.zygote64_32.rc 平台为例。

		service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-		name=zygote
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart media.tuner
    onrestart restart netd
    onrestart restart wificond
    task_profiles ProcessCapacityHigh MaxPerformance
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

Service 是一个服务类型的程序,以 service 开头,由 init 进程启动,其中每一个 service ,在启动时会通过 fork 方式生成子进程。其中,zygote 是进程的名字,/system/bin/app_process 是执行程序的路径,它是通过编译生成的,其包含了 main() 函数在内的一系列代码。在编译过程中,编译器会将源代码编译成目标文件,并将目标文件链接成可执行文件。在链接过程中,编译器会将不同的目标文件链接到一起,形成一个统一的可执行文件。在这个过程中, app_process 可执行文件会链接到 app_main.cpp 文件中定义的 main() 函数,因此运行 app_process 可执行文件时,系统会自动调用 app_main.cpp 文件中的 main() 函数。

后面几项则是传递给执行程序的参数,其中 --start-system-server 表示在 Zygote 进程启动后需要启动 System Server 进程。Zygote 进程是使用 Socket 来进行跨进程通信的,所以会创建一个名为 zygote 的 socket,660 表示访问权限 rw-rw----,表示文件拥有者和同一群组用户具有读写权限。

了解更多关于 init.rc 语法约定参考:Android启动初始化 init.rc 详解

接着 zygote 进程通过以下代码被启动:

system/core/init/service.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Result<void> Service::Start() {
		...
    
    pid_t pid = -1;
    if (namespaces_.flags) {
        pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
    } else {
        pid = fork();
    }

    if (pid == 0) {
        umask(077);
        cgroups_activated.CloseWriteFd();
        setsid_finished.CloseReadFd();
        RunService(descriptors, std::move(cgroups_activated), std::move(setsid_finished));
        _exit(127);
    } else {
        cgroups_activated.CloseReadFd();
        setsid_finished.CloseWriteFd();
    }

    if (pid < 0) {
        pid_ = 0;
        return ErrnoError() << "Failed to fork";
    }
  	...
}

可以看到最终是通过 clone 或者 fork 的方式来创建一个进程,并返回 pid,其实最终它们都是通过系统调用基于父进程孵化出一个子进程,并与当前进程共享地址空间和文件描述符等资源。

zygote 进程

通过上面分析我们知道,zygote 进程在启动后会执行到 app_main.cpp 的 main 函数中:

frameworks/base/cmds/app_process/app_main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif

int main(int argc, char* const argv[])
{
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
      	// 通过 init.rc 中约定的 `--zygote` 来判断是zygote进程
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    ...
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {
      	// 进入 AppRunTime 中继续执行,准备穿越到 Java 世界
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

通过上述代码我们可以发现,zygote 进程通过 --zygote 参数标记,如果是 zygote 进程,最终会执行到 AppRuntime.start 中:

frameworks/base/core/jni/AndroidRuntime.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");
    // Whether this is the primary zygote, meaning the zygote which will fork system server.
    bool primary_zygote = false;

    ...

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    ...

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

通过这部分代码我们了解到,jni 层的 AndroidRuntimestart 函数主要完成了三件事:

  • 启动 zygote 进程的虚拟机
  • 完成 JNI 方法注册(在 VM 上注册 Android 本地方法,只为了能够让 native 调用到 Java 层方法)
  • 调用 Java 层的 com.android.internal.os.ZygoteInit#main 方法

至此,终于来到了我们熟悉的 Java 世界了,继续 zygote 的初始化逻辑:

com.android.internal.os.ZygoteInit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
     * This is the entry point for a Zygote process.  It creates the Zygote server, loads resources,
     * and handles other tasks related to preparing the process for forking into applications.
     *
     * This process is started with a nice value of -20 (highest priority).  All paths that flow
     * into new processes are required to either set the priority to the default value or terminate
     * before executing any non-system code.  The native side of this occurs in SpecializeCommon,
     * while the Java Language priority is changed in ZygoteInit.handleSystemServerProcess,
     * ZygoteConnection.handleChildProc, and Zygote.childMain.
     *
     * @param argv  Command line arguments used to specify the Zygote's configuration.
     */
    @UnsupportedAppUsage
    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;

        Runnable caller;
        try {
           	...
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                preload(bootTimingsTraceLog);
            }

            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

ZygoteInit#main 中大致做了以下几件事:

  • preload:预加载系统基础类、资源文件、共享库等。
  • ZygoteServer:创建 Socket 服务端,用于和其他进程通信。
  • forkSystemServer:fork 出 system_server 子进程,下面会分析到。
  • ZygoteServer#runSelectLoop:socket 循环监听 AMS 用于创建应用进程的请求。

那么我简单总结一下,zygote 进程负责创建虚拟机,并注册 JNI 方法,成为 Java 进程的母体,用于持续孵化 Java 进程。在创建完system_server 进程后调用 runSelectLoop,随时等待接收创建新进程的请求并立即唤醒开始执行相应创建工作。

system_server 进程

Zygote 的初始化过程涉及到 system_server 进程的创建和启动,那我们就来看下 system_server 进程的启动过程:

com.android.internal.os.ZygoteInit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
     * Prepare the arguments and forks for the system server process.
     *
     * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
     * process; {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
      String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                // system_server 执行程序的类名
                "com.android.server.SystemServer",
        };
        ...
        ZygoteArguments parsedArgs;

        int pid;

        try {
            ...
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

/**
     * Finish remaining work for the newly forked system server process.
     */
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
      	if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName);
        }
        ...
        if (parsedArgs.mInvokeWith != null) {
            ...
            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = getOrCreateSystemServerClassLoader();
            if (cl != null) {
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }

        /* should never reach here */
    }

		public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();
				// 设置异常处理机制
        RuntimeInit.commonInit();
      	// 启动进程的Binder线程池
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

看到上面的参数信息 args 包含了 com.android.server.SystemServer 就可以大致猜到最后应该是反射创建的实例。上面方法 ZygoteInit#forkSystemServer 继续追踪下去,system_server 进程的创建最终通过 Zygote.forkSystemServer 实现的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
     * Special method to start the system server process. In addition to the
     * common actions performed in forkAndSpecialize, the pid of the child
     * process is recorded such that the death of the child process will cause
     * zygote to exit.
     *
     * @param uid the UNIX uid that the new process should setuid() to after
     * fork()ing and and before spawning any threads.
     * @param gid the UNIX gid that the new process should setgid() to after
     * fork()ing and and before spawning any threads.
     * @param gids null-ok; a list of UNIX gids that the new process should
     * setgroups() to after fork and before spawning any threads.
     * @param runtimeFlags bit flags that enable ART features.
     * @param rlimits null-ok an array of rlimit tuples, with the second
     * dimension having a length of 3 and representing
     * (resource, rlim_cur, rlim_max). These are set via the posix
     * setrlimit(2) call.
     * @param permittedCapabilities argument for setcap()
     * @param effectiveCapabilities argument for setcap()
     *
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();

        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);

        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

        ZygoteHooks.postForkCommon();
        return pid;
    }

system_server 进程的最终实现是在 native 层,但是从注释来看,它的返回值如果是 0 则说明当前是子进程,否则可能依然是父进程或者 fork 失败。如果 system_server 进程创建成功,会依次执行到 handleSystemServerProcesszygoteInit 方法,继续跟进到 RuntimeInit.applicationInit 一探究竟:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        
  			...

        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }
/**
     * Helper class which holds a method and arguments and can call them. This is used as part of
     * a trampoline to get rid of the initial process setup stack frames.
     */
    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

最终不出我们所料,findStaticMain 中传递的 className 对应的就是我们之前的 com.android.server.SystemServer 类,我们来看看它里面都做了些什么(SystemServer#main 会执行到 run 方法):

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
private void run() {
        try {
            ...

            // Prepare the main looper thread (this thread).
            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper();
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

            SystemServiceRegistry.sEnableServiceNotFoundWtf = true;
						...

            // Initialize the system context.
            createSystemContext();

						...
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            mDumper.addDumpable(mSystemServiceManager);

            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool tp = SystemServerInitThreadPool.start();
            mDumper.addDumpable(tp);
          	...
        } finally {
            t.traceEnd();  // InitBeforeStartServices
        }

        // Setup the default WTF handler
        RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);

        // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
            startApexServices(t);
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }
				...
        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

通过分析上面代码可以发现 system_server 为我们做了很多事情:

  • 创建系统服务管理器 SystemServiceManager
  • 启动引导服务(AMS、PMS等)、核心服务和其他各种服务
  • 创建主线程 Looper 并一直循环,等待其他线程通过 Handler 发送消息再唤醒并处理。
nativeZygoteInit

上面的 com.android.internal.os.ZygoteInit#forkSystemServerZygoteInit.nativeZygoteInit() 方法主要从 native 层创建了进程的 Binder 线程池。值得注意的,这一切发生在 system_server 进程创建之后。最终可以追溯到:

frameworks/native/libs/binder/ProcessState.cpp

1
2
3
4
5
6
7
8
9
10
11
12
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = sp<PoolThread>::make(isMain);
        t->run(name.string());
        pthread_mutex_lock(&mThreadCountLock);
        mKernelStartedThreads++;
        pthread_mutex_unlock(&mThreadCountLock);
    }
}

系统启动日志分析

从 Android 开机开始到我们系统初始化完毕,这中间设有大量的关键日志,如果能够好好利用,对于我们排查一些系统性问题或者性能问题会有巨大帮助。以下列举部分关键节点的 Tag:

可查看启动耗时
  • boot_progress_start:表示 kernel 启动完成,第一个用户空间进程 init 进程启动
  • boot_progress_preload_start:zygote 进程开始预加载 class 资源(记录于 ZygoteInit#preload 调用时机)
  • boot_progress_preload_end:zygote 进程 class 资源预加载结束
  • boot_progress_system_run:表示 system_server 进程启动(记录于 SystemServer#run 调用时机)
  • boot_progress_pms_start:表示 PMS 服务启动并开始扫描应用的动作
  • boot_progress_pms_ready:表示 PMS 服务应用扫描完毕
  • boot_progress_ams_ready:表示 AMS 已经进入 systemReady 状态可以启动桌面应用了
  • boot_progress_enable_screen:标志着锁频界面已经点亮显示,开机完成并统计耗时

更多 native 层相关统计的 tag 参照:system/logging/logcat/event.logtags

我们可以额外留意一些系统进程和服务的相关日志,比如 zygote 运行相关日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Zygote64进程(Zygote):  AndroidRuntime::start
11-23 14:36:51.260   557   557 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
// Zygote64进程:  AndroidRuntime::startVm
11-23 14:36:51.304   557   557 D AndroidRuntime: CheckJNI is OFF

// 执行ZygoteInit.preload()
11-23 14:36:52.134   557   557 D Zygote  : begin preload
// 执行ZygoteInit.preloadClasses(), 预加载3860classes, 花费时长746ms
11-23 14:36:52.134   557   557 I Zygote  : Preloading classes...
11-23 14:36:52.881   557   557 I Zygote  : ...preloaded 3860 classes in 746ms.

// 执行ZygoteInit.preloadClasses(), 预加载86组资源, 花费时长179ms
11-23 14:36:53.114   557   557 I Zygote  : Preloading resources...
11-23 14:36:53.293   557   557 I Zygote  : ...preloaded 86 resources in 179ms.

// 执行ZygoteInit.preloadSharedLibraries()
11-23 14:36:53.494   557   557 I Zygote  : Preloading shared libraries...
11-23 14:36:53.503   557   557 D Zygote  : end preload

// 执行com_android_internal_os_Zygote_nativeForkSystemServer(),成功forksystem_server进程
11-23 14:36:53.544   557   557 I Zygote  : System server process 1274 has been created
// Zygote开始进入runSelectLoop()
11-23 14:36:53.546   557   557 I Zygote  : Accepting command socket connections

system_server 进程运行相关日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//进入system_server, 建立跟Zygote进程的socket通道
11-23 14:36:53.586  1274  1274 I Zygote  : Process: zygote socket opened, supported ABIS: armeabi-v7a,armeabi
// 执行SystemServer.run()
11-23 14:36:53.618  1274  1274 I SystemServer: Entered the Android system server!   <===> boot_progress_system_run
// 等待installd准备就绪
11-23 14:36:53.707  1274  1274 I Installer: Waiting for installd to be ready.

//服务启动
11-23 14:36:53.732  1274  1274 I ActivityManager: Memory class: 192

//phase100
11-23 14:36:53.883  1274  1274 I SystemServiceManager: Starting phase 100
11-23 14:36:53.902  1274  1274 I SystemServer: Package Manager
11-23 14:37:03.816  1274  1274 I SystemServer: User Service
...
11-23 14:37:03.940  1274  1274 I SystemServer: Init Watchdog
11-23 14:37:03.941  1274  1274 I SystemServer: Input Manager
11-23 14:37:03.946  1274  1274 I SystemServer: Window Manager
...
11-23 14:37:04.081  1274  1274 I SystemServiceManager: Starting com.android.server.MountService$Lifecycle
11-23 14:37:04.088  1274  2717 D MountService: Thinking about reset, mSystemReady=false, mDaemonConnected=true
11-23 14:37:04.088  1274  1274 I SystemServiceManager: Starting com.android.server.UiModeManagerService
11-23 14:37:04.520  1274  1274 I SystemServer: NetworkTimeUpdateService

//phase480 && 500
11-23 14:37:05.056  1274  1274 I SystemServiceManager: Starting phase 480
11-23 14:37:05.061  1274  1274 I SystemServiceManager: Starting phase 500
11-23 14:37:05.231  1274  1274 I ActivityManager: System now ready  <==> boot_progress_ams_ready
11-23 14:37:05.234  1274  1274 I SystemServer: Making services ready
11-23 14:37:05.243  1274  1274 I SystemServer: WebViewFactory preparation

//phase550
11-23 14:37:05.234  1274  1274 I SystemServiceManager: Starting phase 550
11-23 14:37:05.237  1274  1288 I ActivityManager: Force stopping com.android.providers.media appid=10010 user=-1: vold reset

//Phase600
11-23 14:37:06.066  1274  1274 I SystemServiceManager: Starting phase 600
11-23 14:37:06.236  1274  1274 D MountService: onStartUser 0

基于记录以上关键日志的目的,我们可以通过以下 logcat 命令在手机开机后使用:

  • adb logcat -b events |grep “boot_progress”
  • adb logcat -s Zygote|SystemServer|SystemServiceManager|ActivityManager

总结

笔者认为,源码分析过程中如果能输出关键类调用的流程,能够显著加强后续理解。关于普通应用进程的创建和启动过程将在后续 Activity 启动分析中一并介绍。下图就是关于本文各进程启动过程的方法调用链路总结。

init_method_call

参考


许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。