在具体讲解Binder调用流程之前,有必要先把调用流程中和数据相关的类介绍下,通过前面两节介绍,我们知道Binder对象分为本地和远程,在远程调用进行数据系列化时对这两种对象处理也是有区别的,下面是Binder调用流程中和数据直接相关的类。
JAVA端
BinderProxy:远程服务在本地的代理;
Binder:实现IBinder接口,实体Service具体实现一般继承这个类,表示具体业务逻辑实现;
Parcel:android的数据系列化类,直接在内存中操作,在JAVA端其只是个容器,真正实现在本地端;
对应本地端
BpBinder:远程服务代理对象,每个服务都会经过Binder驱动生成对应的handle一一对应;
BBinder:据图服务的实现,其功能之一返回本地IBinder对象,这个对象相关信息会直接传给Binder驱动;
Parcel:android数据系列化和反系列化本地管理类;
在分析这些类之前,我们先看下本地IBinder对本地对象和远程对象的接口支持的定义。
frameworks/native/include/binder/IBinder.h
50class IBinder : public virtual RefBase
......
161 virtual BBinder* localBinder(); // (1)
162 virtual BpBinder* remoteBinder(); // (2)
163
164protected:
165 virtual ~IBinder();
166
167private:
168};
(1)返回的是一个本地IBinder对象,什么叫本地对象?就是调用的进程就是实现这个IBinder的宿主进程,IBinder实体类就存储在此进程中。
(2)返回的是一个远程代理对象,就是调用进程和IBinder实体不在同一个进程,其和远程IBinder实体对象是通过对象的handle进行关联的。
下面一一分析这些类的具体实现细节,这里我们只会讲和Binder调用流程相关,其它读者自行查看源码。
BinderProxy
文件:frameworks/base/core/java/android/os/Binder.java
查看BinderProxy的源码:
733final class BinderProxy implements IBinder {
......
744 public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
.....
763 try {
764 return transactNative(code, data, reply, flags);
765 } finally {
766 if (tracingEnabled) {
767 Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
768 }
769 }
770 }
上面我们只留下关键代码,首先BinderProxy是从IBinder继承过来,所有其具有Binder通行的基础,在其具体实现方法transact里,我们发现其实际调用的是transactNative方法,这是一个本地方法,定义如下:
public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;
这是一个JNI方法,其实现在如下文件中:
frameworks/base/core/jni/android_util_Binder.cpp
在这个文件我们发现定义了BinderProxy的本地方法映射:
static const JNINativeMethod gBinderProxyMethods[] = {
1305 /* name, signature, funcPtr */
1306 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
1307 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1308 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1309 {"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1310 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1311 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1312 {"destroy", "()V", (void*)android_os_BinderProxy_destroy},
1313};
transactNative方法在本地对应的实现是android_os_BinderProxy_transact,下面看看这个方法具体做了些什么:
1141static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1142 jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
1143{
......
1149 Parcel* data = parcelForJavaObject(env, dataObj); // (1)
......
1153 Parcel* reply = parcelForJavaObject(env, replyObj); // (2)
......
1158 IBinder* target = (IBinder*)
1159 env->GetLongField(obj, gBinderProxyOffsets.mObject); // (3)
......
1182 status_t err = target->transact(code, *data, reply, flags);
1183 ......
1198 return JNI_FALSE;
1199}
其中(1)和(2)后面讲Parcel会说,我们来看看(3),这里从BinderProxy直接取出其成员变量mObject的值,它就是一个本地IBinder类型的对象,那么这个本地对象是怎么设置给JAVA层的BinderProxy的呢?从这里我们可以大致推断这个JAVA层的BinderProxy对象有可能是在native层创建的。
从上面代码发现这里有个结构gBinderProxyOffsets,其定义如下:
96static struct binderproxy_offsets_t
97{
98 // Class state.
99 jclass mClass;
100 jmethodID mConstructor;
101 jmethodID mSendDeathNotice;
102
103 // Object state.
104 jfieldID mObject;
105 jfieldID mSelf;
106 jfieldID mOrgue;
107
108} gBinderProxyOffsets;
这个结构其实就是保持了JAVA层BinderProxy类成员变量和成员方法的相关信息,其中的mObject保存了本地对象,我们看看这个mObject在那里设置进来的,搜索SetLongField(为什么要搜索这个方法?)方法,发现和mObject相关代码如下:
5jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
596{
......
624 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
625 if (object != NULL) {
......
628 env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
629 val->incStrong((void*)javaObjectForIBinder);
630
在方法中javaObjectForIBinder创建了BinderProxy对象,并把参数val设置给了BinderProxy的mObject成员变量,继续找javaObjectForIBinder在那里调用:
950static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
951{
952 sp b = ProcessState::self()->getContextObject(NULL);
953 return javaObjectForIBinder(env, b);
954}
这里有一处调用,原来这个IBinder是ProcessState::self()->getContextObject(NULL);创建的,看下这个方法就知道了:
238sp ProcessState::getStrongProxyForHandle(int32_t handle)
239{
......
244 handle_entry* e = lookupHandleLocked(handle);
245
246 if (e != NULL) {
......
279 b = new BpBinder(handle);
280 e->binder = b;
......
292 return result;
293}
经过层层调用发现,最终会调getStrongProxyForHandle这个方法,原来返回的IBinder是由b = new BpBinder(handle);这句代码创建的,到这里我们知道了设置给BinderProxy的mObject成员变量的native对象就是BpBinder,这就对应上了。细心的读者可能发现,这里是对本地的BpBinder做了缓存处理的,通过handle来保存。另外,大家也要注意此方法也在Parcel被调用,可见它是获取远程服务的本地代理的方法入口。
接着我们看看本地实际的远程代理对象的实现。
frameworks/native/libs/binder/BpBinder.cpp
307BpBinder* BpBinder::remoteBinder()
308{
309 return this;
310}
看到了吧,其远程接口 remoteBinder()直接返回BpBinder对象本身,而其本地接口返回的是NULL(IBinder中实现)。
讲完了BinderProxy,接下来看下Binder和本地的BBinder又是怎么回事?
Binder
文件:frameworks/base/core/java/android/os/Binder.java
Binder定义如下:
70public class Binder implements IBinder {
其构造方法如下:
363 public Binder() {
364 init();
......
374 }
其构造方法里调用了init,init方法是个本地方法,其定义如下:
678 private native final void init();
和上面一样,在native找到其对应的实现,其定义在如下文件中:
frameworks/base/core/jni/android_util_Binder.cpp
856static void android_os_Binder_init(JNIEnv* env, jobject obj)
857{
858 JavaBBinderHolder* jbh = new JavaBBinderHolder();
......
865 env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
866}
和BinderProxy一样的套路,我们发现在native其实就是new一个JavaBBinderHolder对象,并把它设置到Binder的mObject成员变量中,这里就不多说,下面我们看看JavaBBinderHolder实现。
362class JavaBBinderHolder : public RefBase
363{
364public:
365 sp get(JNIEnv* env, jobject obj)
366 {
367 AutoMutex _l(mLock);
368 sp b = mBinder.promote();
369 if (b == NULL) {
370 b = new JavaBBinder(env, obj); // (1)
371 mBinder = b;
......
384
385private:
386 Mutex mLock;
387 wp mBinder; // (2)
388};
最终JavaBBinderHolder 通过其get方法返回JavaBBinder对象,这里先不管JavaBBinderHolder.get在哪儿被调用,先看看JavaBBinder的定义。
265class JavaBBinder : public BBinder
266{
267public:
268 JavaBBinder(JNIEnv* env, jobject object)
269 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
270 {
271 ALOGV("Creating JavaBBinder %p\n", this);
272 android_atomic_inc(&gNumLocalRefs);
273 incRefsCreated(env);
274 }
关键来了,原来JavaBBinder就是一个BBinder对象,所以和我们一开始说的一样,从Binder继承的Service在本地其实是一个BBinder,而且这个JavaBBinder还持有实体IBinder的引用(mObject(env->NewGlobalRef(object))),其把实体IBinder对象保存在mObject中,而这个对象就是JAVA层实现的Service。在Binder驱动把业务逻辑转到Service宿主进程的时候最终会执行到JavaBBinder的onTransact方法。
295 virtual status_t onTransact(
296 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
297 {
298 JNIEnv* env = javavm_to_jnienv(mVM);
......
308 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
309 code, reinterpret_cast(&data), reinterpret_cast(reply), flags);
从上面代码我们知道最终会把调用转到JAVA层实现的Service的execTransact方法,这个execTransact就是JAVA层的Binder对象的一个方法,Service重载这个方法从而完成把逻辑转到业务层的调度。
接下来我们看下BBinder的定义。
在文件frameworks/native/libs/binder/Binder.cpp中找到localBinder的定义。
199BBinder* BBinder::localBinder()
200{
201 return this;
202}
这里我们看到了BBinder对本地接口返回是自身对象,远程接口返回的是NULL(在IBinder中实现),到这里就明白了为什么实现Binder的服务就是一个本地对象。
最后看下Parcel的实现,这里JAVA层的Parcel就不讲了,因为都是一个套路,JAVA层的Parcel只是一个容器,实际实现在本地的Parcel类中。
Parcel
frameworks/native/libs/binder/include/binder/Parcel.h
这里JAVA层的Parcel接口对应实现在下面文件中。
frameworks/base/core/jni/android_os_Parcel.cpp
这里重点看下nativeReadStrongBinder的实现。
451static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
452{
453 Parcel* parcel = reinterpret_cast(nativePtr);
454 if (parcel != NULL) {
455 return javaObjectForIBinder(env, parcel->readStrongBinder()); // (1)
456 }
457 return NULL;
458}
这里调用javaObjectForIBinder生成JAVA对象,其实就是BinderProxy,在看javaObjectForIBinder方法之前,先看下parcel->readStrongBinder()这个怎么返回IBinder对象的,经过层层调用最终会进入如下方法:
323status_t unflatten_binder(const sp& proc,
324 const Parcel& in, wp* out)
325{
326 const flat_binder_object* flat = in.readObject(false);
327
328 if (flat) {
329 switch (flat->type) {
......
342 case BINDER_TYPE_HANDLE:
343 case BINDER_TYPE_WEAK_HANDLE:
344 *out = proc->getWeakProxyForHandle(flat->handle); // (1)
345 return finish_unflatten_binder(
346 static_cast(out->unsafe_get()), *flat, in);
347 }
348 }
349 return BAD_TYPE;
350}
这里有个flat_binder_object结构,我们简单说下,这个结构其实就是IBinder对象在Binder驱动层的二进制描述,存储了IBinder的相关信息。我们重点看下代码(1)出的逻辑,这里最终调用还是ProcessSate的getWeakProxyForHandle方法,这个方法上面介绍过,其实就是返回BpBinder对象,而且根据handle做了缓存处理。
这样我们知道javaObjectForIBinder的第二个参数其实就是BpBinder类型的IBinder对象,这个方法上面也介绍过了,就是生成BinderProxy对象,然后把BpBinder类型的IBinder设置给BinderProxy的成员变量mObject。
到这里我们把和Binder调用流程相关的几个关键类介绍完了,有了这个基础,后面讲解Binder的调用流程就会轻松多了。
本系列文章均为原创,主要总结作者多年在软件行业的一些经验,和大家共同学习、进步,转载请注明出处,谢谢!