[Android进程间通信-1]Context.getSystemService原理详解

1,872 阅读2分钟

context.getSystemService 源代码解析

    先看图,下图主要说明了从context.getSystemService开始到获取到目标系统service对象所做的第一步流程。其中涉及到了核心类ServiceFetcher和SystemServiceRegistry。

    SystemServiceRegistry主要负责缓存系统服务名字(即Context.ACTIVITY_SERVICE)和ServiceFectcher的映射Map,类加载节点就会将这些信息存储进去。每个APP都会自己有个独立进程,所以这里每个APP都会有一个 SystemServiceRegistry 对象。

context.getSystemService原理-1 (1).png

    接着我们看ServiceFetcher做了什么事。

ServiceFetcher

    首先ServiceFetcher是定义在 SystemServiceRegistry 中的,它是一个接口,其下有两个实现抽象类,以便系统服务在SystemServiceRegistry类加载阶段去实例化自己的ServiceFetcher。

image.png

CachedServiceFetcher

context.getSystemService原理-3 (3).png     CachedServiceFetcher,核心思想是从对应的contextImpl对象的缓存池中获取服务对象,如果不存在则新创建一个。

    因为这里可能涉及到多线程问题,所以代码中通过对contextImpl中的缓存数组加锁,来保证多线程的安全。

StaticServiceFetcher

context.getSystemService原理-4.png

    StaticServiceFetcher 不会针对每个contextImpl做缓存,直接在当前进程中,缓存一个对象。用起来比较简单,也是线程安全的。

接下来,继续看方法 createService()。

createService()

     createService()方法主要用于创建service对象实例,其实创建的是代理对象实例。我们以 ActivityManager 为例来看下。

    首先 ActivityManager 的ServiceFetcher 时候,createService代码如下:

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

    可见,这里是直接new了一个对象。

    所以拿ActivityManager为例,通过context.getSystemService方法返回的是ActivityManager对象,但是我们进入到AM对象中,可以看到,当我们实际使用其里边方法时,都会先调用getTaskService()方法获取一个IActivityManager,然后再调用具体方法。这是因为我们直接通过new出来的对象拿到的是AM的代理对象,AM服务系统只有一个,不会因为我们进程new一个对象就会出现一个新的服务。

    所以这里接着看getTaskService的源码,可以层层往下看,最终可以看到,它其实是从ServiceManager中拿到了binder对象,然后使用其代理对象通过AIDL方式来间接调用真正的AM中的方法。

    所有的系统服务使用方式都和AM这种方式一致,最终都会通过ServiceManager来找到对应服务的代理,然后代理通过AIDL方式和实际服务进行交互。

image.png

OK,后续我们研究下ServiceManger是如何获取服务的。