系统启动流程分析之SystemServiceManager的startService函数流程分析

731 阅读2分钟

「这是我参与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函数来说,主要是做了如下的几个事情:

  1. 初始化对应的SystemService,并且调用其以Context对象为参数的单参构造函数,而传递的参数是在SystemServer中通过createSystemContext创建的Context对象
  2. 将传入参数SystemService对象添加到SystemServiceManager.mServices中保存,mServices是一个SystemService对象组成的ArrayList对象
  3. 调用传入参数SystemService对象的onStart函数