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 版本的服务清单、方法位置和部分调用层级可能变化,但进程角色和主干流程基本稳定。
一、整体流程
整个过程可以理解为三次状态切换:
Zygote -> system_server:系统从"具备进程孵化能力"进入"开始搭建系统服务"的阶段。SystemServer.run() -> AMS.systemReady():系统服务从"已创建"逐步进入"可协作、可对应用开放"的阶段。system_server -> Zygote -> Launcher:系统服务反向请求 Zygote 创建普通应用进程,并真正启动 HOME 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
在进入源码调用链之前,需要先回答三个问题:
- Zygote 如何快速创建一个新进程?
- 新进程为什么不需要立刻复制 Zygote 的全部内存?
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 中的主线可以概括为:
- 解析 ABI、Socket 名称和
start-system-server参数; - 调用
preload()预加载常用类和资源; - 执行一次 GC,清理预加载阶段的临时对象;
- 创建
ZygoteServer; - 调用
forkSystemServer(); - 父进程进入
runSelectLoop(),持续处理应用进程创建请求; 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();
}
}
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()
这些阶段不是严格的业务分层,而是启动顺序和依赖关系的体现。真正理解 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 等依赖服务。
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()。
因此,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 的系统侧调度主线为:
到达 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()
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 启动包含两个不同阶段:
- 系统侧调度动作 :解析 HOME、创建
ActivityRecord、选择任务与显示区域、检查宿主进程; - 应用侧执行动作 :创建/绑定进程、接收
LaunchActivityItem、执行 Launcher Activity 生命周期。
六、完整调用链回顾
七、关键源码位置
| 环节 | 源码位置 | 关键方法 |
|---|---|---|
| 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_serverReady、用户解锁、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 启动事务。