(3) Android中Binder調用流程 --- 相關類介紹

       在具體講解Binder調用流程之前,有必要先把調用流程中和數據相關的類介紹下,通過前面兩節介紹,我們知道Binder對象分爲本地和遠程,在遠程調用進行數據系列化時對這兩種對象處理也是有區別的,下面是Binder調用流程中和數據直接相關的類。

       JAVA端

       BinderProxy:遠程服務在本地的代理;

       Binder:實現IBinder接口,實體Service具體實現一般繼承這個類,表示具體業務邏輯實現;

       Parcel:android的數據系列化類,直接在內存中操作,在JAVA端其只是個容器,真正實現在本地端;

       對應本地端

       BpBinder:遠程服務代理對象,每個服務都會經過Binder驅動生成對應的handle一一對應;

       BBinder:據圖服務的實現,其功能之一返回本地IBinder對象,這個對象相關信息會直接傳給Binder驅動;

       Parcel:android數據系列化和反系列化本地管理類;

       在分析這些類之前,我們先看下本地IBinder對本地對象和遠程對象的接口支持的定義。

       frameworks/native/include/binder/IBinder.h

50class IBinder : public virtual RefBase
......
161    virtual BBinder*        localBinder();   // (1)
162    virtual BpBinder*       remoteBinder(); // (2)
163
164protected:
165    virtual          ~IBinder();
166
167private:
168};

       (1)返回的是一個本地IBinder對象,什麼叫本地對象?就是調用的進程就是實現這個IBinder的宿主進程,IBinder實體類就存儲在此進程中。

       (2)返回的是一個遠程代理對象,就是調用進程和IBinder實體不在同一個進程,其和遠程IBinder實體對象是通過對象的handle進行關聯的。

       下面一一分析這些類的具體實現細節,這裏我們只會講和Binder調用流程相關,其它讀者自行查看源碼。

BinderProxy

文件:frameworks/base/core/java/android/os/Binder.java

       查看BinderProxy的源碼:

733final class BinderProxy implements IBinder {
......
744    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
.....
763        try {
764            return transactNative(code, data, reply, flags);
765        } finally {
766            if (tracingEnabled) {
767                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
768            }
769        }
770    }

       上面我們只留下關鍵代碼,首先BinderProxy是從IBinder繼承過來,所有其具有Binder通行的基礎,在其具體實現方法transact裏,我們發現其實際調用的是transactNative方法,這是一個本地方法,定義如下:

public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;

       這是一個JNI方法,其實現在如下文件中:

      frameworks/base/core/jni/android_util_Binder.cpp

       在這個文件我們發現定義了BinderProxy的本地方法映射:

static const JNINativeMethod gBinderProxyMethods[] = {
1305     /* name, signature, funcPtr */
1306    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
1307    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1308    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1309    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1310    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1311    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1312    {"destroy",             "()V", (void*)android_os_BinderProxy_destroy},
1313};

       transactNative方法在本地對應的實現是android_os_BinderProxy_transact,下面看看這個方法具體做了些什麼:

1141static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1142        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
1143{
......
1149    Parcel* data = parcelForJavaObject(env, dataObj);  // (1)
......
1153    Parcel* reply = parcelForJavaObject(env, replyObj); // (2)
......
1158    IBinder* target = (IBinder*)
1159        env->GetLongField(obj, gBinderProxyOffsets.mObject); // (3)
......
1182    status_t err = target->transact(code, *data, reply, flags);
1183    ......
1198    return JNI_FALSE;
1199}

       其中(1)和(2)後面講Parcel會說,我們來看看(3),這裏從BinderProxy直接取出其成員變量mObject的值,它就是一個本地IBinder類型的對象,那麼這個本地對象是怎麼設置給JAVA層的BinderProxy的呢?從這裏我們可以大致推斷這個JAVA層的BinderProxy對象有可能是在native層創建的。

       從上面代碼發現這裏有個結構gBinderProxyOffsets,其定義如下:

96static struct binderproxy_offsets_t
97{
98    // Class state.
99    jclass mClass;
100    jmethodID mConstructor;
101    jmethodID mSendDeathNotice;
102
103    // Object state.
104    jfieldID mObject;
105    jfieldID mSelf;
106    jfieldID mOrgue;
107
108} gBinderProxyOffsets;

       這個結構其實就是保持了JAVA層BinderProxy類成員變量和成員方法的相關信息,其中的mObject保存了本地對象,我們看看這個mObject在那裏設置進來的,搜索SetLongField(爲什麼要搜索這個方法?)方法,發現和mObject相關代碼如下:

5jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
596{
......
624    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
625    if (object != NULL) {
......
628        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
629        val->incStrong((void*)javaObjectForIBinder);
630

       在方法中javaObjectForIBinder創建了BinderProxy對象,並把參數val設置給了BinderProxy的mObject成員變量,繼續找javaObjectForIBinder在那裏調用:

950static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
951{
952    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
953    return javaObjectForIBinder(env, b);
954}

       這裏有一處調用,原來這個IBinder是ProcessState::self()->getContextObject(NULL);創建的,看下這個方法就知道了:

238sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
239{
......
244    handle_entry* e = lookupHandleLocked(handle);
245
246    if (e != NULL) {
......
279            b = new BpBinder(handle);
280            e->binder = b;
......
292    return result;
293}

       經過層層調用發現,最終會調getStrongProxyForHandle這個方法,原來返回的IBinder是由b = new BpBinder(handle);這句代碼創建的,到這裏我們知道了設置給BinderProxy的mObject成員變量的native對象就是BpBinder,這就對應上了。細心的讀者可能發現,這裏是對本地的BpBinder做了緩存處理的,通過handle來保存。另外,大家也要注意此方法也在Parcel被調用,可見它是獲取遠程服務的本地代理的方法入口。

       接着我們看看本地實際的遠程代理對象的實現。

       frameworks/native/libs/binder/BpBinder.cpp

307BpBinder* BpBinder::remoteBinder()
308{
309    return this;
310}

   看到了吧,其遠程接口 remoteBinder()直接返回BpBinder對象本身,而其本地接口返回的是NULL(IBinder中實現)。

   講完了BinderProxy,接下來看下Binder和本地的BBinder又是怎麼回事?

Binder

文件:frameworks/base/core/java/android/os/Binder.java

       Binder定義如下:

70public class Binder implements IBinder {

       其構造方法如下:

363    public Binder() {
364        init();
......
374    }

       其構造方法裏調用了init,init方法是個本地方法,其定義如下:

678    private native final void init();

       和上面一樣,在native找到其對應的實現,其定義在如下文件中:

       frameworks/base/core/jni/android_util_Binder.cpp

856static void android_os_Binder_init(JNIEnv* env, jobject obj)
857{
858    JavaBBinderHolder* jbh = new JavaBBinderHolder();
......
865    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
866}

       和BinderProxy一樣的套路,我們發現在native其實就是new一個JavaBBinderHolder對象,並把它設置到Binder的mObject成員變量中,這裏就不多說,下面我們看看JavaBBinderHolder實現。

362class JavaBBinderHolder : public RefBase
363{
364public:
365    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
366    {
367        AutoMutex _l(mLock);
368        sp<JavaBBinder> b = mBinder.promote();
369        if (b == NULL) {
370            b = new JavaBBinder(env, obj);  // (1)
371            mBinder = b;
......
384
385private:
386    Mutex           mLock;
387    wp<JavaBBinder> mBinder; // (2)
388};

       最終JavaBBinderHolder 通過其get方法返回JavaBBinder對象,這裏先不管JavaBBinderHolder.get在哪兒被調用,先看看JavaBBinder的定義。

265class JavaBBinder : public BBinder
266{
267public:
268    JavaBBinder(JNIEnv* env, jobject object)
269        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
270    {
271        ALOGV("Creating JavaBBinder %p\n", this);
272        android_atomic_inc(&gNumLocalRefs);
273        incRefsCreated(env);
274    }

       關鍵來了,原來JavaBBinder就是一個BBinder對象,所以和我們一開始說的一樣,從Binder繼承的Service在本地其實是一個BBinder,而且這個JavaBBinder還持有實體IBinder的引用(mObject(env->NewGlobalRef(object))),其把實體IBinder對象保存在mObject中,而這個對象就是JAVA層實現的Service。在Binder驅動把業務邏輯轉到Service宿主進程的時候最終會執行到JavaBBinder的onTransact方法。

295    virtual status_t onTransact(
296        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
297    {
298        JNIEnv* env = javavm_to_jnienv(mVM);
......
308        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
309            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

       從上面代碼我們知道最終會把調用轉到JAVA層實現的Service的execTransact方法,這個execTransact就是JAVA層的Binder對象的一個方法,Service重載這個方法從而完成把邏輯轉到業務層的調度。

       接下來我們看下BBinder的定義。

       在文件frameworks/native/libs/binder/Binder.cpp中找到localBinder的定義。

199BBinder* BBinder::localBinder()
200{
201    return this;
202}

       這裏我們看到了BBinder對本地接口返回是自身對象,遠程接口返回的是NULL(在IBinder中實現),到這裏就明白了爲什麼實現Binder的服務就是一個本地對象。

       最後看下Parcel的實現,這裏JAVA層的Parcel就不講了,因爲都是一個套路,JAVA層的Parcel只是一個容器,實際實現在本地的Parcel類中。

Parcel

frameworks/native/libs/binder/include/binder/Parcel.h

       這裏JAVA層的Parcel接口對應實現在下面文件中。

       frameworks/base/core/jni/android_os_Parcel.cpp

       這裏重點看下nativeReadStrongBinder的實現。

451static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
452{
453    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
454    if (parcel != NULL) {
455        return javaObjectForIBinder(env, parcel->readStrongBinder());  // (1)
456    }
457    return NULL;
458}

       這裏調用javaObjectForIBinder生成JAVA對象,其實就是BinderProxy,在看javaObjectForIBinder方法之前,先看下parcel->readStrongBinder()這個怎麼返回IBinder對象的,經過層層調用最終會進入如下方法:

323status_t unflatten_binder(const sp<ProcessState>& proc,
324    const Parcel& in, wp<IBinder>* out)
325{
326    const flat_binder_object* flat = in.readObject(false);
327
328    if (flat) {
329        switch (flat->type) {
......
342            case BINDER_TYPE_HANDLE:
343            case BINDER_TYPE_WEAK_HANDLE:
344                *out = proc->getWeakProxyForHandle(flat->handle);  // (1)
345                return finish_unflatten_binder(
346                    static_cast<BpBinder*>(out->unsafe_get()), *flat, in);
347        }
348    }
349    return BAD_TYPE;
350}

       這裏有個flat_binder_object結構,我們簡單說下,這個結構其實就是IBinder對象在Binder驅動層的二進制描述,存儲了IBinder的相關信息。我們重點看下代碼(1)出的邏輯,這裏最終調用還是ProcessSate的getWeakProxyForHandle方法,這個方法上面介紹過,其實就是返回BpBinder對象,而且根據handle做了緩存處理。

       這樣我們知道javaObjectForIBinder的第二個參數其實就是BpBinder類型的IBinder對象,這個方法上面也介紹過了,就是生成BinderProxy對象,然後把BpBinder類型的IBinder設置給BinderProxy的成員變量mObject。

       到這裏我們把和Binder調用流程相關的幾個關鍵類介紹完了,有了這個基礎,後面講解Binder的調用流程就會輕鬆多了。

       本系列文章均爲原創,主要總結作者多年在軟件行業的一些經驗,和大家共同學習、進步,轉載請註明出處,謝謝!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章