第六章 SystemServer进程:系统服务启动与注册
SystemServer,这个名字听起来就很有分量。它是Android系统的“大管家”,几乎所有你叫得上名字的系统服务——ActivityManagerService、WindowManagerService、PackageManagerService——都在这里启动和运行。今天我们就来聊聊这个进程是怎么启动的,以及那些核心服务是怎么注册和初始化的。
6.1 SystemServer的启动流程
还记得Zygote进程吗?它孵化了第一个Java进程——SystemServer。具体来说,Zygote在fork自身之后,会调用SystemServer的main方法。嗯,这里有个细节:Zygote启动SystemServer时,会通过反射调用com.android.server.SystemServer的main方法。
// 在ZygoteInit.java中
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
我刚开始看这段代码时,觉得挺简单的。但实际项目中,SystemServer的启动远比想象中复杂。它要加载各种库、初始化服务、注册到ServiceManager……每一步出错都可能导致系统无法正常启动。
SystemServer的main方法做了三件大事:
- 加载本地库(如android_servers)
- 创建SystemServer实例并调用run方法
- 在run方法中启动所有系统服务
说白了,run方法就是整个SystemServer的核心。它按照优先级顺序,依次启动引导服务、核心服务和其他服务。我习惯把run方法比作一场交响乐的指挥——每个服务就像不同的乐器,必须在正确的时机加入演奏。
关键点:SystemServer的启动顺序是严格定义的。引导服务(如Installer、DeviceIdentifiersPolicyService)最先启动,然后是核心服务(如AMS、WMS、PMS),最后是其他服务(如CameraService、MediaService)。
6.2 系统服务注册与管理(ServiceManager)
ServiceManager是什么?你可以把它想象成一个“服务黄页”。每个系统服务启动后,都要到ServiceManager这里注册自己的名字和Binder引用。其他进程想用某个服务时,先通过ServiceManager查询,拿到Binder引用后再调用。
你想想看,如果没有ServiceManager,每个服务都得自己暴露端口、自己处理连接请求,那得多乱?ServiceManager的存在,让服务发现变得简单而统一。
// 服务注册示例
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.ACTIVITY_SERVICE, am);
ServiceManager本身也是一个服务,但它比较特殊——它是在init进程中启动的,比SystemServer还早。我记得有一次排查问题,发现某个服务注册失败,导致系统一直重启。后来定位到是ServiceManager的Binder线程池满了,无法处理新的注册请求。嗯,这种问题在低端设备上更容易出现。
避坑指南:我曾经遇到过服务注册后无法被其他进程找到的情况。原因是服务注册时使用的名称与查询时使用的名称不一致——大小写差了一个字母。ServiceManager的键是大小写敏感的,这一点务必注意。
6.3 核心服务初始化
核心服务有三个:ActivityManagerService(AMS)、WindowManagerService(WMS)、PackageManagerService(PMS)。它们各自负责什么?简单来说:
- AMS:管理Activity的生命周期、任务栈、进程调度
- WMS:管理窗口的创建、布局、输入事件分发
- PMS:管理应用的安装、卸载、权限、组件信息
这三个服务的初始化顺序是固定的:先PMS,再AMS,最后WMS。为什么?因为AMS需要PMS提供已安装应用的信息,WMS又需要AMS提供Activity的窗口状态。说白了,它们之间有依赖关系。
6.3.1 PackageManagerService的初始化
PMS的初始化是最耗时的。它要扫描所有已安装的应用,解析AndroidManifest.xml,构建包信息数据库。我见过一些低端手机首次开机要等很久,就是因为PMS在扫描大量预装应用。
// PMS初始化核心逻辑
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// 扫描系统应用
scanDirLI(systemDir, ...);
// 扫描非系统应用
scanDirLI(vendorDir, ...);
// 扫描data分区应用
scanDirLI(dataDir, ...);
}
PMS初始化完成后,会通过ServiceManager注册自己。这样其他服务就能通过ServiceManager查询到PMS的Binder引用,进而调用它的方法。
6.3.2 ActivityManagerService的初始化
AMS的初始化相对复杂。它要创建系统进程的ActivityRecord、初始化任务栈、启动系统UI(如SystemUI)。我记得有一次,AMS初始化时因为SystemUI启动失败,导致整个系统卡在开机动画——嗯,这就是所谓的“死机”现象。
// AMS初始化核心逻辑
public ActivityManagerService(Context systemContext) {
// 创建系统进程的ActivityRecord
mSystemThread = ActivityThread.systemMain();
// 初始化任务栈
mStackSupervisor = new ActivityStackSupervisor(this);
// 启动系统UI
startSystemUi();
}
注意事项:AMS初始化时,会调用startSystemUi()启动SystemUI。如果SystemUI的apk损坏或签名不正确,AMS会抛出异常,导致SystemServer进程崩溃。我曾经在OTA升级后遇到过这个问题——新版本的SystemUI与旧版本的AMS不兼容。
6.3.3 WindowManagerService的初始化
WMS的初始化依赖于AMS。它需要AMS提供当前焦点Activity的信息,才能正确管理窗口的Z-order。WMS初始化时,会创建WindowManagerPolicy(策略类),用于处理窗口的显示策略(如状态栏、导航栏的显示与隐藏)。
// WMS初始化核心逻辑
public WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
// 创建窗口策略
mPolicy = new PhoneWindowManager();
// 初始化输入系统
mInputManager = inputManager;
// 创建窗口管理器
mWindowMap = new HashMap<IBinder, WindowState>();
}
WMS初始化完成后,会注册到ServiceManager。这样,其他进程(如应用进程)就能通过ServiceManager获取WMS的Binder引用,进而创建窗口、调整窗口大小等。
6.4 知识体系总览
下面这张图展示了SystemServer进程的核心知识体系。你可以看到,从Zygote孵化开始,到SystemServer启动,再到三个核心服务的初始化与注册,整个流程环环相扣。
6.5 总结
SystemServer的启动流程,说白了就是“Zygote孵化 → 加载库 → 启动服务 → 注册到ServiceManager”。核心服务的初始化顺序是PMS → AMS → WMS,它们之间有明确的依赖关系。ServiceManager作为服务注册中心,是整个系统服务架构的基石。
我在实际项目中,经常遇到SystemServer启动慢或崩溃的问题。排查思路通常是:先看logcat中SystemServer的启动日志,定位到哪个服务初始化失败;然后检查该服务的依赖是否满足;最后看ServiceManager是否正常工作。嗯,这套方法屡试不爽。
个人建议:如果你刚开始学习SystemServer,不要试图一次性理解所有细节。先掌握启动流程和三个核心服务的职责,然后逐步深入每个服务的内部实现。我在带新人时,通常让他们先画一张SystemServer启动流程图,把每个阶段的关键代码标注出来——这个方法很有效。