Android 系统服务的注册以及 getService() 方法源码解析

写在前面

开发过程中,我们经常需要一些系统服务,比如 LayoutInflater、ActivityManager 等等,每次获取的时候我们都直接调用 Activity,Service 的 getSystemService(String name) 这个方法,然而这个方法是什么工作的?每次获取的对象是不是一个?我们都不太清楚,今天,我们就来揭开 getSystemService 方法的面纱,剖析他的工作过程。

概要

系统启动

系统启动时会调用 SystemServer.main(),其中会调用 SystemThread.run() 方法,该方法中调用 SystemServiceManager 的 startService 方法使用反射实例化 AMS、PMS... 等系统对象

IServiceManager 通过 Binder 机制向外提供 AMS、PMS... 等系统服务

应用进程

在 Native 层通过通过 Binder 获取 IServiceManager 在应用进程的代理

ServiceManager 类代理 ServiceManagerProxy(是 IServiceManager 在客户端的代理类)

通过 ServiceManager 获取 AMS、PMS 等系统服务在客户端的代理

IServiceManager 是 Binder 进程间通信机制的守护进程,其目的非常简单,就是管理 Android 系统里的 Binder 对象

通过下面的解析,我们会发现一个毁三观的事情,那就是 LayoutInflater 、ActivityManager 并不是单例的,我靠,大神们快来撕逼,反正我今天搞完是大吃一惊。

注意:以下说的 service 是指系统服务的对象名,并不是我们的四大组件中的 Service ,千万不要乱,这里不涉及四大组件中的 Service

开始

平时我们获取系统服务都是直接通过 Context 对象的 getService(String name) 方法来获取,这个方法是在 ContextImpl 中的实现的

    @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

调用了 SystemServiceRegistry.getSystemService(this, name) 方法,我们接着往下看

    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

getSystemService 方法中会在 SYSTEM_SERVICE_FETCHERS 中根据 name 来取一个 ServiceFetcher 对象,有必要先看看这两个对象是什么了

private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
    new HashMap<Class<?>, String>();

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

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

SYSTEM_SERVICE_NAMES 是 SystemServiceRegistry 类中的一个常量,类型为一个 HashMap,key 为想要获取的系统服务的对应 Class,value 为 Context 中定义的对应当前 Service 的 String 常量。

SYSTEM_SERVICE_FETCHERS 是 SystemServiceRegistry 类中的一个常量,类型为一个 HashMap,key 在 Context 中定义的对应当前 Service 的 String 常量,value 为 ServiceFetcher 对象。

ServiceFetcher 为一个接口,需要一个泛型,并且定义了 getService 方法,这个方法返回的就是泛型 T 的对象

我们看到 getSystemService 方法在 ServiceFetcher 不为 null 时最终返回的是 ServiceFetcher 的 getService 方法的返回值,并没有通过别的方式来获取 Service,说明 SYSTEM_SERVICE_FETCHERS 中已经存在了我们要的东西,我们就看看 SYSTEM_SERVICE_FETCHERS 什么时候添加了内容

    final class SystemServiceRegistry {    
    
        static {
            registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                    new CachedServiceFetcher<AccessibilityManager>() {
                @Override
                public AccessibilityManager createService(ContextImpl ctx) {
                    return AccessibilityManager.getInstance(ctx);
                }});
    
            registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
                    new CachedServiceFetcher<CaptioningManager>() {
                @Override
                public CaptioningManager createService(ContextImpl ctx) {
                    return new CaptioningManager(ctx);
                }});
    
            registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
                    new CachedServiceFetcher<AccountManager>() {
                @Override
                public AccountManager createService(ContextImpl ctx) {
                    IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE);
                    IAccountManager service = IAccountManager.Stub.asInterface(b);
                    return new AccountManager(ctx, service);
                }});
    
            registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                    new CachedServiceFetcher<ActivityManager>() {
                @Override
                public ActivityManager createService(ContextImpl ctx) {
                    return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
                }});
                
            ......// 省略更多的 registerService 方法调用
        }
        
        
    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }        
        
    }

可以看到,SYSTEM_SERVICE_NAMES 和 SYSTEM_SERVICE_FETCHERS 添加内容是在 registerService 方法,中,那么哪里调用了这个方法呢,原来在 SystemServiceRegistry 类的静态代码块中调用了多次 registerService 方法。我们来具体看一个,就挑我们最熟悉的 ActivityManagerService 的方法

    registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
            new CachedServiceFetcher<ActivityManager>() {
        @Override
        public ActivityManager createService(ContextImpl ctx) {
            return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
        }
    });

可以看到,注册方法中,创建了一个 CachedServiceFetcher 的匿名内部类,看一下这个类

    static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
        private final int mCacheIndex;

        public CachedServiceFetcher() {
            mCacheIndex = sServiceCacheSize++;
        }

        @Override
        @SuppressWarnings("unchecked")
        public final T getService(ContextImpl ctx) {
            final Object[] cache = ctx.mServiceCache;
            synchronized (cache) {
                // Fetch or create the service.
                Object service = cache[mCacheIndex];
                if (service == null) {
                    service = createService(ctx);
                    cache[mCacheIndex] = service;
                }
                return (T)service;
            }
        }

        public abstract T createService(ContextImpl ctx);
    }

CachedServiceFetcher 类继承了 ServiceFetcher ,所以说添加到 SYSTEM_SERVICE_FETCHERS 中没有问题,CachedServiceFetcher 中有一个 final 的 mCacheIndex 属性,还有一个 final 的 getService 方法, 还有一个抽象的 createService 方法,下面一一介绍

  • mCacheIndex 这个属性在创建对象的时候赋值,赋值为 mCacheIndex = sServiceCacheSize++; sServiceCacheSize 是 SystemServiceRegistry 中的一个静态的值,初始值为 0

      private static int sServiceCacheSize;
    

也就是说静态代码块中每调用一次 registerService 方法,这个值就会自加一,并且每个 CachedServiceFetcher 在 HashMap 中的索引都由 mCacheIndex 属性来记录。也就是说 sServiceCacheSize 是的值就是下一个放入 HashMap 中的 CachedServiceFetcher 对象的索引。而每一个
CachedServiceFetcher 在 HashMap 中的索引也就是自己的 mCacheIndex 属性的值。

剩下的两个方法后面讲,先看上面的代码,到静态代码块执行结束,也就是 Context 的 getService 能得到的系统 Service 对应的 CachedServiceFetcher 都已经初始化,SYSTEM_SERVICE_NAMES 和 SYSTEM_SERVICE_FETCHERS 都被赋值。

返回去看 getSystemService 方法,由于 SYSTEM_SERVICE_FETCHERS 中的 key 为 String 类型的 name,我们根据 name 在 SYSTEM_SERVICE_FETCHERS 中取出对应的 ServiceFetcher ,这里是 CachedServiceFetcher ,在调用其 getService 方法,并将 ContextImpl 参数传入,这几就详细说一下 getService 方法

  • getService 由上面 CachedServiceFetcher 类的代码中可以看到,getService 方法中首选创建了一个 Object 数组,其值为 ctx.mServiceCache ,而 mServiceCache 的值是根据 sServiceCacheSize 的长度创建的数组,源码如下:
        final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
        
        public static Object[] createServiceCache() { // 该方法在 ContextImpl 实例化时调用,所以 sServiceCacheSize 已经为注册的系统服务的数量值
            return new Object[sServiceCacheSize];
        }

得到数组 cache 之后,使用 synchronized 锁防止多个线程同时访问,从 cache 数组中根据 mCacheIndex 索引得到 Object 类型的 service 对象,如果 service 为 null ,则调用 creatService 方法来创建 service,创建之后为 service[mCacheIndex] 赋值。如果 service 不为 null ,则直接返回。createService 为抽象方法,具体的实现在匿名内部类中,以 ActivityManager 为例:

    registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
            new CachedServiceFetcher<ActivityManager>() {
        @Override
        public ActivityManager createService(ContextImpl ctx) {
            return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
        }
    });

createService 方法中,直接 new 了一个 ActivityManager ,然后返回,这里我们不深究 ActivityManager 的创建过程,只注重系统服务的注册流程, 不要深入代码忘了根本目的。由 creatService 方法就得到了 ActivityManager 实例,然后,cache[mCacheIndex] = service; 将该实例放入 cache 数组,cache 数组为每一个 ContextImpl 对象自有的,并不是静态的。由 getService 方法可以看出,系统服务在 ContextImpl 中第一次被调用时才会通过 createService 方法赋值,并且第一次初始化之后,同一个 ContextImpl 再次获取的时候并不会重新创建新的 PhoneLayoutInflater 实例,也就是说 LayoutInflater 是同一 ContextImpl 单例,不同的 ContextImpl 会创建不同的 LayoutInflater。

ActivityManager 并不是单例的,其构造模式同 LayoutInflater

注意: 在学习了 Binder 之后,会发现 ActivityManager 其实只是系统的 AMS 在客户端(上层应用)的代理 ActivityManagerProxy 的代理(这里包含两层代理,ActivityManagerProxy 对 AMS 远程代理,ActivityManager 对 ActivityManagerProxy 代理),ActivityManagerProxy 并不是整个系统单例的,但是 AMS 确实整个系统单例的,有关 Binder 和代理模式的知识点请看这里

Binder
代理模式

有没有单例的系统服务?

当然有了,其实 ServiceFetcher 的实现了还有两个,StaticServiceFetcher,StaticApplicationContextServiceFetcher ,我们看一个就行了,看一个就可以,他们的 create 方法创建的服务会赋值给他们的一个内部属性,这个属性就是对于的系统服务对象,其不为 null 之后,再获取都会返回这个对象。

    static abstract class StaticServiceFetcher<T> implements ServiceFetcher<T> {
        private T mCachedInstance;

        @Override
        public final T getService(ContextImpl unused) {
            synchronized (StaticServiceFetcher.this) {
                if (mCachedInstance == null) {
                    // 第一次创建之后赋值给自己的内部属性 mCachedInstance
                    mCachedInstance = createService();
                }
                return mCachedInstance;
            }
        }

        public abstract T createService();
    }
    
    registerService(Context.HDMI_CONTROL_SERVICE, HdmiControlManager.class,
            new StaticServiceFetcher<HdmiControlManager>() {
        @Override
        public HdmiControlManager createService() {
            IBinder b = ServiceManager.getService(Context.HDMI_CONTROL_SERVICE);
            return new HdmiControlManager(IHdmiControlService.Stub.asInterface(b));
        }
    });

总结

ActivitityManagerService 等作为系统中最重要的服务,在开机时就会被启动,而且一直存在,注意运行在系统进程,AMS对象随系统进程启动而构建,随着系统进程退出而消亡,可以说,AMS 等系统服务与系统进程共存亡。

在应用开发中使用 AMS 等系统服务时都是通过 Binder 机制获取 AMS 等服务的代理,通过代理调用 AMS 等服务的方法。此工作在 Android 中由 ServiceManager 完成,ServiceManager 其实是 IManagerService 在应用进程的代理,其获取是由 Native 层 通过 Binder 获取的。

SystemServiceRegistry 类第一次加载时就会把获取一些系统服务或者应用进程通用服务的 ServiceFetcher 放进自己内部的一个 HashMap,其中 ServiceFetcher 有两种,第一种是 LayoutInflater ActivityManager 等对应的 CacheServiceFetcher;第二种是 StaticServiceFetcher 跟 StaticApplicationContextServiceFetcher 的。

ServiceFetcher 中定义了创建以及获取对应服务的方法。其实在每次获取服务时都是通过 SystemServiceRegistry 找到内部系统服务对应的 ServiceFetcher ,再由 ServiceFetcher 来获取自己对应的系统服务。

其中有一个需要注意的点,CacheServiceFetcher 是每个 Context 都会创建一个服务对象。而 StaticServiceFetcher 和 StaticApplicationContextServiceFetcher 这种创建的系统服务是单例的服务对象。

终于,撕开了 getSystemService 方法的面纱。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,873评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,483评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,525评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,595评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,018评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,958评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,118评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,873评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,643评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,813评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,293评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,615评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,306评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,170评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,968评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,107评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,894评论 2 278

推荐阅读更多精彩内容