SystemServiceManager
SystemServiceManager 管理的是 SystemServer 进程内的 SystemService 实例和生命周期,不是 servicemanager 的 Binder 名称表。它接收 class、class name、standalone jar 或现成实例,统一执行反射构造、类名去重、加入 mServices、调用 onStart(),并在后续 boot phase 中遍历同一列表调用 onBootPhase()。
1. 状态owner
源码文件:frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
public SystemServiceManager(Context context) {
mContext = context;
mServices = new ArrayList<>();
mServiceClassnames = new ArraySet<>();
mNumUserPoolThreads = Math.min(
Runtime.getRuntime().availableProcessors(),
DEFAULT_MAX_USER_POOL_THREADS);
}mContext 是 SS018 创建的 system context;mServices 保存已经登记的实例并成为 boot/user lifecycle 遍历源;mServiceClassnames 防止同一个类重复启动。user lifecycle 线程数按 CPU 数和上限取最小值,与普通服务 onStart() 不共用线程池。
2. 三种类型入口
public SystemService startService(String className) {
Class<SystemService> serviceClass = loadClassFromLoader(
className, this.getClass().getClassLoader());
return startService(serviceClass);
}
public SystemService startServiceFromJar(
String className, String path) {
PathClassLoader loader =
SystemServerClassLoaderFactory.getOrCreateClassLoader(
path, this.getClass().getClassLoader(),
isJarInTestApex(path));
Class<SystemService> serviceClass =
loadClassFromLoader(className, loader);
return startService(serviceClass);
}String 入口使用当前 SystemServer classloader,适合运行时 classpath 中但编译期无法直接引用的类;jar 入口建立/复用 PathClassLoader,适合 standalone SystemServer jar/APEX jar;显式 Class<T> 入口类型最安全。三者最终都进入 startService(Class)。
3. 反射构造约束
public <T extends SystemService> T startService(
Class<T> serviceClass) {
try {
String name = serviceClass.getName();
Trace.traceBegin(
Trace.TRACE_TAG_SYSTEM_SERVER,
"StartService " + name);
if (!SystemService.class.isAssignableFrom(serviceClass)) {
throw new RuntimeException(
"service must extend SystemService");
}
Constructor<T> constructor =
serviceClass.getConstructor(Context.class);
T service = constructor.newInstance(mContext);
startService(service);
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}服务类必须继承 SystemService,并拥有 public Constructor(Context)。无法实例化、构造器不可访问、缺少构造器或构造器内部异常分别包装为不同 RuntimeException。trace finally 保证失败也结束 StartService <class> 区间。
4. 登记与onStart
public void startService(@NonNull SystemService service) {
String className = service.getClass().getName();
if (mServiceClassnames.contains(className)) {
Slog.i(TAG,
"Not starting an already started service "
+ className);
return;
}
mServiceClassnames.add(className);
mServices.add(service);
long time = SystemClock.elapsedRealtime();
try {
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException(
"Failed to start service "
+ service.getClass().getName()
+ ": onStart threw an exception", ex);
}
warnIfTooLong(
SystemClock.elapsedRealtime() - time,
service, "onStart");
}源码先加入 class name 和实例列表,再调用 onStart()。因此 onStart() 抛异常时实例已经存在于 mServices,但外层 SystemServer 启动通常会终止,不会把该半启动状态当作可继续服务。重复类名只记录并返回,传入的新实例不会执行 onStart()。
onStart() 的职责通常是发布 Binder/LocalServices、注册监听或启动内部线程;具体行为属于服务实现。SystemServiceManager 只负责调用时机和耗时告警。
5. 加载失败
private static Class<SystemService> loadClassFromLoader(
String className, ClassLoader classLoader) {
try {
return (Class<SystemService>) Class.forName(
className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Failed to create service " + className
+ " from class loader " + classLoader
+ ": service class not found...", ex);
}
}Class.forName(..., true, loader) 会执行静态初始化。错误文本提示调用者先检查 PackageManager.hasSystemFeature() 和 jar path,这说明“类不存在”经常是条件分支或 classloader 配置错误,而不是 SystemServiceManager 自身状态损坏。
6. BootPhase单调性
源码文件:frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
public void startBootPhase(
@NonNull TimingsTraceAndSlog t, int phase) {
if (phase <= mCurrentPhase) {
throw new IllegalArgumentException(
"Next phase must be larger than previous");
}
mCurrentPhase = phase;
t.traceBegin("OnBootPhase_" + phase);
...
}phase 必须严格递增;mCurrentPhase 是进程级阶段 owner。重复或倒退会在遍历服务前抛异常,避免某些服务收到重复/乱序生命周期回调。
7. 串行与并行回调
for (SystemService service : mServices) {
if (!Flags.parallelizeOnbootphase()
|| service.getBootPhaseSerial(mCurrentPhase)) {
serialServices.add(service);
} else {
parallelServices.add(service);
}
}
for (SystemService service : serialServices) {
service.onBootPhase(mCurrentPhase);
warnIfTooLong(..., service, "onBootPhase");
}
Future[] futures = new Future[parallelServices.size()];
for (int i = 0; i < parallelServices.size(); i++) {
SystemService service = parallelServices.get(i);
futures[i] = SystemServerInitThreadPool.submit(
() -> service.onBootPhase(mCurrentPhase),
"OnBootPhase_" + phase + "_"
+ service.getClass().getName());
}是否允许并行由全局 flag 和服务的 getBootPhaseSerial(phase) 共同决定。串行服务在调用线程执行;并行服务提交到 SystemServerInitThreadPool,随后方法必须等待 Future 并传播异常,不能把“已提交”写成 phase 已完成。
8. 服务封口
源码文件:frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
public void sealStartedServices() {
mServiceClassnames = Collections.emptySet();
mServices = Collections.unmodifiableList(mServices);
}封口发生在 Apex 服务组之后。已有服务仍接受 boot/user lifecycle 回调,但列表不能再新增;这是平台与可更新 APEX 依赖边界。封口不是清空服务,mServices 只是转为不可修改视图。
9. 失败定位与导航
- class not found:检查 feature gate、classpath 和 jar path;
- 构造失败:检查是否继承 SystemService、public Context 构造器和静态初始化;
onStart()失败:回到具体服务发布/线程/监听器逻辑;- boot phase 乱序:检查调用者 phase 顺序;
- 并行回调失败:检查 Future 异常,不只看提交日志;
- 重复服务:检查相同 class 是否由两个启动分支触发。
# 启动入口、反射、去重、onStart 和封口。
rg -n "startService\(|startServiceFromJar|loadClassFromLoader|mServiceClassnames|mServices|onStart|sealStartedServices" \
frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
# Boot phase 单调性、串并行分类和 Future 等待。
rg -n "startBootPhase|mCurrentPhase|getBootPhaseSerial|parallelServices|SystemServerInitThreadPool|onBootPhase|warnIfTooLong" \
frameworks/base/services/core/java/com/android/server/SystemServiceManager.java下一篇将进入 SystemService 基类生命周期,解释 onStart/onBootPhase/onUser* 和 publishBinderService/publishLocalService;不会重复本文的反射和列表管理。
