系统启动流程分析之Context的getSystemService函数分析

957 阅读4分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。

在分析源码的时候,经常会看到由很多调用Context的getSystemService函数的例子,其实很简单,本篇记录一下这个函数的调用过程!

mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

首先,调用Context的getSystemService函数,上述函数在初始化WindowManagerService的时候,调用的一个语句,而在WindowManagerService的初始化函数的context参数是从SystemServer中传入的

wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);

分析过SystemServer启动流程的话,我们应该知道,此处的context参数是通过ActivityThread的getSystemContext函数得到的,而在此前分析的文章SystemServer.createSystemContext函数流程分析中可以知道,此处的getSystemContext函数获取到的是一个ContextImpl对象,因此,此处调用的是ContextImpl的getSystemService函数

public Object getSystemService(String name) {
    // ...... 代码暂与本篇无关,省略
    // 最终调用的是SystemServiceRegistry的getSystemService函数
    return SystemServiceRegistry.getSystemService(this, name);
}

public static Object getSystemService(ContextImpl ctx, String name) {
    // ......
    // 可以看到,此处是从SYSTEM_SERVICE_FETCHERS中获取name对应的VALUE
    final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    // ...... 功能无关代码,省略

    // 调用对应的getService函数
    final Object ret = fetcher.getService(ctx);
    // ...... 功能无关代码,省略
    return ret;
}

可以看到,此处有两个步骤

  1. 从SYSTEM_SERVICE_FETCHERS中获取name对应的VALUE,此处的name为Context.DISPLAY_SERVICE
  2. 调用获取的对应VALUE值的getService函数

获取ServiceFetcher对象

首先,我们需要分析一下SYSTEM_SERVICE_FETCHERS究竟是什么

private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new ArrayMap<String, ServiceFetcher<?>>();

这个对象的定义在SystemServiceRegister类中,且其为static的一个Map容器对象,而对应地SystemServiceRegister.java

static {
    // ...... 跟本篇无关代码,省略
    registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
            new CachedServiceFetcher<DisplayManager>() {
        @Override
        public DisplayManager createService(ContextImpl ctx) {
            return new DisplayManager(ctx.getOuterContext());
        }});
    // ...... 跟本篇无关代码,省略
}

可以看到,这边会调用registerService函数,而这边注意第三个参数,是一个CachedServiceFetcher对象 如下,查看这个类对象的类图结构

classDiagram
ServiceFetcher <|-- CachedServiceFetcher
class CachedServiceFetcher {
    +createService(in ContextImpl ctx) *
    +getService(in ContextImpl ctx)
}
<<abstract>> CachedServiceFetcher
<<abstract>> ServiceFetcher

从这个类图中可以看到,此处CachedServiceFetcher类为一个抽象类,其中包含一个抽象函数createService,还有一个函数getService 再继续查看registerService函数

/**
 * Statically registers a system service with the context.
 * This method must be called during static initialization only.
 */
private static <T> void registerService(@NonNull String serviceName,
        @NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) {
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    // 可以看到SYSTEM_SERVICE_FETCHERS中添加的是,传入的名称serviceName和第三个参数ServiceFetcher对象组成的一个键值对
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}

因此,此处名称为Context.DISPLAY_SERVICE对应的VALUE值为传入的第三个参数ServiceFetcher对象

调用对应的getService函数

如上分析可知,此时会调用传入的第三个参数CachedServiceFetcher对象的getService函数 因此

new CachedServiceFetcher<DisplayManager>() {
    @Override
    public DisplayManager createService(ContextImpl ctx) {
        return new DisplayManager(ctx.getOuterContext());
    }
}

public final T getService(ContextImpl ctx) {
    final Object[] cache = ctx.mServiceCache;
    final int[] gates = ctx.mServiceInitializationStateArray;
    boolean interrupted = false;
    // 传入的T模板是DisplayManager类
    T ret = null;

    for (;;) {
        // for循环中,先将这个值设置为false
        boolean doInitialize = false;
        synchronized (cache) {
            // Return it if we already have a cached instance.
            // 第一次肯定没有添加,此处使用这种方式,能够优化调用速度
            // 如果已经调用过一次,就直接从这边的cache数组中获取即可
            T service = (T) cache[mCacheIndex];
            if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
                ret = service;
                break; // exit the for (;;)
            }
            // ...... 代码暂与本篇无关,省略
            // At this point, the gate must be either UNINITIALIZED or INITIALIZING.
            // 第一次进入,设置doInitialize的值为true
            if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
                doInitialize = true;
                gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
            }
        }

        if (doInitialize) {
            // Only the first thread gets here.

            T service = null;
            @ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
            try {
                // This thread is the first one to get here. Instantiate the service
                // *without* the cache lock held.
                // 调用createService函数,创建一个T模板DisplayManager对象
                service = createService(ctx);
                newState = ContextImpl.STATE_READY;

            }
            // ...... 代码暂与本篇无关,省略
            // 返回对应的service
            ret = service;
            break; // exit the for (;;)
        }
        // ...... 代码暂与本篇无关,省略
    }
    // ...... 代码暂与本篇无关,省略
    return ret;
}

如上代码可知,当第一次进入这个函数的时候,会直接通过调用其createService函数来创建一个服务对象,若非第一次进入,则直接从对应的数组中获取一个该对象即可

总结

Context的getSystemService函数,在此处最终通过ContextImpl对象的getSystemService函数调用到SystemServiceManager的getSystemService函数

而在SystemServiceManager对象中,其包含有static块,在第一次初始化的时候,会注册所有的Service

当getSystemService函数被调用的时候,会直接从对应的Map集合中获取对应的服务