源码视角下的 Android 开机流程:从 Zygote、SystemServer 到 Launcher

Android 从内核进入用户空间后,会依次完成 native 服务启动、Java 运行环境建立、SystemServer服务初始化以及桌面应用启动。本文不展开 Boot ROM、Bootloader、Kernel 和 init 的全部细节,而是聚焦 Java 层主干链路:

text 复制代码
init
  -> Zygote
  -> system_server
  -> AMS/ATMS systemReady
  -> 解析 HOME Activity
  -> Zygote fork Launcher 进程
  -> ActivityThread.attach
  -> Launcher Activity 启动并显示

本文主要依据Android 14(API 34)源码整理。不同 Android 版本的服务清单、方法位置和部分调用层级可能变化,但进程角色和主干流程基本稳定。

一、整体流程

整个过程可以理解为三次状态切换:

  1. Zygote -> system_server:系统从"具备进程孵化能力"进入"开始搭建系统服务"的阶段。
  2. SystemServer.run() -> AMS.systemReady():系统服务从"已创建"逐步进入"可协作、可对应用开放"的阶段。
  3. system_server -> Zygote -> Launcher:系统服务反向请求 Zygote 创建普通应用进程,并真正启动 HOME Activity。
sequenceDiagram autonumber participant Init as init/app_process participant Z as Zygote participant SS as system_server participant AM as AMS/ATMS participant L as Launcher Init->>Z: 启动 ZygoteInit.main() Z->>Z: preload classes/resources Z->>SS: forkSystemServer() SS->>SS: startBootstrap/Core/Other/Apex services SS->>AM: AMS.systemReady() AM->>AM: 解析 CATEGORY_HOME AM->>Z: 通过 zygote socket 请求创建 HOME 进程 Z->>L: fork + specialize L->>L: ActivityThread.main() / attach() L->>AM: attachApplication() AM-->>L: 下发 Activity 启动事务

关键组件

组件 核心职责
init 用户空间 PID 1,解析 .rc 文件并启动 Zygote 等关键服务
Zygote 启动 ART、预加载共享资源,作为 system_server 和应用进程的父进程
system_server 承载 AMS、ATMS、PMS、WMS 等 Java 系统服务
AMS 管理应用进程、四大组件和系统运行状态
ATMS 管理 Activity、Task、Display Area 和多屏启动调度
Launcher 一个声明了 HOME intent-filter 的普通应用,其进程同样由 Zygote 创建

二、预备知识:fork、COW 与 Zygote Socket

在进入源码调用链之前,需要先回答三个问题:

  1. Zygote 如何快速创建一个新进程?
  2. 新进程为什么不需要立刻复制 Zygote 的全部内存?
  3. system_server 如何通知 Zygote:"请帮我创建这个应用进程"?

这三个问题分别对应 fork()、Copy-On-Write 和 Zygote Socket。它们共同构成了 Android 应用进程创建机制的基础。

2.1 fork:从已经准备好的模板创建进程

Linux fork() 会以当前进程为基础创建一个子进程。调用完成后,父子进程从同一个位置继续执行,只是返回值不同:

scss 复制代码
pid_t pid = fork();

if (pid > 0) {
    // 父进程:pid 是子进程的进程号
} else if (pid == 0) {
    // 子进程:从这里继续执行自己的启动逻辑
}

fork() 会为子进程创建新的进程管理结构,并继承父进程的虚拟地址空间和文件描述符等运行上下文。但这种"继承"不是完整复制:用户内存页最初通过 COW 共享;文件、Socket 等内核资源通常也不会被完整复制,而是由父子进程的文件描述符共同引用底层内核对象。

状态或资源 fork() 后的处理
PID、task_struct 为子进程创建新的进程标识和管理结构
虚拟地址空间、页表 建立子进程自己的管理结构,并保留与父进程相同的内存布局
物理内存页 父子进程最初通过 COW 共享,发生写入时才复制
文件描述符表 子进程获得一份表的副本,但表项仍引用相同的底层文件对象
Socket FD 子进程继承 FD,并引用相同的内核 Socket 对象
Binder FD 子进程继承 FD,但不会因此自动获得一套独立的 Binder Runtime

Zygote 正是一个提前准备好的"进程模板":它先启动 ART,并预加载 Framework 常用类、资源和部分运行时数据;需要创建应用时,再从这个模板 fork() 出一个子进程。这样每个应用都不必从零搭建 Java 运行环境。

2.2 COW:先共享,写入时再复制

fork() 之后,父子进程拥有彼此独立的虚拟地址空间,但其中很多虚拟页最初仍映射到相同的物理内存页,并被标记为只读:

markdown 复制代码
Zygote 虚拟页 ─┐
               ├──> 同一份物理页(类信息、资源等)
App 虚拟页 ────┘

只要双方都不修改,这些物理页就可以继续共享。当某一方尝试写入时,内核才复制对应的页,再让写入发生在新的副本上,这就是 Copy-On-Write(写时复制):

css 复制代码
写入前:Zygote 与 App -> 共享物理页 A
App 写入:内核复制 A -> B
写入后:Zygote -> A,App -> B

因此,Zygote 预加载的稳定数据越容易保持只读,多个应用就越能共享这些内存页。这既减少了重复加载,也降低了应用冷启动成本。

预加载并非越多越好。它会增加 Zygote 的启动时间和常驻内存,因此 Android 需要在开机速度、应用冷启动和内存压力之间权衡。

2.3 Zygote Socket:谁来下达创建命令

Zygote 具备 fork() 能力,但它并不知道系统下一步要启动哪个应用。真正决定启动目标的是 system_server 中的 AMS、ATMS 和 ProcessList 等模块。

当系统需要创建普通应用进程时,system_server 内的 ZygoteProcess 会通过 Unix Domain Socket 向 Zygote 发送一组启动参数,包括 UID、GID、ABI、SELinux seInfo、进程名、目标 SDK 和入口类等。Zygote 校验并解析参数后执行 fork(),再把子进程 PID 返回给 system_server

rust 复制代码
system_server
    -> ZygoteProcess
    -> /dev/socket/zygote
    -> ZygoteServer.runSelectLoop()
    -> fork()
    -> 返回子进程 PID

这个 Socket 并不是 Zygote 自己临时创建的。在 init.zygote*.rc 中,init 通过 socket zygote stream ... 提前创建监听 Socket,再把对应文件描述符交给 Zygote。Zygote 在早期预加载阶段明确禁止创建线程;预加载结束后解除限制,并由主线程进入 Socket 监听循环:

ini 复制代码
ZygoteHooks.startZygoteNoThreadCreation();
preload(bootTimingsTraceLog);
ZygoteHooks.stopZygoteNoThreadCreation();

zygoteServer = new ZygoteServer(isPrimaryZygote);
caller = zygoteServer.runSelectLoop(abiList);

Unix Domain Socket 只在本机进程之间通信,不需要经过完整的 TCP/IP 路由流程,并且可以结合 Socket 权限、SELinux 与对端凭据校验限制调用方。对于"发送创建参数并返回 PID"这种命令式请求,它足够简单直接。

对比项 Unix Domain Socket TCP/IP Socket(Loopback)
通信范围 同一台设备 本机或跨网络
寻址方式 文件系统/抽象命名空间,如 /dev/socket/zygote IP 地址与端口
协议路径 本地 IPC,不经过完整 IP 路由流程 经过 TCP/IP 协议栈
Android 中的用途 Zygote 进程创建请求等本机 IPC 网络服务或通用网络通信

一个重要区别:system_server 是 Zygote 启动早期直接调用 forkSystemServer() 创建的;Launcher 和其他应用进程才是由 system_server 通过 Zygote Socket 发起创建请求。

2.4 Binder 明明已经存在,为什么 Zygote 不使用它

常见说法是"Zygote 启动时 Binder 还不可用",但这并不准确。这里需要区分 Binder 的三个层次:

层次 Zygote 启动时的状态
Binder 驱动 已由内核提供
servicemanager init 在早期启动
Zygote 自己的 Binder 运行时 刻意不在 fork() 前初始化

前两项已经存在,并不意味着 Zygote 必须把自己设计成 Binder 服务。关键在于第三项:Zygote 需要长期充当应用进程的父进程,反复执行 fork(),因此它需要严格控制跨越 fork() 边界的线程、锁和进程级状态。

这里的"Binder 运行时"不是某一个类,而是进程使用 Binder 时逐步建立的一整套运行状态,例如:

复制代码
ProcessState / IPCThreadState
Binder Driver FD 与 mmap 缓冲区
Binder 线程池
Binder 对象、代理缓存和各种锁

如果一个多线程进程执行 fork(),子进程只保留调用 fork() 的那条线程,其他线程不会跟着复制;但用户空间中的锁和状态仍可能保留在 fork() 时的样子。假如某把锁原本由已经消失的线程持有,子进程继续使用它就可能死锁。

因此,问题不是 Binder "做不到通信",而是让 Zygote 在 fork() 前建立复杂的 Binder 运行时,会给每次创建子进程引入没有必要的状态继承与修复成本。Unix Domain Socket 可以在单线程循环中完成 accept()、读取参数、fork() 和回写 PID,更符合 Zygote 的职责。

libbinder 也设置了 fork() 保护。frameworks/native/libs/binder/ProcessState.cpp 中,如果某个进程已经创建了 ProcessState,子进程会把继承来的 Binder 状态标记为不可继续使用,并关闭继承的 Binder Driver FD:

ini 复制代码
void ProcessState::childPostFork() {
    if (gProcess) {
        gProcess->mForked = true;
        close(gProcess->mDriverFD);
        gProcess->mDriverFD = -1;
    }
}

这段代码更像一道"保险",而不是正常应用启动时都要执行的 Binder 重建流程。正常情况下,Zygote 父进程不会提前创建 ProcessState,所以 gProcess 为空;应用子进程完成 fork() 后,才第一次初始化属于自己的 Binder 环境:

rust 复制代码
ZygoteInit.zygoteInit()
  -> ZygoteInit.nativeZygoteInit()
  -> AppRuntime.onZygoteInit()
  -> ProcessState::self()
  -> startThreadPool()

AppRuntime.onZygoteInit() 中真正执行的核心代码只有两步:创建当前子进程自己的 ProcessState,再启动 Binder 线程池:

ini 复制代码
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();

这也解释了两条 IPC 链路的分工:

rust 复制代码
创建进程:system_server -> ZygoteProcess -> Unix Socket -> Zygote
创建完成:ApplicationThread <-> AMS/ATMS -> Binder

2.5 设计思想:Minimal Parent,Rich Child

理解这一节的关键,不是简单记住"Socket 比 Binder 轻量",而是理解 Zygote 如何划分父子进程的职责:

scss 复制代码
Zygote 父进程:ART + 预加载类/资源 + Zygote Socket + 尽量少的线程与运行状态
                                      |
                                    fork()
                                      |
应用子进程:Binder + Looper + ActivityThread + 应用自身的对象与业务状态

可以把这种设计概括为 Minimal Parent,Rich Child

  • 父进程只保留适合被大量子进程继承和共享的稳定内容;
  • 复杂、强状态、必须属于单个进程的运行环境,在 fork() 后由子进程独立初始化。

Zygote 的核心并不是"复制一切",而是共享适合共享的只读资源,重建必须独立的有状态运行环境。fork() 负责创建进程,COW 负责降低复制成本,Unix Domain Socket 负责传递创建命令;三者配合,才构成了 Android 高效而可靠的应用进程孵化机制。

三、模块一:从 Zygote 到 system_server

3.1 init 启动 app_process

以 64 位主 Zygote 为例,system/core/rootdir/init.zygote64.rc 中定义了:

text 复制代码
service zygote /system/bin/app_process64 -Xzygote /system/bin \
        --zygote --start-system-server --socket-name=zygote
    class main
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system

这里有三个关键参数:

  • --zygote:以 Zygote 模式运行;
  • --start-system-server:要求主 Zygote 创建 system_server
  • --socket-name=zygote:指定主 Zygote Socket 名称。

不同 ABI 配置会选择 init.zygote32.rcinit.zygote64.rcinit.zygote64_32.rc 等组合,并可能同时启动 zygotezygote_secondary

3.2 app_process 从 native 层进入Java层

app_process 的入口位于:

text 复制代码
frameworks/base/cmds/app_process/app_main.cpp

main() 的关键任务是识别 Zygote 模式、组装启动参数,然后调用 AndroidRuntime::start()

c++ 复制代码
int main(int argc, char* const argv[]) {
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    bool zygote = false;
    bool startSystemServer = false;

    // 省略 VM 参数及其他运行模式的解析
    if (strcmp(arg, "--zygote") == 0) {
        zygote = true;
    } else if (strcmp(arg, "--start-system-server") == 0) {
        startSystemServer = true;
    }

    Vector<String8> args;
    if (startSystemServer) {
        args.add(String8("start-system-server"));
    }
    // 省略 --abi-list、--socket-name 等参数的加入过程

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
}

AndroidRuntime::start() 负责启动 ART、注册 JNI,并反射调用 ZygoteInit.main()。至此,启动主线从 native 层进入 Java 层。

对应的核心代码位于 frameworks/base/core/jni/AndroidRuntime.cpp

c++ 复制代码
void AndroidRuntime::start(const char* className,
        const Vector<String8>& options, bool zygote) {
    // 启动 ART 虚拟机
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 注册 Android Framework JNI 方法
    if (startReg(env) < 0) {
        return;
    }

    // 找到 ZygoteInit 类及其 main(String[]) 方法
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    jmethodID startMeth = env->GetStaticMethodID(
            startClass, "main", "([Ljava/lang/String;)V");

    // 调用 ZygoteInit.main()
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
    free(slashClassName);
}

startVm() 内部通过 JNI_CreateJavaVM() 真正创建 ART 虚拟机:

c++ 复制代码
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
    return -1;
}

startReg() 内部遍历 gRegJNI,注册 Android Framework 的 JNI 方法:

c++ 复制代码
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
    return -1;
}

3.3 ZygoteInit.main() 做了什么

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 中的主线可以概括为:

  1. 解析 ABI、Socket 名称和 start-system-server 参数;
  2. 调用 preload() 预加载常用类和资源;
  3. 执行一次 GC,清理预加载阶段的临时对象;
  4. 创建 ZygoteServer
  5. 调用 forkSystemServer()
  6. 父进程进入 runSelectLoop(),持续处理应用进程创建请求;
  7. system_server 子进程关闭继承的 Zygote 服务端 Socket,进入 SystemServer.main()

下面省略日志、Trace 和异常处理,只保留 ZygoteInit.main() 中影响启动流程的核心代码:

Java 复制代码
public static void main(String[] argv) {
    ZygoteServer zygoteServer = null;
    Runnable caller;

    // fork 前禁止创建其他线程,避免多线程状态被复制到子进程
    ZygoteHooks.startZygoteNoThreadCreation();

    boolean startSystemServer = false;
    String zygoteSocketName = "zygote";
    String abiList = null;
    boolean enableLazyPreload = false;

    // 解析 start-system-server、ABI 列表和 Socket 名称等启动参数
    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());
        }
    }

    final boolean isPrimaryZygote =
            zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);

    // 预加载 Framework 常用类、资源和共享库
    if (!enableLazyPreload) {
        preload(bootTimingsTraceLog);
    }
    gcAndFinalize();

    Zygote.initNativeState(isPrimaryZygote);
    ZygoteHooks.stopZygoteNoThreadCreation();

    // 创建服务端,准备接收后续进程创建请求
    zygoteServer = new ZygoteServer(isPrimaryZygote);

    // 主 Zygote fork system_server
    if (startSystemServer) {
        Runnable r = forkSystemServer(
                abiList, zygoteSocketName, zygoteServer);

        // 子进程执行该 Runnable,最终进入 SystemServer.main()
        if (r != null) {
            r.run();
            return;
        }
    }

    // 父进程留在 Zygote 中,持续监听进程创建请求
    caller = zygoteServer.runSelectLoop(abiList);

    // runSelectLoop() 只会在新创建的子进程中返回 Runnable
    if (caller != null) {
        caller.run();
    }
}
flowchart LR A[&#34;init.zygote*.rc<br/>启动 app_process&#34;] --> B[&#34;app_process<br/>AndroidRuntime.start()&#34;] B --> C[&#34;ZygoteInit.main()&#34;] C --> D[&#34;preload()&#34;] D --> E[&#34;new ZygoteServer()&#34;] E --> F[&#34;forkSystemServer()&#34;] F --> G{&#34;fork 返回值&#34;} G -->|父进程 pid > 0| H[&#34;runSelectLoop()<br/>监听 Zygote Socket&#34;] G -->|子进程 pid = 0| I[&#34;关闭 Zygote Server Socket&#34;] I --> J[&#34;handleSystemServerProcess()&#34;] J --> K[&#34;ZygoteInit.zygoteInit()&#34;] K --> L[&#34;SystemServer.main()&#34;]

3.4 system_server 子进程如何找到入口类

forkSystemServer() 为子进程准备的参数中包含:

text 复制代码
--setuid=1000
--setgid=1000
--nice-name=system_server
com.android.server.SystemServer

子进程进入 handleSystemServerProcess() 后,创建 system_server ClassLoader,再调用:

text 复制代码
ZygoteInit.zygoteInit()
  -> RuntimeInit.commonInit()
  -> ZygoteInit.nativeZygoteInit()
  -> RuntimeInit.applicationInit()
  -> findStaticMain("com.android.server.SystemServer")
  -> SystemServer.main()

这里返回的 Runnable 最终执行目标类的静态 main()。模块一完成后,父进程 Zygote 保持"进程孵化器"身份,子进程则脱离 Zygote 主循环并转变为系统服务容器。

四、模块二:SystemServer 如何让系统服务进入 Ready

4.1 SystemServer.main() 与 run()

源码入口:

text 复制代码
frameworks/base/services/java/com/android/server/SystemServer.java

主线如下:

text 复制代码
SystemServer.main()
  -> new SystemServer().run()
      -> prepareMainLooper()
      -> createSystemContext()
      -> System.loadLibrary("android_servers")
      -> 创建 SystemServiceManager
      -> startBootstrapServices()
      -> startCoreServices()
      -> startOtherServices()
      -> startApexServices()
      -> Looper.loop()
flowchart LR A[&#34;SystemServer.main()&#34;] --> B[&#34;new SystemServer().run()&#34;] B --> C[&#34;创建主线程 Looper&#34;] C --> D[&#34;创建 SystemContext&#34;] D --> E[&#34;加载 android_servers&#34;] E --> F[&#34;创建 SystemServiceManager&#34;] F --> G[&#34;startBootstrapServices()&#34;] G --> H[&#34;startCoreServices()&#34;] H --> I[&#34;startOtherServices()&#34;] I --> J[&#34;startApexServices()&#34;] J --> K[&#34;Looper.loop()&#34;]

这些阶段不是严格的业务分层,而是启动顺序和依赖关系的体现。真正理解 SystemServer,重点不是背诵全部服务,而是能够理解关键依赖和 Ready 节点。

4.2 startBootstrapServices:搭起基础骨架

startBootstrapServices() 启动相互依赖最紧密、其他服务赖以运行的基础组件,主线包括:

  • 尽早启动 Watchdog,监控 system_server 卡死;
  • 加载 SystemConfig、启动 Installer 等基础能力;
  • 初始化 ATMS 和 AMS,建立 Activity 与进程调度框架;
  • 启动 Power、Thermal、Lights、Display 等底层服务;
  • 等待默认 Display 就绪;
  • 创建 PMS,使包解析和组件查询能力可用;
  • 在 PMS 之后启动 User、Overlay、Resources、Sensor 等依赖服务。
flowchart TD A[&#34;Watchdog / SystemConfig / Installer&#34;] --> B[&#34;ATMS + AMS&#34;] B --> C[&#34;Power / Thermal / Lights&#34;] C --> D[&#34;DisplayManagerService&#34;] D --> E[&#34;PHASE_WAIT_FOR_DEFAULT_DISPLAY&#34;] E --> F[&#34;PackageManagerService.main()&#34;] F --> G[&#34;User / Overlay / Resources / Sensor 等服务&#34;]

4.3 startCoreServices:核心但依赖关系较轻的服务

培训资料中的 startCoreServices() 可以按职责理解为:

类别 代表服务 作用
系统状态与运行信息 SystemConfigServiceBatteryServiceUsageStatsServiceCachedDeviceStateService 提供系统配置、电量、使用统计和设备状态
运行时观测与性能统计 BinderCallsStatsServiceLooperStatsServiceCpuMonitorService 统计 Binder、Looper 和 CPU 运行信息
升级、回滚与异常诊断 WebViewUpdateServiceRollbackManagerServiceNativeTombstoneManagerServiceBugreportManagerService 管理 WebView、APK 回滚、native 崩溃和 bugreport
其他核心能力 GpuServiceRemoteProvisioningService 管理 GPU 信息和远程密钥配置

服务启动存在条件判断。例如当前 Android 14 分支中,WebViewUpdateService 依赖设备具备 WebView feature,CpuMonitorService 只在 debuggable/eng 构建中启动。

4.4 startOtherServices:从"已创建"走向"可用"

startOtherServices() 很长,可以按四个大的节点来阅读。

节点一:系统 Provider 可用

text 复制代码
AccountManagerService
  -> ContentService
  -> installSystemProviders()
  -> SettingsProvider 等系统 Provider 可访问
  -> DropBoxManagerService / RoleManagerService / 后续服务

很多服务需要读取 Settings 或其他 Provider 数据,因此 Provider Ready 是后续初始化的重要前提。

节点二:Input、WMS 与 Display 协同就绪

text 复制代码
InputManagerService
  -> WindowManagerService.main()
  -> AMS.setWindowManager(wm)
  -> wm.onInitReady()
  -> inputManager.start()
  -> DisplayManagerService.windowManagerAndInputReady()
  -> wm.displayReady()

至此,系统逐渐具备窗口组织、显示输出和输入分发能力,但"服务对象已经创建"仍不代表所有服务已经对外 Ready。

节点三:通过 Boot Phase 推进系统状态

SystemServiceManager.startBootPhase() 会按阶段回调各个 SystemService.onBootPhase()。常见阶段包括:

Boot Phase 含义
PHASE_WAIT_FOR_DEFAULT_DISPLAY 100 等待默认显示设备
PHASE_LOCK_SETTINGS_READY 480 LockSettings 已就绪
PHASE_SYSTEM_SERVICES_READY 500 核心系统服务已具备协作条件
PHASE_DEVICE_SPECIFIC_SERVICES_READY 520 设备定制服务已就绪
PHASE_ACTIVITY_MANAGER_READY 550 AMS 已就绪
PHASE_THIRD_PARTY_APPS_CAN_START 600 可以启动第三方应用
PHASE_BOOT_COMPLETED 1000 Boot Completed 阶段

Boot Phase 的价值在于:服务不必相互硬编码全部依赖,而是可以在统一阶段完成延迟初始化。

节点四:AMS.systemReady()

SystemServer 最终调用 mActivityManagerService.systemReady(...)。AMS 在这里会:

  • 通知 ATMS、UserController、AppOps、ProcessList 等模块进入 Ready;
  • 设置 mSystemReadymProcessesReady
  • 执行 SystemServer 传入的回调,推进 PHASE_ACTIVITY_MANAGER_READY 等工作;
  • 启动 Direct Boot Aware 的 persistent app;
  • 对正在启动的系统用户调用 startHomeOnAllDisplays()
flowchart LR A[&#34;Input / WMS / Display Ready&#34;] --> B[&#34;LockSettings.systemReady()&#34;] B --> C[&#34;PHASE_LOCK_SETTINGS_READY&#34;] C --> D[&#34;PHASE_SYSTEM_SERVICES_READY&#34;] D --> E[&#34;WMS / PMS / DMS systemReady()&#34;] E --> F[&#34;AMS.systemReady()&#34;] F --> G[&#34;mSystemReady / mProcessesReady&#34;] G --> H[&#34;startHomeOnAllDisplays()&#34;]

因此,systemReady() 离真正开机完成,系统发送开机广播仍有一段距离;真正的 BOOT_COMPLETED 在更后面。

五、模块三:从 AMS.systemReady 到 Launcher 显示

5.1 先解析 HOME Activity

AMS 通过 ATMS 内部接口调用:

Java 复制代码
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady")

随后进入:

text 复制代码
RootWindowContainer.startHomeOnAllDisplays()
  -> startHomeOnDisplay()
  -> startHomeOnTaskDisplayArea()
  -> ActivityTaskManagerService.getHomeIntent()
  -> resolveHomeActivity()
  -> ActivityStartController.startHomeActivity()

默认 HOME Intent 的核心是:

Java 复制代码
action   = android.intent.action.MAIN
category = android.intent.category.HOME

PMS 根据用户状态、组件 enabled 状态、Direct Boot 可用性、preferred activity 和 intent-filter 优先级解析出当前 HOME。因此,"Launcher"并不是 Framework 写死的某一个包名,而是当前解析出的 HOME Activity。

5.2 为什么开机时可能先看到 FallbackHome(在AOSP中表现为黑屏Loading加载页面)

如果用户尚未解锁,而用户选择的 Launcher 不支持加密状态下运行,Settings中的 FallbackHome 可以作为低优先级兜底 HOME:

XML 复制代码
<intent-filter android:priority="-1000">
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.HOME" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

它的目的不是替代真正 Launcher,而是在 Direct Boot 阶段提供一个可解析、可显示的 HOME。此时 Device Encrypted(DE)数据已经可用,但 Credential Encrypted(CE)数据仍处于锁定状态,依赖 CE 数据且不支持 Direct Boot 的 Launcher 暂时无法启动。

用户完成解锁后,系统会同时推进系统服务和 HOME 界面两条链路。

系统服务链路

用户密钥解锁后,UserController 先后通知 SystemServiceManager 用户正在解锁和已经解锁:

Java 复制代码
case USER_UNLOCK_MSG:
    int userId = msg.arg1;
    mInjector.getSystemServiceManager().onUserUnlocking(userId);
    finishUserUnlocked((UserState) msg.obj);
    break;

case USER_UNLOCKED_MSG:
    mInjector.getSystemServiceManager().onUserUnlocked(msg.arg1);
    break;

SystemServiceManager 再将事件分发给各个 SystemServiceonUserUnlocking()onUserUnlocked()。其中,onUserUnlocking() 表示 CE 数据已经可以访问;Account、Wallpaper、InputMethod、Shortcut 等依赖用户数据的服务可以在此后读取配置、恢复状态或建立用户级连接。

HOME 界面链路

FallbackHome 监听 ACTION_USER_UNLOCKED,收到广播后重新解析 MAIN + HOME。下面只保留决定是否退出的核心代码:

Java 复制代码
private void maybeFinish() {
    if (getSystemService(UserManager.class).isUserUnlocked()) {
        Intent homeIntent = new Intent(Intent.ACTION_MAIN)
                .addCategory(Intent.CATEGORY_HOME);
        ResolveInfo homeInfo =
                getPackageManager().resolveActivity(homeIntent, 0);

        if (!Objects.equals(getPackageName(),
                homeInfo.activityInfo.packageName)) {
            finish();
        }
    }
}

与此同时,ATMS 也会在用户解锁回调中重新调度 HOME:

scss 复制代码
SystemServiceManager.onUserUnlocked()
  -> ActivityTaskManagerService.Lifecycle.onUserUnlocked()
  -> ActivityTaskSupervisor.onUserUnlocked()
  -> scheduleStartHome("userUnlocked")

因此,系统服务链路负责让依赖 CE 数据的系统能力进入完整状态;HOME 链路负责退出临时的 FallbackHome 并启动真实 Launcher。两条链路由同一次用户解锁事件触发,但承担的职责不同。

5.3 从 Home 调度到 startSpecificActivity

HOME Activity 的系统侧调度主线为:

sequenceDiagram participant AMS participant ATMS participant RWC as RootWindowContainer participant ASC as ActivityStartController participant AS as ActivityStarter participant ATS as ActivityTaskSupervisor AMS->>ATMS: startHomeOnAllDisplays() ATMS->>RWC: startHomeOnAllDisplays() RWC->>RWC: startHomeOnDisplay() RWC->>RWC: resolveHomeActivity() RWC->>ASC: startHomeActivity() ASC->>AS: obtainStarter(...).execute() AS->>RWC: resumeFocusedTasksTopActivities() RWC->>RWC: resumeTopActivityUncheckedLocked() RWC->>ATS: startSpecificActivity()

到达 ActivityTaskSupervisor.startSpecificActivity() 后,系统先判断 Activity 的宿主进程是否存在:

  • 进程存在且已完成 Binder attach:调用 realStartActivityLocked()
  • 进程不存在:调用 ActivityTaskManagerService.startProcessAsync(),异步转交 AMS 创建进程,避免持有 ATMS 全局锁时同步调用 AMS 导致死锁。

5.4 system_server 通过 Socket 请求 Zygote fork Launcher

进程不存在时,调用链可以概括为:

text 复制代码
ActivityTaskSupervisor.startSpecificActivity()
  -> ActivityTaskManagerService.startProcessAsync()
  -> ActivityManagerInternal.startProcess()
  -> ActivityManagerService.startProcessLocked()
  -> ProcessList.startProcessLocked()
  -> Process.start()
  -> ZygoteProcess.start()
  -> startViaZygote()
  -> zygoteSendArgsAndGetResult()

ZygoteProcess 根据目标 ABI 选择 zygotezygote_secondary,再发送 UID、GID、supplementary groups、runtime flags、mount mode、SELinux seInfo、nice-name、目标 SDK 和入口类等参数。

Zygote 侧的处理主线是:

text 复制代码
ZygoteServer.runSelectLoop()
  -> ZygoteConnection.processCommand()
  -> Zygote.forkAndSpecialize()
  -> native fork
  -> ZygoteConnection.handleChildProc()
  -> ZygoteInit.zygoteInit()
  -> RuntimeInit.applicationInit()
  -> ActivityThread.main()
sequenceDiagram participant SS as system_server participant ATS as ActivityTaskSupervisor participant AMS as AMS/ProcessList participant ZP as ZygoteProcess participant Z as Zygote participant LP as Launcher Process SS->>ATS: startSpecificActivity(Home) ATS->>ATS: 检查宿主进程 alt 进程已存在且已 attach ATS-->>LP: realStartActivityLocked() else 进程不存在 ATS->>AMS: startProcessAsync() AMS->>ZP: Process.start() / startViaZygote() ZP->>Z: Socket 发送进程参数 Z->>Z: processCommand() / forkAndSpecialize() Z->>LP: 子进程进入 ActivityThread.main() end

5.5 进程创建完成不等于 Activity 已启动

Launcher 子进程进入 ActivityThread.main() 后,会创建主线程 Looper 并调用:

text 复制代码
ActivityThread.attach(false, startSeq)
  -> AMS.attachApplication(IApplicationThread, startSeq)

AMS 根据 PID、UID 和 startSeq 找到此前记录的 ProcessRecord,将应用进程中的 IApplicationThread Binder 代理与系统侧进程记录绑定,然后通过 ATMS 继续启动等待该进程的 Activity:

text 复制代码
AMS.attachApplication()
  -> attachApplicationLocked()
  -> ATMS.attachApplication(WindowProcessController)
  -> realStartActivityLocked()
  -> ClientTransaction / LaunchActivityItem
  -> ActivityThread.handleLaunchActivity()
  -> Launcher.onCreate() / onStart() / onResume()

因此 Home 启动包含两个不同阶段:

  1. 系统侧调度动作 :解析 HOME、创建 ActivityRecord、选择任务与显示区域、检查宿主进程;
  2. 应用侧执行动作 :创建/绑定进程、接收 LaunchActivityItem、执行 Launcher Activity 生命周期。

六、完整调用链回顾

sequenceDiagram autonumber participant Init participant Z as Zygote participant SS as system_server participant AMS participant ATMS participant RWC as RootWindowContainer participant PMS participant LP as Launcher Process participant AT as ActivityThread Init->>Z: 启动 app_process / ZygoteInit.main() Z->>Z: preload() Z->>SS: forkSystemServer() SS->>SS: SystemServer.main() / run() SS->>SS: 启动系统服务并推进 Boot Phase SS->>AMS: systemReady() AMS->>ATMS: startHomeOnAllDisplays() ATMS->>RWC: startHomeOnDisplay() RWC->>PMS: resolve MAIN + HOME PMS-->>RWC: 返回当前 Home ActivityInfo RWC->>ATMS: startHomeActivity() ATMS->>AMS: 需要创建 HOME 进程 AMS->>Z: 通过 Zygote Socket 发送 fork 参数 Z->>LP: fork + specialize LP->>AT: ActivityThread.main() AT->>AMS: attachApplication() AMS->>ATMS: 进程已 attach,继续启动 Activity ATMS-->>AT: LaunchActivityItem AT->>LP: Launcher 生命周期与首帧显示

七、关键源码位置

环节 源码位置 关键方法
init 启动 Zygote system/core/rootdir/init.zygote*.rc service zygote
app_process 入口 frameworks/base/cmds/app_process/app_main.cpp main()runtime.start()
Zygote 主流程 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java main()preload()forkSystemServer()
Zygote Socket 循环 frameworks/base/core/java/com/android/internal/os/ZygoteServer.java runSelectLoop()
处理创建请求 frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java processCommand()handleChildProc()
native fork 封装 frameworks/base/core/java/com/android/internal/os/Zygote.java forkAndSpecialize()
SystemServer frameworks/base/services/java/com/android/server/SystemServer.java main()run()、各 start services 方法
AMS Ready 与 Home 入口 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java systemReady()attachApplication()
HOME 解析与多屏调度 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java startHomeOnAllDisplays()resolveHomeActivity()
Activity/进程分流 frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java startSpecificActivity()
AMS/ATMS 异步桥接 frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java startProcessAsync()
进程参数组装 frameworks/base/services/core/java/com/android/server/am/ProcessList.java startProcessLocked()
Zygote 客户端 frameworks/base/core/java/android/os/ZygoteProcess.java startViaZygote()
应用主线程 frameworks/base/core/java/android/app/ActivityThread.java main()attach()handleLaunchActivity()
FallbackHome packages/apps/Settings/src/com/android/settings/FallbackHome.java maybeFinish()

八、如何用日志验证这条链路

8.1 查看进程父子关系

shell 复制代码
adb shell ps -A -o USER,PID,PPID,NAME | grep -E 'zygote|system_server|launcher|Launcher'

通常可以看到:

  • system_server 的 PPID 指向主 Zygote;
  • Launcher 进程的 PPID 也指向与其 ABI 对应的 Zygote。

8.2 观察启动关键日志

Shell 复制代码
adb logcat -b all -v threadtime | grep -E \
  'Zygote|SystemServer|ActivityManager|ActivityTaskManager|FallbackHome|Launcher'

重点关注:

  • Zygote 接收请求并 fork 出 PID;
  • ActivityManager 的 Start proc 日志和 hosting type;
  • system_server Ready、用户解锁、HOME 切换日志;
  • Launcher 进程开始输出日志的时间点。

8.3 查看当前 HOME 解析结果

Shell 复制代码
adb shell cmd package resolve-activity --brief \
  -a android.intent.action.MAIN \
  -c android.intent.category.HOME

锁定与解锁状态下结果可能不同,排查 FallbackHome 问题时应同时确认用户状态和目标 Launcher 是否 Direct Boot Aware。

8.4 判断开机阶段

Shell 复制代码
adb shell getprop sys.boot_completed
adb logcat -b events -v threadtime | grep -E 'boot_progress|am_proc_start'

sys.boot_completed=1 表示系统已越过后续开机完成阶段,不能与 AMS.systemReady() 简单画等号。

九、总结

Android Java 层开机主线的本质,是三个进程角色之间的控制权交接:

  • init 启动 Zygote,建立 ART 和进程孵化环境;
  • Zygote fork system_server,后者搭建系统服务并推进 Ready 状态;
  • AMS/ATMS 解析 HOME,经 Zygote 创建 Launcher 进程;
  • Launcher 通过 ActivityThread.attach() 回到 AMS,系统再下发真正的 Activity 启动事务。
相关推荐
二流小码农1 小时前
鸿蒙开发:以登录案例了解代码架构MVVM
android·ios·harmonyos
用户69371750013842 小时前
从代码生产者到 AI 协作者:软件工程师的角色重构
android·前端·后端
GitLqr2 小时前
别在 Flutter 的 main() 里乱锁屏幕方向,小心 iPad 分屏功能被你搞没了
android·flutter·ios
sg_knight3 小时前
MySQL 存储过程详解:从入门到实战
android·数据库·mysql·database·dba·关系型数据库·db
爱笑鱼3 小时前
Binder(四):ioctl(BINDER_WRITE_READ) 之后,事务怎样到达目标进程?
android
AFinalStone3 小时前
Android 7系统休眠唤醒(二)开机全链路—BootROM到Launcher
android·电源管理·休眠唤醒
Mr YiRan3 小时前
Android NDK开发之统计到未被回收的图片
android
浮江雾4 小时前
Flutter第十七节-----路由管理(3)
android·开发语言·前端·javascript·flutter·入门
admin and root4 小时前
「移动安全」安卓APP 反编译&frida脱壳技巧分享
android·开发语言·python·web安全·微信小程序·移动安全·攻防演练