IPC機(jī)制(六)——Binder原理分析(二)

Binder整體架構(gòu)

image

之前的文章從binder驅(qū)動(dòng)層赢乓,到最終要的ServiceManager靖避,分析了ServiceManager的啟動(dòng)攀芯,開(kāi)啟一個(gè)服務(wù)進(jìn)行binder通信如何獲取到ServiceManager,以及注冊(cè)服務(wù)和獲取服務(wù)。整個(gè)流程下來(lái)解孙,對(duì)binder通信的理解是更深了一層萎馅。不只是覺(jué)得它浮于表面了双戳。

上面的binder整體架構(gòu)圖出自一位大神之手。從圖中可以看到binder在framework層糜芳,采用JNI技術(shù)來(lái)調(diào)用native(c/c++)層的binder架構(gòu)飒货,從而為上層應(yīng)用程序提供服務(wù)。native層也是分為C/S架構(gòu)峭竣,分為Bn(server)端和Bp(client)端塘辅,同樣實(shí)現(xiàn)了一套IPC通信架構(gòu)。

圖解:

  • 圖中紅色代表整個(gè)framework層binder架構(gòu)相關(guān)組件
    • Binder類(lèi)代表Server端皆撩,BinderProxy類(lèi)代表Client端
  • 圖中藍(lán)色代表Native層Binder架構(gòu)相關(guān)組件
  • 上層framework層的Binder邏輯是建立在Native層架構(gòu)基礎(chǔ)之上的扣墩,核心邏輯都是交予Native層方法來(lái)處理的。
  • framework層的ServiceManager類(lèi)與Native層的功能并不完全對(duì)應(yīng)扛吞,framework層的ServiceManager類(lèi)的實(shí)現(xiàn)最終是通過(guò)BinderProxy傳遞給Native層來(lái)完成的呻惕。

Binder類(lèi)圖

image

這張圖出自gityuan之手,他把framework層和Binder相關(guān)的類(lèi)之間的關(guān)系都表示很清楚滥比,主要就是Binder和ServiceManager亚脆,主要就是要去搞清楚上層和底層的Binder是如何交互的。先看看這幾個(gè)類(lèi)分別在干什么盲泛。

  1. ServiceManager:通過(guò)getIServiceManager方法獲取的是ServiceManagerProxy對(duì)象;ServiceManager的addService濒持,getService實(shí)際工作都由ServiceManagerProxy的相應(yīng)方法來(lái)處理;
  2. ServiceManagerProxy: 其成員變量mRemote指向BinderProxy對(duì)象查乒,ServiceManagerProxy的addService弥喉,getService方法最終是交由mRomate來(lái)完成郁竟;
  3. ServiceManagerNative:其方法asInterface()返回的是ServiceManagerProxy對(duì)象玛迄,ServiceManager便是借助ServiceManagerNative類(lèi)來(lái)找到ServiceManagerProxy;
  4. Binder:其成員變量mObject和方法execTransact()用于native方法
  5. BinderInternal:內(nèi)部有一個(gè)GcWatcher類(lèi),用于處理和調(diào)試與Binder相關(guān)的垃圾回收
  6. IBinder:接口常量FLAG_ONEWAY:客戶(hù)端利用Binder跟服務(wù)端通信是阻塞式的棚亩,但如果設(shè)置了FLAG_ONEWAY,這成為非阻塞式的調(diào)用方式蓖议,客戶(hù)端能立即返回虏杰,服務(wù)端采用回調(diào)方式來(lái)通知客戶(hù)端完成情況。另外IBinder接口有一個(gè)內(nèi)部接口DeathDecipient(死亡通告)

根據(jù)這幾個(gè)類(lèi)的作用在去源碼中看看勒虾,整個(gè)Binder從Kernel至Native,JNI,Framework層到底是怎么串到一起的纺阔。

初始化

在Android系統(tǒng)開(kāi)機(jī)過(guò)程中,Zygote啟動(dòng)時(shí)會(huì)有一個(gè)虛擬機(jī)注冊(cè)過(guò)程修然,該過(guò)程調(diào)用AndroidRunntime::startReg方法來(lái)完成jni方法的注冊(cè)

startReg

int AndroidRuntime::startReg(JNIEnv* env)
{
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    env->PushLocalFrame(200);

    //注冊(cè)jni方法
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    return 0;
}

注冊(cè)jni方法笛钝,其中g(shù)RegJNI是一個(gè)數(shù)組,記錄所有需要注冊(cè)的jni方法愕宋,其中有一項(xiàng)就是REG_JNI(register_android_os_Binder)玻靡。

register_android_os_Binder

int register_android_os_Binder(JNIEnv* env) {
    // 注冊(cè)Binder類(lèi)的jni方法
    if (int_register_android_os_Binder(env) < 0)
        return -1;

    // 注冊(cè)BinderInternal類(lèi)的jni方法
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;

    // 注冊(cè)BinderProxy類(lèi)的jni方法
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;
    ...
    return 0;
}

注冊(cè)Binder

static int int_register_android_os_Binder(JNIEnv* env) {
    //其中kBinderPathName = "android/os/Binder";查找kBinderPathName路徑所屬類(lèi)
    jclass clazz = FindClassOrDie(env, kBinderPathName);

    //將Java層Binder類(lèi)保存到mClass變量;
    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    //將Java層execTransact()方法保存到mExecTransact變量中贝;
    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
    //將Java層mObject屬性保存到mObject變量
    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

    //注冊(cè)JNI方法
    return RegisterMethodsOrDie(env, kBinderPathName, gBinderMethods,
        NELEM(gBinderMethods));
}

注冊(cè)Binder的方法中一直在和java層的Binder打交道囤捻。把有關(guān)Binder的重要變量都保存到了gBinderOffsets中。主要有三步:

  1. mClass:保存java層的Binder類(lèi)
  2. mExecTransact:保存execTransact()方法
  3. mObject:保存mObject屬性

gBinderOffsets

gBinderOffsets是全局靜態(tài)結(jié)構(gòu)體邻寿,定義如下:

static struct bindernative_offsets_t
{
    jclass mClass; //記錄Binder類(lèi)
    jmethodID mExecTransact; //記錄execTransact()方法
    jfieldID mObject; //記錄mObject屬性

} gBinderOffsets;

gBinderOffsets保存了Binder.java類(lèi)本身以及成員方法execTransact()和成員屬性mObject蝎土,這為JNI層訪問(wèn)java層提供通道。另外是通過(guò)查詢(xún)獲取java層Binder信息后保存到gBidnerOffsets不需要每次查找binder類(lèi)信息的方式大幅度提高效率绣否。解決了每次查詢(xún)需要花費(fèi)較多cpu事件誊涯,用結(jié)構(gòu)體保存也是一種空間換時(shí)間的方法。

去看看Binder.java中的這三個(gè)重要的豎向和方法:

//指向JavaBBinderHolder對(duì)象的原始本機(jī)指針蒜撮。由此java對(duì)象擁有醋拧,不為空。
private final long mObject;

//mObject出現(xiàn)在Binder中
public Binder() {
    mObject = getNativeBBinderHolder();//調(diào)用native層的方法
    ····
}

可以看出在execTransact方法中調(diào)用了onTransact方法向Binder線程池發(fā)送Parcel數(shù)據(jù)
//android_util_Binder.cpp的onTransact的入口
private boolean execTransact(int code, long dataObj, long replyObj,
            int flags) {
        BinderCallsStats binderCallsStats = BinderCallsStats.getInstance();
        BinderCallsStats.CallSession callSession = binderCallsStats.callStarted(this, code);
        Parcel data = Parcel.obtain(dataObj);
        Parcel reply = Parcel.obtain(replyObj);
      
        boolean res;
       
        final boolean tracingEnabled = Binder.isTracingEnabled();
        try {
            if (tracingEnabled) {
                Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
            }
            res = onTransact(code, data, reply, flags);
        } catch (RemoteException|RuntimeException e) {
            if (LOG_RUNTIME_EXCEPTION) {
                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
            }
            if ((flags & FLAG_ONEWAY) != 0) {
                if (e instanceof RemoteException) {
                    Log.w(TAG, "Binder call failed.", e);
                } else {
                    Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
                }
            } else {
                reply.setDataPosition(0);
                reply.writeException(e);
            }
            res = true;
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
        reply.recycle();
        data.recycle();

        StrictMode.clearGatheredViolations();
        binderCallsStats.callEnded(callSession);

        return res;
    }

//Binder實(shí)現(xiàn)了IBinder淀弹,Binder是遠(yuǎn)程對(duì)象的基類(lèi)丹壕,我們一般在aidl文件中繼承Binder實(shí)現(xiàn)了自定義的RPC協(xié)議。Binder類(lèi)只是一個(gè)基本的IPC原語(yǔ)薇溃,它對(duì)應(yīng)用程序的生命周期并且在創(chuàng)建它的進(jìn)程中運(yùn)行才有效菌赖。
public class Binder implements IBinder     

gBinderMethods

static const JNINativeMethod gBinderMethods[] = {
     /* 名稱(chēng), 簽名, 函數(shù)指針 */
    { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
    { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
    { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
    { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
    { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
    { "init", "()V", (void*)android_os_Binder_init },
    { "destroy", "()V", (void*)android_os_Binder_destroy },
    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};

RegisterMethodsOrDie()中為gBinderMethods數(shù)組中的方法建立了一一映射關(guān)系,從而為java層訪問(wèn)JNI層提供通道沐序。

int_register_android_os_Binder方法的主要功能:

  • 通過(guò)gBinderOffsets,保存java層Binder類(lèi)的信息琉用,為JNI層訪問(wèn)java層提供通道
  • 通過(guò)RegisterMethodsOrDie,將gBinderMethods數(shù)組完成映射關(guān)系,從而為java層訪問(wèn)jni層提供通道策幼。

也就是說(shuō)該過(guò)程建立了Binder類(lèi)在Native層與framework層之間相互調(diào)用的橋梁邑时。

注冊(cè)BinderInternal

static int int_register_android_os_BinderInternal(JNIEnv* env) {
    //其中kBinderInternalPathName = "com/android/internal/os/BinderInternal"
    jclass clazz = FindClassOrDie(env, kBinderInternalPathName);

    gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");

    return RegisterMethodsOrDie(
        env, kBinderInternalPathName,
        gBinderInternalMethods, NELEM(gBinderInternalMethods));
}

注冊(cè)了BinderInternal類(lèi)的jni方法,gBinderInternalOffsets保存了BinderInternal的forceBinderGC()方法特姐。

下面是BinderInternal類(lèi)的jni方法注冊(cè):

static const JNINativeMethod gBinderInternalMethods[] = {
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
};

和注冊(cè)Binder非常類(lèi)似晶丘,該過(guò)程建立了BinderInternal類(lèi)在Native層與framework層之間的相互調(diào)用的橋梁。

注冊(cè)BinderProxy

static int int_register_android_os_BinderProxy(JNIEnv* env) {
    //gErrorOffsets保存了Error類(lèi)信息
    jclass clazz = FindClassOrDie(env, "java/lang/Error");
    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

    //gBinderProxyOffsets保存了BinderProxy類(lèi)的信息
    //其中kBinderProxyPathName = "android/os/BinderProxy"
    clazz = FindClassOrDie(env, kBinderProxyPathName);
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
    gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
    gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
    gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
    gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");

    //gClassOffsets保存了Class.getName()方法
    clazz = FindClassOrDie(env, "java/lang/Class");
    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");

    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

注冊(cè)BinderProxy類(lèi)的jni方法,gBinderProxyOffsets保存了BinderProxy的構(gòu)造方法浅浮,sendDeathNotice(),mObject,mSelf,mOrgue信息沫浆。

BinderProxy類(lèi)在Binder類(lèi)中,是本地IBinder對(duì)象的java代理滚秩,由本地javaObjectforIBinder函數(shù)分配構(gòu)造专执。BinderProxy類(lèi)中還有一個(gè)靜態(tài)不可變的內(nèi)部類(lèi)ProxyMap,將BinderProxy作為弱引用對(duì)象放入ArrayList集合。

這里也是建立了BinderProxy類(lèi)在Native層與framework層之間相互調(diào)用的橋梁郁油。

注冊(cè)服務(wù)

SM.addService

public static void addService(String name, IBinder service, boolean allowIsolated) {
    try {
        //先獲取SMP對(duì)象本股,則執(zhí)行注冊(cè)服務(wù)操作
        getIServiceManager().addService(name, service, allowIsolated);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

getIServiceManager

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }
    
    //這里調(diào)用了ServiceManagerNative獲取sServiceManager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

采用單例模式獲取ServiceManager getIServiceManager()返回的是ServiceManagerProxy對(duì)象

getContextObject

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

BinderInternal.java中有一個(gè)native方法getContextObject(),JNI調(diào)用執(zhí)行上述方法。

這里有個(gè)熟悉的ProcessState::self()->getContextObject()在分析獲取ServiceManager的時(shí)候調(diào)用過(guò)桐腌,就相當(dāng)于是new BpBinder(0)

javaObjectForIBinder

object javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
    if (val == NULL) return NULL;

    if (val->checkSubclass(&gBinderOffsets)) { //返回false
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        return object;
    }

    AutoMutex _l(mProxyLock);

    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) { //第一次object為null
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            return res;
        }
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

    //創(chuàng)建BinderProxy對(duì)象
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        //BinderProxy.mObject成員變量記錄BpBinder對(duì)象
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);

        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        //將BinderProxy對(duì)象信息附加到BpBinder的成員變量mObjects中
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

        sp<DeathRecipientList> drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        //BinderProxy.mOrgue成員變量記錄死亡通知對(duì)象
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

        android_atomic_inc(&gNumProxyRefs);
        incRefsCreated(env);
    }
    return object;
}

這個(gè)方法中出現(xiàn)了重要的BinderPrody對(duì)象痊末。根據(jù)BpBinder(c++)生成BinderProxy(java)對(duì)象,并把BpBinder對(duì)象地址保存到BinderProxy.mObject成員變量哩掺≡涞可以知道:

ServiceManagerNative.asInterface(BinderInternal.getContextObject())

等價(jià)于

ServiceManagerNative.asInterface(new BinderProxy());

SMN.asInterface

 static public IServiceManager asInterface(IBinder obj)
{
    if (obj == null) { //obj為BpBinder
        return null;
    }
    //由于obj為BpBinder,該方法默認(rèn)返回null
    IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    return new ServiceManagerProxy(obj);
}

這里可以知道ServiceManagerNative.asInterface(new BinderProxy())等價(jià)于ServiceManagerProxy(new BinderProxy)

ServiceManagerProxy初始化

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
}

mRemote為BinderProxy對(duì)象嚼吞,該BinderProxy對(duì)象對(duì)應(yīng)于BpBinder(0),其作為Binder代理端盒件,指向Native層大管家SerivceManager。

可以說(shuō)ServiceManager.getIServiceManager == new ServiceManagerProxy(new BinderProxy()),也就意味著getIServiceManager.addService == ServiceManagerProxy.addService()

總結(jié)

  1. framework層的ServiceManager的調(diào)用實(shí)際上是交給了ServiceManagerProxy的成員變量BinderProxy舱禽;
  2. BinderProxy通過(guò)jni方式炒刁,最終會(huì)調(diào)用BpBinder對(duì)象。

說(shuō)明上層binder架構(gòu)的核心功能依賴(lài)native架構(gòu)誊稚。

SMP.addService

public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    
    data.writeStrongBinder(service);
    data.writeInt(allowIsolated ? 1 : 0);
    //mRemote為BinderProxy
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

這段代碼有一種很熟悉的感覺(jué)翔始,在寫(xiě)aidl的文件中Proxy代理類(lèi)中就這樣包裝數(shù)據(jù),并調(diào)用transact()方法發(fā)送數(shù)據(jù)里伯。

writeStrongBinder

public writeStrongBinder(IBinder val){
    //此處為Native調(diào)用
    nativewriteStrongBinder(mNativePtr, val);
}

android_os_Parcel_writeStrongBinder

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) {
    //將java層Parcel轉(zhuǎn)換為native層Parcel
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

ibinderForJavaObject

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;

    //Java層的Binder對(duì)象
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    //Java層的BinderProxy對(duì)象
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
    return NULL;
}

根據(jù)Binder(java)生成JavaBBinderHolder(C++)對(duì)象城瞎。主要工作是創(chuàng)建JavaBBinderHolder對(duì)象,并把JavaBBinderHolder對(duì)象地址保存到Binder.mObject成員變量疾瓮。

JavaBBinderHolder.get()

sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
    AutoMutex _l(mLock);
    sp<JavaBBinder> b = mBinder.promote();
    if (b == NULL) {
        //首次進(jìn)來(lái)脖镀,創(chuàng)建JavaBBinder對(duì)象
        b = new JavaBBinder(env, obj);
        mBinder = b;
    }
    return b;
}

JavaBBinderHolder有一個(gè)成員變量mBinder,保存當(dāng)前創(chuàng)建的JavaBBinder對(duì)象,這是一個(gè)弱引用類(lèi)型的狼电,可能會(huì)被垃圾回收器給回收蜒灰,所以每次使用前都需要判斷是否存在。

JavaBBinder初始化

JavaBBinder(JNIEnv* env, jobject object)
    : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
    android_atomic_inc(&gNumLocalRefs);
    incRefsCreated(env);
}

創(chuàng)建JavaBBinder,該對(duì)象繼承于BBinder對(duì)象肩碟。

data.writeStrongBinder(service)等價(jià)于parcel->writeStrongBinder(new JavaBinder(env,obj));

writeStrongBinder(C++)

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

flatten_binder

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;

    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE; //遠(yuǎn)程Binder
            obj.binder = 0;
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            obj.type = BINDER_TYPE_BINDER; //本地Binder强窖,進(jìn)入該分支
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;  //本地Binder
        obj.binder = 0;
        obj.cookie = 0;
    }
    
    return finish_flatten_binder(binder, obj, out);
}

將Binder對(duì)象扁平化,轉(zhuǎn)成flat_binder_object對(duì)象削祈。

  • 對(duì)于Binder實(shí)體翅溺,則cookie記錄Binder實(shí)體指針;
  • 對(duì)于Binder代理,則用handle記錄Binder代理的句柄未巫。

BinderProxy.transact

回到mRemote.transact方法

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    //用于檢測(cè)Parcel大小是否大于800k
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
    return transactNative(code, data, reply, flags);
}

mRemote是BinderProxy窿撬。transactNative經(jīng)過(guò)jni調(diào)用启昧,進(jìn)入下面的方法

android_os_BinderProxy_transact

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
    jint code, jobject dataObj, jobject replyObj, jint flags)
{
    ...
    //java Parcel轉(zhuǎn)為native Parcel
    Parcel* data = parcelForJavaObject(env, dataObj);
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ...

    //gBinderProxyOffsets.mObject中保存的是new BpBinder(0)對(duì)象
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ...

    //此處便是BpBinder::transact(), 經(jīng)過(guò)native層叙凡,進(jìn)入Binder驅(qū)動(dòng)程序
    status_t err = target->transact(code, *data, reply, flags);
    ...
    return JNI_FALSE;
}

java層的BinderProxy.transact()最終交由Native層的BpBinder::transact()完成。

小結(jié)

addService核心過(guò)程:

public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
    ...
    Parcel data = Parcel.obtain(); //此處還需要將java層的Parcel轉(zhuǎn)為Native層的Parcel
    data->writeStrongBinder(new JavaBBinder(env, obj));
    BpBinder::transact(ADD_SERVICE_TRANSACTION, *data, reply, 0); //與Binder驅(qū)動(dòng)交互
    ...
}

注冊(cè)服務(wù)過(guò)程就是通過(guò)BpBinder來(lái)發(fā)送ADD_SERVICE_TRANSACTION命令密末,與實(shí)現(xiàn)與binder驅(qū)動(dòng)進(jìn)行數(shù)據(jù)交互握爷。

參考資料

Binder系列7——framework層分析

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市严里,隨后出現(xiàn)的幾起案子新啼,更是在濱河造成了極大的恐慌,老刑警劉巖刹碾,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燥撞,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡迷帜,警方通過(guò)查閱死者的電腦和手機(jī)物舒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)戏锹,“玉大人冠胯,你說(shuō)我怎么就攤上這事〗跽耄” “怎么了荠察?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)奈搜。 經(jīng)常有香客問(wèn)我悉盆,道長(zhǎng),這世上最難降的妖魔是什么馋吗? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任舀瓢,我火速辦了婚禮,結(jié)果婚禮上耗美,老公的妹妹穿的比我還像新娘京髓。我一直安慰自己,他們只是感情好商架,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布堰怨。 她就那樣靜靜地躺著,像睡著了一般蛇摸。 火紅的嫁衣襯著肌膚如雪备图。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音揽涮,去河邊找鬼抠藕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蒋困,可吹牛的內(nèi)容都是我干的盾似。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼雪标,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼零院!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起村刨,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤告抄,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后嵌牺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體打洼,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年逆粹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了募疮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡枯饿,死狀恐怖酝锅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情奢方,我是刑警寧澤搔扁,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站蟋字,受9級(jí)特大地震影響稿蹲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹊奖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一苛聘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忠聚,春花似錦设哗、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至赂毯,卻和暖如春战虏,著一層夾襖步出監(jiān)牢的瞬間拣宰,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工烦感, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留巡社,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓手趣,卻偏偏與公主長(zhǎng)得像晌该,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子回懦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容