SystemServiceManager 这个名字很容易让人想象出一个完整的依赖框架:服务声明依赖,Manager 自动做拓扑排序,依次创建、发布并判定 ready。
Android 16 的真实实现没有这么"自动"。
先说明这个 Manager 真正负责的范围:
system_server 的大顺序主要写死在
SystemServer.java的显式调用序列中;SystemServiceManager负责构造并启动由它管理的SystemService、保存列表、按单调递增的 Boot Phase 依次回调。服务之间更细的依赖,靠源码顺序、Boot Phase、LocalServices/Binder 查询、异步等待和服务专用systemReady()等机制共同表达。它不是通用依赖图求解器,也不管理 system_server 中的所有服务。
本文围绕一个核心问题展开: "服务对象已经创建"到"能力真的可用",中间经过哪些里程碑?
源码基线: Android 16 QPR2
android-16.0.0_r4,frameworks/basecommit45034f0663f960d9ee5fb0a101a4732b71f6e2f4。
一、先把五个容易混成一个点的状态拆开

一个 Framework 服务常见但非强制统一的状态链是:
markdown
1. constructed
Java 对象已经构造
2. started
onStart() / main() / start() 已执行
3. published
Binder 名称进入 ServiceManager,或本地接口进入 LocalServices
4. phase-ready
收到某个 Boot Phase,允许依赖某类系统能力
5. service-ready / user-ready
完成服务专用 systemReady、异步初始化、用户解锁或数据加载
这些状态不能互相替代:对象存在不等于已发布,已发布不等于内部依赖齐全;到达某个 phase 不等于所有异步任务结束,全局 ready 也不等于每个用户都已解锁并收到广播。
二、startService(Class) 实际做了什么?
SystemServiceManager.startService(Class) 的主流程并不复杂:
kotlin
确认 class 是 SystemService 子类
→ 查找接收 Context 的 public constructor
→ 反射构造实例
→ startService(instance)
→ 把实例放进 mServices
→ 调用 service.onStart()
用近似伪代码表示:
ini
T service = constructor.newInstance(mContext);
mServices.add(service);
service.onStart();
return service;
1. 构造函数用于建立对象,不宜宣称能力已经 ready
SystemService 文档把构造函数描述为接收 System Context、初始化服务对象。需要 Binder 发布、依赖其他服务或启动外部交互的动作,通常放到 onStart() 或更晚阶段。
但这是 Framework 约定,不是运行时魔法。某个具体服务的构造函数究竟做了多少工作,仍要看实现。
2. onStart() 是"启动回调",不是统一的"所有依赖完成回调"
SystemService.onStart() 是 abstract。基类文档建议服务在这里发布 Binder 接口,并可发布 system_server 内部 LocalService。
它可以创建核心对象、发布 Binder/Local 接口、启动线程、注册监听或发起异步加载,并把依赖更晚系统能力的动作留给 onBootPhase()。
所以 startService() 正常返回,最多证明构造与 onStart() 没有同步抛异常;不能自动证明服务的所有后台初始化都结束。
三、SystemServiceManager 会自动分析服务依赖吗?
不会。
SystemServiceManager 没有读取一张"Service A dependsOn Service B"的全局图再拓扑排序。启动顺序主要来自 SystemServer.java 中直接书写的顺序:
ini
mSystemServiceManager.startService(ServiceA.class);
mSystemServiceManager.startService(ServiceB.class);
LegacyService serviceC = LegacyService.main(...);
...
mSystemServiceManager.startBootPhase(..., PHASE_SYSTEM_SERVICES_READY);
如果 B 的构造或 onStart() 必须同步使用 A,SystemServer 就必须先启动 A,或把依赖动作推迟到双方都应存在的 Boot Phase。
因此,阅读依赖必须同时看 SystemServer 的显式顺序、服务在 onStart() 中查询和发布的对象、onBootPhase() 使用依赖的阶段、初始化线程池与显式等待,以及是否还有专用 systemReady() 调用。
不能只看 SystemServiceManager 一个文件就还原全部依赖图。
四、Boot Phase 解决的是什么问题?
如果所有服务都在 onStart() 里立即访问所有依赖,SystemServer 会陷入复杂的互相等待。Boot Phase 提供一组全局单调里程碑:服务可以先创建/发布最小接口,再把依赖后置。
Android 16 的核心阶段定义在 SystemService.java:
| Phase | 常量 | 主要语义 |
|---|---|---|
| 100 | PHASE_WAIT_FOR_DEFAULT_DISPLAY |
默认显示已满足早期服务继续启动的条件 |
| 200 | PHASE_WAIT_FOR_SENSOR_SERVICE |
等待 Native SensorService 可用的阶段 |
| 480 | PHASE_LOCK_SETTINGS_READY |
可以取得 lock settings 数据 |
| 500 | PHASE_SYSTEM_SERVICES_READY |
可以安全调用 PowerManager、PackageManager 等核心能力 |
| 520 | PHASE_DEVICE_SPECIFIC_SERVICES_READY |
设备特定服务已到可使用阶段 |
| 550 | PHASE_ACTIVITY_MANAGER_READY |
可广播 Intent 等 AMS ready 能力 |
| 600 | PHASE_THIRD_PARTY_APPS_CAN_START |
可以启动/绑定第三方 App |
| 1000 | PHASE_BOOT_COMPLETED |
全局 Framework 启动进入 boot-completed 阶段 |
数字中故意留有间隔,便于平台插入阶段;调用必须严格递增。
五、startBootPhase() 怎样分发?
SystemServiceManager.startBootPhase() 的核心是:
scss
检查 phase > mCurrentPhase
→ 更新 mCurrentPhase
→ 按 mServices 列表顺序
→ 逐个调用 service.onBootPhase(phase)
→ 记录耗时,异常则把启动失败向上抛
这里还有一个诊断上非常重要的顺序:mCurrentPhase 在遍历服务之前就被更新。因此 dumper 显示 Current phase: 500,只能证明 Manager 已经进入 phase 500;它可能仍阻塞在某个服务的 onBootPhase(500) 中。看到更晚 phase、当前 phase 之后的 SystemServer 日志,或 sys.boot_completed=1 这类后续里程碑,才能进一步证明相应同步分发已经返回。
1. 同步分发不等于固定线程,更不是异步任务 barrier
这里要同时保留"文档契约""Manager 实现"和"某次实际调用"三层事实:
| 观察层 | 能得出的结论 |
|---|---|
SystemService 文档契约 |
生命周期方法应由 system_server 主 Looper 线程调用 |
SystemServiceManager 实现 |
startService()、startBootPhase() 都在当前调用线程同步执行;方法内部没有统一 post 到主 Looper,也没有线程断言 |
| 某一次真实调用 | 回调实际落在哪条线程,由调用点、进程内调用链以及中途是否显式切线程决定 |
多数早期 startService() 和 Boot Phase 调用直接发生在 SystemServer 的启动控制流上,此时调用线程就是后来进入主 Looper 的 system_server 主线程。但不能据此推出"所有 phase 在任何路径上都必然运行于主线程"。
Android 16 的 phase 1000 是一个关键反例:WMS 完成显示启用后调用 bootAnimationComplete(),AMS 再直接进入 finishBooting(),最后调用 SystemServiceManager.startBootPhase(1000);这条同步链没有天然重投到主 Looper。实机同一 FrameworkGeneration 的连续日志中,wm_boot_animation_done 与 Starting phase 1000 落在同一个 system_server 非主 TID(TID != PID),说明那一轮 phase 1000 的实际调用线程不是主线程。第九篇会把这条路径放回"显示完成 → phase 1000 → 属性跃迁"的整体顺序。
因此,写设计契约时可以说"应由主 Looper 调用";分析卡顿、锁或 trace 时,则必须沿实际调用点确认线程。无论同步回调落在哪条线程,只要服务把工作提交给 HandlerThread、SystemServerInitThreadPool 或自己的 executor,就已经进入另一段异步工作;Manager 不会自动等待,除非服务或 SystemServer 显式建立等待关系。
2. 回调顺序沿用服务注册顺序
它没有按运行时依赖重新排序。一个 phase 内先回调哪个服务,由 mServices 的加入顺序决定。
3. 更晚启动的对象不能假设自动补收所有旧阶段
startBootPhase() 对"截至调用时已启动的服务"遍历。若平台在某个阶段后才创建新服务,是否需要旧阶段语义必须由其设计与启动位置保证,不能凭想象认为 Manager 会重放全部历史阶段。
六、SystemServer 中的四个分组不是 Boot Phase
再次对齐两套坐标:
startBootstrap/Core/Other/ApexServices() |
PHASE_* |
|---|---|
| SystemServer 源码组织和大体启动顺序 | 分发给已启动 SystemService 的生命周期里程碑 |
| 一个方法中可以穿插多个 phase | 同一 phase 会回调多个已启动服务 |
| 不是数字状态 | 有单调递增的 mCurrentPhase |
| 也会直接启动 legacy service | 只由 SystemServiceManager 分发给其列表中的服务 |
尤其不要把 startCoreServices() 与 init rc 的 class_start core 混为一套系统。前者是 Java 方法,后者是 init Service class 命令。
七、Binder 发布与 LocalService 发布有什么区别?
SystemService 提供两类便捷方法。
1. publishBinderService()
publishBinderService() 最终调用:
ini
ServiceManager.addService(name, binder, allowIsolated, dumpPriority);
发布后,其他进程可按权限和 SELinux 规则通过 Binder 查找、调用这个接口。
它只证明"名称已可发现",不自动证明所有方法都能成功、底层 daemon/HAL 已连接、当前用户数据已解锁、异步缓存已加载或调用方拥有权限。
服务可以为了打破循环依赖而较早发布接口,再在方法内部拒绝、排队或降级处理尚未 ready 的请求。
2. publishLocalService()
publishLocalService() 把 Java 对象放进 LocalServices,只在 system_server 进程内按 Class 查找,不经过 Binder 驱动,通常用于更高权限、更细粒度的内部接口;具体调用仍可能跨线程、加锁或触发其他 IPC。
"Local"表示进程内发现机制,不等于所有方法都便宜、同步或无锁。
八、统一框架之外:legacy service 与专用 systemReady()
system_server 保留了许多历史形成的启动模式。Android 16 中可直接看到:
scss
PackageManagerService.main(...)
WindowManagerService.main(...)
ServiceManager.addService(Context.WINDOW_SERVICE, wm, ...)
这些对象可能有自己的 Lifecycle 包装,也可能由 SystemServer 直接构造、保存并调用 systemReady();并非每个对象都通过 mSystemServiceManager.startService() 加入 mServices。专用 systemReady() 也不是统一接口:复杂旧服务常用它传入依赖、执行回调或取得结果,调用阶段和具体语义必须回到对应类与 SystemServer 调用点判断。
此外,"Android system service"还可能位于别的 Linux 进程,例如 SurfaceFlinger、vold、netd、HAL/vendor service、独立应用或模块进程,以及其他由 init 管理的 daemon。
所以应使用窄结论:
SystemServiceManager 统一管理通过它启动的 SystemService 实例 及其 Boot Phase,而不是 Android 全系统的所有服务;方法都叫
systemReady(),也不代表它们共享同一接口、阶段或完成语义。
九、一个服务怎样设计分阶段启动?
概念模型可以压成三步:构造函数只建立最小对象状态;onStart() 发布最小 Binder/Local 接口;onBootPhase() 再在约定里程碑启用依赖更重的能力。这样可以先打破部分循环依赖,再逐步开放功能。
服务仍必须自己定义"未 ready 调用"如何处理------拒绝、降级、排队还是显式等待。SystemService 基类和 Boot Phase 都不会代替服务判断业务状态。
十、接下来要定义的不是"最后一个 phase",而是"完成"
Android 的服务依赖不是由 SystemServiceManager 自动解图;SystemServer 用显式源码顺序先构造和启动服务,服务通过 Binder/LocalService 发布最小接口,再由单调 Boot Phase 与专用
systemReady()逐步开放依赖能力。要判断"可用",必须说明是构造、发布、哪个 phase,还是用户级 ready。
现在已经能解释服务怎样从"对象"走到"分阶段可用",仍缺最后一个定义:当 system_server、Binder 名称和 Boot Phase 都已经出现时,哪个时刻才配得上"Android 启动完成"?下一篇专门拆开这个词。
源码定位
SystemServiceManager.startService():反射构造、注册列表与onStart()。SystemServiceManager.startBootPhase():单调阶段与逐服务回调。SystemService:生命周期、主 Looper 线程约束与 phase 定义。WindowManagerService.performEnableScreen()与ActivityManagerService.bootAnimationComplete():phase 1000 实际调用线程为何取决于显示完成调用链。publishBinderService()/publishLocalService():跨进程和进程内发布。SystemServer.run():四组服务启动与显式顺序。