frameworkAndroid知识Android开发

Framework基础:应用是如何跟系统服务打交道的

2017-02-12  本文已影响131人  我在等你回复可你没回

Android有许多系统服务,例如ActivityManagerService,PowerManagerService等,这些系统服务都跑在SystemServer进程之中。而普通的应用跑在自己的进程里面。那普通应用要怎样才能使用到系统服务呢?这个就相当于普通应用进程跟SystemServer进程进行通行,不同进程进行通信,就是跨进程的通信啦。Android中特有的跨进程通信的方式是binder通信。下面说下应用与系统ActivityManagerService交互的过程。

应用是如何获取到ActivityManager的呢?###

下图是获取ActivityManager的内部时序图

获取ActivityManager内部时序图.png

应用层调用Context的getSystemService方法获取到ActivityManager

ActivityManager mActivityManager;
mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);  

下面调用到ContextImpl的getSystemService

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

进入SystemServiceRegistry.getSystemService(this, name)方法,可以看到首先通过SYSTEM_SERVICE_FETCHERS的get方法返回一个ServiceFetcher,然后通过ServiceFetcher的getService方法返回一个ActivityManager。

   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是一个HashMap,key是服务名称,内容是ServiceFetcher对象。

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

SYSTEM_SERVICE_FETCHERS是保存着所有ServiceFetcher的全局变量,我们看看这个全局变量是怎么填充的。通过静态块中的registerService方法填充。

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

看看这个registerService函数,可以看到SYSTEM_SERVICE_FETCHERS通过put把系统服务填充到自己里面。

    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);
    }

ServiceFetcher是一个接口,他的实现是CachedServiceFetcher。

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

就是说一个CachedServiceFetcher是跟一个系统服务相关联的,其通过createService创建关联的系统服务,通过getService获取关联的系统服务。看createService方法,可以看到new了一个ActivityManager对象,所以返回的就是一个ActivityManager对象啦。

        registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                new CachedServiceFetcher<ActivityManager>() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});
系统服务数据结构图.png

那ActivityManager是怎么跟ActivityManagerService通信的呢?###

我们以ActivityManager的一个方法为例子看一下就行了,例如获取最近任务的方法ActivityManager.getRecentTasks

    public List<RecentTaskInfo> getRecentTasks(int maxNum, int flags)
            throws SecurityException {
        try {
            return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
                    flags, UserHandle.myUserId());
        } catch (RemoteException e) {
            // System dead, we will be dead too soon!
            return null;
        }
    }

进入ActivityManagerNative的getDefault()方法,方法返回一个IActivityManager的单例,IActivityManager是一个接口,继承于Interface接口。IActivityManager 的实现是ActivityManagerProxy,所以方法其实是返回一个 ActivityManagerProxy的单例对象。这是一个代理对象,用于跟ActivityManagerService进行binder通信。
套路差不多都这样
1.ServiceManager.getService获取到Ibinder
2.通过asInterface获取到远程服务的本地代理。

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
}

    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

ActivityManagerNative相当于aidl通信中的stub的角色,stub继承于binder,专门用于binder通信。ActivityManagerService会继承于这个stub。
很多地方都可以看到这个stub,这个stub可以看作一个中间者的角色吧。这个中间者里面包含着本地代理的类定义,同时这个中间者被远端服务所继承。

IActivityManager是本地代理和远端服务都要实现的接口,就是说本地代理里面的方法要和远端服务的方法一一对应。

首先ActivityManagerService会发布本地的接口,通过ActivityManagerNative的构造方法发布了,接口用descriptor标示,在IActivityManager定义,String descriptor = "android.app.IActivityManager";

  public ActivityManagerNative() {
      attachInterface(this, descriptor);
  }

然后通过Binder的queryLocalInterface可以找到本地对应的接口,这个接口的引用被代理所持有,所以代理就可以使用这个本地接口跟远端服务通信了。

        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);

代理每次调用方法,都会调用到这个本地接口transact方法,把参数跨进程发送到远端服务,远端服务通过onTransact方法,调用到实际的方法。

上面的说法有些逆向,为了正向理解,我们想想基于binder通信你会怎么写呢?
首先整个架构要有两个要素
1.远端服务
2.本地代理
所以有了两个类,远端服务ActivityManagerService,本地代理ActivityManagerProxy。

远端服务和本地代理肯定要实现同样的方法嘛,所有最好设计一个接口给两者实现。所以设计一个接口IActivityManager。

ActivityManagerService为了能够远程被调用到,必须继承于Binder类。所以这时ActivityManagerService既要继承binder,也要实现IActivityManager。因为有binder发布本地接口等操作,把这些东西写到ActivityManagerService会让文件很难看。所以干脆新建立一个stub类ActivityManagerNative类好了,里面包含一些发布本地接口的操作。顺便在这个stub类定义代理类好了,节省一个文件。

几个类的关系图

类关系.png
参考文章:
http://blog.csdn.net/u012950099/article/details/51987036
android的aidl-手动实现aidl自动生成的Java文件
上一篇下一篇

猜你喜欢

热点阅读