Binder世界中的代理机制(上)

本文分析基于Android P(9.0) 源码java

Binder是Android中RPC(Remote Procedure Call)的主要实现机制,它在Android中随处可见,是基石通常的存在。了解Binder的朋友可能都听过代理(Proxy)、引用(Ref)之类的名词,然而关于它们的细节可能未必清楚。node

以前在学习Binder的时候,参考过不少书籍和博客。几乎全部文章在谈到如何获取Binder代理对象时,都认为首先须要将service对象注册到ServiceManager中去,以后再由Client进程从ServiceManager中获取它的代理对象。这种说法并无错,但却不够深刻。android

  1. ServiceManager中存储的也是service对象的代理对象,那么(一个service对象的)第一个代理对象究竟是如何生成的呢?
  2. 获取Binder代理对象有两种方式,除了经过ServiceManager获取外,还能够经过已有的 Binder通讯管道将本端的实体对象(或代理对象)发送到对端,使对端获取到Binder代理对象。
  3. 经过调用一个Binder代理对象的方法,为什么能够将数据发送到对端的实体对象?这中间涉及代理对象到实体对象的路由过程(“路由”用在这里,表示如何从Binder代理对象出发,找到其对应的Binder实体对象),须要详述。【见Binder世界中的代理机制(下)】

我认为以上这些才是理解“代理”二字的关键。而ServiceManager只是一种集中管理的方式,它经过字符串和Binder代理对象的键值对来记录整个系统中的service,相似于咱们上网时的DNS服务器。但本质上说它和“代理”二字并无必然的关联。c++

因此本文但愿经过一个新的视角,将Binder世界中的代理过程和盘托出。服务器

咱们假设在最初始的状态,进程和进程之间是没法通讯的。这时为了解决通讯问题,出现了Binder机制。但是Binder机制有一个前提,就是若是想要和对端进程通讯,必需要先拿到对端进程中Binder实体对象的代理对象。但是这个代理对象要怎么得到呢?是向ServiceManager获取么?注意,向ServiceManager获取也是一个跨进程通讯过程。因此为了跨进程通讯,咱们须要获取一个Binder代理对象,但是为了获取Binder代理对象,咱们又须要跨进程通讯。这个过程彷佛陷入一个“死锁”。cookie

为了解决这个问题,Android在设计整套机制时预先加入了一个先验知识:ServiceManager的代理对象在每个进程中的handle值都为0。所以,任何进程和ServiceManager进程的通讯便再也不须要事先获取它的代理对象,而只须要告诉Binder Driver:我须要和handle值为0的进程通讯。Binder Driver便会自动将该进程的通讯请求转发到ServiceManager进程。这样上面所说的“死锁”便被打破了,下面接着讨论Binder代理对象如何得到。session

当一个进程A须要往ServiceManager中注册service时,本质上是将A进程中建立的service对象(Binder实体对象)做为addService的参数发送到ServiceManager进程(在此次Binder通讯中,传输的数据含有Binder实体对象)。这个Binder实体对象做为参数,会经历writeStrongParcel和readStrongParcel的打包和解包过程。一般,一个普通数据的打包解包主要就是序列化和反序列化的过程,而Binder实体对象除了这些常规操做外,还会在打包过程当中建立Binder实体对象的Native层中间形态,在解包过程当中建立Binder代理对象的Java层/Native层中间形态。另外,在Binder Driver所控制的传输过程当中也会建立Binder实体对象和代理对象的Kernel层中间形态。这样一来,ServiceManager在接收到Binder实体对象时,它实际上已经变成了Binder代理对象的Java层中间形态:BinderProxy对象。app

事实上,这个Binder实体对象通过Binder通讯传输转化为Binder代理对象的过程不只能够普通进程和ServiceManager进程之间,也一样能够发生在两个普通进程之间。除此以外,Binder通讯过程当中不只能够完成实体对象到代理对象的转换,也能够完成一个代理对象到另外一个代理对象的转换。异步

下面咱们具体阐述两个普通进程间Binder实体对象转换为Binder代理对象的过程。为了方便分析,咱们选定ApplicationThread类做为研究对象。ide

老子说:“一辈子二,二生三,三生万物”。那么在Binder的世界中,“一”到底来自何方?

1. Binder实体对象的出现和意义

1.1 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 {
复制代码

1.2 Binder实体对象的建立过程

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层拥有以下所示的继承和实现关系。

ApplicationThread类的继承关系

IBinder接口中声明的都是与跨进程通讯相关的方法,而IApplicationThread接口中声明的都是ApplicationThread中应该实现的方法(表示ApplicationThread这个类所具有的能力)。因为ApplicationThread最终继承于Binder,因此它兼具了跨进程通讯的能力。

若是ApplicationThread是一个正常的本地类(不须要进行跨进程通讯),那么它只须要实现IApplicationThread接口便可,以下图所示。如今之因此继承关系变得复杂,就是为了支持跨进程通讯。

若是ApplicationThread是一个本地类

上文中提到,对于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尚未感知到它的存在。

1.3 Binder实体对象如何让驱动感知到它的存在?

接下来是关键的一步,不管是向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层的中间形态

至此,Binder实体对象及其有关的两个Native层对象均已建立完成,它们分别是Jave层的ApplicationThread对象、Native层的JavaBBinderHolder对象以及Native层的JavaBBinder对象。JavaBBinder对象的mObject字段记录了ApplicationThread对象的信息,因此一旦找到JavaBBinder对象,即可以经过其mObject字段调用其Java对象的方法。下图展现了三个对象之间的关系。

Binder实体对象和Native层中间形态的关系

接下来再回到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代理对象是如何被建立的。

2. Binder代理对象的建立过程

所谓Binder代理对象,就是一次RPC发起时,应用开发者所可以知道的惟一入口。譬如经过IApplicationThread.bindApplication方法来发起一次RPC时,那么IApplicationThread对象就是Binder代理对象。

2.1 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中被唤醒过来。

2.2 Binder代理对象在Native层的中间形态

对端进程接收到数据后,会一层层往上传,最终交由上层处理。这里假设最终的处理方法以下:

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}
复制代码

2.3 Binder代理对象在Java层的中间形态

获得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代理对象中间形态之间的关系

2.4 Binder代理对象的出现

接下来就是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代理对象和全部中间形态的关系

3 总结

获取Binder代理对象有两种方式,除了经过ServiceManager获取外,还能够经过已有的 Binder通讯管道将本端的实体对象发送到对端。两者看似不一样,但其实第一种方式只是第二种方式的封装,它们本质都是经过已有的Binder通讯通道将flat_binder_object发送到对端。

为了可以让对端进程获取到本进程Binder实体对象的代理对象,首先须要在本进程中建立它。建立完以后,即可以经过已有的Binder通讯通道将它发送到对端进程。下图展现了这中间全部对象的建立时序和关系。

Binder全部对象建立时序

这是Binder代理机制的上篇,主要讲述了Binder代理对象的建立过程以及各个中间形态的建立时序和关系。下篇将会详细阐述如何经过Binder代理对象调用Binder实体对象的方法,敬请期待。

原文连接:banshan.tech/Binder世界中的代…

相关文章
相关标签/搜索