Android Binder(也許是最容易理解的)

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


前言

咱們在上一篇中比較詳盡的介紹了Android的消息機制,不過有一些內容咱們在不理解Android Binder的話是沒法講解清楚的。對於初學Android的朋友而言,最難卻又最想掌握的恐怕就是Binder機制了,由於Android系統基本上能夠看做是一個基於Binder通訊的C/S架構。 Binder就像網絡同樣,把系統的各個部分鏈接在了一塊兒,所以它是很是重要的。咱們下面會Android Binder機制進行從上到下從易到難的分層次講解,從而既能讓初學者對Binder有必定認識,也能讓有必定Android基礎的人得到收穫。
注:下文中的源碼均出自android-6.0.0_r5linux

Binder概述

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

進程

在該系列博客中的第一章咱們就提及了Android進程相關問題,Android故意弱化了進程的概念,而用相對容易理解的四大組件。但是咱們在稍微深刻Android的時候,那麼進程是繞不過的。默認狀況下,同一個應用程序中的全部組件運行在同一個進程中,並且絕大多數的應用程序也都是這樣的。這個默認進程是用這個應用的包名來命名的。程序員

進程間通訊

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

管道(Pipe)

管道是由內核管理的一個緩衝區,至關於咱們放入內存中的一個紙條。管道的一端鏈接一個進程的輸出。這個進程會向管道中放入信息。管道的另外一端鏈接一個進程的輸入,這個進程取出被放入管道的信息。安全

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

命名管道(FIFO)

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

共享內存(Share Memory)

共享內存是在多個進程之間共享內存區域的一種進程間的通訊方式,由IPC爲進程建立的一個特殊地址範圍,它將出如今該進程的地址空間中。其餘進程能夠將同一段共享內存鏈接到本身的地址空間中。全部進程均可以訪問共享內存中的地址,若是一個進程向共享內存中寫入了數據,所作的改動將馬上被其餘進程看到。cookie

  • 共享內存是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經過SM的代理與SM進程交互(讀者也能夠把這個過程想象爲你所能理解的進程間通訊方式,例如管道、Socket等),並把本身註冊在SM中
SystemServer建立出ActivityManagerService後,最終將調用其setSystemProcess方法:

[SystemServer.java]

public void setSystemProcess() {
    try {
        //註冊服務,第二個參數爲this,這裏假設SystemServer經過「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);
            }
    return NO_ERROR;
}

本篇總結

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


下篇預告

很差意思各位,下週有個比較重要的面試,因此暫時不會更新該系列的博客,可是也會更新其餘博客。記錄準備面試的過程當中須要用到的比較容易錯誤的知識。


此致,敬禮

相關文章
相關標籤/搜索