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 添加系统服务

时间: 2024-10-09 04:09:36

android中Stub Proxy答疑的相关文章

Android中AIDL详解

欢迎转载,转载请注明出处http://blog.csdn.net/l664675249/article/details/50649676 介绍 Android Interface Definition Language (AIDL), Android接口定义语言.系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信Interprocess communication (IPC).AIDL就是解决这个问题的. 阅读本文需要了解Service的相关知识,关于Service的

Android技术22:Android中AIDL

在Android中进程内部通过全局变量,文件,preference,数据库作为数据的载体实现数据共享和通信.然后在进程之间则需要借助Binder实现IPC调用.Android进程通信框架:服务端,客户端,Linux binder驱动.Binder驱动成为连接两端的桥梁.我们首先通过aidl语言实现一个简单的多进程通信.具体实现步骤如下: 1.定义aidl文件 IService.aidl,定义一个接口,test() ,不包含负责的类和数据. 1 package com.demo.ipc; 2 3

Android中的Binder机制的简要理解

转载自:http://www.linuxidc.com/Linux/2012-07/66195.htm http://blog.csdn.net/sunxingzhesunjinbiao/article/details/42195013 我们知道,在Android系统中,每一个应用程序都运行在独立的进程中,这也保证了当其中一个程序出现异常而不会影响另一个应用程序的正常运转.在许多情况下,我们activity都会与各种系统的service打交道,很显然,我们写的程序中activity与系统serv

理清Android中Binder机制的使用

---恢复内容开始--- 昨天好不容易把Binder的使用方式搞清楚了,今天看代码的时候又被轰炸地体无完肤.最主要的问题是,在系统service和client的交互中,Binder使用的太频繁了,一次调用可能伴随着多个Binder的多次传递,不搞清楚这些Binder的来源和具体作用,往往就无法深刻理解交互是如何进行的.另外,对于Binder子类的命名方式又非常繁杂,这间接导致了代码阅读理解的困难.今天决定花些时间好好梳理下交互过程中Binder的具体使用,在此记录. 在开始前,先声明下个人对Bi

Android 中的IPC机制

Android IPC 介绍 IPC是 Inter-Proscess Communication的缩写,含义为进程间的通讯或者跨进程通讯,是指两个进程之间进行数据交换的过程.按操作系统的中的描述,线程是CPU调度最小的单元,同时线程是一种有限的系统资源,而进程是指一个执行单元,在PC和移动设备上指一个程序或者一个应用.一个进程可以包含多个线程,因此进程和线程是包含于被包含的关系. IPC的使用场景就必须提到多进程,只有面对多进程这种场景下,才需要考虑进程间通讯.多进程的情况分为两种:第一种是一个

Android 手写Binder 教你理解android中的进程间通信

关于Binder,我就不解释的太多了,网上一搜资料一堆,但是估计还是很多人理解的有困难.今天就教你如何从 app层面来理解好Binder. 其实就从我们普通app开发者的角度来看,仅仅对于android应用层的话,Binder就是客户端和服务端进行通信的媒介. AIDL就是我们理解Binder 最好的事例. 我们都知道 我们写好aidl 文件以后,开发工具 会自动帮我们生成好代码.实际上 我们最终apk里面 是只有这些代码的,我们写的aidl文件 是不会被打包进去的,也就是说aidl文件 实际上

Android中AIDL实现进程通信(附源码下载)

AIDL概述 之前的博客<Android中通过Messenger与Service实现进程间双向通信>演示了如何通过Messenger实现与Service进行跨进程通信,即IPC.但用Messenger实现的IPC存在一点不足:Service内部维护着一个Messenger,Messenger内部又维护着一个Hanlder,当多个client向该Service发送Message时,这些Message需要依次进入Hanlder的消息队列中,Hanlder只能处理完一个Message之后,再从消息队

Android 中AIDL的使用与理解

AIDL的使用: 最常见的aidl的使用就是Service的跨进程通信了,那么我们就写一个Activity和Service的跨进程通信吧. 首先,我们就在AS里面新建一个aidl文件(ps:现在AS建aidl不要求和java包名相同了): package aidl; interface IMyInterface { String getInfor(String s); } 可以看到,在这里面我们就一个方法getInfor(String s),接受一个字符串参数,然后返回一个字符串,恩,相当的简单

Android 中的 Service 全面总结详解【下】

上一篇文章Android 中的 Service 全面总结详解[下] 介绍了Service的一些知识以及本地Service的使用,如果对Service还不太了解的建议先看下上篇文章:本文主要接着上一篇讲下远程服务的使用: 在说到远程服务的时候,我们需要先了解一些预备的知识: 首先来了解一下AIDL机制: AIDL的作用 由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象.在Android平台,一个进程通常不能访问另一个进程的内存空间,