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世界中的代…

相關文章
相關標籤/搜索