Android getSystemService原理

前言

  • 下面会把getSystemService简称为GSS

为什么我需要搞清楚getSystemService的原理?
在分析源码时错误的把GSS以为是基于binder实现的,但发现打印的日志内容与我所设想的不一样,按理来说audioService调用Binder.getCallingPid()时应该返回获取到的audioManager的pid,因为是从audioManager通过binder调用到的audioService的。但实际打印确实上层应用的,然后看到AudioManager的constructor有Context参数,后面才发现自己望文生义了,GSS返回的是实例类对象,不是一个独立进程的binder。

先给个结论。对于缓存类的系统服务(大部分情况),会通过map根据服务名称返回实例对象,第一次获取时才真正创建对象,后面获取时都是返回缓存。真正做这工作的在SystemServiceRegistry.java中,其中处理多线程并发获取服务实例的过程很精妙。

        public final T getService(ContextImpl ctx) {
    
    
            final Object[] cache = ctx.mServiceCache;
            final int[] gates = ctx.mServiceInitializationStateArray;

            for (;;) {
    
    
                boolean doInitialize = false;
                synchronized (cache) {
    
    
                    // Return it if we already have a cached instance.
                    T service = (T) cache[mCacheIndex];
                    if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
    
    
                        return service;
                    }

                    // If we get here, there's no cached instance.

                    // Grr... if gate is STATE_READY, then this means we initialized the service
                    // once but someone cleared it.
                    // We start over from STATE_UNINITIALIZED.
                    if (gates[mCacheIndex] == ContextImpl.STATE_READY) {
    
    
                        gates[mCacheIndex] = ContextImpl.STATE_UNINITIALIZED;
                    }

                    // It's possible for multiple threads to get here at the same time, so
                    // use the "gate" to make sure only the first thread will call createService().

                    // At this point, the gate must be either UNINITIALIZED or INITIALIZING.
                    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.
                        service = createService(ctx);
                        newState = ContextImpl.STATE_READY;

                    } catch (ServiceNotFoundException e) {
    
    
                        onServiceNotFound(e);

                    } finally {
    
    
                        synchronized (cache) {
    
    
                            cache[mCacheIndex] = service;
                            gates[mCacheIndex] = newState;
                            cache.notifyAll();
                        }
                    }
                    return service;
                }
                // The other threads will wait for the first thread to call notifyAll(),
                // and go back to the top and retry.
                synchronized (cache) {
    
    
                    while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
    
    
                        try {
    
    
                            cache.wait();
                        } catch (InterruptedException e) {
    
    
                            Log.w(TAG, "getService() interrupted");
                            Thread.currentThread().interrupt();
                            return null;
                        }
                    }
                }
            }
        }

调用链为:
首先mainActivity调用到的是继承的父类Activity的GSS。

  1. Activity.getSystemService(),这一步过滤服务名WINDOW_SERVICE或者SEARCH_SERVICE,这两个特殊服务可以直接返回。
if (WINDOW_SERVICE.equals(name)) {
    
    
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
    
    
            ensureSearchManager();
            return mSearchManager;
        }
  1. ContextThemeWrapper.getSystemService(),这一步过滤掉服务LAYOUT_INFLATER_SERVICE,他的处理其实和下一步差不多,但是返回的服务会再调用一下cloneInContext(this),不理解为什么这个服务要特殊处理这一下。
mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);

下一步会调用到保存的mBase,这个参数是ContextThemeWrapper构造时传递的,估计是activity时就创建好了,但具体怎么传递context、哪里地方、什么时候创建的暂时不清楚。context是一个abstract class,他的实现类是contextImpl。

  1. contextImpl.getSystemService()。这一步只是转给SystemServiceRegistry处理
return SystemServiceRegistry.getSystemService(this, name);```
  1. SystemServiceRegistry.getSystemService()。这里会从hashMap SYSTEM_SERVICE_FETCHERS根据服务名取出一个叫做ServiceFetcher的东西,然后由fetcher负责获取服务实例。

ServiceFetcher就是一个接口,实现该接口需要实现getService函数

static abstract interface ServiceFetcher<T> {
    
    
        T getService(ContextImpl ctx);
    }

关于这个hashmap,SYSTEM_SERVICE_FETCHERS是在SystemServiceRegistry实例化是初始化的,也就是在该类的static语句块中。这一步注册很多服务。

static {
    
    
	......
	registerService(Context.AUDIO_SERVICE, AudioManager.class,
                new CachedServiceFetcher<AudioManager>() {
    
    
            @Override
            public AudioManager createService(ContextImpl ctx) {
    
    
                return new AudioManager(ctx);
            }});
    ......
}

registerSerivce只是一个put元素进hashmap的封装,把服务名和一个CachedServiceFetcher的类对象扔进去。可以猜到CachedServiceFetcher实现了ServiceFetcher

CachedServiceFetcher() {
    
    
            // Note this class must be instantiated only by the static initializer of the
            // outer class (SystemServiceRegistry), which already does the synchronization,
            // so bare access to sServiceCacheSize is okay here.
            mCacheIndex = sServiceCacheSize++;
        }

这是该类的构造函数,需要解释一下,所以缓存的服务实例对象是存储在context的cached数组中的,另外一个int类型数组gates是表示缓存的每一个服务实例对象的当前状态,因此mCacheIndex就是存储的这个fetcher所指服务实例对象在cached数组中的索引。注释解释了为什么不用给sServiceCacheSize加锁。

从开头的实例过程可以看出,每一个服务对象都是lazy initialized,因此可以加快activity的启动速度(我的理解),并且避免了实例化一些并不需要的服务对象,只在真正需要的时候才会实例化。
另外实例化过程还涉及到了多线程的race condition情况的处理,解决的很巧妙(对我这个菜鸟而言)。

猜你喜欢

转载自blog.csdn.net/weixin_45719581/article/details/132106715