Android之IPC6————Binder3 Framework層分析

Android之IPC6————Binder3 Framework層分析

一.概述

在前兩篇我們分析了Binder在Native層的實現,我們今天來看在Framework層,Binder相關的內容,這一篇也是以註冊服務和獲取服務來看Binder的流程。

image

bidner在Framework層,採用JNI技術來調用native層的binder架構,從而爲上層應用提供服務。

java JNI本意是Java native interface,是爲了方便javad調用C,C++等本地代碼所封裝的異常接口。jni也是JVM規範中的一部份,因此可以將我們寫的 JNI 程序在任何實現了 JNI 規範的 Java 虛擬機中運行。
這篇文章主要講下面幾個方面:

  • BinderJNI初始化(註冊)
  • FrameWork層的註冊服務
  • FrameWork層的獲取服務

下面這個是framework的binder類關係圖:
image

二.BinderJNI初始化

在Android系統開機的過程中,Zygote啓動時會有一個虛擬機註冊過程,該過程調用AndroidRuntime::startReg方法來完成jni方法的註冊。

1.註冊JNI方法

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

    env->PushLocalFrame(200);

    //註冊jni方法 【見下】
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    return 0;
}

註冊jni方法

int register_android_os_Binder(JNIEnv* env) {
    // 註冊Binder類的jni方法【見下】
    if (int_register_android_os_Binder(env) < 0)
        return -1;

    // 註冊BinderInternal類的jni方法【見下】
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;

    // 註冊BinderProxy類的jni方法【見下】
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;
    ...
    return 0;
}

2.註冊Binder類

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

    jclass clazz;

    clazz = env->FindClass(kBinderPathName);
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");


	//將java層的Binder類保存到mClass變量;
    gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);

	//將Java層execTransact()方法保存到mExecTransact變量;
    gBinderOffsets.mExecTransact
        = env->GetMethodID(clazz, "execTransact", "(IJJI)Z");
    assert(gBinderOffsets.mExecTransact);

	//將Java層mObject屬性保存到mObject變量
    gBinderOffsets.mObject
        = env->GetFieldID(clazz, "mObject", "J");
    assert(gBinderOffsets.mObject);

    return AndroidRuntime::registerNativeMethods(
        env, kBinderPathName,
        gBinderMethods, NELEM(gBinderMethods));
}

gBinderoffers是全局靜態結構體,其定義如下:

static struct bindernative_offsets_t
{
    // Class state.
    jclass mClass; //記錄Binder類
    jmethodID mExecTransact;//記錄execTransact()方法

    // Object state.
    jfieldID mObject; //記錄mObject屬性

} gBinderOffsets;

gBinderoffers保存了Binder.java類本身的以及其成員方法,execTransact()和成員屬性mObject,這爲JNI層訪問Java層提供通道。另外通過查詢獲取Java層 binder信息後保存到gBinderOffsets。

再看看registerNativeMethods中第三個參數,即 gBinderMethods

//爲Java層訪問JNI層提供通道。

static const JNINativeMethod gBinderMethods[] = {
     /* name, signature, funcPtr */
    { "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 }
};

在int_register_android_os_Binder中:

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

3.註冊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));
}

上面是BinderInternal類的jni方法,gBinderInternalOffsets保存了BinderInternal的forceBinderGc()方法。

gBinderInternalOffsets:

//BinderInternal類的JNI方法註冊:
static const JNINativeMethod gBinderInternalMethods[] = {
     /* name, signature, funcPtr */
    { "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 }
};

和上面的類似,也是給Native層與framework層之間的相互調用的橋樑。

4. 註冊BinderProxy

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));
}

gBinderProxyMethods中:

//下面BinderProxy類的JNI方法註冊:  
static const JNINativeMethod gBinderProxyMethods[] = {
     /* name, signature, funcPtr */
    {"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},
};

和上面一樣,也是Native層與framework層之間的相互調用的橋樑

三.註冊服務

1.SM.addService

從framework的ServiceManager.java開始

public static void addService(String name, IBinder service, boolean allowIsolated) {
    try {
        //先獲取SMP對象,則執行註冊服務操作【見小節3.2/3.4】
        getIServiceManager().addService(name, service, allowIsolated); 
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

在addService中先獲去ServiceManagerProxy

2.獲取SMP

getIServiceManager

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

    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

獲取SMP有兩步關鍵步驟,即BinderInternal.getContextObject(),和ServiceManagerNative.asInterface()

BinderInternal.getContextObject()中最終會去獲取JNI( android_util_binder.cpp)中android_os_BinderInternal_getContextObject方法,

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

對於ProcessState::self()->getContextObject(),在上一節中以及解決過,即ProcessState::self()->getContextObject()等價於 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);
    }

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

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

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

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

根據BpBinder(C++)生成BinderProxy(Java)對象. 主要工作是創建BinderProxy對象,並把BpBinder對象地址保存到BinderProxy.mObject成員變量. 到此,可知ServiceManagerNative.asInterface(BinderInternal.getContextObject()) 等價於

ServiceManagerNative.asInterface(new BinderProxy())

回到上面的ServiceManagerNative.asInterface()中

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

所以ServiceManagerNative.asInterface(BinderInternal.getContextObject())等價於

new ServiceManagerProxy(new BinderProxy()).

來看看 ServiceManagerProxy()的構造函數

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

mRemote爲BinderProxy對象,該BinderProxy對象對應於BpBinder(0),其作爲binder代理端,指向native層大管家service Manager。

3.SMP.addService()

通過上面的分析可知getIServiceManager()最終獲取的是ServiceManagerProxy(),所以我們來看看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);
    //mRemote爲BinderProxy【見下文】
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

這裏我們發現,和Native層註冊服務的步驟幾乎一模一樣。
所以問題變爲FrameWork層的Binder轉換爲Native層。

當時我們分析Native層的時候,主要看的是writeStrongBinder和transact方法,這裏我們繼續看這兩個方法是如何從java到c++的。

4.writeStrongBinder

public writeStrongBinder(IBinder val){
    //此處爲Native調用
    nativewriteStrongBinder(mNativePtr, val);
}

看調用JNI的方法

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) {
        //ibinderForJavaObject【見下】
        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對象
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL; 
    }
    //Java層的BinderProxy對象
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
    return NULL;
}

在這裏面將Binde(Java)生成JavaBBinderHolder(C++)對象. 主要工作是創建JavaBBinderHolder對象,並把JavaBBinderHolder對象地址保存到Binder.mObject成員變量。

我們看看 ibinderForJavaObject最終返回的結果,即JavaBBinderHolder.get()

sp<JavaBBinder> get(JNIEnv* env, jobject obj) {
    AutoMutex _l(mLock);
    sp<JavaBBinder> b = mBinder.promote();
    if (b == NULL) {
        //首次進來,創建JavaBBinder對象
        b = new JavaBBinder(env, obj);
        mBinder = b;
    }
    return b;
}

所以最終data.writeStrongBinder(service);轉換爲parcel->writeStrongBinder(new JavaBBinder(env, obj));

最後來看看parcel->writeStrongBinder。

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

沒錯,這就是我們上一篇博客中分析的writeStrongBinder的內容。

5.mRemote.transact

在第一節中,我們知道mRemote 其實就BinderProxy。

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

transactNative經過jni調用,進入方法 jni的android_os_BinderProxy_transact

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中保存的是new BpBinder(0)對象
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ...

    //此處便是BpBinder::transact(), 經過native層,進入Binder驅動程序
    status_t err = target->transact(code, *data, reply, flags);
    ...
    return JNI_FALSE;
}

Java層的BinderProxy.transact()最終交由Native層的BpBinder::transact()完成。之後的內容在就是上一篇博客的內容,也就是交給了Native。

6.小結

在framework中,也是先獲取ServiceManagerm,他最終獲得的是一個ServiceManagermProxy,在它之中含有一個BinderProxy的成員變量,它含有Native層的BpBInder,而BpBinder含有Binder驅動中ServiceManager的binder對象。

之後和Native層一樣,調用Parcel的writeStrongBinder和BinderProxy的transact
,最終經過JNI,調用Native層對應的方法。

四.獲取服務

和註冊服務一樣,調用ServiceManager中的getService方法。

1. SM.getService

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;
}

return getIServiceManager().getService(name)

這行代碼和獲取服務一樣,最終轉換爲ServiceManagerNative.getService(name);所以我們直接看對應代碼

2. SMP.getService

lass ServiceManagerProxy implements IServiceManager {
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        //mRemote爲BinderProxy 
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); 
        //從reply裏面解析出獲取的IBinder對象
        IBinder binder = reply.readStrongBinder(); 
        reply.recycle();
        data.recycle();
        return binder;
    }
}

這裏的代碼還是Native層幾乎一樣,我們一樣關注reply.readStrongBinder和 mRemote.transact如何調用到Native層的代碼

3.mRemote.transact

final class BinderProxy implements IBinder {
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
        return transactNative(code, data, reply, flags);
    }
}

transactNative最後會調用jni中的android_os_BinderProxy_transact方法

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中保存的是new BpBinder(0)對象
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ...

    //此處便是BpBinder::transact()
    status_t err = target->transact(code, *data, reply, flags);
    ...
    return JNI_FALSE;
}

在這裏的最後,發現調用了BpBinder的transact方法,之後就是上一篇博客的內容了。

4.readStrongBinder

java層的

public final IBinder readStrongBinder() {
        return nativeReadStrongBinder(mNativePtr);
    }

jni層

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}

parcel->readStrongBinder()此處就是Native層的方法,也就是我們上一篇文章分析的地方

來看看javaObjectForIBinder是幹什麼的

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

   if (val->checkSubclass(&gBinderOffsets)) {
       // One of our own!
       //本線程
       jobject object = static_cast<JavaBBinder*>(val.get())->object();
       LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
       return object;
   }

   // For the rest of the function we will hold this lock, to serialize
   // looking/creation of Java proxies for native Binder proxies.
   //加鎖
   AutoMutex _l(mProxyLock);

   // Someone else's...  do we know about it?
   //其他線程的
   jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
   if (object != NULL) {
       jobject res = jniGetReferent(env, object);
       if (res != NULL) {
           ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
           return res;
       }
       LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
       android_atomic_dec(&gNumProxyRefs);
       val->detachObject(&gBinderProxyOffsets);
       env->DeleteGlobalRef(object);
   }

   object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
   if (object != NULL) {
       LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
       // The proxy holds a reference to the native object.
       env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
       val->incStrong((void*)javaObjectForIBinder);

       // The native object needs to hold a weak reference back to the
       // proxy, so we can retrieve the same proxy if it is still active.
       //本機對象需要將一個弱引用保留回代理,以便我們可以檢索相同的代理(如果它仍然是活動的)。
       jobject refObject = env->NewGlobalRef(
               env->GetObjectField(object, gBinderProxyOffsets.mSelf));
       val->attachObject(&gBinderProxyOffsets, refObject,
               jnienv_to_javavm(env), proxy_cleanup);

       // Also remember the death recipients registered on this proxy
       //還請記住在此代理上註冊的死亡收件人
       sp<DeathRecipientList> drl = new DeathRecipientList;
       drl->incStrong((void*)javaObjectForIBinder);
       env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

       // Note that a new object reference has been created.
       //注意,已經創建了一個新的對象引用
       android_atomic_inc(&gNumProxyRefs);
       incRefsCreated(env);
   }

   return object;
}

在這裏主要是將Native層返回的Binder,轉換爲Framework的Binder。

5.總結

獲取服務時,也是先獲得ServiceManagerProxy,它其中包含BinderProxy的成員變量,它含有Native層的BpBInder,而BpBinder指向Binder驅動中ServiceManager的binder對象。

在SMP中,獲取服務的代碼和Native層中幾乎一樣,最終經過JNI,轉換爲NAtive層的代碼

五.總結

這一篇來說,相對容易理解一下,特別是ServiceManager和BinderProxy在Native層都有對應的對象,可以類比。

在ServiceManagerProxy中的AddService和getService的代碼幾乎和Native層一樣,之後利用JNI調用到Native層的代碼。

六.參考資料

Binder系列7—framework層分析

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