zoukankan      html  css  js  c++  java
  • 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 添加系统服务

  • 相关阅读:
    Jquery Mobile事件
    Jquery Mobile表单
    Jquery Mobile列表
    Jquery Mobile基本元素
    媒体查询
    JS模块化开发(四)——构建工具gulp
    JS模块化开发(三)——seaJs+grunt
    JS模块化开发(二)——构建工具grunt
    原生JS和JQ窗口定位属性对照表
    localstorage在safri下的坑
  • 原文地址:https://www.cnblogs.com/vendanner/p/5140614.html
Copyright © 2011-2022 走看看