Binder-系统服务和ServiceManager

系统服务分析

1 获取系统服务

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

内部是调用了SystemServiceRegistry.getSystemService(this, name);,那我们进入其getSystemService查看

/**
 * Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
      ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
      return fetcher != null ? fetcher.getService(ctx) : null;
}

通过SYSTEM_SERVICE_FETCHERS获取ServiceFetcher,再使用fetcher.getService(ctx)获取服务。那SYSTEM_SERVICE_FETCHERS是什么,又是在什么时候初始化的呢?

在SystemServiceRegistry中我们看到
1 类型:PSYSTEM_SERVICE_FETCHERS是一个map,key为Service的名字,value为ServiceFetcher
2 初始化:

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);
        }});
    ……………
    ……………
    // 省略部分代码

SystemServiceRegistry在一个静态代码块创建并注册各种服务,再进入到registerService方法中,查看是如何注册的(当类被加载时,静态代码块被执行,且只被执行一次,静态块常用来执行类属性的初始化)

/**
 * Statically registers a system service with the context.
 * This method must be called during static initialization only.
 */
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);
}

registerService方法只是将各种服务添加到SYSTEM_SERVICE_FETCHERS中,就是在类被加载时,SYSTEM_SERVICE_FETCHERS被初始化,各种服务被添加到其中去

2 服务的创建(以AlarmManagerService为例)

registerService(Context.ALARM_SERVICE, AlarmManager.class,
                new CachedServiceFetcher<AlarmManager>() {
     @Override
     public AlarmManager createService(ContextImpl ctx) {
         IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
         IAlarmManager service = IAlarmManager.Stub.asInterface(b);
         return new AlarmManager(service, ctx);
     }});

这里有两个步骤:

  1. 通过ServiceManager.getService(Context.ALARM_SERVICE);获取到AlarmManagerService服务对应的Binder对象

  2. IAlarmManager.Stub.asInterface()方法返回一个IAlarmManager的统一接口

那ServiceManager.getService(Context.ALARM_SERVICE)是如何获取服务对应的Binder对象的呢?我们进入这个方法:

/**
 * Returns a reference to a service with the given name.
 * 
 * @param name the name of the service to get
 * @return a reference to the service, or <code>null</code> if the service doesn't exist
 */
public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

这里也有两个步骤:

  1. 通过sCache.get(name)查看缓存中是否有该服务对应的Binder对象,有则返回

  2. 如果缓存没有,则通过getIServiceManager().getService(name);获取

3 ServiceManager分析

ServiceManager本身也是一个Service,那它的Binder引用是怎么获取的呢?

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }

    // Find the service manager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

在getIServiceManager()方法中可以看到,可以通过BinderInternal.getContextObject()获取该Service对应的Binder引用

4 理解Manager

ServiceManager所管理的所有Service都是以相应的Manager返回给客户端

  1. 客户端一般不直接通过Binder引用去访问具体的服务,而是经过一个Manager,相应的Manager对客户端是可见的,而远程的服务类对客户端是隐藏的

  2. 这些Manager内部会有一个远程服务的Binder变量,一般情况下,会通过够走啊函数初始化这个Bind而变量:即先通过ServiceManager获取远程服务的Binder引用,然后使用这个Bindre引用构造一个客户端本地可以访问的Manager,然后客户端就通过这个Manager访问远程的服务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值