Binder系列6—獲取服務(wù)(getService)

一、 獲取服務(wù)

在Native層的服務(wù)注冊,我們選擇以media為例來展開講解,先來看看media的類關(guān)系圖。

1.1 類圖


圖解:

藍色: 代表獲取MediaPlayerService服務(wù)相關(guān)的類;

綠色: 代表Binder架構(gòu)中與Binder驅(qū)動通信過程中的最為核心的兩個類;

紫色: 代表注冊服務(wù)和獲取服務(wù)的公共接口/父類;

二. 獲取Media服務(wù)

2.1 getMediaPlayerService

[-> framework/av/media/libmedia/IMediaDeathNotifier.cpp]


其中defaultServiceManager()過程在上一篇文章獲取ServiceManager已講過,返回BpServiceManager。

在請求獲取名為”media.player”的服務(wù)過程中,采用不斷循環(huán)獲取的方法。由于MediaPlayerService服務(wù)可能還沒向ServiceManager注冊完成或者尚未啟動完成等情況,故則binder返回為NULL,休眠0.5s后繼續(xù)請求,直到獲取服務(wù)為止。

2.2 BpSM.getService

[-> IServiceManager.cpp ::BpServiceManager]


通過BpServiceManager來獲取MediaPlayer服務(wù):檢索服務(wù)是否存在,當(dāng)服務(wù)存在則返回相應(yīng)的服務(wù),當(dāng)服務(wù)不存在則休眠1s再繼續(xù)檢索服務(wù)。該循環(huán)進行5次。為什么是循環(huán)5次呢,這估計跟Android的ANR時間為5s相關(guān)。如果每次都無法獲取服務(wù),循環(huán)5次,每次循環(huán)休眠1s,忽略checkService()的時間,差不多就是5s的時間

2.3 BpSM.checkService

[-> IServiceManager.cpp ::BpServiceManager]


檢索指定服務(wù)是否存在, 其中remote()為BpBinder。

2.4 BpBinder::transact

[-> BpBinder.cpp]


Binder代理類調(diào)用transact()方法,真正工作還是交給IPCThreadState來進行transact工作,

2.4.1 IPCThreadState::self

[-> IPCThreadState.cpp]


TLS是指Thread local storage(線程本地儲存空間),每個線程都擁有自己的TLS,并且是私有空間,線程之間不會共享。通過pthread_getspecific/pthread_setspecific函數(shù)可以獲取/設(shè)置這些空間中的內(nèi)容。從線程本地存儲空間中獲得保存在其中的IPCThreadState對象。

2.4.2 IPCThreadState初始化

[-> IPCThreadState.cpp]


每個線程都有一個IPCThreadState,每個IPCThreadState中都有一個mIn、一個mOut。成員變量mProcess保存了ProcessState變量(每個進程只有一個)。

mIn 用來接收來自Binder設(shè)備的數(shù)據(jù),默認大小為256字節(jié);

mOut用來存儲發(fā)往Binder設(shè)備的數(shù)據(jù),默認大小為256字節(jié)。

2.5 IPC::transact

[-> IPCThreadState.cpp]


2.6 IPC.writeTransactionData

[-> IPCThreadState.cpp]


其中handle的值用來標(biāo)識目的端,注冊服務(wù)過程的目的端為service manager,此處handle=0所對應(yīng)的是binder_context_mgr_node對象,正是service manager所對應(yīng)的binder實體對象。binder_transaction_data結(jié)構(gòu)體是binder驅(qū)動通信的數(shù)據(jù)結(jié)構(gòu),該過程最終是把Binder請求碼BC_TRANSACTION和binder_transaction_data結(jié)構(gòu)體寫入到mOut。

2.7 IPC.waitForResponse

[-> IPCThreadState.cpp]


2.8 IPC.talkWithDriver

[-> IPCThreadState.cpp]


binder_write_read結(jié)構(gòu)體用來與Binder設(shè)備交換數(shù)據(jù)的結(jié)構(gòu), 通過ioctl與mDriverFD通信,是真正與Binder驅(qū)動進行數(shù)據(jù)讀寫交互的過程。 先向service manager進程發(fā)送查詢服務(wù)的請求(BR_TRANSACTION),見Binder系列3—啟動ServiceManager。當(dāng)service manager進程收到該命令后,會執(zhí)行do_find_service() 查詢服務(wù)所對應(yīng)的handle,然后再binder_send_reply()應(yīng)答 發(fā)起者,發(fā)送BC_REPLY協(xié)議,然后調(diào)用binder_transaction(),再向服務(wù)請求者的Todo隊列 插入事務(wù)。

接下來,再看看binder_transaction過程。

2.8.1 binder_transaction

這個過程非常重要,分兩種情況來說:

當(dāng)請求服務(wù)的進程與服務(wù)屬于不同進程,則為請求服務(wù)所在進程創(chuàng)建binder_ref對象,指向服務(wù)進程中的binder_node;

當(dāng)請求服務(wù)的進程與服務(wù)屬于同一進程,則不再創(chuàng)建新對象,只是引用計數(shù)加1,并且修改type為BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。

2.8.2 binder_thread_read

2.9 readStrongBinder

[-> Parcel.cpp]


2.9.1 unflatten_binder

[-> Parcel.cpp]


2.9.2 getStrongProxyForHandle

[-> ProcessState.cpp]


readStrongBinder的功能是flat_binder_object解析并創(chuàng)建BpBinder對象.

2.9.3 lookupHandleLocked


根據(jù)handle值來查找對應(yīng)的handle_entry.

二. 總結(jié)

請求服務(wù)(getService)過程,就是向servicemanager進程查詢指定服務(wù),當(dāng)執(zhí)行binder_transaction()時,會區(qū)分請求服務(wù)所屬進程情況。

當(dāng)請求服務(wù)的進程與服務(wù)屬于不同進程,則為請求服務(wù)所在進程創(chuàng)建binder_ref對象,指向服務(wù)進程中的binder_node;

最終readStrongBinder(),返回的是BpBinder對象;

當(dāng)請求服務(wù)的進程與服務(wù)屬于同一進程,則不再創(chuàng)建新對象,只是引用計數(shù)加1,并且修改type為BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。

最終readStrongBinder(),返回的是BBinder對象的真實子類;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容