鍍金池/ 教程/ Android/ <span>第6章 深入理解Binder</span>
第4章 ?深入理解 Zygote
第10章 深入理解MediaScanner
第3章 ?深入理解init
第8章 ?深入理解Surface系統(tǒng)
第5章 深入理解常見類
第7章 ?深入理解Audio系統(tǒng)
第一章 ?閱讀前的準備工作
<span>第6章 深入理解Binder</span>
第9章 ?深入理解Vold和Rild
第2章? 深入理解JNI

<span>第6章 深入理解Binder</span>

本章主要內(nèi)容

·? 以MediaServer為切入點,對Binder的工作機制進行分析。

·? 剖析ServiceManager的原理。

·? 以MediaPlayerService為切入點對Client和Service的交互進行分析。

·? 學(xué)以致用,探討如何寫自己的Service。

本章涉及的源代碼文件名及位置

下面是我們本章分析的源碼文件名及其位置。

·? Main_mediaserver.cpp

framework/base/Media/MediaServer/Main_mediaserver.cpp

·? Static.cpp

framework/base/libs/binder/Static.cpp

·? ProcessState.cpp

framework/base/libs/binder/ProcessState.cpp

·? IServiceManager.cpp

framework/base/libs/binder/IServiceManager.cpp

·? BpBinder.cpp

framework/base/libs/binder/BpBinder.cpp

·? IInterface.h

framework/base/include/binder/IInterface.h

·? IServiceManager.h

framework/base/include/binder/IServiceManager.h

·? IServiceManager.cpp

framework/base/libs/binder/IServiceManager.cpp

·? binder.cpp

framework/base/libs/binder/binder.cpp

·? MediaPlayerService.cpp

framework/base/media/libmediaplayerservice/MediaPlayerService.cpp

·? IPCThreadState.cpp

framework/base/libs/binder/ IPCThreadState.cpp

·? binder_module.h

framework/base/include/private/binder.h

·? Service_manager.c

framework/base/cmds/ServiceManager/Service_manager.c

·? Binder.c

framework/base/cmds/ServiceManager/Binder.c

·? ?IMediaDeathNotifier

framework/base/media/libmedia/ IMediaDeathNotifier.cpp

·? MediaMetadataRetriever

framework/base/media/libmedia/ MediaMetadataRetriever.cpp

6.1 ?概述

Binder是Android系統(tǒng)提供的一種IPC(進程間通信)機制。由于Android是基于Linux內(nèi)核的,因此,除了Binder外,還存在其他的IPC機制,例如管道和socket等。Binder相對于其他IPC機制來說,就更加靈活和方便了。對于初學(xué)Android的朋友而言,最難卻又最想掌握的恐怕就是Binder機制了,因為Android系統(tǒng)基本上可以看作是一個基于Binder通信的C/S架構(gòu)。Binder就像網(wǎng)絡(luò)一樣,把系統(tǒng)各個部分連接在了一起,因此它是非常重要的。

在基于Binder通信的C/S架構(gòu)體系中,除了C/S架構(gòu)所包括的Client端和Server端外,Android還有一個全局的ServiceManager端,它的作用是管理系統(tǒng)中的各種服務(wù)(Service)。Client、Server和ServiceManager這三者之間的交互關(guān)系,如圖6-1所示 :

http://wiki.jikexueyuan.com/project/deep-android-v1/images/chapter6/image001.png" alt="image" />

圖6-1?Client、Server和ServiceManager三者之間的交互關(guān)系

注意:一個Server進程可以注冊多個Service,就像即將講解的MediaServer一樣。

根據(jù)圖6-1,可以得出如下結(jié)論:

·? Server進程要先注冊一些Service到ServiceManager中,所以Server是ServiceManager的客戶端,而ServiceManager就是服務(wù)端了。

·? 如果某個Client進程要使用某個Service,必須先到ServiceManager中獲取該Service的相關(guān)信息,所以Client是ServiceManager的客戶端。

·? Client根據(jù)得到的Service信息建立與Service所在的Server進程通信的通路,然后就可以直接與Service交互了,所以Client也是Server的客戶端。

·? 最重要的一點是,三者的交互都是基于Binder通信的,所以通過任意兩者之間的關(guān)系,都可以揭示Binder的奧秘。

這里,要重點強調(diào)的是Binder通信與C/S架構(gòu)之間的關(guān)系。Binder只是為C/S架構(gòu)提供了一種通信的方式,我們完全可以采用其他IPC方式進行通信,例如,系統(tǒng)中有很多其他的程序采用的就是Socket或Pipe的方法進行進程間通信。很多初學(xué)者可能覺得Binder較復(fù)雜,尤其是看到諸如BpXXX、BnXXX之類的定義便感到頭暈,這很有可能是把Binder通信層結(jié)構(gòu)和應(yīng)用的業(yè)務(wù)層結(jié)構(gòu)搞混了。如果能搞清楚這二者的關(guān)系,完全可以自己實現(xiàn)一個不使用BpXXX和BnXXX的Service。須知,ServiceManager可并沒有使用它們。

6.2 ?庖丁解MediaServer

為了能像“庖丁”那樣解析Binder,我們必須得找一頭“?!眮碜鼋馄?,而MediaServer(簡稱MS)正是一頭比較好的“牛”。它是一個可執(zhí)行程序,雖然Android的SDK提供Java層的API,但Android系統(tǒng)本身還是一個完整的基于Linux內(nèi)核的操作系統(tǒng),所以不會是所有程序都用Java編寫,這里的MS就是一個用C++編寫的可執(zhí)行程序。

之所以選擇MediaServer作為切入點,是因為這個Server是系統(tǒng)諸多重要Service的棲息地,它們包括:

·? AudioFlinger:音頻系統(tǒng)中的重要核心服務(wù)。

·? AudioPolicyService:音頻系統(tǒng)中關(guān)于音頻策略的重要服務(wù)。

·? MediaPlayerService:多媒體系統(tǒng)中的重要服務(wù)。

·? CameraService:有關(guān)攝像/照相的重要服務(wù)。

可以看到,MS除了不涉及Surface系統(tǒng)外,其他重要的服務(wù)基本上都涉及到了,它不愧是“庖丁”所要的好“?!?。

本章將以其中的MediaPlayerService為主切入點進行分析。先來分析MediaServer本身。

6.2.1 ?MediaServer的入口函數(shù)

MS是一個可執(zhí)行程序,入口函數(shù)是main,代碼如下所示:

[-->Main_MediaServer.cpp]

int main(int argc, char** argv)

{

? //①獲得一個ProcessState實例

?sp<ProcessState>proc(ProcessState::self());

?

?//②MS作為ServiceManager的客戶端,需要向ServiceManger注冊服務(wù)

?//調(diào)用defaultServiceManager,得到一個IServiceManager。

?sp<IServiceManager>sm = defaultServiceManager();

?

?//初始化音頻系統(tǒng)的AudioFlinger服務(wù)

?AudioFlinger::instantiate();

?//③多媒體系統(tǒng)的MediaPlayer服務(wù),我們將以它作為主切入點

?MediaPlayerService::instantiate();

?//CameraService服務(wù)

?CameraService::instantiate();

?//音頻系統(tǒng)的AudioPolicy服務(wù)

?AudioPolicyService::instantiate();

?

?//④根據(jù)名稱來推斷,難道是要創(chuàng)建一個線程池嗎?

?ProcessState::self()->startThreadPool();

?//⑤下面的操作是要將自己加入到剛才的線程池中嗎?

?IPCThreadState::self()->joinThreadPool();

}

上面的代碼中,確定了5個關(guān)鍵點,讓我們通過對這5個關(guān)鍵點逐一進行深入分析,來認識和理解Binder。

6.2.2 ?獨一無二的ProcessState

我們在main函數(shù)的開始處便碰見了ProcessState。由于每個進程只有一個ProcessState,所以它是獨一無二的。它的調(diào)用方式如下面的代碼所示:

[-->Main_MediaServer.cpp]

//①獲得一個ProcessState實例

sp<ProcessState> proc(ProcessState::self());

下面,來進一步分析這個獨一無二的ProcessState。

1. 單例的ProcessState

ProcessState的代碼如下所示:

[-->ProcessState.cpp]

sp<ProcessState> ProcessState::self()

{

?? //gProcess是在Static.cpp中定義的一個全局變量

?? //程序剛開始執(zhí)行,gProcess一定為空

??? if(gProcess != NULL) return gProcess;

??????? AutoMutex_l(gProcessMutex);

???? //創(chuàng)建一個ProcessState對象,并賦值給gProcess

??? if(gProcess == NULL) gProcess = new ProcessState;

?

???? returngProcess;

}

self函數(shù)采用了單例模式,這很明確地告訴了我們一個信息:每個進程只有一個ProcessState對象。這一點,從它的命名中也可看出些端倪。

2. ProcessState的構(gòu)造

再來看ProcessState的構(gòu)造函數(shù)。這個函數(shù)非常重要,它悄悄地打開了Binder設(shè)備。代碼如下所示:

[-->ProcessState.cpp]

ProcessState::ProcessState()

?? // Android的中有很多代碼都是這么寫的,稍不留神就容易忽略這里調(diào)用了一個很重要的函數(shù)

??? :mDriverFD(open_driver())

??? ,mVMStart(MAP_FAILED)//映射內(nèi)存的起始地址

??? ,mManagesContexts(false)

??? ,mBinderContextCheckFunc(NULL)

??? , mBinderContextUserData(NULL)

??? ,mThreadPoolStarted(false)

??? ,mThreadPoolSeq(1)

{

? if(mDriverFD >= 0) {

??/*

BIDNER_VM_SIZE定義為(1*1024*1024) - (4096 *2) = 1M-8K

?? mmap的用法希望讀者man一下,不過這個函數(shù)真正的實現(xiàn)和驅(qū)動有關(guān)系,而Binder驅(qū)動會分配一塊

內(nèi)存用來接收數(shù)據(jù)。

*/

??mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ,MAP_PRIVATE | MAP_NORESERVE,

???????????????????? mDriverFD, 0);

??? }

??? ......

}

3. 打開binder設(shè)備

open_driver的作用就是打開/dev/binder這個設(shè)備,它是android在內(nèi)核中專門用于完成進程間通信而設(shè)置的一個虛擬設(shè)備,具體實現(xiàn)如下所示:

[-->ProcessState.cpp]

static int open_driver()

{

??? int fd =open("/dev/binder", O_RDWR);//打開/dev/binder設(shè)備

??? if (fd>= 0) {

?? ????? ......

???????size_t maxThreads = 15;

?????? //通過ioctl方式告訴binder驅(qū)動,這個fd支持的最大線程數(shù)是15個

???????result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);??

?? }

return fd;

......

}

至此,Process::self函數(shù)就分析完了。它到底干了什么呢?通過前面的分析,總結(jié)如下:

·? 打開/dev/binder設(shè)備,這就相當(dāng)于與內(nèi)核的Binder驅(qū)動有了交互的通道。

·? 對返回的fd使用mmap,這樣Binder驅(qū)動就會分配一塊內(nèi)存來接收數(shù)據(jù)。

·? 由于ProcessState的惟一性,因此一個進程只打開設(shè)備一次。

分析完P(guān)rocessState,接下來將要分析第二個關(guān)鍵函數(shù)defaultServiceManager。

6.2.3 ?時空穿越魔術(shù)——defaultServiceManager

defaultServiceManager函數(shù)的實現(xiàn)在IServiceManager.cpp中完成。它會返回一個IServiceManager對象,通過這個對象,我們可以神奇地與另一個進程ServiceManager進行交互。是不是有一種觀看時空穿越魔術(shù)表演的感覺?

1. 魔術(shù)前的準備工作

先來看看defaultServiceManager都調(diào)用了哪些函數(shù)?返回的這個IServiceManager到底是什么?具體實現(xiàn)代碼如下所示:

[-->IServiceManager.cpp]

sp<IServiceManager> defaultServiceManager()

{

??? //看樣子又是一個單例,英文名叫 Singleton,Android是一個優(yōu)秀的源碼庫,大量使用了

?? //設(shè)計模式,建議讀者以此為契機學(xué)習(xí)設(shè)計模式,首推GOF的《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》

??? if(gDefaultServiceManager != NULL) return gDefaultServiceManager;

???? {

???????AutoMutex _l(gDefaultServiceManagerLock);

??????? if(gDefaultServiceManager == NULL) {

??????? ? //真正的gDefaultServiceManager是在這里創(chuàng)建的。

???????????gDefaultServiceManager = interface_cast<IServiceManager>(

??????????? ?????????????????????? ProcessState::self()->getContextObject(NULL));

??????? }

??? }

?? returngDefaultServiceManager;

}

哦,是調(diào)用了ProcessState的getContextObject函數(shù)!注意:傳給它的參數(shù)是NULL,即0。既然是“庖丁解牛”,就還要一層一層往下切。下面再看getContextObject函數(shù),如下所示:

[-->ProcessState.cpp]

sp<IBinder>ProcessState::getContextObject(const sp<IBinder>& caller)

{

? ?/*

caller的值為0!注意,該函數(shù)返回的是IBinder。它是什么?我們后面再說。

??? supportsProcesses函數(shù)根據(jù)openDriver函數(shù)打開設(shè)備是否成功來判斷是否支持process

真實設(shè)備肯定支持process。

?? */

? if(supportsProcesses()) {

?? //真實設(shè)備上肯定是支持進程的,所以會調(diào)用下面這個函數(shù)

???????return getStrongProxyForHandle(0);

??? } else {

???????return getContextObject(String16("default"), caller);

??? }

}

getStrongProxyForHandle這個函數(shù)名怪怪的,可能會讓人感到些許困惑。請注意,它的調(diào)用參數(shù)的名字叫handle,Windows編程中經(jīng)常使用這個名稱,它是對資源的一種標識。說白了,其實就是有一個資源項,保存在一個資源數(shù)組(也可以是別的組織結(jié)構(gòu))中,handle的值正是該資源項在數(shù)組中的索引。

[-->ProcessState.cpp]

sp<IBinder>ProcessState::getStrongProxyForHandle(int32_t handle)

{

???sp<IBinder> result;

?AutoMutex_l(mLock);

/*

根據(jù)索引查找對應(yīng)資源。如果lookupHandleLocked發(fā)現(xiàn)沒有對應(yīng)的資源項,則會創(chuàng)建一個新的項并返回。

這個新項的內(nèi)容需要填充。

??? */

???handle_entry* e = lookupHandleLocked(handle);

??? if (e !=NULL) {

???????IBinder* b = e->binder;

??????? if (b== NULL || !e->refs->attemptIncWeak(this)) {

???????????//對于新創(chuàng)建的資源項,它的binder為空,所以走這個分支。注意,handle的值為0

??????????? b= new BpBinder(handle); //創(chuàng)建一個BpBinder

???????????e->binder = b; //填充entry的內(nèi)容

???????????if (b) e->refs = b->getWeakRefs();

???????????result = b;

??????? }else {

???????????result.force_set(b);

???????????e->refs->decWeak(this);

??????? }

??? }

??? returnresult; //返回BpBinder(handle),注意,handle的值為0

}

2. 魔術(shù)表演的道具——BpBinder

眾所周知,玩魔術(shù)是必須有道具的。這個穿越魔術(shù)的道具就是BpBinder。BpBinder是什么呢?有必要先來介紹它的孿生兄弟BBinder。

BpBinder和BBinder都是Android中與Binder通信相關(guān)的代表,它們都從IBinder類中派生而來,如圖6-2所示:

http://wiki.jikexueyuan.com/project/deep-android-v1/images/chapter6/image002.png" alt="image" />

圖6-2 Binder家族圖譜

從上圖中可以看出:

·? BpBinder是客戶端用來與Server交互的代理類,p即Proxy的意思。

·? BBinder則是proxy相對的一端,它是proxy交互的目的端。如果說Proxy代表客戶端,那么BBinder則代表服務(wù)端。這里的BpBinder和BBinder是一一對應(yīng)的,即某個BpBinder只能和對應(yīng)的BBinder交互。我們當(dāng)然不希望通過BpBinderA發(fā)送的請求,卻由BBinderB來處理。

剛才我們在defaultServiceManager()函數(shù)中創(chuàng)建了這個BpBinder。這里有兩個問題:

·? 為什么創(chuàng)建的不是BBinder?

因為我們是ServiceManager的客戶端,當(dāng)然得使用代理端以與ServiceManager交互了。

·? 前面說了,BpBinder和BBinder是一一對應(yīng)的,那么BpBinder如何標識它所對應(yīng)的BBinder端呢?

答案是Binder系統(tǒng)通過handler來對應(yīng)BBinder。以后我們會確認這個Handle值的作用。

注意:我們給BpBinder構(gòu)造函數(shù)傳的參數(shù)handle的值是0。這個0在整個Binder系統(tǒng)中有重要含義—因為0代表的就是ServiceManager所對應(yīng)的BBinder。

BpBinder是如此重要,必須對它進行深入分析,其代碼如下所示:

[-->BpBinder.cpp]

BpBinder::BpBinder(int32_t handle)

??? :mHandle(handle)//handle是0

??? ,mAlive(1)

??? ,mObitsSent(0)

??? ,mObituaries(NULL)

{

?? extendObjectLifetime(OBJECT_LIFETIME_WEAK);

?? //另一個重要對象是IPCThreadState,我們稍后會詳細講解。

???IPCThreadState::self()->incWeakHandle(handle);

}

看上面的代碼,會覺得BpBinder確實簡單,不過再仔細查看,你或許會發(fā)現(xiàn),BpBinder、BBinder這兩個類沒有任何地方操作ProcessState打開的那個/dev/binder設(shè)備,換言之,這兩個Binder類沒有和binder設(shè)備直接交互。那為什么說BpBinder會與通信相關(guān)呢?注意本小節(jié)的標題,BpBinder只是道具嘛!所以它后面一定還另有機關(guān)。不必急著揭秘,還是先回顧一下道具出場的歷程。

我們是從下面這個函數(shù)開始分析的:

gDefaultServiceManager =interface_cast<IServiceManager>(

???????????????????????????????????????????ProcessState::self()->getContextObject(NULL));

現(xiàn)在這個函數(shù)調(diào)用將變成如下所示:

gDefaultServiceManager =interface_cast<IServiceManager>(new BpBinder(0));

這里出現(xiàn)了一個interface_cast。它是什么?其實是一個障眼法!下面就來具體分析它。

3. 障眼法——interface_cast

interface_cast、dynamic_cast和static_cast看起來是否非常眼熟?它們是指針類型轉(zhuǎn)換的意思嗎?如果是,那又是如何將BpBinder*類型強制轉(zhuǎn)化成IServiceManager*類型的?BpBinder的家譜我們剛才也看了,它的“爸爸的爸爸的爸爸”這條線上沒有任何一個與IServiceManager有任何關(guān)系。

問題談到這里,我們得去看看interface_cast的具體實現(xiàn),其代碼如下所示:

[-->IInterface.h]

template<typename INTERFACE>

inline sp<INTERFACE> interface_cast(constsp<IBinder>& obj)

{

??? returnINTERFACE::asInterface(obj);

}

哦,僅僅是一個模板函數(shù),所以interface_cast<IServiceManager>()等價于:

inline sp<IServiceManager>interface_cast(const sp<IBinder>& obj)

{

??? return IServiceManager::asInterface(obj);

}

又轉(zhuǎn)移到IServiceManager對象中去了,這難道不是障眼法嗎?既然找到了“真身”,不妨就來見識見識它吧。

4. 撥開浮云見月明——IServiceManager

剛才提到,IBinder家族的BpBinder和BBinder是與通信業(yè)務(wù)相關(guān)的,那么業(yè)務(wù)層的邏輯又是如何巧妙地架構(gòu)在Binder機制上的呢?關(guān)于這些問題,可以用一個絕好的例子來解釋,它就是IServiceManager。

(1)定義業(yè)務(wù)邏輯

先回答第一個問題:如何表述應(yīng)用的業(yè)務(wù)層邏輯??梢韵确治鲆幌翴ServiceManager是怎么做的。IServiceManager定義了ServiceManager所提供的服務(wù),看它的定義可知,其中有很多有趣的內(nèi)容。IServiceManager定義在IServiceManager.h中,代碼如下所示:

[-->IServiceManager.h]

class IServiceManager : public IInterface

{

?public:

?? //關(guān)鍵無比的宏!

?? DECLARE_META_INTERFACE(ServiceManager);

?

??? //下面是ServiceManager所提供的業(yè)務(wù)函數(shù)

??? virtualsp<IBinder>??? getService( constString16& name) const = 0;

??? virtualsp<IBinder>??? checkService( constString16& name) const = 0;

??? virtualstatus_t????? ??addService( const String16& name,

??????????????????????????? ???????????????????const sp<IBinder>&service) = 0;

?? ?virtual Vector<String16>??? listServices() = 0;

??? ......

};

(2)業(yè)務(wù)與通信的掛鉤

Android巧妙地通過DECLARE_META_INTERFACE和IMPLENT宏,將業(yè)務(wù)和通信牢牢地鉤在了一起。DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE這兩個宏都定義在剛才的IInterface.h中。先看DECLARE_META_INTERFACE這個宏,如下所示:

[-->IInterface.h::DECLARE_META_INTERFACE]

#define DECLARE_META_INTERFACE(INTERFACE)?????????????????????????????? \

??? staticconst android::String16 descriptor;????????????????????????? \

??? staticandroid::sp<I##INTERFACE> asInterface(?????????????????????? \

???????????const android::sp<android::IBinder>& obj);???????????????? ?\

??? virtualconst android::String16& getInterfaceDescriptor() const;??? \

???I##INTERFACE();????????????????????????????????????????????????????\

??? virtual~I##INTERFACE();????

將IServiceManager的DELCARE宏進行相應(yīng)的替換后得到的代碼如下所示:

[--->DECLARE_META_INTERFACE(IServiceManager)]

//定義一個描述字符串

static const android::String16 descriptor;

?

//定義一個asInterface函數(shù)

static android::sp< IServiceManager >

asInterface(constandroid::sp<android::IBinder>& obj)

?

//定義一個getInterfaceDescriptor函數(shù),估計就是返回descriptor字符串

virtual const android::String16&getInterfaceDescriptor() const;

?

//定義IServiceManager的構(gòu)造函數(shù)和析構(gòu)函數(shù)

IServiceManager ();???????????????????????????????????????????????????

virtual ~IServiceManager();

DECLARE宏聲明了一些函數(shù)和一個變量,那么,IMPLEMENT宏的作用肯定就是定義它們了。IMPLEMENT的定義在IInterface.h中,IServiceManager是如何使用了這個宏呢?只有一行代碼,在IServiceManager.cpp中,如下所示:

IMPLEMENT_META_INTERFACE(ServiceManager,"android.os.IServiceManager");

很簡單,可直接將IServiceManager中的IMPLEMENT宏的定義展開,如下所示:

const android::String16

IServiceManager::descriptor(“android.os.IServiceManager”);

//實現(xiàn)getInterfaceDescriptor函數(shù)

const android::String16& IServiceManager::getInterfaceDescriptor()const

?{?

??? //返回字符串descriptor,值是“android.os.IServiceManager”

????? return IServiceManager::descriptor;

? }????

//實現(xiàn)asInterface函數(shù)

?android::sp<IServiceManager>

?????????????IServiceManager::asInterface(constandroid::sp<android::IBinder>& obj)

{

???????android::sp<IServiceManager> intr;

??????? if(obj != NULL) {??????????? ??????????????????????????????????

???????????intr = static_cast<IServiceManager *>(?????????????????????????

???????????????obj->queryLocalInterface(IServiceManager::descriptor).get());??

???????????if (intr == NULL) {

?????????????//obj是我們剛才創(chuàng)建的那個BpBinder(0)

???????????????intr = new BpServiceManager(obj);

??????????? }

??????? }

???????return intr;

}

//實現(xiàn)構(gòu)造函數(shù)和析構(gòu)函數(shù)

IServiceManager::IServiceManager () { }

IServiceManager::~ IServiceManager() { }

我們曾提出過疑問:interface_cast是如何把BpBinder指針轉(zhuǎn)換成一個IServiceManager指針的呢?答案就在asInterface函數(shù)的一行代碼中,如下所示:

intr = new BpServiceManager(obj);

明白了!interface_cast不是指針的轉(zhuǎn)換,而是利用BpBinder對象作為參數(shù)新建了一個BpServiceManager對象。我們已經(jīng)知道BpBinder和BBinder與通信有關(guān)系,這里怎么突然冒出來一個BpServiceManager?它們之間又有什么關(guān)系呢?

(3)IServiceManager家族

要搞清這個問題,必須先了解IServiceManager家族之間的關(guān)系,先來看圖6-3,它展示了IServiceManager的家族圖譜。

http://wiki.jikexueyuan.com/project/deep-android-v1/images/chapter6/image003.png" alt="image" />

圖6-3 IServiceManager的家族圖譜

根據(jù)圖6-3和相關(guān)的代碼可知,這里有以下幾個重要的點值得注意:

·? IServiceManager、BpServiceManager和BnServiceManager都與業(yè)務(wù)邏輯相關(guān)。

·? BnServiceManager同時從BBinder派生,表示它可以直接參與Binder通信。

·? BpServiceManager雖然從BpInterface中派生,但是這條分支似乎與BpBinder沒有關(guān)系。

·? BnServiceManager是一個虛類,它的業(yè)務(wù)函數(shù)最終需要子類來實現(xiàn)。

重要說明:以上這些關(guān)系很復(fù)雜,但ServiceManager并沒有使用錯綜復(fù)雜的派生關(guān)系,它直接打開Binder設(shè)備并與之交互。后文,還會詳細分析它的實現(xiàn)代碼。

圖6-3中的BpServiceManager,既然不像它的兄弟BnServiceManager那樣直接與Binder有血緣關(guān)系,那么它又是如何與Binder交互的呢?簡言之,BpRefBase中的mRemote的值就是BpBinder。如果你不相信,仔細看BpServiceManager左邊的派生分支樹上的一系列代碼,它們都在IServiceManager.cpp中,如下所示:

[-->IServiceManager.cpp::BpServiceManager類]

//通過它的參數(shù)可得知,impl是IBinder類型,看來與Binder有間接關(guān)系,它實際上是BpBinder對象

BpServiceManager(const sp<IBinder>& impl)

?? //調(diào)用基類BpInterface的構(gòu)造函數(shù)

?? : BpInterface<IServiceManager>(impl)

{

}

BpInterface的實現(xiàn)代碼如下所示:

[-->IInterface.h::BpInterface類]

template<typename INTERFACE>

inlineBpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)

??? :BpRefBase(remote)//基類構(gòu)造函數(shù)

{

}

BpRefBase()的實現(xiàn)代碼如下所示:

[-->Binder.cpp::BpRefBase類]

BpRefBase::BpRefBase(const sp<IBinder>&o)

? //mRemote最終等于那個new 出來的BpBinder(0)

??? :mRemote(o.get()), mRefs(NULL), mState(0)

{

???extendObjectLifetime(OBJECT_LIFETIME_WEAK);

?

??? if(mRemote) {

???????mRemote->incStrong(this);??????????

??????? mRefs= mRemote->createWeak(this);

??? }

}

原來,BpServiceManager的一個變量mRemote是指向了BpBinder。至此,我們的魔術(shù)表演完了,回想一下defaultServiceManager函數(shù),可以得到以下兩個關(guān)鍵對象:

·? 有一個BpBinder對象,它的handle值是0。

·? 有一個BpServiceManager對象,它的mRemote值是BpBinder。

BpServiceManager對象實現(xiàn)了IServiceManager的業(yè)務(wù)函數(shù),現(xiàn)在又有BpBinder作為通信的代表,接下來的工作就簡單了。下面,要通過分析MediaPlayerService的注冊過程,進一步分析業(yè)務(wù)函數(shù)的內(nèi)部是如何工作的。

6.2.4 ?注冊MediaPlayerService

1. 業(yè)務(wù)層的工作

再回到MS的main函數(shù),下一個要分析的是MediaPlayerService,它的代碼如下所示:

[-->MediaPlayerService.cpp]

void MediaPlayerService::instantiate() {

??? defaultServiceManager()->addService(

???????????String16("media.player"), new MediaPlayerService());

}

根據(jù)前面的分析,defaultServiceManager()實際返回的對象是BpServiceManager,它是IServiceManager的后代,代碼如下所示:

[-->IServiceManager.cpp::BpServiceManager的addService()函數(shù)]

virtual status_t addService(const String16&name, const sp<IBinder>& service)

{

??? //Parcel:就把它當(dāng)作是一個數(shù)據(jù)包。

??? Parceldata, reply;

?? ?data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

??? data.writeString16(name);

??? data.writeStrongBinder(service);

??? //remote返回的是mRemote,也就是BpBinder對象

??? status_terr = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

??? returnerr == NO_ERROR ? reply.readInt32() : err;

}

別急著往下走,應(yīng)先思考以下兩個問題:

·? 調(diào)用BpServiceManager的addService是不是一個業(yè)務(wù)層的函數(shù)?

·? addService函數(shù)中把請求數(shù)據(jù)打包成data后,傳給了BpBinder的transact函數(shù),這是不是把通信的工作交給了BpBinder?

兩個問題的答案都是肯定的。至此,業(yè)務(wù)層的工作原理應(yīng)該是很清晰了,它的作用就是將請求信息打包后,再交給通信層去處理。

2. 通信層的工作

下面分析BpBinder的transact函數(shù)。前面說過,在BpBinder中確實找不到任何與Binder設(shè)備交互的地方嗎?那它是如何參與通信的呢?原來,秘密就在這個transact函數(shù)中,它的實現(xiàn)代碼如下所示:

[-->BpBinder.cpp]

status_t BpBinder::transact(uint32_t code, constParcel& data, Parcel* reply,

???????????????????????????????? uint32_tflags)

{

??? if(mAlive) {

?????//BpBinder果然是道具,它把transact工作交給了IPCThreadState

???????status_t status = IPCThreadState::self()->transact(

????? ???????????????????? mHandle,code, data, reply, flags);//mHandle也是參數(shù)

??????? if(status == DEAD_OBJECT) mAlive = 0;

???????return status;

??? }

?

??? returnDEAD_OBJECT;

}

這里又遇見了IPCThreadState,之前也見過一次??磥?,它確實與Binder通信有關(guān),所以必須對其進行深入分析!

(1)“勞者一份”的IPCThreadState

誰是“勞者”?線程,是進程中真正干活的伙計,所以它正是勞者。而“勞者一份”,就是每個伙計一份的意思。IPCThreadState的實現(xiàn)代碼在IPCThreadState.cpp中,如下所示:

[-->IPCThreadState.cpp]

IPCThreadState* IPCThreadState::self()

{

??? if(gHaveTLS) {//第一次進來為false

restart:

??????? constpthread_key_t k = gTLS;

?/*

?? TLS是Thread Local Storage(線程本地存儲空間)的簡稱。

?? 這里只需知曉:這種空間每個線程都有,而且線程間不共享這些空間。

? ?通過pthread_getspecific/pthread_setspecific函數(shù)可以獲取/設(shè)置這些空間中的內(nèi)容。

? ?從線程本地存儲空間中獲得保存在其中的IPCThreadState對象。

?? 有調(diào)用pthread_getspecific的地方,肯定也有調(diào)用pthread_setspecific的地方

?*/

???????IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);

??????? if(st) return st;

// new一個對象,構(gòu)造函數(shù)中會調(diào)用pthread_setspecific

???????return new IPCThreadState;

??? }

???

??? if(gShutdown) return NULL;

????pthread_mutex_lock(&gTLSMutex);

??? if(!gHaveTLS) {

??????? if(pthread_key_create(&gTLS, threadDestructor) != 0) {

???????????pthread_mutex_unlock(&gTLSMutex);

???????????return NULL;

??????? }

???????gHaveTLS = true;

??? }

? pthread_mutex_unlock(&gTLSMutex);

//其實goto沒有我們說的那么不好,匯編代碼也有很多跳轉(zhuǎn)語句(沒辦法,太低級的語言了),關(guān)鍵是要用好

? goto restart;

}

接下來,有必要轉(zhuǎn)向分析它的構(gòu)造函數(shù)IPCThreadState(),如下所示:

[-->IPCThreadState.cpp]

IPCThreadState::IPCThreadState()

??? :mProcess(ProcessState::self()), mMyThreadId(androidGetTid())

{

? //在構(gòu)造函數(shù)中,把自己設(shè)置到線程本地存儲中去。

???pthread_setspecific(gTLS, this);

??? clearCaller();

???//mIn和mOut是兩個Parcel。把它看成是發(fā)送和接收命令的緩沖區(qū)即可。

mIn.setDataCapacity(256);

??? ?mOut.setDataCapacity(256);

}

每個線程都有一個IPCThreadState,每個IPCThreadState中都有一個mIn、一個mOut,其中mIn是用來接收來自Binder設(shè)備的數(shù)據(jù)的,而mOut則是用來存儲發(fā)往Binder設(shè)備的數(shù)據(jù)的。

(2)勤勞的transact

傳輸工作是很辛苦的。我們剛才看到BpBinder的transact調(diào)用了IPCThreadState的transact函數(shù),這個函數(shù)實際完成了與Binder通信的工作,如下面的代碼所示:

[-->IPCThreadState.cpp]

//注意,handle的值為0,代表了通信的目的端

status_t IPCThreadState::transact(int32_t handle,

????????????????????????????????? uint32_tcode, const Parcel& data,

?????????????????????? ???????????Parcel* reply, uint32_t flags)

{

??? status_terr = data.errorCheck();

?

??? flags |=TF_ACCEPT_FDS;

?

??? ......

/*

?注意這里的第一個參數(shù)BC_TRANSACTION,它是應(yīng)用程序向binder設(shè)備發(fā)送消息的消息碼,

而binder設(shè)備向應(yīng)用程序回復(fù)消息的消息碼以BR_開頭。消息碼的定義在binder_module.h中,

?請求消息碼和回應(yīng)消息碼的對應(yīng)關(guān)系,需要查看Binder驅(qū)動的實現(xiàn)才能將其理清楚,我們這里暫時用不上。

*/

???? err =writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);

??? ?......

?? ??err = waitForResponse(reply);

???? ......

???

??? returnerr;

}

多熟悉的流程:先發(fā)數(shù)據(jù),然后等結(jié)果。再簡單不過了!不過,我們有必要確認一下handle這個參數(shù)到底起了什么作用。先來看writeTransactionData函數(shù),它的實現(xiàn)如下所示:

[-->IPCThreadState.cpp]

status_tIPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,

??? int32_thandle, uint32_t code, const Parcel& data, status_t* statusBuffer)

{

? ?//binder_transaction_data 是和binder設(shè)備通信的數(shù)據(jù)結(jié)構(gòu)。???

? ?binder_transaction_data tr;

?

? ?//果然,handle的值傳遞給了target,用來標識目的端,其中0是ServiceManager的標志。

?? tr.target.handle= handle;

?? //code是消息碼,用來switch/case的!

??? tr.code =code;

??? tr.flags= binderFlags;

???

??? conststatus_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(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 = statusBuffer;

???????tr.offsets_size = 0;

???????tr.data.ptr.offsets = NULL;

??? } else {

???????return (mLastError = err);

??? }

?? //把命令寫到mOut中, 而不是直接發(fā)出去,可見這個函數(shù)有點名不副實。

???mOut.writeInt32(cmd);

???mOut.write(&tr, sizeof(tr));

??? returnNO_ERROR;

}

現(xiàn)在,已經(jīng)把addService的請求信息寫到mOut中了。接下來再看發(fā)送請求和接收回復(fù)部分的實現(xiàn),代碼在waitForResponse函數(shù)中,如下所示:

[-->IPCThreadState.cpp]

status_t IPCThreadState::waitForResponse(Parcel*reply, status_t *acquireResult)

{

??? int32_tcmd;

??? int32_terr;

?

while (1) {

??????? //好家伙,talkWithDriver!

??????? if((err=talkWithDriver()) < NO_ERROR) break;

??????? err =mIn.errorCheck();

??????? if(err < NO_ERROR) break;

??????? if(mIn.dataAvail() == 0) continue;

???????

??????? cmd =mIn.readInt32();

?????? switch(cmd) {

??????? caseBR_TRANSACTION_COMPLETE:

???????????if (!reply && !acquireResult) goto finish;

???????????break;

??????? ......

??????? default:

???????????err = executeCommand(cmd);//看這個!

???????????if (err != NO_ERROR) goto finish;

???????????break;

??????? }

??? }

?

finish:

??? if (err!= NO_ERROR) {

??????? if(acquireResult) *acquireResult = err;

??????? if(reply) reply->setError(err);

???????mLastError = err;

??? }

???

??? returnerr;

}

OK,我們已發(fā)送了請求數(shù)據(jù),假設(shè)馬上就收到了回復(fù),后續(xù)該怎么處理呢?來看executeCommand函數(shù),如下所示:

[-->IPCThreadState.cpp]

status_t IPCThreadState::executeCommand(int32_tcmd)

{

??? BBinder*obj;

???RefBase::weakref_type* refs;

??? status_tresult = NO_ERROR;

???

??? switch(cmd) {

??? caseBR_ERROR:

???????result = mIn.readInt32();

???????break;

??????? ......

???? caseBR_TRANSACTION:

??????? {

???????????binder_transaction_data tr;

???????????result = mIn.read(&tr, sizeof(tr));

???????????if (result != NO_ERROR) break;

??? ????????Parcel buffer;

???????????Parcel reply;

???????????if (tr.target.ptr) {

????????? ?/*

?? ??????????看到了BBinder,想起圖6-3了嗎?BnServiceXXX從BBinder派生,

?? ??????????這里的b實際上就是實現(xiàn)BnServiceXXX的那個對象,關(guān)于它的作用,我們要在6.5節(jié)中講解。

??????????? */

???????????? ???sp<BBinder> b((BBinder*)tr.cookie);

???????????????const status_t error = b->transact(tr.code, buffer, &reply, 0);

?? ?????????????if (error < NO_ERROR)reply.setError(error);

?????????????} else {

?? ???????/*

? ?????????the_context_object是IPCThreadState.cpp中定義的一個全局變量,

??? ?????可通過setTheContextObject函數(shù)設(shè)置

?? ????????*/

???????????????const status_t error =

??????????? ?????????????????the_context_object->transact(tr.code,buffer, &reply, 0);

???????????????if (error < NO_ERROR) reply.setError(error);

???????? }

???????break;

??? ......

??? caseBR_DEAD_BINDER:

??????? {

???????? /*

?????????? 收到binder驅(qū)動發(fā)來的service死掉的消息,看來只有Bp端能收到了,

?????????? 后面,我們將會對此進行分析。

*/

???????????BpBinder *proxy = (BpBinder*)mIn.readInt32();

???????????proxy->sendObituary();

???????????mOut.writeInt32(BC_DEAD_BINDER_DONE);

???????????mOut.writeInt32((int32_t)proxy);

??????? }break;

??????? ......

case BR_SPAWN_LOOPER:

? //特別注意,這里將收到來自驅(qū)動的指示以創(chuàng)建一個新線程,用于和Binder通信。

???????mProcess->spawnPooledThread(false);

???????break;

??????default:

????????result = UNKNOWN_ERROR;

???????break;

??? }

?? ......

??? if(result != NO_ERROR) {

???????mLastError = result;

??? }

??? returnresult;

}

(3)打破砂鍋問到底

你一定想知道如何和Binder設(shè)備交互的吧?是通過write和read函數(shù)來發(fā)送和接收請求的嗎?來看talkwithDriver函數(shù),如下所示:

[-->IPCThreadState.cpp]

status_t IPCThreadState::talkWithDriver(booldoReceive)

{

? // binder_write_read是用來與Binder設(shè)備交換數(shù)據(jù)的結(jié)構(gòu)

? ??binder_write_read bwr;

??? constbool needRead = mIn.dataPosition() >= mIn.dataSize();

??? constsize_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

???

??? //請求命令的填充

???bwr.write_size = outAvail;

???bwr.write_buffer = (long unsigned int)mOut.data();

?

? if(doReceive && needRead) {

?????? //接收數(shù)據(jù)緩沖區(qū)信息的填充。如果以后收到數(shù)據(jù),就直接填在mIn中了。

???????bwr.read_size = mIn.dataCapacity();

???????bwr.read_buffer = (long unsigned int)mIn.data();

??? } else {

???????bwr.read_size = 0;

??? }

???

??? if((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;

???

???bwr.write_consumed = 0;

???bwr.read_consumed = 0;

??? status_terr;

??? do {

? #ifdefined(HAVE_ANDROID_OS)

?? ?????//看來不是read/write調(diào)用,而是ioctl方式。

??????? if(ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)

???????????err = NO_ERROR;

??????? else

???????????err = -errno;

#else

??????? err =INVALID_OPERATION;

#endif

?????? }while (err == -EINTR);

???

???? if (err>= NO_ERROR) {

??????? if(bwr.write_consumed > 0) {

???????????if (bwr.write_consumed < (ssize_t)mOut.dataSize())

???????????????mOut.remove(0, bwr.write_consumed);

???????????else

???????????????mOut.setDataSize(0);

??????? }

??????? if(bwr.read_consumed > 0) {

???????????mIn.setDataSize(bwr.read_consumed);

???????????mIn.setDataPosition(0);