「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
在SystemServer的启动流程中,初始化了一个SystemServiceManager对象,然后使用这个对象的startService启动了多个服务对象,因此,今天我们单独将这个函数拎出来分析一下
SystemServiceManager初始化
SystemServiceManager的初始化时在SystemServer的run函数中
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
可以看到,此处首先通过new方式直接初始化一个SystemServiceManager的对象,然后调用其setStartInfo函数,最后通过LocalServices.addService函数添加该对象
new SystemServiceManager
SystemServiceManager构造函数
SystemServiceManager(Context context) {
mContext = context;
}
调用SystemServiceManager.setStartInfo
函数代码
void setStartInfo(boolean runtimeRestarted,
long runtimeStartElapsedTime, long runtimeStartUptime) {
mRuntimeRestarted = runtimeRestarted;
mRuntimeStartElapsedTime = runtimeStartElapsedTime;
mRuntimeStartUptime = runtimeStartUptime;
}
LocalServices.addService
public static <T> void addService(Class<T> type, T service) {
synchronized (sLocalServiceObjects) {
// 判断此前是否已经添加,若已添加,此处直接抛出异常
// 这边也表明,在系统的开发中要注意不能对于同一个Service重复使用LocalServices.addService
if (sLocalServiceObjects.containsKey(type)) {
throw new IllegalStateException("Overriding service registration");
}
sLocalServiceObjects.put(type, service);
}
}
这边会将type对应的SystemServiceManager对应的Class对象和对应的刚刚初始化的SystemServiceManager服务对象组成键值对添加到sLocalServiceObjects参数中,sLocalServiceObjects是一个静态的、final的ArrayMap对象
SystemServiceManager.startService
从SystemServiceManager.java文件中可以看到,在这个类中包含了三个startService函数
public SystemService startService(String className) {
// 通过ClassLoader根据类的名称加载对应的Class对象
final Class<SystemService> serviceClass = loadClassFromLoader(className,
this.getClass().getClassLoader());
// 调用同名函数,注意其参数为Class对象
return startService(serviceClass);
}
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {
final String name = serviceClass.getName();
// ...... 一些判断性操作,此处省略
final T service;
try {
// 此处调用serviceClass对应的单个参数为Context对象的构造函数,
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
}
// ...... catch语句省略
// 同名函数调用,注意传入参数为SystemService类对象
startService(service);
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
可以看到,上述两个函数,最终会通过ClassLoader加载对应的Class类,然后通过该Class的单参(Context对象)构造函数生成一个SystemService对象,最后依旧调用同名函数startService启动服务
public void startService(@NonNull final SystemService service) {
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
try {
service.onStart();
}
// ...... catch语句省略
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
也就是说,对于SystemServiceManager的startService函数来说,主要是做了如下的几个事情:
- 初始化对应的SystemService,并且调用其以Context对象为参数的单参构造函数,而传递的参数是在SystemServer中通过createSystemContext创建的Context对象
- 将传入参数SystemService对象添加到SystemServiceManager.mServices中保存,mServices是一个SystemService对象组成的ArrayList对象
- 调用传入参数SystemService对象的onStart函数