Android 系统启动机制(七):进入 SystemServer.main() 以后,system_server 还是一个空进程吗?

85 阅读7分钟

前面追到 system_server 的出生点:Zygote fork 出子进程,子分支完成 specialize,最后进入 com.android.server.SystemServer.main()

这时容易出现两种相反的误解:

“它刚出生,所以里面什么都没有”;
“它继承了 Zygote,所以系统服务已经都在里面了”。

两种说法都把“运行环境”和“系统服务”混成了一层。

进入 SystemServer.main() 时,system_server 已是拥有 ART、Framework JNI、预加载页面和 Binder IPC 基础设施的独立进程;但 System Context、主 Looper 的长期循环、SystemServiceManager 以及 AMS/PMS/WMS 等服务仍要由 SystemServer.run() 组织建立。

本篇只回答“一个可运行的子进程怎样搭好服务容器骨架”。服务怎样从构造走到 ready,留给下一篇。

源码基线: Android 16 QPR2 android-16.0.0_r4frameworks/base commit 45034f0663f960d9ee5fb0a101a4732b71f6e2f4

一、进入 main 的那一刻,已经有什么?

到达 Java 入口前,子进程已经走过:

Zygote preload
  → fork
  → system_server specialize
  → 完成通用 child 初始化
  → 进入 SystemServer.main()

Binder 线程池的完整 child 调用链已在 第五篇给出;本篇只讨论它与主 Looper 的职责区别。

于是“出生清单”可以分成两列:

已经具备仍未建立
独立 PID、system UID/GID/capability 与 SELinux 身份System Context / System UI Context
ART、Framework JNI 与 fork 后运行时状态system_server 主线程的长期 Looper 循环
Zygote 预加载的类、资源和库页面SystemServiceManager
Binder IPC 线程池AMS、PMS、WMS 等服务对象及其发布状态

因此,system_server 不是“空地址空间”,却仍是一个尚未完成 Framework 服务装配的容器

二、SystemServer.main() 只是装配入口

SystemServer.main() 很短:

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

这里没有创建新进程。当前代码已经运行在 Zygote fork 出来的 system_server 中,只是创建一个 Java SystemServer 对象并调用 run()

四个名字必须分开:

名称类型角色
system_serverLinux 进程承载大量 Framework 核心系统服务
SystemServerJava 类/对象组织这个进程的初始化与服务启动
SystemServiceManagerJava 管理对象启动并分发一部分 SystemService 生命周期
SystemServiceJava 抽象基类一类具有统一生命周期回调的服务实现

SystemServer 不是 AMS,也不是发布给 ServiceManager 的 Binder Service。它更像一次性的装配总控:把进程规则、Context、管理对象和服务启动顺序接起来,最后让主线程进入长期消息循环。

三、SystemServer.run() 要补齐哪几类设施?

image.png

不要把 SystemServer.run() 看成一串互不相干的初始化。它做的工作可以按目的归为四层:

1. 进程规则
   调整 runtime、Binder、SQLite、Parcel、调度与安全相关策略
​
2. 执行基础设施
   准备主 Looper,启动允许并行的初始化线程池
​
3. Framework 运行上下文
   加载 android_servers,建立 System Context / System UI Context
​
4. 服务容器
   创建 SystemServiceManager,随后开始分组启动系统服务

这个顺序有因果关系:服务构造需要 Context;统一生命周期需要 Manager;可能阻塞的远端调用和长期主线程则需要提前配置进程规则。

run() 末尾的 Looper.loop() 也不是“启动完成标志”。它表示主线程从一次性装配控制流进入长期事件循环,服务和用户级启动工作仍会继续发生。

四、system_server 中至少有三套执行路径

理解服务容器,不能只画对象,还要知道代码可能在哪条线程执行。

1. Java 主线程 / 主 Looper

SystemServer.run() 在当前启动线程调用:

Looper.prepareMainLooper();

服务启动的大顺序由这条主控制流组织;末尾进入 Looper.loop() 后,它继续处理投递到 system_server 主 Looper 的消息。下一篇会进一步区分两件事:SystemService 文档要求生命周期方法由主 Looper 调用,但一次回调在实机上究竟落到哪条线程,仍由 SystemServiceManager 的实际调用点以及是否显式切线程决定。

2. Binder 线程

进入 Java main 前,system_server 已具备 Binder IPC 线程池;SystemServer.run() 还会配置线程数量与调度策略。此处重要的不是重复启动调用链,而是线程职责:

Binder 线程负责接收远端 transaction。它们不是主线程,也不会天然服从主 Looper 的消息顺序。服务若要把 IPC 工作转到主线程或自己的 HandlerThread,必须显式投递。

3. 初始化线程池与服务自有线程

SystemServerInitThreadPool 允许少量明确可并行的初始化任务与主线重叠。各服务启动后还可能创建自己的 HandlerThread、executor 或 Native 工作线程。

所以准确模型是:

SystemServer 主线程控制总体装配顺序;明确提交的初始化任务可以并行,Binder transaction 与服务内部后台工作又属于其他执行路径。

这一区分很重要:一个 Binder 线程阻塞,不自动等于 SystemServer 主启动线程卡死;反过来,主线程卡在服务启动,也不能靠观察某个 Binder 线程活跃来证明启动仍在推进。

五、为什么先要 System Context,再要 SystemServiceManager?

1. System Context:让服务获得 Framework 运行环境

createSystemContext() 的核心是:

ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();

这里没有启动普通 Activity。ActivityThread 也不只服务于三方 App;systemMain() 为 system_server 建立资源、包与 Context 运行环境,使后续服务能够获得系统资源、ContentResolver 等基础能力。

System Context 不是“所有服务都 ready”的证明。它是后续服务构造和运行所依赖的容器环境。

2. SystemServiceManager:让部分服务共享生命周期框架

System Context 建立后,run() 创建:

mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

此时它只是 system_server 进程内的 Java 对象和 LocalServices 条目,不是独立进程,也不是面向 App 的 Binder 接口。

它出现是因为接下来需要统一完成几件事:

以 System Context 构造 SystemService;
记录由它启动的服务实例;
调用 onStart();
保存当前 Boot Phase;
向已纳管服务分发生命周期回调。

它不会读取全局依赖图自动拓扑排序,也不管理 system_server 中的每一种服务形态。显式顺序与 ready 机制是下一篇的主线。

六、什么时候才真正开始创建服务?

容器骨架建立以后,run() 才进入服务装配:

startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
startApexServices(t);

这些名称首先是 SystemServer.java 的源码分组与大体顺序,不是四个 Boot Phase,也不对应 init rc 的 class_start core

服务的启动形态也并不统一:

mSystemServiceManager.startService(SomeLifecycle.class)
SomeLegacyService.main(...)
ServiceManager.addService(name, binder)
对象构造后再显式调用 systemReady()

因此,“开始调用 startBootstrapServices()”只能说明服务创建阶段已经开始,不能说明所有 Bootstrap 服务已完成,更不能说明 Framework 已 ready。

Watchdog 会在 bootstrap 早期启动,以便尽早发现启动死锁;system_server_dumper 也会较早发布,给调试构建提供内部状态入口。这些设施很重要,但在本篇只需知道它们位于容器基础设施与早期服务装配之间,不需要抢占主线。

容器已经搭好,为什么能力仍不能立即使用?

到这里,system_server 已经从“可运行的 Zygote 子进程”变成“能够开始承载 Framework 服务的容器”:

有独立进程身份
  → 有 ART 与 Binder 基础设施
  → 有主 Looper 与初始化执行路径
  → 有 System Context
  → 有 SystemServiceManager
  → 开始创建服务

但“开始创建”与“服务可用”之间仍有一段关键距离:构造函数、onStart()、Binder/LocalService 发布、Boot Phase、服务专用 systemReady() 与异步初始化分别代表什么?下一篇专门拆开这些里程碑。

源码定位