Android10.0 Binder通訊原理(八)-Framework層分析

摘要:本節主要來說解Android10.0 Binder 在Framework的使用分析html

閱讀本文大約須要花費15分鐘。java

文章首發微信公衆號:IngresGelinux

專一於Android系統級源碼分析,Android的平臺設計,歡迎關注我,謝謝!android

[Android取經之路] 的源碼都基於Android-Q(10.0) 進行分析git

[Android取經之路] 系列文章:數組

《系統啓動篇》緩存

  1. Android系統架構
  2. Android是怎麼啓動的
  3. Android 10.0系統啓動之init進程
  4. Android10.0系統啓動之Zygote進程
  5. Android 10.0 系統啓動之SystemServer進程
  6. Android 10.0 系統服務之ActivityMnagerService
  7. Android10.0系統啓動之Launcher(桌面)啓動流程
  8. Android10.0應用進程建立過程以及Zygote的fork流程
  9. Android 10.0 PackageManagerService(一)工做原理及啓動流程
  10. Android 10.0 PackageManagerService(二)權限掃描
  11. Android 10.0 PackageManagerService(三)APK掃描
  12. Android 10.0 PackageManagerService(四)APK安裝流程

《日誌系統篇》微信

  1. Android10.0 日誌系統分析(一)-logd、logcat 指令說明、分類和屬性
  2. Android10.0 日誌系統分析(二)-logd、logcat架構分析及日誌系統初始化
  3. Android10.0 日誌系統分析(三)-logd、logcat讀寫日誌源碼分析
  4. Android10.0 日誌系統分析(四)-selinux、kernel日誌在logd中的實現​

《Binder通訊原理》cookie

  1. Android10.0 Binder通訊原理(一)Binder、HwBinder、VndBinder概要
  2. Android10.0 Binder通訊原理(二)-Binder入門篇
  3. Android10.0 Binder通訊原理(三)-ServiceManager篇
  4. Android10.0 Binder通訊原理(四)-Native-C\C++實例分析
  5. Android10.0 Binder通訊原理(五)-Binder驅動分析
  6. Android10.0 Binder通訊原理(六)-Binder數據如何完成定向打擊
  7. Android10.0 Binder通訊原理(七)-Framework binder示例
  8. Android10.0 Binder通訊原理(八)-Framework層分析
  9. Android10.0 Binder通訊原理(九)-AIDL Binder示例​​​​​​​

1.概述

前面幾節,咱們已經把Native層和Binder驅動層的Binder數據流轉給理清楚了,也知道了相應的概念。這一節讓咱們繼續往上進行分析,咱們進入到Framework層,看看Framework是如何實現服務的註冊、獲取的流程。架構

2.Binder架構

Framework層要實現服務的註冊須要經過JNI 來調用Native C\C++層的相應接口,最終把服務註冊到Native層的ServiceManager中。
應用層的進行經過Framework的接口,也通過JNI技術進入Native C\C++,最終在Native層的ServiceManager中獲得服務handle,最終轉成相應的服務對象。

3.源碼分析

3.1 Binder-JNI

當Init進程啓動後,孵化Zygote進程時,會有一個虛擬機註冊過程,在這個過程當中完成了JNI的註冊,咱們如今不須要深刻去理解JNI的原理,後面有時間,我再單獨出一章來進行分析。

如今咱們只要知道 JAVA和Native側的函數對應關係在哪裏便可。

Binder的JNI中有個三個Binder的映射數組:gBinderMethods、gBinderInternalMethods、gBinderInternalMethods。

咱們在擼代碼時,是要根據JAVA的函數入口找到JNI的函數調用便可,不要太追求細枝末節。

gBinderMethods:

[/frameworks/base/core/jni/android_util_Binder.cpp]
static const JNINativeMethod gBinderMethods[] = {
     /* name, signature, funcPtr */
    // @CriticalNative
    { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
    // @CriticalNative
    { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
    // @CriticalNative
    { "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction },
    // @CriticalNative
    { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
    { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
    // @CriticalNative
    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
    // @CriticalNative
    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
    // @CriticalNative
    { "setCallingWorkSourceUid", "(I)J", (void*)android_os_Binder_setCallingWorkSourceUid },
    // @CriticalNative
    { "getCallingWorkSourceUid", "()I", (void*)android_os_Binder_getCallingWorkSourceUid },
    // @CriticalNative
    { "clearCallingWorkSource", "()J", (void*)android_os_Binder_clearCallingWorkSource },
    { "restoreCallingWorkSource", "(J)V", (void*)android_os_Binder_restoreCallingWorkSource },
    { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
    { "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder },
    { "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer },
    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};

gBinderInternalMethods:

[/frameworks/base/core/jni/android_util_Binder.cpp]
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 },
    { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc },
    { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
    { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
};

gBinderInternalMethods:

[/frameworks/base/core/jni/android_util_Binder.cpp]
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 },
    { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc },
    { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
    { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
};

3.2 服務註冊

在上一節的Framework Binder Demo示例中,咱們知道服務註冊的時候,調用的是ServiceManager.java的addService(),那咱們就拿addService()開刀。

註冊服務調用棧:

3.2.1 addService()

[/frameworks/base/core/java/android/os/ServiceManager.java]
public static void addService(String name, IBinder service, boolean allowIsolated,
        int dumpPriority) {
    try {
        //獲取ServiceManagerProxy對象,執行addService操做
        getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

拿到ServiceManagerProxy對象,來執行addService操做,這個ServiceManagerProxy對象須要咱們來揭開面紗。

3.2.2 getIServiceManager()

[/frameworks/base/core/java/android/os/ServiceManager.java]
private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }

    // Find the service manager
    sServiceManager = ServiceManagerNative
            .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
    return sServiceManager;
}

這裏也採用了單例模式來獲取ServiceManagerProxy對象,減小對象重複建立。

[/frameworks/base/core/java/android/os/ServiceManagerNative.java]
static public IServiceManager asInterface(IBinder obj)
{
    if (obj == null) {
        return null;
    }
    IServiceManager in =
        (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }

    return new ServiceManagerProxy(obj);
}

asInterface()中的主要做用就是建立ServiceManagerProxy()對象,可是須要帶一個IBinder的 obj,我來看看這個obj是如何拿到的。

3.2.3 getContextObject()

[/frameworks/base/core/java/com/android/internal/os/BinderInternal.java]
public static final native IBinder getContextObject();

BinderInternal.java中有一個native方法getContextObject(),JNI調用執行上述方法,在JNI的 gBinderInternalMethods數組中找到了getContextObject的對應關係,即爲android_os_BinderInternal_getContextObject。

android_os_BinderInternal_getContextObject()
[/frameworks/base/core/jni/android_util_Binder.cpp]
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

ProcessState::self()->getContextObject(NULL) 在《Binder--Native-C\C++實例分析》 的[5.3.1]節已經進行了詳細分析,最終等價於 new BpBinder(0),這裏就不重複展開了。

 

javaObjectForIBinder()

若是參數是JavaBBinder,返回用於建立它的Java對象;不然返回一個BinderProxy的對象。

若是上一個調用被傳遞給同一個IBinder,而原來的BinderProxy還活着,返回一樣的BinderProxy。

[/frameworks/base/core/jni/android_util_Binder.cpp]
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    if (val == NULL) return NULL;

    if (val->checkSubclass(&gBinderOffsets)) {
            //若是參數是JavaBBinder,返回用於建立它的Java對象;不然返回一個BinderProxy的對象。
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }

        //申請一個BinderProxyNativeData的內存
    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
    nativeData->mOrgue = new DeathRecipientList;
    nativeData->mObject = val;

    //建立BinderProxy對象,設置BinderProxy的相關參數,可以與JAVA層的BinderProx參與工做
    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
    if (env->ExceptionCheck()) {
        return NULL;
    }
    BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
    if (actualNativeData == nativeData) {
        // Created a new Proxy
        uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
        uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
        if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
            if (gProxiesWarned.compare_exchange_strong(numLastWarned,
                        numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
                ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
            }
        }
    } else {
        delete nativeData;
    }

    return object;
}

javaObjectForIBinder()中,申請一個BinderProxyNativeData的內存,傳入的BpBinder的對象地址保存到BinderProxyNativeData.mObject成員變量中,經過虛擬機的轉換,BinderProxyNativeData在JAVA空間會被轉換成 BinderProxy對象。

最終,BinderInternal.getContextObject()等價於 new BinderProxy(),因此getIServiceManager等價於new ServiceManagerProxy(new BinderProxy())。

 

3.2.4 ServiceManagerProxy.addService()

上一節,咱們已經拿到了ServiceManager在JAVA空間的代理,即ServiceManagerProxy,接着調用addService()來進行服務的註冊。

[/frameworks/base/core/java/android/os/IServiceManager.java]
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
        throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    //將Binder對象扁平化,轉換成flat_binder_object對象,這裏爲服務註冊,對應的是Binder實體
    data.writeStrongBinder(service); 
    data.writeInt(allowIsolated ? 1 : 0);
    data.writeInt(dumpPriority);
       //Code:ADD_SERVICE_TRANSACTION ,parcel的數據 發到C空間,進行事務處理,註冊服務。
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); 
    reply.recycle();
    data.recycle();
}

組裝一個Parcel數據,把服務的名稱和對象寫入Parcel中,而後把它拍扁,服務轉成flat_binder_object對象,在Native層爲Binder實體。

 

3.2.5  writeStrongBinder()

把傳入的服務對象拍扁,轉成flat_binder_object對象,代碼流程太羅嗦,這裏列出如下調用棧流程:

data.writeStrongBinder(service)等價於parcel->writeStrongBinder(new JavaBBinder(env, obj));最終調用的是flatten_binder(),目的是把一個Binder實體「壓扁」並寫入Parcel。

這裏"壓扁"的含義,其實就是把Binder對象整理成flat_binder_object變量。若是壓扁的是Binder實體,那麼flat_binder_object用cookie域記錄binder實體的指針,即BBinder指針,而若是打扁的是Binder代理,那麼flat_binder_object用handle域記錄的binder代理的句柄值。

接着flatten_binder()調用了一個關鍵的finish_flatten_binder()函數。這個函數內部會記錄下剛剛被扁平化的flat_binder_object在parcel中的位置。說得更詳細點兒就是,parcel對象內部會有一個buffer,記錄着parcel中全部扁平化的數據,有些扁平數據是普通數據,而另外一些扁平數據則記錄着binder對象。因此parcel中會構造另外一個mObjects數組,專門記錄那些binder扁平數據所在的位置,示意圖以下:

flatten_binder()的流程能夠參考《Binder--Native-C\C++實例分析》 的[5.4]節

 

3.2.6 mRemote對象

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

mRemote 是ServiceManagerProxy的一個成員,執行一個IBinder對象,mRemote在ServiceManagerProxy()構造函數中進行了賦值,從[4.2.3]和[4.2.4] 可知getIServiceManager()中調用了 以下內容:

sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()))

從而可知 mRemote = BinderInternal.getContextObject() = new BinderProxy(),因此mRemote就是BinderProxy的對象。

mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0) 等價於BinderProxy.transact(ADD_SERVICE_TRANSACTION, data, reply, 0)

 

3.2.7 BiderProxy.transact()

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        //檢查Parcel的大小是否大於800K
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");

    try {
        return transactNative(code, data, reply, flags);
    } finally {
            ...
    }
}

邏輯很簡單,先檢查Parcel的大小是否大於800K,而後調用了transactNative()進行數據傳遞。 

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

transactNative()一個Native方法,根據以前的JNI數組表,能夠查到JNI的對應入口。

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    ...
    Parcel* data = parcelForJavaObject(env, dataObj);
    ...
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ...
    IBinder* target = getBPNativeData(env, obj)->mObject.get();
    ...
        //根據咱們以前獲取的對象流程來看,BinderProxy在Native空間,對應的是BpBinder,target即爲BpBinder對象
    status_t err = target->transact(code, *data, reply, flags);
    ...
    return JNI_FALSE;
}

根據咱們以前獲取的對象流程來看,BinderProxy在Native空間,對應的是BpBinder,target即爲BpBinder對象。因此target->transact() 等價於BpBinder::transact(), 接下來的流程參考前面Native-C\C++層的分析,這裏的細節再也不闡述,參考 《Binder--Native-C\C++實例分析》 和 《Binder數據如何定向打擊》,也能夠看到上面註冊服務的調用棧。

 

3.2.8 服務註冊總結

framework層的ServiceManager的調用實際的工做確實交給ServiceManagerProxy的成員變量BinderProxy;而BinderProxy經過jni方式,最終會調用BpBinder對象;可見上層binder架構的核心功能依賴native架構的服務來完成的。

註冊服務的核心部分,就是JAVA側把服務名稱和對象,轉入Parcel「扁平」數據,經過Native BpBinder,把code:ADD_SERVICE_TRANSACTION發給Binder驅動,再轉到Native的ServiceManager,ServiceManager把服務名稱和轉換後的handler進行存儲,供Client進行服務獲取。

 

3.3 服務獲取

在上一節的Framework Binder Demo示例中,咱們知道服務註冊的時候,調用的是ServiceManager.java的getService(),那麼獲取服務就從getService()入口。

[/frameworks/base/core/java/android/os/ServiceManager.java]
public static IBinder getService(String name) {
    try {
            //從緩存中獲取服務對象
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
                 //從Native層服務列表中取服務對象
            return Binder.allowBlocking(rawGetService(name));
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

 

3.3.2 rawGetService()

[/frameworks/base/core/java/android/os/ServiceManager.java]
private static IBinder rawGetService(String name) throws RemoteException {
    ...
        //
        //即爲ServiceManagerProxy().getService
    final IBinder binder = getIServiceManager().getService(name);
    ...
    return binder;
}

從上面可知getIServiceManager() 等價於 new ServiceManagerProxy(new BinderProxy()),getIServiceManager().getService(name)等價於ServiceManagerProxy().getService(name)

 

3.3.3 getService()

[/frameworks/base/core/java/android/os/ServiceManagerNative.java]
public IBinder getService(String name) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

從[4.2.6]可知,mRemote.transact(XXX) 等價於BinderProxy.transact(xx),這裏不展開,和[4.2.7流程]同樣,只是ServiceManager獲取到服務的handle後,存入了reply信息中,這裏會再調用reply.readStrongBinder()把binder對象給取出來。

 

3.3.4 readStrongBinder()

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

調用棧以下:

Parcel.cpp -> readStrongBinder() 參考 《Binder--Native-C\C++實例分析》 中的[6.4]節,  javaObjectForIBinder()參考[4.2.3]

readStrongBinder()最終是從reply的Parcel數據中得到BpBinder對象,再轉成BinderProxy對象,參與JAVA層的工做。

 

3.3.5 allowBlocking

[/frameworks/base/core/java/android/os/Binder.java]
public static IBinder allowBlocking(IBinder binder) {
    try {
        //若是binder是代理類,則設置非阻塞式
        if (binder instanceof BinderProxy) {
            ((BinderProxy) binder).mWarnOnBlocking = false;
        } else if (binder != null && binder.getInterfaceDescriptor() != null
                && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
            //若是binder是本地對象,binder描述符不爲空,且和本地binder描述符不相同 
            Log.w(TAG, "Unable to allow blocking on interface " + binder);
        }
    } catch (RemoteException ignored) {
    }
    return binder;
}

做用:

  1. 容許在給定接口上阻塞調用,重寫請求的{setWarnOnBlocking(boolean)}值。
  2. 只有當您徹底肯定遠程接口是一個永遠沒法升級的內置系統組件時,才應該不多調用此命令。尤爲是,決不能對包託管的、可升級或替換的接口調用此命令,不然,若是遠程接口接入,將有系統不穩定的風險。

3.3.6 獲取服務小結

和註冊服務相似,都是須要依賴Native層的接口與Binder驅動通訊,獲取服務主要是從Native的ServieManager取到Binder對象。

 

3.4 Client-Server接口調用

在[3.2] 和[3.3]中,咱們知道了服務註冊addService()和獲取服務getService()的流程,接下來咱們再看一看接口調用是如何進行的。

[MyServiceProxy.java]
public void setValue(String str) throws RemoteException {
    Parcel data = Parcel.obtain(); //準備發送數據,結構爲Parcel
    Parcel reply = Parcel.obtain();//準備返回數據,結構爲Parcel
    try {
            //寫入服務的Token,用來驗證服務的準確性
        data.writeInterfaceToken(IMyService.descriptor); 
        data.writeString(str); //把參數寫入Parcel,服務端會獲取該參數
        mRemote.transact(SET_VALUE_TRANSACTION, data, reply, 0); //code:SET_VALUE_TRANSACTION
        reply.readException();
    } finally {
        reply.recycle();
        data.recycle();
    }
}

上面調用的流程,其實和addService()、getService()相似,都是組裝Parcel數據,準備服務端的code,調用BinderProxy.transact()發送到服務端。

可是和服務註冊不一樣的是,在服務註冊中,Native的ServiceManager是Server端,服務實體是Client端。接口調用時,服務實體是Server端。

服務端接收到CLient的請求後,根據下圖的流程,最終流轉到服務實體的onTransact()中,對解析出來的Parcel數據進行處理。

 

4.總結

Framework層獲取服務、註冊服務,其實都是由JAVA層的ServiceManager代理 ServiecManagerProxy ,經過Binder驅動,訪問Native層的ServiceManager,進行服務註冊和獲取動做。

這一節只是單獨在Framework層進行了分析,不少狀況下咱們都是在應用層進行處理流程,經過AIDL接口進行通訊,下一節會對AIDL進行一下分析。

 

代碼路徑:

Framework:

/frameworks/base/core/java/android/os/Binder.java
/frameworks/base/core/java/android/os/IBinder.java
/frameworks/base/core/java/android/os/BinderProxy.java
/frameworks/base/core/java/android/os/BinderProxy.java
/frameworks/base/core/java/android/os/ServiceManager.java
/frameworks/base/core/java/android/os/IServiceManager.java
/frameworks/base/core/java/android/os/ServiceManagerNative.java
/frameworks/base/core/java/com/android/internal/os/BinderInternal.java






JNI:

/frameworks/base/core/jni/android_util_Binder.h
/frameworks/base/core/jni/android_util_Binder.cpp
/frameworks/base/core/jni/android_os_Parcel.h
/frameworks/base/core/jni/android_os_Parcel.cpp
 



參考:

《Binder framework層分析》

 

個人微信公衆號:IngresGe

發佈了25 篇原創文章 · 獲贊 60 · 訪問量 5萬+
相關文章
相關標籤/搜索