binder-JAVA層機制

根據以前分析過的cpp代碼,以及編寫了JAVA層的代碼,筆者畫了一個圖進行了分層java

JAVA中,RPC層的代碼是直接經過aidl文件生成的,cpp部分是須要咱們本身編寫的android

那麼在JAVA中就存在兩個問題,就是圖中紅色的部分git

client是如何發送數據給server的
Service是如何讀取到數據,如何調用到onTransact函數的數組

經過這兩個問題去分析源碼,就能理解JAVA層的機制了cookie

client流程

既然咱們獲取服務使用 ServieManager 的getService,咱們就分析它(不知道爲何版本28這個類裏面的返回都是null,估計在哪裏作了什麼騷操做了吧)app

public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
複製代碼

這個sCache就是一個HashMap
private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();ide

主要看 getIServiceManager函數

private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }
複製代碼
public static final native IBinder getContextObject();
複製代碼

getContextObject 是一個native方法,之後看到這個native,咱們就應該知道,它是調用cpp的代碼,就是一個JNI調用過程測試

JNI的對應代碼在哪?

這部分主要是分析JNI的函數是如何生成的,不想了解的也能夠直接跳過ui

註冊binder

在Android系統開機過程當中,Zygote啓動時會有一個虛擬機註冊過程,該過程調用 AndroidRuntime::startReg 方法來完成jni方法的註冊(這部分分析來自gityuan)

在 AndroidRuntime.cpp 中

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

    env->PushLocalFrame(200);
    //註冊 gRegJNI是一個數組,記錄全部須要註冊的jni方法,其中有一項是REG_JNI(register_android_os_Binder)
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    return 0;
}
複製代碼

看看 register_android_os_Binder

int register_android_os_Binder(JNIEnv* env) {
    if (int_register_android_os_Binder(env) < 0)
        return -1;

    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;

    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;
    ...
    return 0;
}
複製代碼

看來須要一個一個看了

int_register_android_os_Binder 註冊 Binder類的jni方法

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

    //將Java層Binder類保存到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");

    //註冊JNI方法
    return RegisterMethodsOrDie(env, kBinderPathName, gBinderMethods,
        NELEM(gBinderMethods));
}
複製代碼

gBinderOffsets 是什麼

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

} gBinderOffsets;
複製代碼

gBinderOffsets保存了Binder.java類自己以及其成員方法execTransact()和成員屬性mObject,這爲JNI層訪問Java層提供通道。另外經過查詢獲取Java層 binder信息後保存到gBinderOffsets,而再也不須要每次查找binder類信息的方式能大幅度提升效率,是因爲每次查詢須要花費較多的CPU時間,尤爲是頻繁訪問時,但用額外的結構體來保存這些信息,是以空間換時間的方法

gBinderMethods

static const JNINativeMethod gBinderMethods[] = {
     /* 名稱, 簽名, 函數指針 */
    { "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數組中的方法創建了一一映射關係,從而爲Java層訪問JNI層提供通道

總之,int_register_android_os_Binder方法的主要功能:

  • 經過gBinderOffsets,保存Java層Binder類的信息,爲JNI層訪問Java層提供通道;
  • 經過RegisterMethodsOrDie,將gBinderMethods數組完成映射關係,從而爲Java層訪問JNI層提供通道。

註冊BinderInternal

android_util_Binder.cpp

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));
}
複製代碼

註冊BinderInternal類的jni方法,gBinderInternalOffsets保存了BinderInternal的forceBinderGc()方法。

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 }
};
複製代碼

註冊BinderProxy

android_util_Binder.cpp

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

    //gBinderProxyOffsets保存了BinderProxy類的信息
    //其中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));
}
複製代碼
static const JNINativeMethod gBinderProxyMethods[] = {
     /* 名稱, 簽名, 函數指針 */
    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
    {"destroy",             "()V", (void*)android_os_BinderProxy_destroy},
};
複製代碼

這部份內容,讀者只要清楚這些JNI對應的函數,系統會在運行開始之初幫你作好這些工做就好了

JNI的代碼去哪找?

/frameworks/base/core/jni/

找到 android_util_Binder.cpp(JNI的命名通常是 包名路徑_對應的JAVA函數名稱)

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

看到了熟悉的東西了沒,ProcessState::self()就是前面在cpp代碼時分析過的

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}
複製代碼

它的handle是0,0是什麼,是service_manager,因此 ProcessState::self()->getContextObject(NULL) 返回的是一個 new BpBinder(0)

那麼接下來再看看 javaObjectForIBinder 是個什麼東西

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
    ......
    //使用c代碼調用NewObject來建立JAVA BinderProxy對象
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        //設置該對象的mObject = val.get = b = new BpBinder(0)
        env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());
        ......
    }
    return object;
}
複製代碼

所以 ServiceManagerNative.asInterface 等價於

ServiceManagerNative.asInterface(new BinderProxy())
其中 BinderProxy的mObject指向new BpBinder(0)

接下來看 asInterface

static public IServiceManager asInterface(IBinder obj) {
     //obj爲BpBinder
    if (obj == null) { 
        return null;
    }
    //因爲obj爲BpBinder,該方法默認返回null
    IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    return new ServiceManagerProxy(obj); 
}
複製代碼

所以 ServiceManagerNative.asInterface 等價於

new ServiceManagerProxy(new BinderProxy())

看看ServiceManagerProxy的構造函數

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
}
複製代碼

mRemote爲 BinderProxy 對象,該BinderProxy對象對應於BpBinder(0)
其做爲binder代理端,指向native層的serviceManager

得知,getIServiceManager 就是獲取一個 ServiceManagerProxy對象

既然它是一個BpBinder,在咱們寫cpp代碼的時候,就應該知道它能幹什麼,註冊服務獲取服務等等

那麼,framework層從 ServieManager的getService 開始,ServiceManagerProxy爲本身的mRemote設置 BinderInternal.getContextObject() 從經過JNI方式返回的IBinder(指向service_manager)對象,後續經過 ServiceManagerProxy 來調用服務功能

獲取到服務的binder後,下一步就是使用服務了

咱們以前是這麼用的

IHelloService svr = IHelloService.Stub.asInterface(binder);

如今去找到aidl生成的文件,找到 asInterface

// 根據 IBinder 構建一個 IHelloService 在android的源碼中,這種使用方法很是常見
        public static IHelloService asInterface(android.os.IBinder obj) {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof IHelloService))) {
                return ((IHelloService)iin);
            }
            return new IHelloService.Stub.Proxy(obj);
        }
複製代碼

IHelloService.Stub.Proxy 是什麼,也是aidl爲咱們生成的

//客戶端的代理 是一個RPC過程,遠程調用服務端的方法
private static class Proxy implements IHelloService{
    private android.os.IBinder mRemote;
    Proxy(android.os.IBinder remote){
        mRemote = remote;
    }
}
複製代碼

這樣就把Proxy中的mRemote賦值

而後就是調用服務中的方法了,以前咱們的代碼是svr.sayhello();

sayhello在Proxy中對應的函數方式代碼以下

@Override
            public void sayhello() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
複製代碼

那 mRemote.transact 是調用到哪裏去?

mRemote 分析過他是一個 JAVA 中的 BinderProxy 對象(8.0被抽出來了,8.0的源碼不少結構上都會有小小的變化,可能由於以前的代碼的可讀性確實比較差勁吧)

那麼找到 BinderProxy 的 transact 函數

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        ......
        try {
            return transactNative(code, data, reply, flags);
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
    }
複製代碼

最終調用 transactNative ,又是native,那麼咱們就去源碼裏找

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) {
    ...
    //java Parcel轉爲native Parcel
    Parcel* data = parcelForJavaObject(env, dataObj);
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ...
    
    //在前面的分析過程當中咱們設置了gBinderProxyOffsets.mObject爲BpBinder,如今把這個BpBinder(0)取出來
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ...

    //這個 target->transact 是 BpBinder::transact(),進入Binder驅動曾
    status_t err = target->transact(code, *data, reply, flags);
    ...
    return JNI_FALSE;
}
複製代碼

BpBinder::transact() 是否是很熟悉,cpp部分的源碼,忘記的話回頭看看cpp部分的分析,簡單說下

  • BpBinder::transact()
  • IPCThreadState::self()->transact
  • writeTransactionData
  • waitForResponse
  • talkWithDriver
  • executeCommand

就是開個循環與server端進行通訊,接受server端返回的數據

到此爲止,client端就能夠發送它的數據,這裏是一個RPC遠程調用過程,咱們已經解決了第一個問題,client如何發送數據

接下來看第二個問題,Service是如何讀取到數據,如何調用到onTransact函數的

回頭看看AIDL爲咱們生成的代碼

case TRANSACTION_sayhello:
                {
                    data.enforceInterface(DESCRIPTOR);
                    this.sayhello();
                    reply.writeNoException();
                    return true;
                }
複製代碼

在服務端是調用 this.sayhello()

這個this 是什麼

@Override public android.os.IBinder asBinder() {
    return this;
}
複製代碼

能夠得知他是一個IBinder,那麼這個IBinder具體是指什麼?

要分析server端的邏輯,就要從頭開始了

咱們編寫server端的時候並無本身寫循環,那麼他是怎麼處理的?顯然啊,確定是系統本身處理了

在哪處理的?實際上是使用app_process來啓動server進程的過程當中處理的

對於 AppRuntime 筆者不作過多分析,固然後續會有博文講解

源碼在 /frameworks/base/cmds/app_process/app_main.cpp 中

AppRuntime中有一個 onStarted() 函數

virtual void onStarted() {
    sp<ProcessState> proc = ProcessState::self();
    if (proc->supportsProcesses()) {
        LOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }
    AndroidRuntime* ar = AndroidRuntime::getRuntime();
    ar->callMain(mClassName, mClass, mArgC, mArgV);
    if (ProcessState::self()->supportsProcesses()) {
        IPCThreadState::self()->stopProcess();
    }
}
複製代碼

注意到 proc->startThreadPool(),從名字應該能看出來,他是啓動一個線程池

這個 proc 是一個 ProcessState

ProcessState 是什麼還記得嗎?

表示進程的一個結構體,在cpp部分作過度析

startThreadPool 總不能也忘了吧,忘了回頭看看cpp的內部機制

  • proc->startThreadPool()
  • spawnPooledThread(true)
  • sp<Thread> t = new PoolThread(isMain)
  • t->run(name.string())
  • IPCThreadState::self()->joinThreadPool(mIsMain)

在 joinThreadPool 中就開始循環處理請求了,根據命令處理,若是是 BR_TRANSACTION 就會根據cookie 轉換爲 BBinder,並調用他的 transact,BBinder的transact其實就等價於他的 onTransact

到此,咱們解決了第二問題的一部分,也就是 server 是如何讀取到數據

那麼還剩最後一個問題,如何調用到onTransact函數的

既然BBinder的transact等價於他的 onTransact,那咱們看看AIDL生成的文件中,他的 IBinder 實際對象是否爲前面分析的 BBinder,若是是,整個流程就全通了

那就要從server端的開頭開始分析了

server端流程

看看 addService 函數

public static void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) {
        try {
            getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
}
複製代碼

前面分析知道 getIServiceManager() 獲得的是一個 ServiceManagerProxy ,找到他的 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);
    // code 是 ADD_SERVICE_TRANSACTION
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}
複製代碼

重點在於 writeStrongBinder

writeStrongBinder

public writeStrongBinder(IBinder val){
    nativewriteStrongBinder(mNativePtr, val);
}
複製代碼

又是一個native,去找找他對應的函數,在 android_os_Parcel.cpp 中

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) {
    //將java層Parcel轉換爲native層Parcel
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        // .cookie = ibinderForJavaObject(env, object)獲得一個JavaBBinder對象
        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)
{
    //注意這個 obj 是傳進來的 service 對象
    if (obj == NULL) return NULL;

    //Java層的Binder對象
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL; 
    }
    //把一個Java對象(new XXXService()) 轉換爲cpp IBinder對象
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
    return NULL;
}
複製代碼

看看 JavaBBinderHolder 的 get,他返回的是一個 JavaBBinder

sp<JavaBBinder> get(JNIEnv* env, jobject obj) {
    AutoMutex _l(mLock);
    sp<JavaBBinder> b = mBinder.promote();
    // 這是一個wp類型的,可能會被垃圾回收器給回收,因此每次使用前,都須要先判斷是否存在
    if (b == NULL) {
        b = new JavaBBinder(env, obj);
        mBinder = b;
    }
    return b;
}
複製代碼

看下 JavaBBinder 的構造函數

class JavaBBinder : public BBinder
{
    JavaBBinder(JNIEnv* env, jobject object)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
    {
        android_atomic_inc(&gNumLocalRefs);
        incRefsCreated(env);
    }
}
複製代碼

他是一個 BBinder,愈來愈接近咱們前面的猜測了

data.writeStrongBinder(service)最終等價於 parcel->writeStrongBinder(new JavaBBinder(env, obj));

obj = new XXXService() ,JavaBBinder的mObject = obj

parcel的writeStrongBinder是什麼?

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

看到 flatten_binder 應該熟悉了,根據IBinder構建 flat_binder_object ,而且把binder對象寫道cookie裏去,後續server才能經過cookie裏去讀取並使用

mRemote.transact

回到以前的調用,data.writeStrongBinder(service) 把數據進行一個轉換並放入data後

調用

mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0)

還記得這個mRmote是什麼嗎

咱們分析 IServiceManager 的時候

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
}
複製代碼

mRemote爲 BinderProxy 對象,該 BinderProxy 對象對應於BpBinder(0)

那麼找到 BinderProxy 的 transact 函數,其實前面已經分析過這部分了

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        ......
        try {
            return transactNative(code, data, reply, flags);
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
    }
複製代碼

最終調用 transactNative ,又是native,那麼咱們就去源碼裏找

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) {
    ...
    //java Parcel轉爲native Parcel
    Parcel* data = parcelForJavaObject(env, dataObj);
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ...
    
    //在前面的分析過程當中咱們設置了gBinderProxyOffsets.mObject爲BpBinder,如今把這個BpBinder(0)取出來
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ...

    //這個 target->transact 是 BpBinder::transact(),進入Binder驅動曾
    status_t err = target->transact(code, *data, reply, flags);
    ...
    return JNI_FALSE;
}
複製代碼

BpBinder::transact() cpp部分的源碼

  • BpBinder::transact()
  • IPCThreadState::self()->transact
  • writeTransactionData
  • waitForResponse
  • talkWithDriver
  • executeCommand

開個循環與server端進行通訊,接受server端返回的數據,這裏咱們的client端是server,server端是service_manager

總結註冊服務流程

  • new XXXService()
  • data.writeStrongBinder(service)
  • JNI調用
  • service JAVA對象 轉換爲 JAVABBinder cpp對象
  • 將 JAVABBinder 給 cookie
  • 調用 BinderProxy 的 transact
  • BpBinder::transact()
  • 與驅動進行通訊
  • 驅動接收數據,完成服務的註冊工做

到此爲止,咱們只是分析了他如何註冊服務的,還沒獲得咱們第三個問題的答案

以前分析過,系統會幫咱們建立一個循環來擔任server端的循環處理工做,那麼在循環過程當中,會去讀取客戶端發送過來的消息,在分析cpp的代碼時,會在接收到數據後,取出 cookie 轉換爲 BBinder,並調用BBinder派生類的onTransact函數,咱們註冊服務的時候,BBinder的派生類是 JAVABBinder ,所以咱們只須要去找 JAVABBinder 的 onTransact 函數

virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) {
        JNIEnv* env = javavm_to_jnienv(mVM);
        IPCThreadState* thread_state = IPCThreadState::self();
        const int strict_policy_before = thread_state->getStrictModePolicy();
        thread_state->setLastTransactionBinderFlags(flags);
        //調用JAVA中的某個函數
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, (int32_t)&data, (int32_t)reply, flags);
        jthrowable excep = env->ExceptionOccurred();
        ......
        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }
複製代碼

看 CallBooleanMethod 它到底調用的是JAVA裏的哪一個函數

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
複製代碼

mObject指向 XXXService對象
gBinderOffsets.mExecTransact指向: android/os/Binder類中的 execTransact 方法
那麼上面的 CallBooleanMethod 就是調用XXXService(派生自Binder)對象中的execTransact方法

那麼查找 execTransact,它是在AIDL爲咱們生成的文件中,Stub的父類,Binder裏面

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) {
            ......
        } finally {
            ......
        }
        ......
        return res;
    }
複製代碼

能夠發現,它調用的是 onTransact 函數,這個onTransact就是它的子類實現的 onTransact,它的子類就是AIDL爲咱們生成的 Stub 中,在咱們以前寫的測試代碼中是這樣的

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code)
            {
                case INTERFACE_TRANSACTION:
                {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_sayhello:
                {
                    data.enforceInterface(DESCRIPTOR);
                    this.sayhello();
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_sayhello_to:
                {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    int _result = this.sayhello_to(_arg0);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
複製代碼

至此,咱們已經知道第三個問題的答案了,知道它是如何調用到JAVA層的onTransact函數

筆者完善了開頭的圖

相關文章
相關標籤/搜索