android中Stub Proxy答疑

      在上篇添加账户源码解析的博文中,我们发现功能是由AccountManager的mService成员来实现。而mService其实是AccountManagerService,如果对android系统有了解的话一定会发现AccountManagerService是运行在SystemServer进程中(所有的系统服务都是运行在SystemServer中,若SystemServer挂掉则会导致Zygote挂掉继而android系统重启),AccountManager是运行在setting的app中,那他们跨进程是如何通信的呢。android的IPC是binder,本文不讨论底层通信只讲解binder上层是如何构建的,还是添加账户代码为例(android4.4)

   ok,我们直接来看看AccountManager和AccountManagerService类的定义。

public class AccountManagerService extends IAccountManager.Stub
        implements RegisteredServicesCacheListener<AuthenticatorDescription> {
public class AccountManager {

  AccountManager只是个普通的类,我们先不管;看看AccountManagerService继承的IAccountManager.Stub是个什么东西。但其实你找遍源码都没发现IAccountManager.Stub。这里就要请出aidl(Android Interface definition language),它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口(实质就是函数)。这里的aidl就是IAccountManager.aidl(定义了函数),经系统编译(看参考资料3)后生成IAccountManager.java文件。注意IAccountManager.java是要android编译后才有的,源码中是没有的:

public interface IAccountManager extends android.os.IInterface
{         //out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/accounts/IAccountManager.java
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements android.accounts.IAccountManager
    {
        private static final java.lang.String DESCRIPTOR = "android.accounts.IAccountManager";
        public static android.accounts.IAccountManager asInterface(android.os.IBinder obj){......}
        ......
        private static class Proxy implements android.accounts.IAccountManager{......}
        ....
    }
    ......
    // IAccountManager.aidl中声明过的函数
}

  找到了IAccountManager.Stub的定义后我们先不去深入研究来看下AccountManager和AccountManagerService之间是如何关联的。在上篇的分析中,AccountManager是通过AccountManager.get(this)来创建的,get()函数继续调用getSystemService函数继而来执行

registerService(ACCOUNT_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
                    IAccountManager service = IAccountManager.Stub.asInterface(b);
                    return new AccountManager(ctx, service);
                }})

  这几行的代码涉及的知识点比较多,我们来深入了解下。getService()向ServiceManager返回AccountManagerService的IBinder(这里先这么理解,稍后深入),着重是IAccountManager.Stub.asInterface(b)这行代码,展开asInterface函数

public static android.accounts.IAccountManager asInterface(android.os.IBinder obj)
{
    if ((obj==null)) {
        return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof android.accounts.IAccountManager))) {
        return ((android.accounts.IAccountManager)iin);
    }
    return new android.accounts.IAccountManager.Stub.Proxy(obj);
}

  结合Proxy理解难度不大,它就是返回成员变量mRemote =IBinder的IAccountManager.Stub.Proxy。然后结合AccountManager构造函数知道,AccountManager.get(this)返回的是一个包含AccountManagerService Proxy的AccountManager(记住这个)。再回过头去看AccountManagerService的IBinder是如何得到的。

 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);

  上面提到过系统提供的服务是运行在SystemServer中的,且会去注册这些服务:

 ///frameworks/base/services/java/com/android/server/SystemServer.java
 // The AccountManager must come before the ContentService
            try {
                // TODO: seems like this should be disable-able, but req'd by ContentService
                Slog.i(TAG, "Account Manager");
                accountManager = new AccountManagerService(context);
                ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager);
            } catch (Throwable e) {
                Slog.e(TAG, "Failure starting Account Manager", e);
            }

  代码中将AccountManagerService服务和Context.ACCOUNT_SERVICE("account")字符串关联,这样可以根据字符串来找到对应的服务了。getService(ACCOUNT_SERVICE)就获取到了AccountManagerService的IBinder(可以理解为句柄吧)。故AccountManager和AccountManagerService之间的关系是这样的


  AccountManager获取到一个类型为IAccountManager.Stub.Proxy的mService;AccountManagerService(即IAccountManager.Stub)通过onTransact会接收mService发过来的命令和参数,这就是AccountManager和AccountManagerService交互的流程。当然到此为止并没有分析到IBinder究竟是什么,但我们至少理解Stub和Proxy代表什么:Stub=Service,Proxy= Service代理,client(app)可以通过Proxy和Service交互

 

 

参考资料:

1、使用AIDL实现进程间的通信

2、Android深入浅出之Binder机制

3、Android 添加系统服务

 

posted @ 2016-01-18 21:50  vendanner  阅读(2143)  评论(0编辑  收藏  举报