Skip to content

Android启动全景

以 Android 17.0.0_r1 真实源码串起 init 启动 app_process、Zygote 预加载、fork SystemServer、服务启动与 Zygote socket 循环。

基于android-17.0.0_r1
AndroidZygoteSystemServer源码阅读

Android启动全景 ​

这篇文章是 SystemServer 系列的地图,不把“启动全景”写成一张脱离源码的流程图。我们沿着 Android 17 的真实入口回答五个问题:谁启动 app_process,它如何选择 Zygote 模式,Zygote 为什么先预加载再 fork,SystemServer 在子进程中何时接管,以及父 Zygote 最后由什么事件循环继续服务后续进程创建。

读完后,应该能从一条 boot log 或 trace 反向定位到 app_main.cpp、ZygoteInit.java、ZygoteServer.java 和 SystemServer.java 的对应阶段;也应该能解释“Zygote 已启动但 SystemServer 没起来”和“SystemServer 已发布服务但 Zygote socket 不再接受连接”分别属于哪一个 owner。

1. 先看真正的入口 ​

源码文件:frameworks/base/cmds/app_process/app_main.cpp

相关函数:main()、AppRuntime::start()

cpp
int main(int argc, char* const argv[])
{
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // 解析 VM 参数和 app_process 内部参数。
    ...
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    ...
    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;
    }
    ...
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else {
        runtime.start("com.android.internal.os.RuntimeInit", args, false);
    }
}

这里的 owner 是 native app_process,不是 Java ZygoteInit。它先消费 --zygote、--start-system-server、--application 和 --nice-name,再决定调用哪个 Java 启动类。--start-system-server 只是作为参数传给 Zygote;真正的 fork 发生在后面的 ZygoteInit.forkSystemServer(),因此不能把 app_process 解析到该参数写成“已经创建了 system_server”。

启动配置来自 init 的 service 定义。源码文件:system/core/rootdir/init.zygote64_32.rc。其中 service zygote_secondary 以 /system/bin/app_process32 ... --zygote --socket-name=zygote_secondary 启动 32 位 Zygote,并声明 socket zygote_secondary 与 usap_pool_secondary。init 负责进程、socket 和重启策略;Java Zygote 负责消费这些 socket,不负责创建 init service。

2. Zygote预加载 ​

源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

相关函数:main()、preload()、gcAndFinalize()、forkSystemServer()、ZygoteServer.runSelectLoop()

java
public static void main(String[] argv) {
    ZygoteHooks.startZygoteNoThreadCreation();
    ...
    boolean startSystemServer = false;
    String zygoteSocketName = "zygote";
    String abiList = null;
    ...
    if (!enableLazyPreload) {
        bootTimingsTraceLog.traceBegin("ZygotePreload");
        preload(bootTimingsTraceLog);
        bootTimingsTraceLog.traceEnd();
    }
    gcAndFinalize();
    Zygote.initNativeState(isPrimaryZygote);
    zygoteServer = new ZygoteServer(isPrimaryZygote);
    if (startSystemServer) {
        Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
        if (r != null) {
            r.run();
            return;
        }
    }
    caller = zygoteServer.runSelectLoop(abiList);
}

这段顺序包含三个重要约束:

  1. startZygoteNoThreadCreation() 先禁止过早创建线程,保证 fork 前运行环境可控。
  2. preload() 和 gcAndFinalize() 在父 Zygote 中完成,目的是让常用类、资源和 dex cache 进入可由子进程共享的地址空间;它们不是 SystemServer 服务初始化。
  3. forkSystemServer() 的返回值区分父子进程:父 Zygote得到 null,继续 runSelectLoop();子进程得到 Runnable,运行 SystemServer 后直接返回,不再进入 Zygote socket 循环。

3. SystemServer参数 ​

源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

相关函数:forkSystemServer()

java
String[] args = {
    "--setuid=1000",
    "--setgid=1000",
    "--setgroups=...",
    "--capabilities=" + capabilities + "," + capabilities,
    "--nice-name=system_server",
    "--runtime-args",
    "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
    "com.android.server.SystemServer",
};

ZygoteArguments parsedArgs = ZygoteArguments.getInstance(commandBuffer);
pid = Zygote.forkSystemServer(
        parsedArgs.mUid, parsedArgs.mGid,
        parsedArgs.mGids,
        parsedArgs.mRuntimeFlags,
        null,
        parsedArgs.mPermittedCapabilities,
        parsedArgs.mEffectiveCapabilities);

fork 参数同时决定身份、组、capability、进程名和目标 Java 类。uid=1000 说明子进程身份切换到 system UID;capability 则先由 Zygote 根据当前容器有效能力做交集,不能简单照抄为“system_server 永远拥有完整列表”。如果参数解析、capget 或 native fork 失败,SystemServer 尚未进入 main(),问题应回到 Zygote fork 阶段,而不是查服务注册。

4. SystemServer入口 ​

源码文件:frameworks/base/services/java/com/android/server/SystemServer.java

相关函数:main()、构造函数、run()

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

private void run() {
    TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
    ...
    Looper.prepareMainLooper();
    createSystemContext();
    startBootstrapServices(t);
    startCoreServices(t);
    startOtherServices(t);
    startApexServices(t);
    ...
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

SystemServer 的 owner 是 fork 后的 Java 子进程。createSystemContext() 建立系统上下文;四组 start*Services() 按依赖顺序创建服务、发布 Binder 或加入 LocalServices;最后主线程进入 Looper。这里的 startOtherServices() 并不是“所有服务都在同一阶段完成”,其中还会注册 boot phase 回调、等待依赖或把工作投递到线程池。

5. 父子进程分流 ​

父路径:forkSystemServer() 返回 null 后进入 ZygoteServer.runSelectLoop(),继续接受应用进程创建命令;Zygote socket 的 owner 仍是父 Zygote。子路径:SystemServer 的 run() 进入主 Looper,服务注册和 boot phase 由它继续推进。

失败定位可以按 owner 分三类:

  • app_process 参数或 ABI 属性失败:查 app_main.cpp 与 init service 配置;
  • preload、capability、native fork 失败:查 ZygoteInit.java、Zygote native fork 和 zygote 日志;
  • SystemServer 已进入 run() 但服务启动失败:查 SystemServer.java 的具体 start*Services()、SystemServiceManager 和服务自身异常。

不要把 sys.boot_completed=1 当成这条主线的唯一成功标志;它表示更晚的启动阶段,不能替代 Zygote fork、SystemServer Looper 或某个 Binder 服务实际发布状态。

6. 读源码和复现命令 ​

下面命令只做静态导航:输入是 Android 17 checkout 中的源码路径,输出是入口、分支和阶段调用;命令不会启动设备,也不会证明运行时服务一定成功。

bash
rg -n "int main\(|--zygote|--start-system-server|runtime.start" \
  frameworks/base/cmds/app_process/app_main.cpp

rg -n "public static void main|preload\(|forkSystemServer|runSelectLoop|zygoteInit" \
  frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

rg -n "public static void main|void run\(|startBootstrapServices|startCoreServices|startOtherServices|startApexServices|Looper.loop" \
  frameworks/base/services/java/com/android/server/SystemServer.java

rg -n "service zygote|socket zygote|start-system-server|--zygote" \
  system/core/rootdir/init.zygote*.rc frameworks/base/cmds/app_process

7. 下一篇阅读边界 ​

下一篇只展开 app_process 的 main() 与 AndroidRuntime::start():参数如何分成 VM 参数、Zygote 参数和应用类参数,以及 JNI/ART 初始化如何把控制权交给 ZygoteInit.main()。本文已经给出全景,不在下一篇重复预加载、SystemServer 服务组和 Binder 注册细节。