SystemServer 概述与启动流程

SystemServer 是什么?说白了,它就是 Android 系统的「大管家」。所有你听过的核心服务 —— ActivityManagerService、WindowManagerService、PackageManagerService —— 全都运行在这个进程里。嗯,这个进程是在 Zygote 之后第二个被启动的 Java 层进程,它一旦挂掉,整个系统就黑屏重启,所以它也是整个系统的压舱石。

核心指标:SystemServer 进程在 Android 10 以后稳定占用约 80~150 个线程,堆内存起始分配 8MB,后期根据服务数量动态增长到 200MB 以上。

1.1 启动时机与入口

系统上电后,init 进程解析 init.rc 启动 Zygote,Zygote 在 ZygoteInit.main() 中做完预加载后,会调用 forkSystemServer() 创建子进程。我刚开始学这部分时,一直好奇为什么要在 Zygote 里 fork —— 后来才知道,这是为了利用写时拷贝技术,让 SystemServer 直接继承 Zygote 已经加载好的 Java 框架和资源,省去重复预加载的时间。

1.2 启动流程拆解

从 Zygote 到 SystemServer 跑起来,大致经历以下阶段。我个人习惯把流程记成「一 fork、二 main、三线程、四服务」:

  1. Zygote 创建子进程:ZygoteInit.forkSystemServer() 执行系统调用 fork,并设置进程名 system_server。
  2. 执行 SystemServer.main():子进程从 com.android.server.SystemServer.main() 进入。
  3. 初始化 Looper 和 Binder 线程池:Looper.prepareMainLooper() + BinderInternal.setBlockedThreadCount() 等。
  4. 启动系统服务管理框架:创建 SystemServiceManager,后者负责统一注册、启动和生命周期回调。
  5. 分阶段启动服务:按照引导服务、核心服务、其他服务的顺序依次初始化,每启动一个就会往 ServiceManager 中注册。

1.3 各类服务启动阶段

SystemServer 里服务的启动顺序是有严格讲究的。我曾经踩过坑:早期版本里 PackageManagerService 和 ActivityManagerService 的启动顺序调整过,导致某些设备开机后黑屏。下面这张表格把服务分类和启动时机列清楚:

服务阶段典型服务启动时机作用简述
引导服务Installer, DeviceIdentifiersPolicyService, Cellular第 0 批(最先)提供底层支撑,如包安装、设备标识
核心服务ActivityManagerService, PackageManagerService, PowerManagerService第 1 批管理应用、权限、电源
其他服务WindowManagerService, NotificationManagerService, AlarmManagerService第 2 批及以后界面、通知、闹钟等上层功能

技巧:如果你需要在 SystemServer 里添加自定义服务,务必把启动代码放在 startOtherServices() 方法里,不要插到引导服务阶段,否则可能因为依赖未备齐而崩溃。

1.4 启动进程关系图

我把整个体系画成一张流程图,方便你跟踪进程和服务的启动路径。注意看那个红色的 Watchdog 节点 —— 我之前遇到过因为 SystemServer 卡死在 onStart() 回调里,Watchdog 迟迟没超时(因为没写对时间),结果整整过了 5 分钟才触发重启。嗯,从那以后我每次写新服务都会先调调 Watchdog。下面这张 SVG 清晰地展示了从 Zygote 到各个服务启动的全貌,我特别标出了常见触发埋点的位置。

SystemServer 启动流程总览 Zygote 进程 forkSystemServer() SystemServer.main() (埋点入口:进入此方法) 初始化 Looper + Binder 线程 引导服务 (Installer…) 核心服务 (AMS, PMS…) 其他服务 (WMS, Alarm…) Watchdog 监控 (超时则重启) 系统就绪 / 启动完成 注意:所有的服务初始化都应该 有埋点记录。Watchdog 会检查 每个阶段是否在规定时间内完成。

1.5 埋点时机与关键点

为什么要关注启动流程?因为我们做初始化埋点,本质就是在这条链路的关键节点上插入 trace 或日志。我个人建议在以下几个位置打点:

  • SystemServer.main() 入口:记录进程已经创建,时间戳清零。
  • 每个服务 onStart() 回调前后:记录单个服务的启动耗时。我曾经用这种方式发现某个厂商的定制服务卡在 onBootPhase() 里 2 秒多。
  • Watchdog 触发前:如果某个阶段超时,需要立即 dump 当前线程堆栈——但不是所有团队都记得加这段。

注意:SystemServer 的启动时间直接影响开机速度。Android 官方推荐整体启动时间控制在 30 秒以内(从内核计时起),但很多低端机甚至要 1 分钟。如果埋点发现某个服务超过 3 秒还没启动完,就要警惕了。

嗯,关于 SystemServer 的启动流程就先聊到这里。记住这个流程,我们后面做埋点的时候,会在这些节点上逐次插入统计代码,最终形成一个完整的开机性能看板。