本章主要內(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
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可并沒有使用它們。
為了能像“庖丁”那樣解析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本身。
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。
我們在main函數(shù)的開始處便碰見了ProcessState。由于每個進程只有一個ProcessState,所以它是獨一無二的。它的調(diào)用方式如下面的代碼所示:
[-->Main_MediaServer.cpp]
//①獲得一個ProcessState實例
sp<ProcessState> proc(ProcessState::self());
下面,來進一步分析這個獨一無二的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對象。這一點,從它的命名中也可看出些端倪。
再來看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);
??? }
??? ......
}
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。
defaultServiceManager函數(shù)的實現(xiàn)在IServiceManager.cpp中完成。它會返回一個IServiceManager對象,通過這個對象,我們可以神奇地與另一個進程ServiceManager進行交互。是不是有一種觀看時空穿越魔術(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
}
眾所周知,玩魔術(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。它是什么?其實是一個障眼法!下面就來具體分析它。
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對象中去了,這難道不是障眼法嗎?既然找到了“真身”,不妨就來見識見識它吧。
剛才提到,IBinder家族的BpBinder和BBinder是與通信業(yè)務(wù)相關(guān)的,那么業(yè)務(wù)層的邏輯又是如何巧妙地架構(gòu)在Binder機制上的呢?關(guān)于這些問題,可以用一個絕好的例子來解釋,它就是IServiceManager。
先回答第一個問題:如何表述應(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;
??? ......
};
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)系呢?
要搞清這個問題,必須先了解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)部是如何工作的。
再回到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)該是很清晰了,它的作用就是將請求信息打包后,再交給通信層去處理。
下面分析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),所以必須對其進行深入分析!
誰是“勞者”?線程,是進程中真正干活的伙計,所以它正是勞者。而“勞者一份”,就是每個伙計一份的意思。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ù)的。
傳輸工作是很辛苦的。我們剛才看到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;
}
你一定想知道如何和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);