服务依赖关系
SystemServer 内的“依赖服务”至少有五种表达方式:字段/构造参数直接注入、LocalServices 类型注册表、ServiceManager Binder 名称表、BootPhase 状态屏障、Future/ready callback。它们的 owner、阻塞语义、失败表现完全不同。排查依赖为空或服务未 ready 时,必须先判断依赖属于哪一种。
1. LocalServices
源码文件:frameworks/base/core/java/com/android/server/LocalServices.java
private static final ArrayMap<Class<?>, Object>
sLocalServiceObjects = new ArrayMap<>();
public static <T> T getService(Class<T> type) {
synchronized (sLocalServiceObjects) {
return (T) sLocalServiceObjects.get(type);
}
}
public static <T> void addService(Class<T> type, T service) {
synchronized (sLocalServiceObjects) {
if (sLocalServiceObjects.containsKey(type)) {
throw new IllegalStateException(
"Overriding service registration");
}
sLocalServiceObjects.put(type, service);
}
}LocalServices 是同一进程的 Class→Object map,没有 Binder 序列化、权限检查或死亡通知。重复类型注册直接抛异常;查询未注册类型返回 null,不会等待。它适合高频、特权的 system_server 内部接口。
2. Binder名称表
源码文件:frameworks/base/core/java/android/os/ServiceManager.java
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) return service;
return Binder.allowBlocking(rawGetService(name));
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
return null;
}
}
public static IBinder waitForService(
@NonNull String name) {
return Binder.allowBlocking(
waitForServiceNative(name));
}ServiceManager 是跨进程 name→IBinder,涉及 context manager、servicemanager 权限、Binder handle、死亡和重注册。getService() 单次查询可能返回 null;waitForService() 注册通知并等待,可能触发 lazy AIDL 启动。选择错误 API 会把“依赖尚未注册”变成 null 或长期阻塞。
3. 字段与构造注入
源码文件:frameworks/base/services/java/com/android/server/SystemServer.java
ActivityTaskManagerService atm =
mSystemServiceManager.startService(
ActivityTaskManagerService.Lifecycle.class)
.getService();
mActivityManagerService =
ActivityManagerService.Lifecycle.startService(
mSystemServiceManager, atm);
mActivityManagerService.setInstaller(installer);
mActivityManagerService.setWindowManager(wm);字段/构造注入提供最强的启动顺序:调用点拿到具体实例后直接传入消费者,不经过注册表,也不会查询错误名称。代价是强耦合和必须在同一进程;注入前调用消费者方法会看到 null 或不完整状态。
4. 本地接口消费
mSystemServiceManager.startService(
UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(
UsageStatsManagerInternal.class));
LocalServices.getService(
DisplayManagerInternal.class).onOverlayChanged();UsageStatsService 必须先在 onStart() 发布 UsageStatsManagerInternal,SystemServer 才能注入 AMS。DisplayManagerInternal 同样是进程内接口。此类调用没有 null guard 时,注册顺序就是硬依赖;出现 NPE 应向前检查发布方 onStart(),而不是查 servicemanager。
5. Binder实际消费
storageManager = IStorageManager.Stub.asInterface(
ServiceManager.getService("mount"));
lockSettings = ILockSettings.Stub.asInterface(
ServiceManager.getService("lock_settings"));这里消费者只持有 AIDL proxy,不直接访问实现类。getService() 为空时 asInterface(null) 返回 null,调用方通常用 null guard/reportWtf 降级。若服务应当必定出现,可改用 waitForService,但必须评估启动环依赖,避免双方互相等待。
6. BootPhase屏障
mSystemServiceManager.startBootPhase(
t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
mSystemServiceManager.startBootPhase(
t, SystemService.PHASE_SYSTEM_SERVICES_READY);BootPhase 不返回服务对象,而是向所有已启动 SystemService 广播能力门槛。服务在 onBootPhase() 内获取“此时才安全使用”的可选依赖。phase 失败会阻止后续阶段;它适合一对多状态同步,而不是单一接口查询。
7. Future与回调
mZygotePreload = SystemServerInitThreadPool.submit(
() -> Process.ZYGOTE_PROCESS
.preloadDefault(abi),
"SecondaryZygotePreload");
ConcurrentUtils.waitForFutureNoInterrupt(
mZygotePreload, "Zygote preload");
inputManager.setWindowManagerCallbacks(
wm.getInputManagerCallback());
inputManager.start();
mDisplayManagerService.windowManagerAndInputReady();Future 表示异步任务完成屏障;ready callback 表示两个已存在对象之间建立运行时协作。对象存在、Binder 可查并不代表 Future 已完成或 callback 已安装。WebView/secondary preload、WMS/Input/Display 都依赖这类状态。
8. 选择原则
| 场景 | 推荐依赖方式 | 原因 |
|---|---|---|
| 同进程、高频、特权接口 | LocalServices | 无 Binder 开销,类型化 |
| 跨进程公共系统 API | ServiceManager/AIDL | 生命周期与权限跨进程 |
| 核心服务强顺序 | 构造/字段注入 | 启动点明确,失败立即暴露 |
| 多服务能力门槛 | BootPhase | 一对多阶段同步 |
| 可并行但有最终依赖 | Future | 提前执行,消费前等待 |
| 运行时双向协作 | callback/ready | 对象之间显式联结 |
不能为了“解耦”把硬依赖都改成 ServiceManager 查询,也不能为了性能把跨进程 API 偷换成 LocalServices。依赖方式必须匹配调用方所在进程和生命周期。
9. 失败定位与导航
- LocalServices null:查发布方
onStart()和类型 key; - Binder null:查名称、注册时机、权限、死亡和查询 API;
- 字段 null:查 SystemServer 注入顺序;
- phase 未完成:查
startBootPhase()和某个服务 callback 异常; - Future 卡住:查任务线程、锁、依赖和 wait 点;
- callback 未生效:查 setter 调用是否早于消费者 start。
# LocalServices map 与重复注册。
rg -n "sLocalServiceObjects|getService|addService|Overriding service registration" \
frameworks/base/core/java/com/android/server/LocalServices.java
# Binder 查询、等待和缓存。
rg -n "getService\(|waitForService|sCache|getIServiceManager" \
frameworks/base/core/java/android/os/ServiceManager.java
# SystemServer 中真实依赖边。
rg -n "LocalServices.getService|ServiceManager.getService|setInstaller|setWindowManager|setUsageStatsManager|waitForFutureNoInterrupt|windowManagerAndInputReady" \
frameworks/base/services/java/com/android/server/SystemServer.java下一篇将分析系统服务启动耗时:如何用 TimingsTraceAndSlog、warnIfTooLong、异步 trace 和 Perfetto 把慢启动定位到具体 owner;不会重复依赖类型模型。
