Binder源码分析之Java层

来源:互联网 发布:知乎话题广场 编辑:程序博客网 时间:2024/06/05 13:22
  前面的几节中我们介绍了Native层Binder通讯的原理和用法,那么在Java层如何使用Binder通讯呢?其原理又与Native层的Binder有什么关系呢?
        与Native层的ServiceManager类似,Android在Java层也有一个ServiceManager用于处理Java层Service的注册、申请。只不过,Java层的这个ServiceManager,其实是在Java层建立的ServiceManager的代理,他把Java层客户端的各项请求传递到Native层的ServiceManager进行处理
        而对于其他Java层的Service来说,客户端得到的Service远程代理对象,就是Native层得到的BpXXXService对象。
        接下来我们分四部分来介绍Java层Binder机制:
        1、ServiceManager的结构
        2、如何注册一个Service
        3、如何得到一个Service

        4、Service代理对象方法的过程


一、ServiceManager的结构

        我们来看一下ServiceManager类的代码:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @ServiceManager.java(google-code\frameworks\base\core\java\android\os\ServiceManager.java)  
  2. public final class ServiceManager {  
  3.     private static IServiceManager getIServiceManager() {  
  4.     }  
  5.     public static IBinder getService(String name) {  
  6.     }  
  7.     public static void addService(String name, IBinder service) {  
  8.     }  
  9.     public static void addService(String name, IBinder service, boolean allowIsolated) {  
  10.     }  
  11.     public static IBinder checkService(String name) {  
  12.     }  
  13.     public static String[] listServices() throws RemoteException {  
  14.     }  
  15.     public static void initServiceCache(Map<String, IBinder> cache) {  
  16.     }  
  17. }  

        这个类比较简单,而且我们看到,ServiceManager没有继承任何的类,那么他是如何实现“管理员”的角色呢?


二、如何在Java层通过ServiceManager注册一个Service

        Android启动时,将会在SystemServer中的ServerThread线程中将一些重要的Java层Service注册并启动,我们在这里挑选负责状态栏管理的StatusBarManagerService来分析。
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @SystemServer.java(google-code\frameworks\base\services\java\com\android\server\SystemServer.java)  
  2. class ServerThread extends Thread {  
  3.     @Override  
  4.     public void run() {  
  5.         try {  
  6.             statusBar = new StatusBarManagerService(context, wm);  
  7.             //调用ServiceManager注册服务  
  8.             ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);  
  9.         } catch (Throwable e) {  
  10.             reportWtf("starting StatusBarManagerService", e);  
  11.         }  
  12.     }  
  13. }  
        我们看到,作为一个Service,可以通过调用ServiceManager的addService()方法注册自己。注册的时候传递了两个参数,Context.STATUS_BAR_SERVICE作为该Service的name,StatusBarManagerService作为该Service的BBinder子类对象,一起传递给了ServiceManager。这样的形式正符合Native层ServiceManager中Service的注册方式。
        我们来看ServiceManager的addService()方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @ServiceManager.java  
  2. public static void addService(String name, IBinder service) {  
  3.     try {  
  4.         getIServiceManager().addService(name, service, false);  
  5.     } catch (RemoteException e) {  
  6.         Log.e(TAG, "error in addService", e);  
  7.     }  
  8. }  
        在addService()内部,把addService()的请求转发给了getIServiceManager()得到的对象。
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private static IServiceManager sServiceManager;  
  2. private static IServiceManager getIServiceManager() {  
  3.     if (sServiceManager != null) {  
  4.         //单例模式  
  5.         return sServiceManager;  
  6.     }  
  7.     //得到ServiceManager的Java层代理对象  
  8.     sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  9.     return sServiceManager;  
  10. }  
        这里看到,通过getIServiceManager()可以得到一个IServiceManager类型的sServiceManager对象,那么这个对象究竟是什么属性的呢
        其实我们通过getIServiceManager()得到的就是Java层中的ServiceManager的代理对象ServiceManagerProxy。为了得到这个对象,我们需要经过两步的准备:
        1、通过Native层的调用得到ServiceManager的远程对象BpBinder
            ----也就是BinderInternal.getContextObject()的操作
        2、把ServiceManager的BpBinder封装为Java层可用的ServiceManagerProxy对象
            ----也就是ServiceManagerNative().asInterface()的操作
        下面我们来详细分析这两个步骤

2.1、得到ServiceManager的BpBinder对象过程

        这一步中我们将会看到,如何通过BinderInternal.getContextObject()得到ServiceManager的BpBinder()对象,下面我们来看这个方法的声明:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @BinderInternal.java(google-code\frameworks\base\core\java\com\android\internal\os\BinderInternal.java)  
  2. public static final native IBinder getContextObject();  
        他的声明方式说明这个方法是在Native中被实现的,那么他具体定义是在哪里呢?
        我们简单来说一下流程。
        在Java虚拟机启动时,将会注册一系列的native方法
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @AndroidRuntime.cpp(google-code\frameworks\base\core\jni\AndroidRuntime.cpp)  
  2. void AndroidRuntime::start(const char* className, const char* options) {  
  3.     //开始注册方法  
  4.     if (startReg(env) < 0) {  
  5.         return;  
  6.     }  
  7. }  
        在虚拟机启动时,将会通过startReg()方法去注册jni:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. int AndroidRuntime::startReg(JNIEnv* env) {  
  2.     //注册gRegJNI列表中的jni方法  
  3.     if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {  
  4.         env->PopLocalFrame(NULL);  
  5.         return -1;  
  6.     }  
  7.     return 0;  
  8. }  
        在上面的startReg()中将会遍历gRegJNI列表并注册,我们来看需要注册的列表内容:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static const RegJNIRec gRegJNI[] = {  
  2.     REG_JNI(register_android_os_Binder),  
  3. };  
        其中就包括了register_android_os_Binder():
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @android_util_Binder.cpp(google-code\frameworks\base\core\jni\android_util_Binder.cpp)  
  2. int register_android_os_Binder(JNIEnv* env) {  
  3.     //注册BinderInternal中的jni  
  4.     if (int_register_android_os_BinderInternal(env) < 0)  
  5.         return -1;  
  6.     return 0;  
  7. }  
        在register_android_os_Binder中对BinderInternal中的jni进行注册:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static int int_register_android_os_BinderInternal(JNIEnv* env) {  
  2.     jclass clazz;  
  3.     //根据路径找到类  
  4.     clazz = env->FindClass(kBinderInternalPathName);  
  5.     gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  6.     gBinderInternalOffsets.mForceGc = env->GetStaticMethodID(clazz, "forceBinderGc""()V");  
  7.   
  8.     //注册gBinderInternalMethods中的jni  
  9.     return AndroidRuntime::registerNativeMethods(  
  10.             env, kBinderInternalPathName,  
  11.             gBinderInternalMethods, NELEM(gBinderInternalMethods));  
  12. }  
        我们再来看gBinderInternalMethods中定义的方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static const JNINativeMethod gBinderInternalMethods[] = {  
  2.     { "getContextObject""()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },  
  3.     { "joinThreadPool""()V", (void*)android_os_BinderInternal_joinThreadPool },  
  4.     { "disableBackgroundScheduling""(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },  
  5.     { "handleGc""()V", (void*)android_os_BinderInternal_handleGc }  
  6. };  
        这个数组中就定义了getContextObject方法所对应的jni实现,其实就是android_os_BinderInternal_getContextObject(),也就是说,getContextObject()将会调用到android_os_BinderInternal_getContextObject(),我们看一下这个方法的定义:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) {  
  2.     //得到BpBinder(0)对象  
  3.     sp<IBinder> b = ProcessState::self()->getContextObject(NULL);  
  4.     //将BpBinder对象转换为Java对象  
  5.     return javaObjectForIBinder(env, b);  
  6. }  
        在这个方法中,完成了两步重要的操作:
        1、通过ProcessState的getContextObject(NULL)得到了ServiceManager的BpBinder(0)对象(详细过程在《Binder源码分析之Native层》中做过详细介绍)。
        2、通过javaObjectForIBinder()方法把得到的BpBinder对象封装成Java层可用的类型
        至此,我们就拿到了Java层可用的ServiceManager的BpBinder对象,下面要做的就是把该对象转换为Java层可用的ServiceManager代理对象

2.2、用BpBinder得到ServiceManagerProxy对象过程

        我们在第二节刚开始的地方介绍过,Service注册自己的时候需要在ServiceManager中通过getIServiceManager()方法得到ServiceManager在Java层的代理对象,然后调用该对象的addService()方法完成注册:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private static IServiceManager getIServiceManager() {  
  2.     if (sServiceManager != null) {  
  3.         //单例模式  
  4.         return sServiceManager;  
  5.     }  
  6.     //得到ServiceManager的Java层代理对象  
  7.     sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  8.     return sServiceManager;  
  9. }  
        经过前面2.1的分析,我们了解了通过BinderInternal.getContextObject()可以得到BpBinder(0)的Java层代理对象,接下来就需要调用ServiceManagerNative的asInterface()方法将该对象转换为Java层可用的ServiceManager代理对象
        也就是说,当前的getIServiceManager()相当于:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private static IServiceManager getIServiceManager() {  
  2.     //得到ServiceManager的Java层代理对象  
  3.     sServiceManager = ServiceManagerNative.asInterface(BpBinder(0));  
  4.     return sServiceManager;  
  5. }  
        我们接下来看ServiceManagerNative的asInterface()的过程。
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @ServiceManagerNative.java(google-code\frameworks\base\core\java\android\os\ServiceManagerNative.java)  
  2. static public IServiceManager asInterface(IBinder obj)  
  3. {  
  4.     if (obj == null) {  
  5.         return null;  
  6.     }  
  7.     //查询本地缓存  
  8.     IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);  
  9.     if (in != null) {  
  10.         return in;  
  11.     }  
  12.     //创建代理对象  
  13.     return new ServiceManagerProxy(obj);  
  14. }  
        我们看到,通过asInterface()的转换,我们用BpBinder对象生成了ServiceManagerProxy对象
        也就是说,通过getIServiceManager()得到的sServiceManager对象,其实是ServiceManagerProxy对象

2.3、ServiceManagerProxy对象

        我们先来看一下其继承结构:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. class ServiceManagerProxy implements IServiceManager {}  
        从继承关系上来看,ServiceManagerProxy实现了IServiceManager中定义的接口
        然后再来看其构造函数,在2.2中介绍过,创建ServiceManagerProxy对象时,是用ServiceManager的BpBinder对象作为参数的:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public ServiceManagerProxy(IBinder remote) {  
  2.     mRemote = remote;  
  3. }  
        这里的构造函数中,把BpBinder(0)保存在了mRemote变量中。
        下面我们来看ServiceManagerProxy中的方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. class ServiceManagerProxy implements IServiceManager {  
  2.     public ServiceManagerProxy(IBinder remote) {  
  3.     }  
  4.   
  5.     public IBinder asBinder() {  
  6.     }  
  7.   
  8.     public IBinder getService(String name) throws RemoteException {  
  9.     }  
  10.   
  11.     public IBinder checkService(String name) throws RemoteException {  
  12.     }  
  13.   
  14.     public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {  
  15.     }  
  16.   
  17.     public String[] listServices() throws RemoteException {  
  18.     }  
  19.   
  20.     public void setPermissionController(IPermissionController controller) throws RemoteException {  
  21.     }  
  22. }  
        我们看到,ServiceManagerProxy确实实现了IServiceManager中的方法,提供了add、get、check、list等功能。

2.4、注册Service的过程

        经过以上的分析,我们知道通过getIServiceManager()的调用,我们得到的是ServiceManagerProxy对象,那么当注册Service时调用的addService()方法就会调用到ServiceManagerProxy中:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {  
  2.     Parcel data = Parcel.obtain();  
  3.     Parcel reply = Parcel.obtain();  
  4.     data.writeInterfaceToken(IServiceManager.descriptor);  
  5.     data.writeString(name);  
  6.     data.writeStrongBinder(service);  
  7.     data.writeInt(allowIsolated ? 1 : 0);  
  8.     mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);  
  9.     reply.recycle();  
  10.     data.recycle();  
  11. }  
        在addService的时候,将当前Service的name和service对象封装到Parcel类型的data中,然后调用mRemote对象的transact()方法发送出去,并标记当前的操作是“ADD_SERVICE_TRANSACTION”,还记得我们在分析ServiceManagerProxy的构造函数时传递的参数其实是BpBinder对象,那么这里的transact()就会调用到BpBinder中:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @BpBinder.cpp  
  2. status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     if (mAlive) {  
  4.         //进入IPCThreadState继续调用  
  5.         status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);  
  6.         if (status == DEAD_OBJECT) mAlive = 0;  
  7.         return status;  
  8.     }  
  9.     return DEAD_OBJECT;  
  10. }  
        到这里,就进入了Native层Binder的使用了,接下来就是经过IPCThreadState把请求发送到Binder驱动,然后在ServiceManager的进程中检测到请求并处理,这个过程在Native层分析时详细介绍过,这里就不再分析了。
        经过以上的分析,我们对Java层ServiceManager有了全新的认识,简单来说,Java层的ServiceManager就是Native层ServiceManager的一个Client,而对于Java层其他Service来说,Java层的ServiceManager又是一个Service,负责把其他Client的请求转发给Native层的ServiceManager去处理
        而ServiceManagerProxy又是Java层ServiceManager的代理,其负责将Java层其他客户端对ServiceManager的调用传递给Native层的ServiceManager。

        下面用一张图来示意Java层ServiceManager和Native层ServiceManager的关系:

    

三、客户端如何得到一个Service

        前面分析了如何在Java层注册一个Service,下面我们来分析,如何在Java层得到某个Service服务。
        这一次我们挑选simphonebook这个Service来分析,先简单来看一下其注册成为Service的过程:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @IccPhoneBookInterfaceManagerProxy.java(google-code\frameworks\opt\telephony\src\java\com\android\Internal\telephony\)  
  2. public IccPhoneBookInterfaceManagerProxy(IccPhoneBookInterfaceManager iccPhoneBookInterfaceManager) {  
  3.     mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;  
  4.     if(ServiceManager.getService("simphonebook") == null) {  
  5.         ServiceManager.addService("simphonebook"this);  
  6.     }  
  7. }  
        这就是simphonebook的注册过程,看似简单,但是有个疑问,我们知道,在addService()的操作时,必须传递2个参数:name+IBinder子类对象,但是这里的this所指的IccPhoneBookInterfaceManagerProxy对象,是IBinder子类的对象吗?
        我们来看IccPhoneBookInterfaceManagerProxy这个类的继承关系:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public class IccPhoneBookInterfaceManagerProxy extends IIccPhoneBook.Stub {}  
        我们看到,他继承了一个IIccPhoneBook.Stub的父类,这个父类是什么属性呢?他和BBinder的子类吗?
        我们在代码中找不到IIccPhoneBook.Stub的文件或类,但是找到了IIccPhoneBook.aidl文件,这个文件的作用又是什么呢?
        原来,这里的AIDL文件是Android中定义的接口语言(Android Interface Definition Language)。开发者只要按照指定的格式创建AIDL文件,系统就会自动为该文件生成一个对应的Java文件
        假如我们创建一个IMyService.aidl文件,其内容为:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @IMyService.aidl  
  2. package com.pack;  
  3. interface IMyService{  
  4.     String getValue();  
  5. }  
        这个文件中只有一个方法getValue(),然后我们来看系统为其生成的Java文件:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @IMyService.java  
  2. package com.pack;  
  3. public interface IMyService extends android.os.IInterface {  
  4.     //Stub继承自Binder,并且实现了IMyService的接口  
  5.     public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {  
  6.     }  
  7. }  
        从生成的Java文件可以看出,IMyService.Stub是android.os.Binder的子类,而android.os.Binder又是IBinder的子类:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @Binder.java(google-code\frameworks\base\core\java\android\os\)  
  2. public class Binder implements IBinder{}  
        由此我们推断,IccPhoneBookInterfaceManagerProxy的父类IIccPhoneBook.Stub也是IBinder的子类。下面我们来看这个Service的使用方法。
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @IccProvider.java(google-code\frameworks\opt\telephony\src\java\com\android\internal\telephony\)  
  2. private boolean addIccRecordToEf(int efType, String name, String number, String[] emails, String pin2) {  
  3.     boolean success = false;  
  4.     try {  
  5.         //得到simphonebook的Service  
  6.         IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));  
  7.         if (iccIpb != null) {  
  8.             //添加SIM卡联系人  
  9.             success = iccIpb.updateAdnRecordsInEfBySearch(efType, """", name, number, pin2);  
  10.         }  
  11.     } catch (RemoteException ex) {  
  12.     } catch (SecurityException ex) {  
  13.     }  
  14.     return success;  
  15. }  
        上面这个方法的作用就是向SIM卡中添加联系人的操作,在这个操作过程中,先要通过Java层的ServiceManager得到"simphonebook"的Service,然后通过asInterface()方法将得到的Service对象转换成客户端可以直接调用的代理对象,然后再调用该代理对象的的updateAdnRecordsInEfBySearch()方法
        下面我们将上述动作分解为3步来分析:
        1、通过ServiceManager得到simphonebook的BpBinder对象
        2、通过asInterface()方法得到simphonebook这个Service的Java层代理对象

3.1、通过ServiceManager得到simphonebook的BpBinder对象

        在这一步中,我们来分析ServiceManager.getService("simphonebook")的过程。
        我们先来看ServiceManager的getService()方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @ServiceManager.java  
  2. public static IBinder getService(String name) {  
  3.     try {  
  4.         IBinder service = sCache.get(name);  
  5.         if (service != null) {  
  6.             return service;  
  7.         } else {  
  8.             //调用的是getIServiceManager()对象的getService()方法  
  9.             return getIServiceManager().getService(name);  
  10.         }  
  11.     } catch (RemoteException e) {  
  12.     }  
  13.     return null;  
  14. }  
  15. private static IServiceManager getIServiceManager() {  
  16.     if (sServiceManager != null) {  
  17.         return sServiceManager;  
  18.     }  
  19.     //通过getIServiceManager得到的其实是ServiceManager的Java层代理对象  
  20.     sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  21.     return sServiceManager;  
  22. }  
        在2.2节中我们介绍过,在getIServiceManager()中得到的对象,就是ServiceManager在Java层的代理对象:ServiceManagerProxy。
        那么调用该代理对象的getService()方法将会得到什么呢?
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @ServiceManagerNative.java  
  2. class ServiceManagerProxy implements IServiceManager {  
  3.     //ServiceManagerProxy的getService()方法  
  4.     public IBinder getService(String name) throws RemoteException {  
  5.         Parcel data = Parcel.obtain();  
  6.         Parcel reply = Parcel.obtain();  
  7.         data.writeInterfaceToken(IServiceManager.descriptor);  
  8.         data.writeString(name);  
  9.         //这里的mRemote就是ServiceManager的BpBinder对象  
  10.         mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);  
  11.         IBinder binder = reply.readStrongBinder();  
  12.         reply.recycle();  
  13.         data.recycle();  
  14.         return binder;  
  15.     }  
  16. }  
        我们看到,ServiceManagerProxy将会把我们的请求(getService)转交给Native层的ServiceManager的BpBinder对象,而在《Binder源码分析之Native层》一文中我们分析过,Native层的ServiceManager得到这种请求后,将会把目标Service的BpBinder对象返回给客户端。
        也就是说,经过Java层的ServiceManager.getService("simphonebook")操作,我们得到了simphonebook这个Service的BpBinder对象

3.2、通过asInterface()方法得到simphonebook这个Service的Java层代理对象

        经过3.1的过程,我们得到了simphonebook的BpBinder对象,接下来我们将要分析,如何通过该对象得到simphonebook这个Service的Java层可用的代理对象。
        我们先将代码简化一下:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));  
        上面的代码相当于:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(BpBinder("simphonebook"));  
        接下来的分析,我们就要继续看生成的IIccPhoneBook.java文件了,我们还是借助刚刚生成的IMyService.java文件来看其asInterface()接口:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @IMyService.java  
  2. public interface IMyService extends android.os.IInterface {  
  3.     public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {  
  4.   
  5.         public static com.pack.IMyService asInterface(android.os.IBinder obj) {  
  6.             if ((obj == null)) {  
  7.                 return null;  
  8.             }  
  9.             android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);  
  10.             if (((iin != null) && (iin instanceof com.pack.IMyService))) {  
  11.                 return ((com.pack.IMyService) iin);  
  12.             }  
  13.             //通过asInterface()得到的是Proxy对象,并且把BpBinder对象作为参数传递进去  
  14.             return new com.pack.IMyService.Stub.Proxy(obj);  
  15.         }  
  16.   
  17.         //代理类Proxy继承自IMyService.aidl,需要实现里面的所有接口  
  18.         private static class Proxy implements com.pack.IMyService {  
  19.             private android.os.IBinder mRemote;  
  20.             //保存得到的BpBinder对象  
  21.             Proxy(android.os.IBinder remote) {  
  22.                 mRemote = remote;  
  23.             }  
  24.   
  25.             @Override  
  26.             public java.lang.String getValue() throws android.os.RemoteException {  
  27.             }  
  28.         }  
  29.   
  30.         static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
  31.     }  
  32.     public java.lang.String getValue() throws android.os.RemoteException;  
  33. }  
        原来,我们通过IMyService.Stub.asInterface()得到的是一个Proxy的代理对象,这个对象是IMyService.Stub的内部类,也是IMyService的子类,需要实现IMyService.aidl文件中定义的方法。
        把IMyService换成IIccPhoneBook,我们可以推测,通过IIccPhoneBook.Stub.asInterface(BpBinder)的操作,我们得到的是iccIpb.Stub的内部类Proxy对象,而且在这个类的内部拥有IIccPhoneBook.aidl文件定义的接口。客户端可以把这个代理类当作服务端对象一样去调用AIDL中定义的所有方法
        下面我们用图来总结一下客户端得到服务端的过程:



四、客户端调用Service方法的过程

        经过3.2节的分析我们知道,通过IIccPhoneBook.Stub.asInterface()我们得到了一个服务端的代理对象:IIccPhoneBook.Stub.Proxy,我们可以直接调用IIccPhoneBook.aidl中定义的接口,那么这个代理类如何把接口的调用传递给服务端呢?服务器又是如何把数据返回给客户端的呢?
        现在我们先借用IMyService去分析其调用过程,最后再把过程扩大到其他的Java层Service调用过程中。
        假如客户端调用了IMyService.aidl中的getValue()方法(我们的IMyService.aidl文件中只有这一个方法),那么就会调用到Proxy类的内部:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private static class Proxy implements com.pack.IMyService {  
  2.     private android.os.IBinder mRemote;  
  3.   
  4.     Proxy(android.os.IBinder remote) {  
  5.         mRemote = remote;  
  6.     }  
  7.   
  8.     @Override  
  9.     public java.lang.String getValue() throws android.os.RemoteException {  
  10.         //准备Parcel数据  
  11.         android.os.Parcel _data = android.os.Parcel.obtain();  
  12.         android.os.Parcel _reply = android.os.Parcel.obtain();  
  13.         java.lang.String _result;  
  14.         try {  
  15.             _data.writeInterfaceToken(DESCRIPTOR);  
  16.             //调用mRemote的transact()方法发送数据,并且标记当前调用的方法为getValue  
  17.             mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);  
  18.             //提取服务端的返回值  
  19.             _reply.readException();  
  20.             _result = _reply.readString();  
  21.         } finally {  
  22.             _reply.recycle();  
  23.             _data.recycle();  
  24.         }  
  25.         return _result;  
  26.     }  
  27. }  
        在Proxy的getValue()方法中,将客户端的请求封装为Parcel类型的数据通过mRemote变量发送出去,而且在发送时标记了当前的命令是TRANSACTION_getValue,也就是调用getValue方法,那么这里的mRemote对象是什么呢?
        还记得在创建Proxy类的时候我们是把目标Service的BpBinder对象传递给了mRemote变量,那么这里的transact()就会调用到BpBinder中:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @BpBinder.cpp  
  2. status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     if (mAlive) {  
  4.         //向Service发送请求  
  5.         status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);  
  6.         if (status == DEAD_OBJECT) mAlive = 0;  
  7.         return status;  
  8.     }  
  9.     return DEAD_OBJECT;  
  10. }  
        接下来就是Native层的流程了。看来Proxy代理的作用就是在客户端调用各种方法时,将方法编号(TRANSACTION_getValue)后通过目标Service的BpBinder对象向Native层的Binder机制发送(transact)请求,同时准备在reply中接收服务端的返回值。
        而根据《Binder源码分析之Native层》中的分析,服务端在接收到客户端请求后,最终会调用到服务端父类BBinder的transact()方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @Binder.cpp  
  2. status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     status_t err = NO_ERROR;  
  4.     switch (code) {  
  5.         case PING_TRANSACTION:  
  6.             reply->writeInt32(pingBinder());  
  7.             break;  
  8.         default:  
  9.             //调用BBinder的子类去处理当前请求  
  10.             err = onTransact(code, data, reply, flags);  
  11.             break;  
  12.     }  
  13.     return err;  
  14. }  
        我们看到,在BBinder的transact()方法中,将会调用Service的onTransact()的方法,由于当前的IMyService就是BBinder的子类,因此这里的onTransact()方法将会进入到IMyService的内部,也就是:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public interface IMyService extends android.os.IInterface {  
  2.     public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {  
  3.         public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {  
  4.             switch (code) {  
  5.                 case INTERFACE_TRANSACTION: {  
  6.                     reply.writeString(DESCRIPTOR);  
  7.                     return true;  
  8.                 }  
  9.                 case TRANSACTION_getValue: {  
  10.                     //客户端发起的getValue()的请求  
  11.                     data.enforceInterface(DESCRIPTOR);  
  12.                     //继续调用子类的getValue()方法  
  13.                     java.lang.String _result = this.getValue();  
  14.                     reply.writeNoException();  
  15.                     reply.writeString(_result);  
  16.                     return true;  
  17.                 }  
  18.             }  
  19.             return super.onTransact(code, data, reply, flags);  
  20.         }  
  21.         static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
  22.     }  
  23.     public java.lang.String getValue() throws android.os.RemoteException;  
  24. }  
        我们看到在onTransact()中将会继续调用子类的getValue()方法,而这里的IMyService.Stub的子类,当然就是客户端本身了。如果结合IIccPhoneBook的服务端来看,当在IIccPhoneBook.Stub中调用其onTransact()方法时,就会在相应的TRANSACTION_xxx分支中调用到IccPhoneBookInterfaceManagerProxy.java中的各个方法,这样也就完成了从客户端到服务端的调用过程。
        那么,当客户端调用的方法需要返回值时,服务端是如何把返回值传回给客户端的呢?
        我们还来看getValue()的过程,这个方法当然需要服务端提供返回值,因此在onTransact()调用到子类的this.getValue()时,就会得到服务端的返回值,接下来我们看到,在TRANSACTION_getValue分支中会把返回值(_result)放入reply中,接着就结束了onTransact()的调用。
        也就是说,在服务端的onTransact()过程中,不仅完成了对服务端的调用,而且也带回来了服务端的返回值,这个返回值是通过onTransact()的参数传递出去的
        然后当BBinder的onTransact()结束后,就返回到了BBinder的transact()操作中,接着再层层返回,并经过Native层Binder的传输,再次回到BpBinder的transact()中,然后等BpBinder的transact()返回后,我们就再次回到了IMyService.java中的getValue()方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public java.lang.String getValue() throws android.os.RemoteException {  
  2.     android.os.Parcel _data = android.os.Parcel.obtain();  
  3.     android.os.Parcel _reply = android.os.Parcel.obtain();  
  4.     java.lang.String _result;  
  5.     try {  
  6.         _data.writeInterfaceToken(DESCRIPTOR);  
  7.         //经历了一次漫长的跨进程调用过程  
  8.         mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);  
  9.         _reply.readException();  
  10.         _result = _reply.readString();  
  11.     } finally {  
  12.         _reply.recycle();  
  13.         _data.recycle();  
  14.     }  
  15.     return _result;  
  16. }  
        此时的mRemote.transact()方法已经调用结束,他不仅发起了对服务端的请求,而且带回了服务端的返回值,最后,经过return语句将返回值传递给了客户端。
        如果结合这IIccPhoneBook来分析,此时的调用将会从IIccPhoneBook.Stub中返回到其子类中也就是IccProvider中,从而完成了客户端的调用过程。
        也就是说,我们在IccProvider对客户端的调用经过IIccPhoneBook传递到Native层,然后又经过IccProvider传递给Service的实现者IccPhoneBookInterfaceManagerProxy。完成请求后,再经过逆过程回到IccProvider客户端中
        这就是Java层的Binder调用过程。
        最后,用一张图来示意客户端调用服务端的过程:
0 0
原创粉丝点击