本文分析基于Android P(9.0) 源码
Binder是Android中RPC(Remote Procedure Call)的主要实现机制,它在Android中随处可见,是基石一般的存在。了解Binder的朋友可能都听过代理(Proxy)、引用(Ref)之类的名词,然而关于它们的细节可能未必清楚。
之前在学习Binder的时候,参考过很多书籍和博客。几乎所有文章在谈到如何获取Binder代理对象时,都认为首先需要将service对象注册到ServiceManager中去,之后再由Client进程从ServiceManager中获取它的代理对象。这种说法并没有错,但却不够深入。
我认为以上这些才是理解“代理”二字的关键。而ServiceManager只是一种集中管理的方式,它通过字符串和Binder代理对象的键值对来记录整个系统中的service,类似于我们上网时的DNS服务器。但本质上说它和“代理”二字并没有必然的关联。
所以本文希望通过一个新的视角,将Binder世界中的代理过程和盘托出。
下面为了方便分析,我们选定ApplicationThread类作为研究对象。
老子说:“一生二,二生三,三生万物”。那么在Binder的世界中,“一”到底来自何方?
所有的RPC(远程过程调用),最终都需要一个实体来根据传输数据执行相应的操作。在Binder的世界中可以将它称为Binder实体对象(名字是我自己斟酌的,可能欠妥,但含义已经表达清楚。看过老罗书和文章的人可能听过“实体对象”、“本地对象”、“引用对象”之类的名字,但我认为那样会增加理解的复杂度,因此这里放弃罗哥的命名方式),表示它才是真正干活的那个人。它就是Binder世界中的“一”,从它创建(在Server进程中被创建)的那一刻起,Binder世界便有了基石。对于ApplicationThread的Binder通信而言,其最终的执行体是位于Java层的ApplicationThread对象。因此在接下来的Binder通信过程中,我们将它称为Binder实体对象。
/frameworks/base/core/java/android/app/ActivityThread.java
757 private class ApplicationThread extends IApplicationThread.Stub { 复制代码
ApplicationThread继承于IApplicationThread.Stub类。需要注意的是,后面这个类通常并不存在于源码中,而是由AIDL文件编译生成的。IApplicationThread的AIDL文件如下所示:
/frameworks/base/core/java/android/app/IApplicationThread.aidl
55oneway interface IApplicationThread { 56 void scheduleReceiver(in Intent intent, in ActivityInfo info, 57 in CompatibilityInfo compatInfo, 58 int resultCode, in String data, in Bundle extras, boolean sync, 59 int sendingUser, int processState); 60 void scheduleCreateService(IBinder token, in ServiceInfo info, 61 in CompatibilityInfo compatInfo, int processState); 62 void scheduleStopService(IBinder token); 63 void bindApplication(in String packageName, in ApplicationInfo info, 64 in List<ProviderInfo> providers, in ComponentName testName, 65 in ProfilerInfo profilerInfo, in Bundle testArguments, 66 IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, 67 int debugMode, boolean enableBinderTracking, boolean trackAllocation, 68 boolean restrictedBackupMode, boolean persistent, in Configuration config, 69 in CompatibilityInfo compatInfo, in Map services, 70 in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled); 71 void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs); 72 void scheduleExit(); 73 void scheduleServiceArgs(IBinder token, in ParceledListSlice args); 74 void updateTimeZone(); 75 void processInBackground(); 76 void scheduleBindService(IBinder token, 77 in Intent intent, boolean rebind, int processState); 78 void scheduleUnbindService(IBinder token, 79 in Intent intent); 80 void dumpService(in ParcelFileDescriptor fd, IBinder servicetoken, 81 in String[] args); 82 void scheduleRegisteredReceiver(IIntentReceiver receiver, in Intent intent, 83 int resultCode, in String data, in Bundle extras, boolean ordered, 84 boolean sticky, int sendingUser, int processState); 85 void scheduleLowMemory(); 86 void scheduleSleeping(IBinder token, boolean sleeping); 87 void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType); 88 void setSchedulingGroup(int group); 89 void scheduleCreateBackupAgent(in ApplicationInfo app, in CompatibilityInfo compatInfo, 90 int backupMode); 91 void scheduleDestroyBackupAgent(in ApplicationInfo app, 92 in CompatibilityInfo compatInfo); 93 void scheduleOnNewActivityOptions(IBinder token, in Bundle options); 94 void scheduleSuicide(); 95 void dispatchPackageBroadcast(int cmd, in String[] packages); 96 void scheduleCrash(in String msg); 97 void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path, 98 in ParcelFileDescriptor fd); 99 void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix, 100 in String[] args); 101 void clearDnsCache(); 102 void setHttpProxy(in String proxy, in String port, in String exclList, 103 in Uri pacFileUrl); 104 void setCoreSettings(in Bundle coreSettings); 105 void updatePackageCompatibilityInfo(in String pkg, in CompatibilityInfo info); 106 void scheduleTrimMemory(int level); 107 void dumpMemInfo(in ParcelFileDescriptor fd, in Debug.MemoryInfo mem, boolean checkin, 108 boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable, 109 in String[] args); 110 void dumpMemInfoProto(in ParcelFileDescriptor fd, in Debug.MemoryInfo mem, 111 boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable, 112 in String[] args); 113 void dumpGfxInfo(in ParcelFileDescriptor fd, in String[] args); 114 void dumpProvider(in ParcelFileDescriptor fd, IBinder servicetoken, 115 in String[] args); 116 void dumpDbInfo(in ParcelFileDescriptor fd, in String[] args); 117 void unstableProviderDied(IBinder provider); 118 void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, 119 int requestType, int sessionId, int flags); 120 void scheduleTranslucentConversionComplete(IBinder token, boolean timeout); 121 void setProcessState(int state); 122 void scheduleInstallProvider(in ProviderInfo provider); 123 void updateTimePrefs(int timeFormatPreference); 124 void scheduleEnterAnimationComplete(IBinder token); 125 void notifyCleartextNetwork(in byte[] firstPacket); 126 void startBinderTracking(); 127 void stopBinderTrackingAndDump(in ParcelFileDescriptor fd); 128 void scheduleLocalVoiceInteractionStarted(IBinder token, 129 IVoiceInteractor voiceInteractor); 130 void handleTrustStorageUpdate(); 131 void attachAgent(String path); 132 void scheduleApplicationInfoChanged(in ApplicationInfo ai); 133 void setNetworkBlockSeq(long procStateSeq); 134 void scheduleTransaction(in ClientTransaction transaction); 135} 复制代码
它是一个接口文件。55行的 oneway
表示利用Binder代理对象进行RPC时,并不需要等待对端进程返回,因此是一次单向(异步)的跨进程通信。IApplicationThread中声明了很多方法,代表该接口所具备的能力。AIDL文件生成的IApplicationThread.java如下所示(只展示了片段),在IApplicationThread接口内部定义了一个抽象类Stub。由于是抽象类,所以它并不需要 全部 实现接口(IApplicationThread)中所声明的方法,而其中关键的方法onTransact只有一个作用:将对端进程传递过来的参数解包,并调用对应的方法执行。此外,抽象类Stub会被ApplicationThread继承,所有真正进行数据处理的方法都在这个子类中定义。
IApplicationThread.java(源码编译时自动生成)
181 /** Local-side IPC implementation stub class. */ 182 public static abstract class Stub extends android.os.Binder implements android.app.IApplicationThread 183 { 184 private static final java.lang.String DESCRIPTOR = "android.app.IApplicationThread"; 复制代码
综上,Binder实体对象为ApplicationThread对象,其所属的类在Java层拥有如下所示的继承和实现关系。
IBinder接口中声明的都是与跨进程通信相关的方法,而IApplicationThread接口中声明的都是ApplicationThread中应该实现的方法(表示ApplicationThread这个类所具备的能力)。由于ApplicationThread最终继承于Binder,所以它兼具了跨进程通信的能力。
如果ApplicationThread是一个正常的本地类(不需要进行跨进程通信),那么它只需要实现IApplicationThread接口即可,如下图所示。现在之所以继承关系变得复杂,就是为了支持跨进程通信。
上文中提到,对于ApplicationThread的Binder通信而言,最终执行的实体是ApplicationThread对象。因此,Binder通信的第一步就是创建ApplicationThread对象,而创建这个对象的进程就是Binder通信中所谓的Server进程。
/frameworks/base/core/java/android/app/ActivityThread.java
254 final ApplicationThread mAppThread = new ApplicationThread(); 复制代码
熟悉Binder的朋友应该知道,最终的跨进程通信是通过Binder Driver完成的。而Binder Driver位于内核空间,Java层的Binder对象无法与其直接沟通,所以必须经由Native层进行中转。在中转的过程中,也会创建一些Native层的C++对象来管理中间状态。
ApplicationThread继承于IApplicationThread.Stub,IApplicationThread.Stub又继承于Binder,所以在ApplicationThread对象创建的过程中同样会调用Binder的构造方法。
/frameworks/base/core/java/android/os/Binder.java
402 public Binder() { 403 mObject = getNativeBBinderHolder(); //mObject是Java层Binder对象的一个实例字段 404 NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject); 405 406 if (FIND_POTENTIAL_LEAKS) { 407 final Class<? extends Binder> klass = getClass(); 408 if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && 409 (klass.getModifiers() & Modifier.STATIC) == 0) { 410 Log.w(TAG, "The following Binder class should be static or leaks might occur: " + 411 klass.getCanonicalName()); 412 } 413 } 414 } 复制代码
403行首先通过getNativeBBinderHolder来获取native层的JavaBBinderHolder对象的指针值,其对应的JNI方法如下:
frameworks/base/core/jni/android_util_Binder.cpp
896static jlong android_os_Binder_getNativeBBinderHolder(JNIEnv* env, jobject clazz) 897{ 898 JavaBBinderHolder* jbh = new JavaBBinderHolder(); 899 return (jlong) jbh; 900} 复制代码
898行表示创建一个Native层的JavaBBinderHolder对象,根据类名,我们可以了解到它应该只是一个辅助类。而Native层真正起接力作用的对象还没出现。至此,ApplicationThread对象的创建过程全部完成,除了在Java层创建了一个Binder实体对象外,Native层也创建了一个JavaBBinderHolder对象。
虽然实体对象创建完毕了,但Binder Driver还没有感知到它的存在。
接下来是关键的一步,不论是向ServiceManager中注册,还是通过跨进程通信将此Binder实体对象发送给对端进程,都需要经过Parcel对象的writeStrongBinder方法。
ApplicationThread对象创建出来后,接着会通过跨进程通信发送给对端进程。(这里是一个容易混淆的地方,为了方便理解可以假定这句话中的“跨进程通信”是一个先天存在的渠道,虽然它也是Binder通信,但我们暂时不深究它的来历)
/frameworks/base/core/java/android/os/Parcel.java
736 public final void writeStrongBinder(IBinder val) { //val是ApplicationThread对象 737 nativeWriteStrongBinder(mNativePtr, val); 738 } 复制代码
frameworks/base/core/jni/android_os_Parcel.cpp
298static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) 299{ 300 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 301 if (parcel != NULL) { 302 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); //此object表示的是Java层的ApplicationThread对象 303 if (err != NO_ERROR) { 304 signalExceptionForError(env, clazz, err); 305 } 306 } 307} 复制代码
frameworks/base/core/jni/android_util_Binder.cpp
690sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 691{ 692 if (obj == NULL) return NULL; 693 694 // Instance of Binder? 695 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { 696 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 697 env->GetLongField(obj, gBinderOffsets.mObject); //取出ApplicationThread对象的mObject字段的值,其在之前构造的时候存储了JavaBBinderHolder对象的指针值 698 return jbh->get(env, obj); 699 } 700 701 // Instance of BinderProxy? 702 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { 703 return getBPNativeData(env, obj)->mObject; 704 } 705 706 ALOGW("ibinderForJavaObject: %p is not a Binder object", obj); 707 return NULL; 708} 复制代码
696获得的JavaBBinderHolder对象是在ApplicationThread对象构造时创建的。而JavaBBinderHolder对象内部的成员变量最终在698行的get方法中完成真正的赋值。
frameworks/base/core/jni/android_util_Binder.cpp
396 sp<JavaBBinder> get(JNIEnv* env, jobject obj) 397 { 398 AutoMutex _l(mLock); 399 sp<JavaBBinder> b = mBinder.promote(); //此时JavaBBinderHolder对象的mBinder变量promote后为NULL 400 if (b == NULL) { 401 b = new JavaBBinder(env, obj); //构造一个新的JavaBBinder(c++)对象,obj是ApplicationThread(java)对象 402 mBinder = b; 403 ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "/n", 404 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount()); 405 } 406 407 return b; 408 } 复制代码
401行根据ApplicationThread(Java层)对象构造出一个新的JavaBBinder(Native层)对象。然后402行将它赋值给JavaBBinderHolder对象的mBinder变量。
接下来看看这个新创建的JavaBBinder对象到底是什么来历。它继承于BBinder类,并且持有了ApplicationThread对象的JNI全局引用。
frameworks/base/core/jni/android_util_Binder.cpp
301class JavaBBinder : public BBinder 302{ 303public: 304 JavaBBinder(JNIEnv* env, jobject /* Java Binder */ object) 305 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) 306 { 307 ALOGV("Creating JavaBBinder %p/n", this); 308 gNumLocalRefsCreated.fetch_add(1, std::memory_order_relaxed); 309 gcIfManyNewRefs(env); 310 } 复制代码
因此在writeStrongBinder的初期,又创建了新的Native层对象:JavaBBinder对象,并将它交由JavaBBinderHolder对象持有。以下图例展示了它的持有和继承关系。
至此,Binder实体对象及其有关的两个Native层对象均已创建完成,它们分别是Jave层的ApplicationThread对象、Native层的JavaBBinderHolder对象以及Native层的JavaBBinder对象。JavaBBinder对象的mObject字段记录了ApplicationThread对象的信息,所以一旦找到JavaBBinder对象,便可以通过其mObject字段调用其Java对象的方法。下图展示了三个对象之间的关系。
接下来再回到writeStrongBinder的过程,ibinderForJavaObject返回的是刚刚创建的JavaBBinder对象。
frameworks/base/core/jni/android_os_Parcel.cpp
298static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) 299{ 300 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 301 if (parcel != NULL) { 302 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); //此object表示的是Java层的ApplicationThread对象 303 if (err != NO_ERROR) { 304 signalExceptionForError(env, clazz, err); 305 } 306 } 307} 复制代码
/frameworks/native/libs/binder/Parcel.cpp
1082status_t Parcel::writeStrongBinder(const sp<IBinder>& val) 1083{ 1084 return flatten_binder(ProcessState::self(), val, this); 1085} 复制代码
/frameworks/native/libs/binder/Parcel.cpp
209status_t flatten_binder(const sp<ProcessState>& /*proc*/, 210 const sp<IBinder>& binder, Parcel* out) 211{ 212 flat_binder_object obj; 213 214 if (IPCThreadState::self()->backgroundSchedulingDisabled()) { 215 /* minimum priority for all nodes is nice 0 */ 216 obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS; 217 } else { 218 /* minimum priority for all nodes is MAX_NICE(19) */ 219 obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS; 220 } 221 222 if (binder != NULL) { 223 IBinder *local = binder->localBinder(); //对于JavaBBinder对象而言,其localBinder成员函数获取到的是this指针 224 if (!local) { //这是BinderProxy走的分支 225 BpBinder *proxy = binder->remoteBinder(); 226 if (proxy == NULL) { 227 ALOGE("null proxy"); 228 } 229 const int32_t handle = proxy ? proxy->handle() : 0; 230 obj.hdr.type = BINDER_TYPE_HANDLE; 231 obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */ 232 obj.handle = handle; 233 obj.cookie = 0; 234 } else { //这才是JavaBBinder走的分支 235 obj.hdr.type = BINDER_TYPE_BINDER; 236 obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); 237 obj.cookie = reinterpret_cast<uintptr_t>(local); 238 } 239 } else { 240 obj.hdr.type = BINDER_TYPE_BINDER; 241 obj.binder = 0; 242 obj.cookie = 0; 243 } 244 245 return finish_flatten_binder(binder, obj, out); 246} 复制代码
将这个JavaBBinder对象flatten后,便会加入到Parcel对象mOut中,预示着它将被发送到对端进程。此对象存放在mOut中的位置我们先不深究,接下来深入到Binder Driver中,看看驱动发现传输数据中有JavaBBinder对象后,将会如何处理。
Android P采用的Linux kernel版本为4.14。对于一次Binder通信而言,通信发起进程最终会调用Binder Driver的binder_transaction函数。其中会遍历mOut中存放的所有flat_binder_object,并进行相应的处理。
/kernel/msm-4.14/drivers/android/binder.c
3187 for (; offp < off_end; offp++) { 3188 struct binder_object_header *hdr; 3189 size_t object_size = binder_validate_object(t->buffer, *offp); 3190 3191 if (object_size == 0 || *offp < off_min) { 3192 binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object./n", 3193 proc->pid, thread->pid, (u64)*offp, 3194 (u64)off_min, 3195 (u64)t->buffer->data_size); 3196 return_error = BR_FAILED_REPLY; 3197 return_error_param = -EINVAL; 3198 return_error_line = __LINE__; 3199 goto err_bad_offset; 3200 } 3201 3202 hdr = (struct binder_object_header *)(t->buffer->data + *offp); 3203 off_min = *offp + object_size; 3204 switch (hdr->type) { 3205 case BINDER_TYPE_BINDER: 3206 case BINDER_TYPE_WEAK_BINDER: { //对于JavaBBinder而言,type为BINDER_TYPE_BINDER 3207 struct flat_binder_object *fp; 3208 3209 fp = to_flat_binder_object(hdr); //根据header得到对应的flat_binder_object 3210 ret = binder_translate_binder(fp, t, thread); //这是至关重要的一步 3211 if (ret < 0) { 3212 return_error = BR_FAILED_REPLY; 3213 return_error_param = ret; 3214 return_error_line = __LINE__; 3215 goto err_translate_failed; 3216 } 3217 } break; 复制代码
在binder_translate_binder中,首先会根据binder_flat_object创建一个内核空间的binder_node对象。它是Binder实体对象在内核空间的中间形态,同时为了建立和用户空间对象的联系,它用cookie字段记录了用户空间JavaBBinder对象的指针值。下图展示了Binder实体对象和Native层中间形态及Kernel层中间形态的关系。
至此,Binder实体对象及其在各层的中间形态都已经创建完毕。接下来看看Binder代理对象是如何被创建的。
所谓Binder代理对象,就是一次RPC发起时,应用开发者所能够知道的唯一入口。譬如通过IApplicationThread.bindApplication方法来发起一次RPC时,那么IApplicationThread对象就是Binder代理对象。
再次回到binder_translate_binder中,看看驱动得知传进来的是一个Binder实体对象后将会做哪些处理。
/kernel/msm-4.14/drivers/android/binder.c
2479 static int binder_translate_binder(struct flat_binder_object *fp, 2480 struct binder_transaction *t, 2481 struct binder_thread *thread) 2482 { 2483 struct binder_node *node; 2484 struct binder_proc *proc = thread->proc; 2485 struct binder_proc *target_proc = t->to_proc; 2486 struct binder_ref_data rdata; 2487 int ret = 0; 2488 2489 node = binder_get_node(proc, fp->binder); 2490 if (!node) { 2491 node = binder_new_node(proc, fp); //创建一个新的binder_node对象 2492 if (!node) 2493 return -ENOMEM; 2494 } 2495 if (fp->cookie != node->cookie) { 2496 binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx/n", 2497 proc->pid, thread->pid, (u64)fp->binder, 2498 node->debug_id, (u64)fp->cookie, 2499 (u64)node->cookie); 2500 ret = -EINVAL; 2501 goto done; 2502 } 2503 if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { 2504 ret = -EPERM; 2505 goto done; 2506 } 2507 2508 ret = binder_inc_ref_for_node(target_proc, node, 2509 fp->hdr.type == BINDER_TYPE_BINDER, 2510 &thread->todo, &rdata); //这里会为对端进程创建一个binder_ref对象,它是Binder代理对象在内核空间里的中间形态 2511 if (ret) 2512 goto done; 2513 2514 if (fp->hdr.type == BINDER_TYPE_BINDER) 2515 fp->hdr.type = BINDER_TYPE_HANDLE; //这里完成了“移花接木” 2516 else 2517 fp->hdr.type = BINDER_TYPE_WEAK_HANDLE; 2518 fp->binder = 0; 2519 fp->handle = rdata.desc; 2520 fp->cookie = 0; 2521 2522 trace_binder_transaction_node_to_ref(t, node, &rdata); 2523 binder_debug(BINDER_DEBUG_TRANSACTION, 2524 " node %d u%016llx -> ref %d desc %d/n", 2525 node->debug_id, (u64)node->ptr, 2526 rdata.debug_id, rdata.desc); 2527 done: 2528 binder_put_node(node); 2529 return ret; 2530 } 复制代码
2515是最为关键的一步。虽然在Binder实体对象创建的进程中,我们通过binder_transaction函数意图往对端进程发送一个type为BINDER_TYPE_BINDER的Binder对象(意味着这是一个Binder实体对象),但在2515行却将type改为了BINDER_TYPE_HANDLE。这样一来,对端进程就知道自己接收了一个Binder代理对象。此外,2518行和2520行会分别将flat_binder_object的binder字段和cookie字段置为0,因为这两个字段只有当flat_binder_object表示一个Binder实体对象时才需要,而对端进程接收到flat_binder_object后会将它认为是一个Binder代理对象。
2508行会为对端进程创建一个binder_ref对象,它是Binder代理对象在kernel层的中间形态。其中一个重要的数据便是binder_ref对象的data.desc,它是一个由驱动分配的数字。对于每个进程而言,这个数字会从1开始不断增大,保证每一个binder_ref对象都会拥有一个独一无二的标识。这个数字就是大家经常说的handle值,是用户空间里每个Binder代理对象的“身份证号码”。
/kernel/msm-4.14/drivers/android/binder.c
449 struct binder_ref { 450 /* Lookups needed: */ 451 /* node + proc => ref (transaction) */ 452 /* desc + proc => ref (transaction, inc/dec ref) */ 453 /* node => refs + procs (proc exit) */ 454 struct binder_ref_data data; 455 struct rb_node rb_node_desc; 456 struct rb_node rb_node_node; 457 struct hlist_node node_entry; 458 struct binder_proc *proc; 459 struct binder_node *node; 460 struct binder_ref_death *death; 461 }; 复制代码
425 struct binder_ref_data { 426 int debug_id; 427 uint32_t desc; 428 int strong; 429 int weak; 430 }; 复制代码
这样一来,在对端进程真正处理此次Binder通信之前,驱动已经为对端进程创建了Binder代理对象在内核空间中的中间形态: binder_ref对象。
至此,以上所有的操作都在同一个进程中。接下来视角将会切换到对端进程,它在接收到Binder通信请求后,会从Binder Driver中被唤醒过来。
对端进程接收到数据后,会一层层往上传,最终交由上层处理。这里假设最终的处理方法如下:
IActivityManager.java (编译过程中,根据AIDL文件生成)
1 case TRANSACTION_bindService: 2 { 3 data.enforceInterface(descriptor); 4 android.app.IApplicationThread _arg0; 5 _arg0 = android.app.IApplicationThread.Stub.asInterface(data.readStrongBinder()); 6 android.os.IBinder _arg1; 7 _arg1 = data.readStrongBinder(); 8 android.content.Intent _arg2; 9 if ((0!=data.readInt())) { 10 _arg2 = android.content.Intent.CREATOR.createFromParcel(data); 11 } 12 else { 13 _arg2 = null; 14 } 15 java.lang.String _arg3; 16 _arg3 = data.readString(); 17 android.app.IServiceConnection _arg4; 18 _arg4 = android.app.IServiceConnection.Stub.asInterface(data.readStrongBinder()); 19 int _arg5; 20 _arg5 = data.readInt(); 21 java.lang.String _arg6; 22 _arg6 = data.readString(); 23 int _arg7; 24 _arg7 = data.readInt(); 25 int _result = this.bindService(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7); 26 reply.writeNoException(); 27 reply.writeInt(_result); 28 return true; 29 } 复制代码
而关键代码就是上面的第5行。首先分析readStrongBinder里面做了什么。需要提醒的是,到目前为止Binder代理对象还未创建,只有它在内核空间内的中间形态binder_ref被创建了。
通过JNI调用,Java层的readStrongBinder方法最终调用了Native层的readStrongBinder函数。
/frameworks/base/core/java/android/os/Parcel.java
2026 public final IBinder readStrongBinder() { 2027 return nativeReadStrongBinder(mNativePtr); 2028 } 复制代码
/frameworks/base/core/jni/android_os_Parcel.cpp
451static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr) 452{ 453 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 454 if (parcel != NULL) { 455 return javaObjectForIBinder(env, parcel->readStrongBinder()); 456 } 457 return NULL; 458} 复制代码
上面代码的455行可以分为两个部分来讨论,一个是Native层的readStrongBinder函数,另一个是Native层的javaObjectForIBinder函数。下面先讨论第一部分。
/frameworks/native/libs/binder/Parcel.cpp
2140sp<IBinder> Parcel::readStrongBinder() const 2141{ 2142 sp<IBinder> val; 2143 // Note that a lot of code in Android reads binders by hand with this 2144 // method, and that code has historically been ok with getting nullptr 2145 // back (while ignoring error codes). 2146 readNullableStrongBinder(&val); 2147 return val; 2148} 复制代码
/frameworks/native/libs/binder/Parcel.cpp
2135status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const 2136{ 2137 return unflatten_binder(ProcessState::self(), *this, val); 2138} 复制代码
/frameworks/native/libs/binder/Parcel.cpp
304status_t unflatten_binder(const sp<ProcessState>& proc, 305 const Parcel& in, sp<IBinder>* out) 306{ 307 const flat_binder_object* flat = in.readObject(false); //读出flat_binder_object对象 308 309 if (flat) { 310 switch (flat->hdr.type) { 311 case BINDER_TYPE_BINDER: 312 *out = reinterpret_cast<IBinder*>(flat->cookie); 313 return finish_unflatten_binder(NULL, *flat, in); 314 case BINDER_TYPE_HANDLE: 315 *out = proc->getStrongProxyForHandle(flat->handle); 316 return finish_unflatten_binder( 317 static_cast<BpBinder*>(out->get()), *flat, in); 318 } 319 } 320 return BAD_TYPE; 321} 复制代码
readStrongBinder函数最终调用到unflatten_binder函数,315行表明根据flat_binder_object对象得到一个native层的BpBinder对象。
frameworks/native/libs/binder/ProcessState.cpp
244sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) 245{ 246 sp<IBinder> result; 247 248 AutoMutex _l(mLock); 249 250 handle_entry* e = lookupHandleLocked(handle); 251 252 if (e != NULL) { 253 // We need to create a new BpBinder if there isn't currently one, OR we 254 // are unable to acquire a weak reference on this current one. See comment 255 // in getWeakProxyForHandle() for more info about this. 256 IBinder* b = e->binder; 257 if (b == NULL || !e->refs->attemptIncWeak(this)) { 258 if (handle == 0) { 259 // Special case for context manager... 260 // The context manager is the only object for which we create 261 // a BpBinder proxy without already holding a reference. 262 // Perform a dummy transaction to ensure the context manager 263 // is registered before we create the first local reference 264 // to it (which will occur when creating the BpBinder). 265 // If a local reference is created for the BpBinder when the 266 // context manager is not present, the driver will fail to 267 // provide a reference to the context manager, but the 268 // driver API does not return status. 269 // 270 // Note that this is not race-free if the context manager 271 // dies while this code runs. 272 // 273 // TODO: add a driver API to wait for context manager, or 274 // stop special casing handle 0 for context manager and add 275 // a driver API to get a handle to the context manager with 276 // proper reference counting. 277 278 Parcel data; 279 status_t status = IPCThreadState::self()->transact( 280 0, IBinder::PING_TRANSACTION, data, NULL, 0); 281 if (status == DEAD_OBJECT) 282 return NULL; 283 } 284 285 b = BpBinder::create(handle); 286 e->binder = b; 287 if (b) e->refs = b->getWeakRefs(); 288 result = b; 289 } else { 290 // This little bit of nastyness is to allow us to add a primary 291 // reference to the remote proxy when this team doesn't have one 292 // but another team is sending the handle to us. 293 result.force_set(b); 294 e->refs->decWeak(this); 295 } 296 } 297 298 return result; 299} 复制代码
250行是根据handle值到一个Vector中寻找对应的handle_entry对象。而此时,由于Binder代理对象并不存在,所以Vector中也找不到相应信息。
231ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle) 232{ 233 const size_t N=mHandleToObject.size(); 234 if (N <= (size_t)handle) { 235 handle_entry e; 236 e.binder = NULL; 237 e.refs = NULL; 238 status_t err = mHandleToObject.insertAt(e, N, handle+1-N); 239 if (err < NO_ERROR) return NULL; 240 } 241 return &mHandleToObject.editItemAt(handle); 242} 复制代码
当Vector中找不到相应信息的时候,便会创建一些新的handle_entry加入其中。但这些新加入的handle_entry内部内容是空的,所以最终会调用上面285行代码,通过BpBinder::create方法创建Binder代理对象在native层的中间形态。
BpBinder::create方法最终新建了一个BpBinder对象,该对象就是Binder代理对象在Native层的中间形态。
/frameworks/native/libs/binder/BpBinder.cpp
109BpBinder* BpBinder::create(int32_t handle) { 110 int32_t trackedUid = -1; 111 if (sCountByUidEnabled) { 112 trackedUid = IPCThreadState::self()->getCallingUid(); 113 AutoMutex _l(sTrackingLock); 114 uint32_t trackedValue = sTrackingMap[trackedUid]; 115 if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) { 116 if (sBinderProxyThrottleCreate) { 117 return nullptr; 118 } 119 } else { 120 if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) { 121 ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)", 122 getuid(), trackedUid, trackedValue); 123 sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK; 124 if (sLimitCallback) sLimitCallback(trackedUid); 125 if (sBinderProxyThrottleCreate) { 126 ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy" 127 " count drops below %d", 128 trackedUid, getuid(), sBinderProxyCountLowWatermark); 129 return nullptr; 130 } 131 } 132 } 133 sTrackingMap[trackedUid]++; 134 } 135 return new BpBinder(handle, trackedUid); 136} 复制代码
得到Native层的BpBinder对象后,会不断向上返回,一直回到JNI层android_os_Parcel_readStrongBinder函数的455行。readStrongBinder返回的是BpBinder对象,而javaObjectForIBinder函数则会根据这个native对象创建出Binder代理对象在Java层的中间形态,这个中间形态就是Java层的BinderProxy对象。
/frameworks/base/core/jni/android_os_Parcel.cpp
451static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr) 452{ 453 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 454 if (parcel != NULL) { 455 return javaObjectForIBinder(env, parcel->readStrongBinder()); 456 } 457 return NULL; 458} 复制代码
首先661行会创建一个Native层的BinderProxyNativeData对象。接着在664行回到Java层,根据BinderProxyNativeData对象的指针创建BinderProxy对象。
/frameworks/base/core/jni/android_util_Binder.cpp
644jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) 645{ 646 if (val == NULL) return NULL; 647 648 if (val->checkSubclass(&gBinderOffsets)) { 649 // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object. 650 jobject object = static_cast<JavaBBinder*>(val.get())->object(); 651 LOGDEATH("objectForBinder %p: it's our own %p!/n", val.get(), object); 652 return object; 653 } 654 655 // For the rest of the function we will hold this lock, to serialize 656 // looking/creation/destruction of Java proxies for native Binder proxies. 657 AutoMutex _l(gProxyLock); 658 659 BinderProxyNativeData* nativeData = gNativeDataCache; 660 if (nativeData == nullptr) { 661 nativeData = new BinderProxyNativeData(); 662 } 663 // gNativeDataCache is now logically empty. 664 jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass, 665 gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get()); 666 if (env->ExceptionCheck()) { 667 // In the exception case, getInstance still took ownership of nativeData. 668 gNativeDataCache = nullptr; 669 return NULL; 670 } 671 BinderProxyNativeData* actualNativeData = getBPNativeData(env, object); 672 if (actualNativeData == nativeData) { 673 // New BinderProxy; we still have exclusive access. 674 nativeData->mOrgue = new DeathRecipientList; 675 nativeData->mObject = val; 676 gNativeDataCache = nullptr; 677 ++gNumProxies; 678 if (gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL) { 679 ALOGW("Unexpectedly many live BinderProxies: %d/n", gNumProxies); 680 gProxiesWarned = gNumProxies; 681 } 682 } else { 683 // nativeData wasn't used. Reuse it the next time. 684 gNativeDataCache = nativeData; 685 } 686 687 return object; 688} 复制代码
/frameworks/base/core/jni/android_util_Binder.cpp
619struct BinderProxyNativeData { 620 // Both fields are constant and not null once javaObjectForIBinder returns this as 621 // part of a BinderProxy. 622 623 // The native IBinder proxied by this BinderProxy. 624 sp<IBinder> mObject; 625 626 // Death recipients for mObject. Reference counted only because DeathRecipients 627 // hold a weak reference that can be temporarily promoted. 628 sp<DeathRecipientList> mOrgue; // Death recipients for mObject. 629}; 复制代码
/frameworks/base/core/java/android/os/Binder.java
1060 private static BinderProxy getInstance(long nativeData, long iBinder) { 1061 BinderProxy result; 1062 try { 1063 result = sProxyMap.get(iBinder); 1064 if (result != null) { 1065 return result; 1066 } 1067 result = new BinderProxy(nativeData); 1068 } catch (Throwable e) { 1069 // We're throwing an exception (probably OOME); don't drop nativeData. 1070 NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer, 1071 nativeData); 1072 throw e; 1073 } 1074 NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData); 1075 // The registry now owns nativeData, even if registration threw an exception. 1076 sProxyMap.set(iBinder, result); 1077 return result; 1078 } 复制代码
至此,Binder代理对象所有的中间形态都已经创建完毕。它们是内核空间的binder_ref对象,Native空间的BpBinder对象、BinderProxyNativeData对象,以及Java层的BinderProxy对象。它们之间的关系如下图所示。
接下来就是Binder代理对象真正出场的时候。
回到AIDL文件生成的Java方法中,此时第5行的data.readStrongBinder返回BinderProxy对象。通过调用asInterface方法,我们将得到真正的Binder代理对象。
IActivityManager.java (编译过程中,根据AIDL文件生成)
1 case TRANSACTION_bindService: 2 { 3 data.enforceInterface(descriptor); 4 android.app.IApplicationThread _arg0; 5 _arg0 = android.app.IApplicationThread.Stub.asInterface(data.readStrongBinder()); 复制代码
IActivityManager.java (编译过程中,根据AIDL文件生成)
1 public static android.app.IApplicationThread asInterface(android.os.IBinder obj) 2 { 3 if ((obj==null)) { 4 return null; 5 } 6 android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); 7 if (((iin!=null)&&(iin instanceof android.app.IApplicationThread))) { 8 return ((android.app.IApplicationThread)iin); 9 } 10 return new android.app.IApplicationThread.Stub.Proxy(obj); 11 } 复制代码
对于BinderProxy对象而言,它的queryLocalInterface方法返回为null,所以第7行的判断将会失败。因此asInterface最后会返回一个新的IApplicationThread.Stub.Proxy对象。这个新创建的对象继承了IApplicationThread接口,它就是最终的Binder代理对象,并通过mRemote持有BinderProxy对象的引用。
/frameworks/base/core/java/android/os/Binder.java
1103 public IInterface queryLocalInterface(String descriptor) { 1104 return null; 1105 } 复制代码
IActivityManager.java (编译过程中,根据AIDL文件生成)
1 private static class Proxy implements android.app.IApplicationThread 2 { 3 private android.os.IBinder mRemote; 4 Proxy(android.os.IBinder remote) 5 { 6 mRemote = remote; 7 } 复制代码
如此一来,Binder代理对象及其中间形态的关系便如下所示。
获取Binder代理对象有两种方式,除了通过ServiceManager获取外,还可以通过已有的 Binder通信管道将本端的实体对象发送到对端。二者看似不同,但其实第一种方式只是第二种方式的封装,它们本质都是通过已有的Binder通信通道将flat_binder_object发送到对端。
为了能够让对端进程获取到本进程Binder实体对象的代理对象,首先需要在本进程中创建它。创建完之后,便可以通过已有的Binder通信通道将它发送到对端进程。下图展示了这中间所有对象的创建时序和关系。
这是Binder代理机制的上篇,主要讲述了Binder代理对象的创建过程以及各个中间形态的创建时序和关系。下篇将会详细阐述如何通过Binder代理对象调用Binder实体对象的方法,敬请期待。
原文链接: banshan.tech/Binder世界中的代…