Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

简介:

在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的源代码。细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我们如何使用Java语言来使用系统的Binder机制来进行进程间通信呢?这就是本文要介绍的Android系统应用程序框架层的用Java语言来实现的Binder接口了。

       熟悉Android系统的读者,应该能想到应用程序框架中的基于Java语言的Binder接口是通过JNI来调用基于C/C++语言的Binder运行库来为Java应用程序提供进程间通信服务的了。JNI在Android系统中用得相当普遍,SDK中的Java接口API很多只是简单地通过JNI来调用底层的C/C++运行库从而为应用程序服务的。

       这里,我们仍然是通过具体的例子来说明Binder机制在应用程序框架层中的Java接口,主要就是Service Manager、Server和Client这三个角色的实现了。通常,在应用程序中,我们都是把Server实现为Service的形式,并且通过IServiceManager.addService接口来把这个Service添加到Service Manager,Client也是通过IServiceManager.getService接口来获得Service接口,接着就可以使用这个Service提供的功能了,这个与运行时库的Binder接口是一致的。

       前面我们学习Android硬件抽象层时,曾经在应用程序框架层中提供了一个硬件访问服务HelloService,这个Service运行在一个独立的进程中充当Server的角色,使用这个Service的Client运行在另一个进程中,它们之间就是通过Binder机制来通信的了。这里,我们就使用HelloService这个例子来分析Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码。所以希望读者在阅读下面的内容之前,先了解一下前面在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务这篇文章。

       这篇文章通过五个情景来学习Android系统进程间通信Binder机制在应用程序框架层的Java接口:1. 获取Service Manager的Java远程接口的过程;2. HelloService接口的定义;3. HelloService的启动过程;4. Client获取HelloService的Java远程接口的过程;5.  Client通过HelloService的Java远程接口来使用HelloService提供的服务的过程。

       一.  获取Service Manager的Java远程接口

       我们要获取的Service Manager的Java远程接口是一个ServiceManagerProxy对象的IServiceManager接口。我们现在就来看看ServiceManagerProxy类是长什么样子的:

 

这里可以看出,ServiceManagerProxy类实现了IServiceManager接口,IServiceManager提供了getService和addService两个成员函数来管理系统中的Service。从ServiceManagerProxy类的构造函数可以看出,它需要一个BinderProxy对象的IBinder接口来作为参数。因此,要获取Service Manager的Java远程接口ServiceManagerProxy,首先要有一个BinderProxy对象。下面将会看到这个BinderProxy对象是如何获得的。

         再来看一下是通过什么路径来获取Service Manager的Java远程接口ServiceManagerProxy的。这个主角就是ServiceManager了,我们也先看一下ServiceManager是长什么样子的:

 

 ServiceManager类有一个静态成员函数getIServiceManager,它的作用就是用来获取Service Manager的Java远程接口了,而这个函数又是通过ServiceManagerNative来获取Service Manager的Java远程接口的。

        接下来,我们就看一下ServiceManager.getIServiceManager这个函数的实现,这个函数定义在frameworks/base/core/java/android/os/ServiceManager.java文件中:

 

 
 
  1. public final class ServiceManager {  
  2.     ......  
  3.     private static IServiceManager sServiceManager;  
  4.     ......  
  5.     private static IServiceManager getIServiceManager() {  
  6.         if (sServiceManager != null) {  
  7.             return sServiceManager;  
  8.         }  
  9.  
  10.         // Find the service manager  
  11.         sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  12.         return sServiceManager;  
  13.     }  
  14.     ......  

如果其静态成员变量sServiceManager尚未创建,那么就调用ServiceManagerNative.asInterface函数来创建。在调用ServiceManagerNative.asInterface函数之前,首先要通过BinderInternal.getContextObject函数来获得一个BinderProxy对象。

 

        我们来看一下BinderInternal.getContextObject的实现,这个函数定义在frameworks/base/core/java/com/android/internal/os/BinderInternal.java文件中:

 

 
 
  1. public class BinderInternal {  
  2.     ......  
  3.     /**  
  4.     * Return the global "context object" of the system.  This is usually  
  5.     * an implementation of IServiceManager, which you can use to find  
  6.     * other services.  
  7.     */  
  8.     public static final native IBinder getContextObject();  
  9.       
  10.     ......  

 这里可以看出,BinderInternal.getContextObject是一个JNI方法,它实现在frameworks/base/core/jni/android_util_Binder.cpp文件中:

 

 
 
  1. static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)  
  2. {  
  3.     sp<IBinder> b = ProcessState::self()->getContextObject(NULL);  
  4.     return javaObjectForIBinder(env, b);  

   这里看到我们熟悉的ProcessState::self()->getContextObject函数,具体可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路一文。ProcessState::self()->getContextObject函数返回一个BpBinder对象,它的句柄值是0,即下面语句:

 

 
 
  1. sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 

  相当于是:

 

 
 
  1. sp<IBinder> b = new BpBinder(0); 

     接着调用javaObjectForIBinder把这个BpBinder对象转换成一个BinderProxy对象:

 

 
 
  1. jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)  
  2. {  
  3.     if (val == NULLreturn NULL;  
  4.  
  5.     if (val->checkSubclass(&gBinderOffsets)) {  
  6.         // One of our own!  
  7.         jobject object = static_cast<JavaBBinder*>(val.get())->object();  
  8.         //printf("objectForBinder %p: it's our own %p!\n", val.get(), object);  
  9.         return object;  
  10.     }  
  11.  
  12.     // For the rest of the function we will hold this lock, to serialize  
  13.     // looking/creation of Java proxies for native Binder proxies.  
  14.     AutoMutex _l(mProxyLock);  
  15.  
  16.     // Someone else's...  do we know about it?  
  17.     jobject object = (jobject)val->findObject(&gBinderProxyOffsets);  
  18.     if (object != NULL) {  
  19.         jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet);  
  20.         if (res != NULL) {  
  21.             LOGV("objectForBinder %p: found existing %p!\n", val.get(), res);  
  22.             return res;  
  23.         }  
  24.         LOGV("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());  
  25.         android_atomic_dec(&gNumProxyRefs);  
  26.         val->detachObject(&gBinderProxyOffsets);  
  27.         env->DeleteGlobalRef(object);  
  28.     }  
  29.  
  30.     object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);  
  31.     if (object != NULL) {  
  32.         LOGV("objectForBinder %p: created new %p!\n", val.get(), object);  
  33.         // The proxy holds a reference to the native object.  
  34.         env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());  
  35.         val->incStrong(object);  
  36.  
  37.         // The native object needs to hold a weak reference back to the  
  38.         // proxy, so we can retrieve the same proxy if it is still active.  
  39.         jobject refObject = env->NewGlobalRef(  
  40.                 env->GetObjectField(object, gBinderProxyOffsets.mSelf));  
  41.         val->attachObject(&gBinderProxyOffsets, refObject,  
  42.                 jnienv_to_javavm(env), proxy_cleanup);  
  43.  
  44.         // Note that a new object reference has been created.  
  45.         android_atomic_inc(&gNumProxyRefs);  
  46.         incRefsCreated(env);  
  47.     }  
  48.  
  49.     return object;  

     在介绍这个函数之前,先来看两个变量gBinderOffsets和gBinderProxyOffsets的定义。

 

        先看gBinderOffsets的定义:

 

 
 
  1. static struct bindernative_offsets_t  
  2. {  
  3.     // Class state.  
  4.     jclass mClass;  
  5.     jmethodID mExecTransact;  
  6.  
  7.     // Object state.  
  8.     jfieldID mObject;  
  9.  
  10. } gBinderOffsets; 

 简单来说,gBinderOffsets变量是用来记录上面第二个类图中的Binder类的相关信息的,它是在注册Binder类的JNI方法的int_register_android_os_Binder函数初始化的:

 

 
 
  1. const char* const kBinderPathName = "android/os/Binder";  
  2.  
  3. static int int_register_android_os_Binder(JNIEnv* env)  
  4. {  
  5.     jclass clazz;  
  6.  
  7.     clazz = env->FindClass(kBinderPathName);  
  8.     LOG_FATAL_IF(clazz == NULL"Unable to find class android.os.Binder");  
  9.  
  10.     gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  11.     gBinderOffsets.mExecTransact  
  12.         = env->GetMethodID(clazz, "execTransact""(IIII)Z");  
  13.     assert(gBinderOffsets.mExecTransact);  
  14.  
  15.     gBinderOffsets.mObject  
  16.         = env->GetFieldID(clazz, "mObject""I");  
  17.     assert(gBinderOffsets.mObject);  
  18.  
  19.     return AndroidRuntime::registerNativeMethods(  
  20.         env, kBinderPathName,  
  21.         gBinderMethods, NELEM(gBinderMethods));  

    再来看gBinderProxyOffsets的定义:

 

 
 
  1. static struct binderproxy_offsets_t  
  2. {  
  3.     // Class state.  
  4.     jclass mClass;  
  5.     jmethodID mConstructor;  
  6.     jmethodID mSendDeathNotice;  
  7.  
  8.     // Object state.  
  9.     jfieldID mObject;  
  10.     jfieldID mSelf;  
  11.  
  12. } gBinderProxyOffsets; 

简单来说,gBinderProxyOffsets是用来变量是用来记录上面第一个图中的BinderProxy类的相关信息的,它是在注册BinderProxy类的JNI方法的int_register_android_os_BinderProxy函数初始化的:

 

 
 
  1. const char* const kBinderProxyPathName = "android/os/BinderProxy";  
  2.  
  3. static int int_register_android_os_BinderProxy(JNIEnv* env)  
  4. {  
  5.     jclass clazz;  
  6.  
  7.     clazz = env->FindClass("java/lang/ref/WeakReference");  
  8.     LOG_FATAL_IF(clazz == NULL"Unable to find class java.lang.ref.WeakReference");  
  9.     gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  10.     gWeakReferenceOffsets.mGet  
  11.         = env->GetMethodID(clazz, "get""()Ljava/lang/Object;");  
  12.     assert(gWeakReferenceOffsets.mGet);  
  13.  
  14.     clazz = env->FindClass("java/lang/Error");  
  15.     LOG_FATAL_IF(clazz == NULL"Unable to find class java.lang.Error");  
  16.     gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  17.       
  18.     clazz = env->FindClass(kBinderProxyPathName);  
  19.     LOG_FATAL_IF(clazz == NULL"Unable to find class android.os.BinderProxy");  
  20.  
  21.     gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  22.     gBinderProxyOffsets.mConstructor  
  23.         = env->GetMethodID(clazz, "<init>""()V");  
  24.     assert(gBinderProxyOffsets.mConstructor);  
  25.     gBinderProxyOffsets.mSendDeathNotice  
  26.         = env->GetStaticMethodID(clazz, "sendDeathNotice""(Landroid/os/IBinder$DeathRecipient;)V");  
  27.     assert(gBinderProxyOffsets.mSendDeathNotice);  
  28.  
  29.     gBinderProxyOffsets.mObject  
  30.         = env->GetFieldID(clazz, "mObject""I");  
  31.     assert(gBinderProxyOffsets.mObject);  
  32.     gBinderProxyOffsets.mSelf  
  33.         = env->GetFieldID(clazz, "mSelf""Ljava/lang/ref/WeakReference;");  
  34.     assert(gBinderProxyOffsets.mSelf);  
  35.  
  36.     return AndroidRuntime::registerNativeMethods(  
  37.         env, kBinderProxyPathName,  
  38.         gBinderProxyMethods, NELEM(gBinderProxyMethods));  

 回到前面的javaObjectForIBinder函数中,下面这段代码:

 

 
 
  1. if (val->checkSubclass(&gBinderOffsets)) {  
  2.     // One of our own!  
  3.     jobject object = static_cast<JavaBBinder*>(val.get())->object();  
  4.     //printf("objectForBinder %p: it's our own %p!\n", val.get(), object);  
  5.     return object;  

前面说过,这里传进来的参数是一个BpBinder的指针,而BpBinder::checkSubclass继承于父类IBinder::checkSubclass,它什么也不做就返回false。

 

        于是函数继续往下执行:

 

 
 
  1. jobject object = (jobject)val->findObject(&gBinderProxyOffsets); 

 由于这个BpBinder对象是第一创建,它里面什么对象也没有,因此,这里返回的object为NULL。

 

        于是函数又继续往下执行:

 

 
 
  1. object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); 

 这里,就创建了一个BinderProxy对象了。创建了之后,要把这个BpBinder对象和这个BinderProxy对象关联起来:
 

 
 
  1. env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get()); 

 就是通过BinderProxy.mObject成员变量来关联的了,BinderProxy.mObject成员变量记录了这个BpBinder对象的地址。

 

        接下去,还要把它放到BpBinder里面去,下次就要使用时,就可以在上一步调用BpBinder::findObj把它找回来了:

 

 
 
  1. val->attachObject(&gBinderProxyOffsets, refObject,  
  2.                 jnienv_to_javavm(env), proxy_cleanup); 

   最后,就把这个BinderProxy返回到android_os_BinderInternal_getContextObject函数,最终返回到最开始的ServiceManager.getIServiceManager函数中来了,于是,我们就获得一个BinderProxy对象了。

 

        回到ServiceManager.getIServiceManager中,从下面语句返回:

 

 
 
  1. sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); 

   相当于是:

 

 
 
  1. sServiceManager = ServiceManagerNative.asInterface(new BinderProxy()); 

 接下去就是调用ServiceManagerNative.asInterface函数了,这个函数定义在frameworks/base/core/java/android/os/ServiceManagerNative.java文件中:

 

 
 
  1. public abstract class ServiceManagerNative ......  
  2. {  
  3.     ......  
  4.     static public IServiceManager asInterface(IBinder obj)  
  5.     {  
  6.         if (obj == null) {  
  7.             return null;  
  8.         }  
  9.         IServiceManager in =  
  10.             (IServiceManager)obj.queryLocalInterface(descriptor);  
  11.         if (in != null) {  
  12.             return in;  
  13.         }  
  14.  
  15.         return new ServiceManagerProxy(obj);  
  16.     }  
  17.     ......  

  这里的参数obj是一个BinderProxy对象,它的queryLocalInterface函数返回null。因此,最终以这个BinderProxy对象为参数创建一个ServiceManagerProxy对象。

 

       返回到ServiceManager.getIServiceManager中,从下面语句返回:

 

 
 
  1. sServiceManager = ServiceManagerNative.asInterface(new BinderProxy()); 

    就相当于是:

 

 
 
  1. sServiceManager = new ServiceManagerProxy(new BinderProxy()); 

 于是,我们的目标终于完成了。

 

      总结一下,就是在Java层,我们拥有了一个Service Manager远程接口ServiceManagerProxy,而这个ServiceManagerProxy对象在JNI层有一个句柄值为0的BpBinder对象与之通过gBinderProxyOffsets关联起来。

      这样获取Service Manager的Java远程接口的过程就完成了。

      二. HelloService接口的定义

      前面我们在学习Android系统的硬件抽象层(HAL)时,在在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务这篇文章中,我们编写了一个硬件服务HelloService,它的服务接口定义在frameworks/base/core/java/android/os/IHelloService.aidl文件中:

 

 
 
  1. package android.os;  
  2.  
  3. interface IHelloService  
  4. {  
  5.     void setVal(int val);  
  6.     int getVal();  

这个服务接口很简单,只有两个函数,分别用来读写硬件寄存器。

       注意,这是一个aidl文件,编译后会生成一个IHelloService.java。我们来看一下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。

 

 
 
  1. /*  
  2.  * This file is auto-generated.  DO NOT MODIFY.  
  3.  * Original file: frameworks/base/core/java/android/os/IHelloService.aidl  
  4.  */  
  5. package android.os;  
  6. public interface IHelloService extends android.os.IInterface  
  7. {  
  8.     /** Local-side IPC implementation stub class. */  
  9.     public static abstract class Stub extends android.os.Binder implements android.os.IHelloService  
  10.     {  
  11.         private static final java.lang.String DESCRIPTOR = "android.os.IHelloService";  
  12.         /** Construct the stub at attach it to the interface. */  
  13.         public Stub()  
  14.         {  
  15.             this.attachInterface(this, DESCRIPTOR);  
  16.         }  
  17.  
  18.         /**  
  19.         * Cast an IBinder object into an android.os.IHelloService interface,  
  20.         * generating a proxy if needed.  
  21.         */  
  22.         public static android.os.IHelloService asInterface(android.os.IBinder obj)  
  23.         {  
  24.             if ((obj==null)) {  
  25.                 return null;  
  26.             }  
  27.             android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);  
  28.             if (((iin!=null)&&(iin instanceof android.os.IHelloService))) {  
  29.                 return ((android.os.IHelloService)iin);  
  30.             }  
  31.             return new android.os.IHelloService.Stub.Proxy(obj);  
  32.         }  
  33.  
  34.         public android.os.IBinder asBinder()  
  35.         {  
  36.             return this;  
  37.         }  
  38.  
  39.         @Override   
  40.         public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException  
  41.         {  
  42.             switch (code)  
  43.             {  
  44.                 case INTERFACE_TRANSACTION:  
  45.                 {  
  46.                     reply.writeString(DESCRIPTOR);  
  47.                     return true;  
  48.                 }  
  49.                 case TRANSACTION_setVal:  
  50.                 {  
  51.                     data.enforceInterface(DESCRIPTOR);  
  52.                     int _arg0;  
  53.                     _arg0 = data.readInt();  
  54.                     this.setVal(_arg0);  
  55.                     reply.writeNoException();  
  56.                     return true;  
  57.                 }  
  58.                 case TRANSACTION_getVal:  
  59.                 {  
  60.                     data.enforceInterface(DESCRIPTOR);  
  61.                     int _result = this.getVal();  
  62.                     reply.writeNoException();  
  63.                     reply.writeInt(_result);  
  64.                     return true;  
  65.                 }  
  66.             }  
  67.             return super.onTransact(code, data, reply, flags);  
  68.         }  
  69.  
  70.         private static class Proxy implements android.os.IHelloService  
  71.         {  
  72.             private android.os.IBinder mRemote;  
  73.  
  74.             Proxy(android.os.IBinder remote)  
  75.             {  
  76.                 mRemote = remote;  
  77.             }  
  78.  
  79.             public android.os.IBinder asBinder()  
  80.             {  
  81.                 return mRemote;  
  82.             }  
  83.  
  84.             public java.lang.String getInterfaceDescriptor()  
  85.             {  
  86.                 return DESCRIPTOR;  
  87.             }  
  88.  
  89.             public void setVal(int val) throws android.os.RemoteException  
  90.             {  
  91.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  92.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  93.                 try {  
  94.                     _data.writeInterfaceToken(DESCRIPTOR);  
  95.                     _data.writeInt(val);  
  96.                     mRemote.transact(Stub.TRANSACTION_setVal, _data, _reply, 0);  
  97.                     _reply.readException();  
  98.                 }  
  99.                 finally {  
  100.                     _reply.recycle();  
  101.                     _data.recycle();  
  102.                 }  
  103.             }  
  104.  
  105.             public int getVal() throws android.os.RemoteException  
  106.             {  
  107.                 android.os.Parcel _data = android.os.Parcel.obtain();  
  108.                 android.os.Parcel _reply = android.os.Parcel.obtain();  
  109.                 int _result;  
  110.                 try {  
  111.                     _data.writeInterfaceToken(DESCRIPTOR);  
  112.                     mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0);  
  113.                     _reply.readException();  
  114.                     _result = _reply.readInt();  
  115.                 }  
  116.                 finally {  
  117.                     _reply.recycle();  
  118.                     _data.recycle();  
  119.                 }  
  120.                 return _result;  
  121.             }  
  122.         }  
  123.  
  124.         static final int TRANSACTION_setVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
  125.         static final int TRANSACTION_getVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);  
  126.     }  
  127.  
  128.     public void setVal(int val) throws android.os.RemoteException;  
  129.     public int getVal() throws android.os.RemoteException;  

 





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/965288,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
算法 Java
java面向对象和面向过程分析
java面向对象和面向过程分析
38 0
|
1月前
|
存储 Java 编译器
java和c++的主要区别、各自的优缺点分析、java跨平台的原理的深度解析
java和c++的主要区别、各自的优缺点分析、java跨平台的原理的深度解析
91 0
|
14天前
|
Java 调度
Java中常见锁的分类及概念分析
Java中常见锁的分类及概念分析
15 0
|
14天前
|
Java
Java中ReentrantLock中tryLock()方法加锁分析
Java中ReentrantLock中tryLock()方法加锁分析
12 0
|
30天前
|
人工智能 监控 算法
java智慧城管源码 AI视频智能分析 可直接上项目
Java智慧城管源码实现AI视频智能分析,适用于直接部署项目。系统运用互联网、大数据、云计算和AI提升城市管理水平,采用“一级监督、二级指挥、四级联动”模式。功能涵盖AI智能检测(如占道广告、垃圾处理等)、执法办案、视频分析、统计分析及队伍管理等多个模块,利用深度学习优化城市管理自动化和智能化,提供决策支持。
219 4
java智慧城管源码 AI视频智能分析 可直接上项目
|
14天前
|
Java
Java中关于ConditionObject的signal()方法的分析
Java中关于ConditionObject的signal()方法的分析
21 4
|
14天前
|
Java
Java中关于ConditionObject的分析
Java中关于ConditionObject的分析
18 3
|
17天前
|
设计模式 缓存 安全
分析设计模式对Java应用性能的影响,并提供优化策略
【4月更文挑战第7天】本文分析了7种常见设计模式对Java应用性能的影响及优化策略:单例模式可采用双重检查锁定、枚举实现或对象池优化;工厂方法和抽象工厂模式可通过对象池和缓存减少对象创建开销;建造者模式应减少构建步骤,简化复杂对象;原型模式优化克隆方法或使用序列化提高复制效率;适配器模式尽量减少使用,或合并多个适配器;观察者模式限制观察者数量并使用异步通知。设计模式需根据应用场景谨慎选用,兼顾代码质量和性能。
|
22天前
|
安全 Linux API
Android进程与线程
Android进程与线程
18 0