1. 程式人生 > >Android開發之漫漫長途 Ⅷ——Android Binder(也許是最容易理解的)

Android開發之漫漫長途 Ⅷ——Android Binder(也許是最容易理解的)

pct med ctf 共享 抽象 fin 進程的地址空間 源碼 instance

該文章是一個系列文章,是本人在Android開發的漫漫長途上的一點感想和記錄,我會盡量按照先易後難的順序進行編寫該系列。該系列引用了《Android開發藝術探索》以及《深入理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相關知識,另外也借鑒了其他的優質博客,在此向各位大神表示感謝,膜拜!!!另外,本系列文章知識可能需要有一定Android開發基礎和項目經驗的同學才能更好理解,也就是說該系列文章面向的是Android中高級開發工程師。


前言

我們在上一篇中比較詳盡的介紹了Android的消息機制,不過有一些內容我們在不理解Android Binder的話是無法講解清楚的。對於初學Android的朋友而言,最難卻又最想掌握的恐怕就是Binder機制了,因為Android系統基本上可以看作是一個基於Binder通信的C/S架構。 Binder就像網絡一樣,把系統的各個部分連接在了一起,因此它是非常重要的。我們下面會Android Binder機制進行從上到下從易到難的分層次講解,從而既能讓初學者對Binder有一定認識,也能讓有一定Android基礎的人獲得收獲。
註:下文中的源碼均出自android-6.0.0_r5

Binder概述

對於初學者來說,深入Android Binder機制是非常不明智的。Android Binder機制大都涉及Java層、Native層、驅動層這三三個方面,對於初學者來說想啃這三塊硬骨頭很容易磕著牙。我們這這一節概述從以下幾個方面讓你從比較宏觀的角度理解Android Binder。

進程

在該系列博客中的第一章我們就說起了Android進程相關問題,Android故意弱化了進程的概念,而用相對容易理解的四大組件。可是我們在稍微深入Android的時候,那麽進程是繞不過的。默認情況下,同一個應用程序中的所有組件運行在同一個進程中,而且絕大多數的應用程序也都是這樣的。這個默認進程是用這個應用的包名來命名的。

進程間通信

我們在運行App的時候經常需要使用一些系統服務,比如剪切板服務,而剪切板服務是運行在SystemServer進程中的。那我們的App是怎麽使用剪切板服務的呢,我們都知道進程是相互獨立的,靜態變量等等都無法共用。這就涉及到進程間的通信了,即IPC。我們都知道Android是基於Linux內核的,那我們簡單介紹下Linux下的幾種IPC機制。

管道(Pipe)

管道是由內核管理的一個緩沖區,相當於我們放入內存中的一個紙條。管道的一端連接一個進程的輸出。這個進程會向管道中放入信息。管道的另一端連接一個進程的輸入,這個進程取出被放入管道的信息。

  • 管道是半雙工的,數據只能向一個方向流動;需要雙方通信時,需要建立起兩個管道
  • 只能用於父子進程或者兄弟進程之間(具有親緣關系的進程)。比如fork或exec創建的新進程,在使用exec創建新進程時,需要將管道的文件描述符作為參數傳遞給exec創建的新進程。當父進程與使用fork創建的子進程直接通信時,發送數據的進程關閉讀端,接受數據的進程關閉寫端。
  • 管道只能在本地計算機中使用,而不可用於網絡間的通信。

命名管道(FIFO)

命名管道是一種特殊類型的文件,它在系統中以文件形式存在。這樣克服了管道的弊端,他可以允許沒有親緣關系的進程間通信。

共享內存(Share Memory)

共享內存是在多個進程之間共享內存區域的一種進程間的通信方式,由IPC為進程創建的一個特殊地址範圍,它將出現在該進程的地址空間中。其他進程可以將同一段共享內存連接到自己的地址空間中。所有進程都可以訪問共享內存中的地址,如果一個進程向共享內存中寫入了數據,所做的改動將立刻被其他進程看到。

  • 共享內存是IPC最快捷的方式,共享內存方式直接將某段內存段進行映射,多個進程間的共享內存是同一塊的物理空間,僅僅映射到各進程的地址不同而已,因此不需要進行復制,可以直接使用此段空間。
  • 共享內存本身並沒有同步機制,需要程序員自己控制。

    內存映射(Memory Map)

    內存映射是由一個文件到一塊內存的映射,在此之後進程操作文件,就像操作進程空間裏的內存地址一樣了。

    套接字(Socket)

    套接字機制不但可以單機的不同進程通信,而且使得跨網機器間進程可以通信。
    套接字的創建和使用與管道是有區別的,套接字明確地將客戶端與服務器區分開來,可以實現多個客戶端連到同一服務器。

Binder

作為Android系統下的一種IPC機制,其本質上與上面羅列出的IPC機制並無本質上的不同,都是作為進程間通信的一種手段。並且在Android系統中也不是只存在Binder這一種進程間通信的方式,在有些地方也使用了Socket。既然Linux已經提供了眾多IPC機制,那麽Android 為何還要使用Binder作為主要的進程間通信的方式呢,那麽當然有他的優點存在。

  • 采用C/S的通信模式。而在linux通信機制中,目前只有socket支持C/S的通信模式,但socket有其劣勢,具體參看第二條。
  • 有更好的傳輸性能。對比於Linux的通信機制,socket:是一個通用接口,導致其傳輸效率低,開銷大;管道和消息隊列:因為采用存儲轉發方式,所以至少需要拷貝2次數據,效率低;共享內存:雖然在傳輸時沒有拷貝數據,但其控制機制復雜(比如跨進程通信時,需獲取對方進程的pid,得多種機制協同操作)。
  • 安全性更高。Linux的IPC機制在本身的實現中,並沒有安全措施,得依賴上層協議來進行安全控制。而Binder機制的UID/PID是由Binder機制本身在內核空間添加身份標識,安全性高;並且Binder可以建立私有通道,這是linux的通信機制所無法實現的(Linux訪問的接入點是開放的)。
  • 對用戶來說,通過binder屏蔽了client的調用server的隔閡,client端函數的名字、參數和返回值和server的方法一模一樣,對用戶來說猶如就在本地(也可以做得不一樣),這樣的體驗或許其他ipc方式也可以實現,但binder出生那天就是為此而生。

Java層Binder

Java層Binder的功能,依賴於Native層Binder來實現,可以認為Java層Binder架構是Native層Binder架構的一個鏡像。但是這並不影響我們分析Android Java層Binder的功能。我們用一個例子來說明這個過程。

我們在第一篇中就講解了SystemServer這個進程,這個進程和zygote進程一起撐起了Android 世界,他們之中有一個崩潰,Android世界就會砰然倒塌。Android許多的重要的系統服務如AMS、PMS等都運行在SystemServer進程中。但是還有一個比較重要的進程ServiceManager進程(簡稱SM)跟zygote是兄弟進程。這個進程的作用是用來統一管理服務,如AMS。它們之間的關系如下。

技術分享圖片

我們的AMS需要向SM進程中註冊信息,其他進程如果想使用AMS,那麽先和ServiceManager進程進行通信查詢,接著再和AMS所在SystemServer進程通信。這部分關系圖如下

技術分享圖片

我們這裏僅上圖分析①②③中的一條道路,我們來分析③,即我們的應用進程(Client)如何與服務進程(Server)交互。

Java層的Binder,我們來看涉及的類的結構圖
技術分享圖片
[IBinder.java]

public interface IBinder {
    //交互函數
    public boolean transact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException;
}

我們接著來看Binder和BinderProxy 他們都聲明在Binder.java中

[Binder.java]

/**
    Binder類
    */
public class Binder implements IBinder {
    public final boolean transact(int code, Parcel data, Parcel reply,
                int flags) throws RemoteException {
        ......
        //這裏調用了onTransact函數進行處理,一般情況下這個函數都會被它的子類重寫
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }
}


/**
    BinderProxy類
    */
final class BinderProxy implements IBinder {
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        //直接以JNI的方式調用Native層的transact函數
        return transactNative(code, data, reply, flags);
    }

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

通用的IPC流程如下

技術分享圖片

現在假設下面一個場景,我們的應用進程即我們的App想要使用ActivityManagerService的startActivity函數(這種場景肯定有的,當我們拿到手機的時候,手機已經預裝了許多App,其中Launcher App(桌面管理App)是在Android系統啟動完成之後啟動的第一個App,我們安裝好一個應用後,點擊應用圖標即發出Intent,想要啟動另一個App中的Activity,我們在AndroidManifest.xml中註冊了Main Activity)。Launcher App所在的進程要與AMS所在的進程SystemServer進程交互。
我們來看這個例子。按照上面的通用流程我們猜測Launcher進程與SystemServer進程交互過程也如上圖所示,那麽按照這個思路我們來看。分為3點:

是否存在業務函數的統一聲明?

這一部分是我們的上圖中的test函數所聲明的類或者接口,我們的Client端代理和Server端服務都要實現這個函數。果然有
[IActivityManager.java]

public interface IActivityManager extends IInterface {
    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
            ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
    ......
}

這裏聲明了我們將要調用的業務函數startActivity,那麽接著第二點

是否存在Server端服務代理?

ActivityManagerProxy是在ActivityManagerNative.java中聲明的內部類

class ActivityManagerProxy implements IActivityManager
{
    public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }

    public IBinder asBinder()
    {
        return mRemote;
    }

    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }

        //看這裏果然是通過mRemote.transact函數,這裏的mRemote是BinderProxy類,關於這一點我們在Native層分析的時候再給出
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }
    ......
}

是否存在Server端服務

ActivityManagerNative是繼承於Binder的抽象類,並重寫了onTransact方法

public abstract class ActivityManagerNative extends Binder implements IActivityManager{
     @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        //根據code處理相應的業務邏輯,我們這裏是START_ACTIVITY_TRANSACTION
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();
            int requestCode = data.readInt();
            int startFlags = data.readInt();
            ProfilerInfo profilerInfo = data.readInt() != 0
                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }
    }
}

既然ActivityManagerNative是個抽象類,那麽誰真正實現了呢

技術分享圖片
[ActivityManagerService.java]

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    //重寫了onTransact函數
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        ......
        
        try {
            //調用父類即ActivityManagerNative的onTransact函數
            return super.onTransact(code, data, reply, flags);
        } catch (RuntimeException e) {
           
            throw e;
        }
    }
}

Launcher進程與SystemServer進程交互過程如下

技術分享圖片

本節小結

關於Java層的Binder機制,我們只需要理解以BinderProxy代表的代理端和Binder代表的服務端的概念即可,例如我們本例中的AMS,AMS是運行在SystemServer進程中的服務端,它間接繼承於Binder,在得到相關請求後,會調用AMS重寫的onTransact函數進行邏輯處理。那麽這個請求就是是AMS的客戶端ActivityManagerProxy通過Binder的方式發給它的,ActivityManagerProxy發送這個請求的方式,是通過調用其內部的成員變量mRemote,這個mRemote其實是BinderProxy的對象,然後BinderProxy通過JNI調用Native層對應函數,最終通過Binder驅動達到與SystemServer交互的目的。

那麽還遺留下以下幾個問題:

1. 服務器端的代理怎麽獲得的

2. 位於代理類中的mRemote這個變量

要想理解好上面的個問題,我們必須向Native層進軍。

Native層Binder

我們依然以AMS分析,我們先來想一下我們在用戶進程中即我們的App中想使用AMS或者其他剪切板之類的系統服務函數了怎麽辦??按照上面的分析我們要獲得AMS的代理ActivityManagerProxy

[ActivityManagerNative.java]

//這裏我們的App進程從SM進程得到AMS服務對應的客戶端代理BinderProxy
IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//以BinderProxy為參數得到我們ActivityManagerProxy,並把BinderProxy對象存儲在mRemote變量中
IActivityManager am = asInterface(b);
       
return am;

到這裏我們就有以下問題,本小節分析1,2

1. 既然可以通過SM獲得對應的客戶端代理,那麽AMS必定已經註冊在SM中了,那麽怎麽註冊的呢?

2. AMS代理是如何獲得的?

3. AMS代理是如何與Binder通信的?

我們來一一分析,在分析問題之前我們先做一個假設,這個假設至關重要,那就是不管我們的SystemServer進程與SM進程交互也好還是我們的App進程與SM進程也好,SM的代理已經事先創建完畢,即不管我們在SystemServer端還是App端,在與SM進程交互的時候不用考慮代理怎麽獲得的。為什麽會有如此假設,因為我自己深受其害,由於上述三個過程均是通過Binder,很容易陷入思維混亂。

AMS是如何註冊的?

我們SystemServer進程中的AMS通過"Socket"與SM進程交互,並把自己註冊在SM中
SystemServer創建出ActivityManagerService後,最終將調用其setSystemProcess方法:

[SystemServer.java]

public void setSystemProcess() {
    try {
        //註冊服務,第二個參數為this,這裏通過“socket”與SM交互
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
        ..........
    } catch (PackageManager.NameNotFoundException e) {
        ........
    }
}

上面的請求最終是通過SM服務代理發送的()

[ServiceManagerNative.java]

public void addService(String name, IBinder service, boolean allowIsolated) 
        throws RemoteException {
    //將數據打包寫入Parcel對象
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    //註意這個地方,後文分析,此時的service為ActivityManagerService
    data.writeStrongBinder(service);
    data.writeInt(allowIsolated ? 1 : 0);
    //調用BindProxy的transact函數
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

上面的過程已經分析過了, 這裏我們主要看一下哪個對應的native層的transact函數

[android_ util_Binder.cpp]

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags)
{
    ........
    //將java對象轉化為native對象
    Parcel* data = parcelForJavaObject(env, dataObj);
    .........
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ........
    //得到native層的BpBinder
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ........
    //通過BpBinder利用IPCThreadState,將請求通過Binder驅動發送給SM進程
    status_t err = target->transact(code, *data, reply, flags);
    ........
}

SM進程收到信息後便處理這個消息(這個說法並不準確,準確的說法是,SM進程中主線程一直在與binder設備交互,想必讀者也猜到了for(;;)),有消息時便通過預先定義好的函數進行處理

[service_manager.c]

switch(txn->code) {

    case SVC_MGR_ADD_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        //do_add_service
        if (do_add_service(bs, s, len, handle, txn->sender_euid,
            allow_isolated, txn->sender_pid))
            return -1;
    break;
}

int do_add_service(struct binder_state *bs,
                   const uint16_t *s, size_t len,
                   uint32_t handle, uid_t uid, int allow_isolated,
                   pid_t spid)
{
    //結構體si,用來存儲服務信息
    struct svcinfo *si;

    //判斷服務有沒有權限註冊,並不是所有的服務都能註冊
    if (!svc_can_register(s, len, spid)) {
        return -1;
    }
    
    //查詢服務有沒有註冊過
    si = find_svc(s, len);
    
    if (si) {//已經註冊過
        if (si->handle) {
            ALOGE("add_service(‘%s‘,%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
                 str8(s, len), handle, uid);
            svcinfo_death(bs, si);
        }
        si->handle = handle;
    } else {//還沒有註冊過,我們進入這個分支
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
            ALOGE("add_service(‘%s‘,%x) uid=%d - OUT OF MEMORY\n",
                 str8(s, len), handle, uid);
            return -1;
        }
        //保存一些handle等信息
        si->handle = handle;
        si->len = len;
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = ‘\0‘;
        si->death.func = (void*) svcinfo_death;
        si->death.ptr = si;
        si->allow_isolated = allow_isolated;
        si->next = svclist;
        svclist = si;
    }

    binder_acquire(bs, handle);
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}

看到這裏SM貌似只保留了一些AMS的信息而已,實際上並不只是如此,我們來看一下上面的保留問題

[Parcel.java]

data.writeStrongBinder(service);

public final void writeStrongBinder(IBinder val) {
    //調用了native函數
    nativeWriteStrongBinder(mNativePtr, val);
}

跟進[android_os_Parcel.cpp]

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

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

    //obj為Binder類
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        //調用了JavaBBinderHolder的get方法
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }

    //obj為BinderProxy類
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }

    ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
    return NULL;
}

跟進[Pacel.cpp]

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

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) {//binder不為空
        IBinder *local = binder->localBinder();//是不是本地binder,本地的意思是同一個進程中的調用
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don‘t pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {//我們這裏明顯不是
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {//錯誤信息
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }

    return finish_flatten_binder(binder, obj, out);
}

通過上面的代碼,我們可以看到當一個服務進行註冊時,會將Java層的Binder對象和Native層的BBinder關聯起來,於是服務端綁定到了Native層的Binder架構。
此外,addService中打包傳入的其實不是ActivityManagerService本身,而是對應的JavaBBinder對象。
這裏對應的結構如下圖所示:

AMS代理是如何獲得的?

我們上面SystemServer中的AMS已經在SM中準備好了,那我們ServiceManager.getService(Context.ACTIVITY_SERVICE);
一樣的過程,我們知道最終會在service_manager.c中處理

switch(txn->code) {
    //這裏有個case穿透,,好吧
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        //查詢AMS保存在SM中對應的的那個handle
        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
        bio_put_ref(reply, handle);
        return 0;
}
把寫入數據後的reply返回
bio_put_uint32(reply, 0);

回到我們的調用處
[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);
    //看這裏readStrongBinder,是不是感覺跟我們上面的writeStrongBinder感覺是一對的
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

Parcel的readStrongBinder還是個JNI調用

[android_ os_Parcel.cpp]

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        //這裏我們看到了什麽,,看函數名字應該是為Binder生成一個java對象吧
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}

我們先看Pacel的readStrongBinder方法
[Parcel.cpp]

sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    //看到這裏,還記得writeStrongBinder中的flatten_binder,這裏是unflatten_binder
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}

status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);

    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                //到這裏我們也清楚了進入這個分支
                //調用ProcessState的getStrongProxyForHandle函數
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

繼續跟進[ProcessState.cpp]

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
       
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {//這裏handle為0的情況是為SM準備的,
               
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            //我們的不為0,在這裏創建了BpBinder
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
           
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

好了剩下最後一個了javaObjectForIBinder

[android_ util_Binder.cpp]

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

    //如果val是Binder對象,進入下面分支,此時val是BpBinder
    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;
    }
    .........
    //調用BpBinder的findObject函數
    //在Native層的BpBinder中有一個ObjectManager,它用來管理在Native BpBinder上創建的Java BinderProxy對象
    //findObject用於判斷gBinderProxyOffsets中,是否存儲了已經被ObjectManager管理的Java BinderProxy對象
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        ............
        //如果該Java BinderProxy已經被管理,則刪除這個舊的BinderProxy
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

    //創建一個新的BinderProxy對象
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        // 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));

        //新創建的BinderProxy對象註冊到BpBinder的ObjectManager中,同時註冊一個回收函數proxy_cleanup
        //當BinderProxy對象detach時,proxy_cleanup函數將被調用,以釋放一些資源
        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);
        //將死亡通知list和BinderProxy聯系起來
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

        // Note that a new object reference has been created.
        android_atomic_inc(&gNumProxyRefs);

        //垃圾回收相關;利用gNumRefsCreated記錄創建出的BinderProxy數量
        //當創建出的BinderProxy數量大於200時,該函數將利用BinderInternal的ForceGc函數進行一個垃圾回收
        incRefsCreated(env);

        return object;
    }
}

到這裏總算都打通了總體流程如下

技術分享圖片

驅動層Binder

還剩下遺留下的兩個問題

AMS代理是如何與Binder通信的?

通過Java層的服務端代理最終調用到BpBinder.transact函數

[BpBinder.cpp]

status_t BpBinder:transact(uint32_t code,const Parcel&data,Parcel*reply,uint32_t flags){
    if(mAlive){
        //BpBinder把transact工作交給了IPCThreadState。
        status_t status=IPCThreadState:self()->transact(
        mHandle,code,data,reply,flags);//mHandle也是參數
        if(status==DEAD_OBJECT)mAlive=0;
        return status;
    }
    return DEAD_OBJECT;
}

[IPCThreadState.cpp]

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mMyThreadId(gettid()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    //mIn和mOut是兩個Parcel。 把它看成是發送和接收命令的緩沖區即可。
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}


status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    ......
    /*
    註意這裏的第一個參數BC_TRANSACTION,它是應用程序向binder設備發送消息的消
    息碼,而binder設備向應用程序回復消息的消息碼以BR_開頭。 消息碼的定義在
    binder_module.h中,請求消息碼和回應消息碼的對應關系,需要查看Binder驅動的實
    現才能將其理清楚,我們這裏暫時用不上。
    */
    
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    ......
    err = waitForResponse(NULL, NULL);
    ......
    return err;
}

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
   //binder_transaction_data是和binder設備通信的數據結構。
    binder_transaction_data tr;
    //果然,handle的值傳遞給了target,用來標識目的端,其中0是ServiceManager的標誌。
    tr.target.handle=handle;
    //code是消息碼,是用來switch/case的!
    tr.code = code;
    tr.flags = binderFlags;
    tr.cookie = 0;
    tr.sender_pid = 0;
    tr.sender_euid = 0;
    
    const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
        tr.data_size = data.ipcDataSize();
        tr.data.ptr.buffer = data.ipcData();
        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
        tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
        tr.offsets_size = 0;
        tr.data.ptr.offsets = 0;
    } else {
        return (mLastError = err);
    }
    
    //把命令寫到mOut中,而不是直接發出去,可見這個函數有點名不副實。
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));
    
    return NO_ERROR;
}

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) <NO_ERROR) break;
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;
        //看見沒?這裏開始操作mIn了,看來talkWithDriver中
        //把mOut發出去,然後從driver中讀到數據放到mIn中了。
        cmd = mIn.readInt32();


   }
}

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    binder_write_read bwr;
       //中間東西太復雜了,不就是把mOut數據和mIn接收數據的處理後賦值給bwr嗎?
        status_t err;
        do {
    //用ioctl來讀寫
            if (ioctl(mProcess->mDriverFD,BINDER_WRITE_READ, &bwr) >= 0)
                err = NO_ERROR;
            else
                err = -errno;
      } while (err == -EINTR);
    //到這裏,回復數據就在bwr中了,bmr接收回復數據的buffer就是mIn提供的
            if (bwr.read_consumed > 0) {
                mIn.setDataSize(bwr.read_consumed);
                mIn.setDataPosition(0);
            }
    returnNO_ERROR;
}

本篇總結

我們本篇詳細分析了Binder機制,從概述->Java層Binder->Native層Binder->Binder驅動,位於各層次的讀者都能獲得收獲。


下篇預告

不好意思各位,下周有個比較重要的面試,所以暫時不會更新該系列的博客,但是也會更新其他博客。記錄準備面試的過程中需要用到的比較容易錯誤的知識。


此致,敬禮

Android開發之漫漫長途 Ⅷ——Android Binder(也許是最容易理解的)