Android系统进程间通信Binder机制在应用程序框架层(7)

在JavaBBinderHolder类中,有一个成员变量mBinder,它的类型为JavaBBinder,而JavaBBinder类继承于BBinder类。在前面学习Binder机制的C++语言实现时,我们在Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析这篇文章中,曾经介绍过,IPCThreadState类负责与Binder驱动程序进行交互,它把从Binder驱动程序读出来的请求作简单的处理后,最后把这个请求扔给BBinder的onTransact函数来进一步处理。

这里,我们就是要把JavaBBinderHolder里面的JavaBBinder类型Binder实体添加到Service Manager中去,以便使得这个HelloService有Client来请求服务时,由Binder驱动程序来唤醒这个Server线程,进而调用这个JavaBBinder类型Binder实体的onTransact函数来进一步处理,这个函数我们在后面会继续介绍。

先来看一下JavaBBinderHolder::get函数的实现:

class JavaBBinderHolder : public RefBase   {       ......          JavaBBinderHolder(JNIEnv* env, jobject object)           : mObject(object)       {           ......       }          ......          sp<JavaBBinder> get(JNIEnv* env)       {           AutoMutex _l(mLock);           sp<JavaBBinder> b = mBinder.promote();           if (b == NULL) {               b = new JavaBBinder(env, mObject);               mBinder = b;               ......           }              return b;       }          ......          jobject         mObject;       wp<JavaBBinder> mBinder;   };  

这里是第一次调用get函数,因此,会创建一个JavaBBinder对象,并且保存在mBinder成员变量中。注意,这里的mObject就是上面创建的HelloService对象了,这是一个Java对象。这个HelloService对象最终也会保存在JavaBBinder对象的成员变量mObject中。

回到Android_os_Parcel_writeStrongBinder函数中,下面这个语句:

const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));  

相当于是:

const status_t err = parcel->writeStrongBinder((JavaBBinderHodler*)(obj.mObject));  

因此,这里的效果相当于是写入了一个JavaBBinder类型的Binder实体到parcel中去。这与我们前面介绍的Binder机制的C++实现是一致的。

接着,再回到ServiceManagerProxy.addService这个函数中,最后它通过其成员变量mRemote来执行进程间通信操作。前面我们在介绍如何获取Service Manager远程接口时提到,这里的mRemote成员变量实际上是一个BinderProxy对象,因此,我们再来看看BinderProxy.transact函数的实现:

final class BinderProxy implements IBinder {       ......          public native boolean transact(int code, Parcel data, Parcel reply,                                   int flags) throws RemoteException;          ......   }  

这里的transact成员函数又是一个JNI方法,它定义在frameworks/base/core/jni/android_util_Binder.cpp文件中:

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,                           jint code, jobject dataObj,                           jobject replyObj, jint flags)   {       ......          Parcel* data = parcelForJavaObject(env, dataObj);       if (data == NULL) {           return JNI_FALSE;       }       Parcel* reply = parcelForJavaObject(env, replyObj);       if (reply == NULL && replyObj != NULL) {           return JNI_FALSE;       }          IBinder* target = (IBinder*)           env->GetIntField(obj, gBinderProxyOffsets.mObject);       if (target == NULL) {           jniThrowException(env, "java/lang/IllegalStateException""Binder has been finalized!");           return JNI_FALSE;       }          ......          status_t err = target->transact(code, *data, reply, flags);          ......          if (err == NO_ERROR) {           return JNI_TRUE;       } else if (err == UNKNOWN_TRANSACTION) {           return JNI_FALSE;       }          signalExceptionForError(env, obj, err);       return JNI_FALSE;   }  

这里传进来的参数dataObj和replyObj是一个Java接口实现的Parcel类,由于这里是JNI层,需要把它转换为C++实现的Parcel类,它们就是通过我们前面说的parcelForJavaObject函数进行转换的。

前面我们在分析如何获取Service Manager远程接口时,曾经说到,在JNI层中,创建了一个BpBinder对象,它的句柄值为0,它的地址保存在gBinderProxyOffsets.mObject中,因此,这里通过下面语句得到这个BpBinder对象的IBinder接口:

IBinder* target = (IBinder*)           env->GetIntField(obj, gBinderProxyOffsets.mObject);  

有了这个IBinder接口后,就和我们前面几篇文章介绍Binder机制的C/C++实现一致了。

最后,通过BpBinder::transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒Service Manager响应这个ADD_SERVICE_TRANSACTION请求:

status_t err = target->transact(code, *data, reply, flags);  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwjzdd.html