源码视角下的 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.rc、init.zygote64.rc、init.zygote64_32.rc 等组合,并可能同时启动 zygote 与 zygote_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() 可以按职责理解为:

类别 代表服务 作用
系统状态与运行信息 SystemConfigService、BatteryService、UsageStatsService、CachedDeviceStateService 提供系统配置、电量、使用统计和设备状态
运行时观测与性能统计 BinderCallsStatsService、LooperStatsService、CpuMonitorService 统计 Binder、Looper 和 CPU 运行信息
升级、回滚与异常诊断 WebViewUpdateService、RollbackManagerService、NativeTombstoneManagerService、BugreportManagerService 管理 WebView、APK 回滚、native 崩溃和 bugreport
其他核心能力 GpuService、RemoteProvisioningService 管理 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;
  • 设置 mSystemReady 和 mProcessesReady;
  • 执行 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 再将事件分发给各个 SystemService 的 onUserUnlocking() 和 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 选择 zygote 或 zygote_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 启动事务。
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui