來源 http://blog.csdn.net/bathinbreeze/article/details/8990000
Native層流程大綱
介紹完Binder驅動的構架後,下面我們進入到Binder Native層的流程分析。Binder的整體流程可分爲如下幾個步驟:
-
Service Manager成爲守護進程--- Service Manager告知Binder驅動程序它是Binder機制的上下文管理者。
-
Server和Client獲得Service Manager的遠程接口--- defaultServiceManager接口是如何實現的。
-
Server向SM註冊服務---- IServiceManager::addService接口是如何實現的
-
Client從SM獲得服務----IServiceManager::getService接口是如何實現的
其中,第2步是3和4的基礎。上面4個步驟,是系統中Binder驅動和Native層的主要工作,而Binder Java層的每次調用底層函數都離不開這4步的操作。這裏介紹Native層,Java層將在下章節介紹。
4.1 SM成爲守護進程
SM成爲守護進程的過程中,與驅動交互頻繁,下面會結合之前的驅動框架來分析:
-
Service Manager在用戶空間的源代碼位於frameworks/base/cmds/servicemanager 目錄下,主要是由binder.h、binder.c和service_manager.c三個文件組成。
-
Service Manager的入口位於service_manager.c文件中的main函數。Main函數主要有三個功能:
打開Binder設備文件;
調用mmap
告訴Binder驅動程序自己是Binder上下文管理者,即我們前面所說的守護進程;
進入一個無窮循環,充當Server的角色,等待Client的請求
4.1.1打開Binder設備文件
在service_manager.c打開Binder設備文件的核心代碼見下圖:
函數首先是執行打開Binder設備文件的操作binder_open,這個函數位於frameworks/base/cmds/servicemanager/binder.c文件中, 代碼如下:
主要做了2件主要的事情:
-
打開驅動創建的/dev/binder文件結點,創建binder_proc結構體,保存/dev/binder上下文信息
-
調用驅動的mmap分配空間
4.1.2 打開設備詳細分析
-
通過文件操作函數open打開/dev/binder設備文件,(/dev/binder是在Binder驅動模塊初始化時創建的,創建入口在binder_init());此處調用驅動函數binder_open(),功能如下:
-
threads樹:用來保存binder_proc進程內用於處理用戶請求的線程
-
node樹:保存binder_proc進程內的binder實體
-
refs_by_desc和refs_by_node:保存binder_proc進程內的Binder引用(前者以句柄,後者以節點地址的key來組織)
-
創建struct binder_proc,保存打開設備文件的進程上下文信息到struct file的私有變量private_data中
-
binder_proc下,會掛4棵紅黑樹的節點:
-
-
調用驅動的binder_mmap(),對打開的設備文件進行內存映射mmap:
-
好處:這樣,同一塊物理地址分別映射給了內核和server進程,就減少了數據從內核到server的拷貝了。 (一般是:client到內核、內核到server)
-
通過filp->private_data得到打開/dev/binder時創建的binder_proc結構。
-
同一塊地址,會通過struct vm_area_struct 映射用戶空間server進程的使用信息;通過struct vm_struct 同時映射給內核;
-
檢查:映射內存大小不能超過4M(此處是128*1024爲128K)
-
調用get_vm_area()獲得空間的vm_struct 空間,初始化binder_proc結構體
-
調用binder_update_pange_range()爲虛擬地址空間分配空閒的物理頁面
-
4.1.3 成爲守護進程
回到frameworks/base/cmds/servicemanager/service_manager.c文件中的main函數,下一步 就是調用binder_become_context_manager來通知Binder驅動程序自己是Binder機制的上下文管理者,即守護進程。
binder_become_context_manager函數位於frameworks/base/cmds/servicemanager/binder.c文件中,
這裏通過調用ioctl文件操作函數來通知Binder驅動程序自己是守護進程,命令號是BINDER_SET_CONTEXT_MGR,流程如下:
-
通過filp->private_data獲得proc變量
-
通過binder_get_thread()獲得線程信息,其流程如下:
-
把當前線程pid作爲鍵值,在進程proc->thread表示的紅黑樹中進行查找,看是否創建了binder_thread信息;如果沒有創 建,創建完後會插入到proc->threads紅黑樹中,下次就可從proc中找到
-
-
碰到binder_context_mgr_node和binder_context_mgr_uid。由於第一次用 到,binder_context_mgr_node表示SM的實體,此時爲null; binder_context_mgr_uid表示SM守護進程的id,此時爲-1;於是會初始化binder_context_mgr_uid爲 current->cred->euid,這樣當前線程就成爲Binder機制的守護進程了,並且通過binder_new_node爲 Service Manager創建Binder實體。
-
如果第3步創建了新的binder_node,就會把新建的binder_node指針保存在binder_context_mgr_node中
4.1.4進入loop循環
回到frameworks/base/cmds/servicemanager/service_manager.c文件中的main函數中,繼續往下看,會看到調用了binder_loop()函數進入循環,等待Client來請求。
binder_loop函數定義在frameworks/base/cmds/servicemanager/binder.c文件中,流程如下:
-
首先是通過binder_write()執行BC_ENTER_LOOPER命令告訴Binder驅動程序,Service Manager要進入循環了,調用驅動 ioctl():
-
調用binder_get_thread函數獲取binder_thread,就能從proc中直接找到了,不需要創建一個新的。這裏進入case BINDER_WRITE_READ:
-
首先是通過copy_from_user(&bwr, ubuf, sizeof(bwr))語句把用戶傳遞進來的參數轉換成struct binder_write_read 結構,並保存在本地變量bwr中,這裏可以看出bwr.write_size等於4,
-
於是進入binder_thread_write函數,這裏我們只關注BC_ENTER_LOOPER相關的代碼
-
在執行完BC_ENTER_LOOPER時,thread->looper值就變爲BINDER_LOOPER_STATE_ENTERED了,表明當前線程進入循環狀態了
-
回到binder_ioctl函數,由於bwr.read_size == 0,binder_thread_read函數就不會被執行了,這樣,binder_ioctl的任務就完成了
-
-
回到binder_loop函數,進入for循環,又會執行一個ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 由於bwr.write_size等於0,會執行binder_thread_write函數,bwr.read_size等於32,於是進入到 binder_thread_read()。
4.1.5 SM成爲守護進程-總結
至此,我們就從源代碼一步一步地分析完Service Manager是如何成爲Android進程間通信(IPC)機制Binder守護進程的了。總結一下,Service Manager是成爲Android進程間通信(IPC)機制Binder守護進程的過程是這樣的:
1. 打開/dev/binder文件:open("/dev/binder", O_RDWR);
2. 建立128K內存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
3. 通知Binder驅動程序它是守護進程:binder_become_context_manager(bs);
4. 進入循環等待請求的到來:binder_loop(bs, svcmgr_handler);
在這個過程中,在Binder驅動程序中建立了一個struct binder_proc結構、一個struct binder_thread結構和一個struct binder_node結構,這樣,Service Manager就在Android系統的進程間通信機制Binder擔負起守護進程的職責了。
4.2 Server和Client獲得Service Manager遠程接口
我們知道,Service Manager在Binder機制中既充當守護進程的角色,同時它也充當着Server角色,然而它又與一般的Server不一樣。對於普通的 Server來說,Client如果想要獲得Server的遠程接口,那麼必須通過Service Manager遠程接口提供的getService接口來獲得,這本身就是一個使用Binder機制來進行進程間通信的過程。而對於Service Manager這個Server來說,Client如果想要獲得Service Manager遠程接口,卻不必通過進程間通信機制來獲得,因爲Service Manager遠程接口是一個特殊的Binder引用,它的引用句柄一定是0。
獲取Service Manager遠程接口的函數是defaultServiceManager,這個函數聲明在frameworks/base/include/binder/IServiceManager.h文件中:
4.2.1 Service Manager繼承關係
那麼爲什麼要獲取遠程端口呢?!是因爲要實現業務以及完成通信。先來看看網上的一個關於繼承關係的圖示:
IServiceManager類提供的業務函數:getService(), checkService(), addService();
BpServiceManager類繼承了BpInterface類,而BpInterface類繼承了BpRefBase類。
在BpRefBase類中,有一個成員變量mRemote,它的類型是IBinder*,實現類爲BpBinder,它表示一個Binder引用,引用句柄值保存在BpBinder類的mHandle成員變量中。
BpBinder類通過IPCThreadState類來和Binder驅動程序並互,而IPCThreadState又通過它的成員變量mProcess來打開/dev/binder設備文件,mProcess成員變量的類型爲ProcessState。
ProcessState類打開設備/dev/binder之後,將打開文件描述符保存在mDriverFD成員變量中,以供後續使用。
4.2.2 defaultServiceManager
理清了上述的繼承關係後,我們再來看看defaultServicemanager這個函數。
從這個函數可以看出:gDefaultServiceManager是單例模式,調用defaultServiceManager函數時,如果 gDefaultServiceManager已經創建,則直接返回,否則通過 interface_cast<IServiceManager> (ProcessState::self()->getContextObject(NULL))來創建一個,並保存在 gDefaultServiceManager全局變量中。
在這個過程中,有4個關鍵步驟:
-
調用ProcessStaate::self()
-
調用getContextObject(NULL)
-
使用interface_cast
-
使用 <IserviceManager>
下面來分析這4個步驟
4.2.2.1 ProcessState::self()
ProcessState::self()是ProcessState的靜態成員函數,它的作用是返回一個全局唯一的ProcessState實例 變量,就是單例模式了,這個變量名爲gProcess。如果gProcess尚未創建,就會執行創建操作,在ProcessState的構造函數中,會通 過open文件操作函數打開設備文件/dev/binder,並且返回來的設備文件描述符保存在成員變量mDriverFD中。也就是得到了一個可以和底 層打交道的ProcessState類型的gProcess對象。在addervice()的流程裏,會深入分析。
4.2.2.2 getContextObject()
gProcess->getContextObject(NULL),傳遞的值爲NULL即0,返回的值爲 sp<IBinder>類型的getStrongProxyForHandle(0)。 getStrongProxyForHanlde(int32_t handle)中,handle的值是一個資源項數組中的索引值。
-
作用:根據索引查找對應的資源,如果lookupHandleLocked發現沒有對應資源項,則創建一個新的BpBinder項,填充BpBinder,並返回(handle值爲0)
結果爲:返回一個handle爲0的Binder引用,即BpBinder;於是創建Service Manager遠程接口的語句可以簡化爲:gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));
4.2.2.3 interface_cast
再來看函數interface_cast<IServiceManager>的實現,它是一個模板函數,定義在framework/base/include/binder/IInterface.h文件中:
這裏的《INTERFACE>是IServiceManager,於是調用了IServiceManager::asInterface函 數,那麼 gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0)); 可以變成:gDefaultServiceManager = IServiceManager::asInterface(new BpBinder(0));
IserviceManager::asInterface是通過DECLARE_META_INTERFACE(ServiceManager) 宏在IServiceManager類中聲明的,它位於framework/base/include/binder/IServiceManger.h 文件中。IServiceManager::asInterface的實現是通過 IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")宏定義的,它位於framework/base/libs/binder /IServiceManager.cpp文件中。
4.2.2.4 IServiceManager::asInterface
最終,在IServiceManager::asInterface函數中會調用:Return intr = new BpServiceManager(obj); 這裏的obj就則剛纔創建的new BpBinder(0),上面的代碼爲:
-
intr = new BpServiceManager(new BpBinder(0));
回到defaultServiceManager函數中,最終結果爲:gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
這樣,Service Manager遠程接口就創建完成了,它本質上是一個BpServiceManager,包含了一個句柄值爲0的Binder引用。這裏,實現asInterface函數,是利用BpBinder對象新建了一個BpServiceManager對象
4.3 Server向SM註冊服務
實際上,BnMediaPlayerService並不是直接接收到Client處發送過來的請求,而是使用了IPCThreadState接收 Client處發送過來的請求,而IPCThreadState又藉助了ProcessState類來與Binder驅動程序交互。
IPCThreadState接收到了Client處的請求後,就會調用BBinder類的transact函數,並傳入相關參數,BBinder類的 transact函數最終調用BnMediaPlayerService類的onTransact函數,於是,就開始真正地處理Client的請求了。
以MediaServer作爲Server的例子,這裏我們只看MediaPlayerService:多媒體系統的重要服務。MS的入口函數在 \frameworks\av\media\mediaserver\ main_mediaserver.cpp 如下圖,
可分爲5步:
-
創建ProcessState
-
創建IServiceManager對象
-
初始化MediaPlayerService服務對象
-
創建進程的線程池
-
把自己加入線程池
下面來分別分析。
4.3.1 ProcessState
之前分析過,這裏詳細介紹下參數傳遞的流程。ProcessState::self()調用創建一個ProcessState實例。 ProcessState::self()是ProcessState類的一個靜態成員變量,定義在frameworks/base/libs /binder/ProcessState.cpp文件中:
這裏可以看出,這個函數作用是返回一個全局唯一的ProcessState實例gProcess。全局唯一實例變量gProcess定義在frameworks/base/libs/binder/Static.cpp文件中
再來看ProcessState的構造函數:ProcessState::ProcessState()的流程:
-
通過open_driver()打開binder設備 /dev/binder,並將打開設備文件描述符保存在成員變量mDriverFD中,這樣,與Binder驅動有了交互的通道。open_driver 這個函數同樣位於frameworks/base/libs/binder/ProcessState.cpp文件中,流程如下:
-
通過調用驅動open()打開/dev/binder,在打開/dev/binder設備文件後,Binder驅動程序就爲 MediaPlayerService進程創建了一個struct binder_proc結構體實例來維護MediaPlayerService進程上下文相關信息。
-
調用ioctl()執行BINDER_VERSION獲得當前Binder驅動程序的版本號。將BINDER_CURRENT_PROTOCOL_VERSION寫入到傳入的參數arg指向的用戶緩衝區中。
-
調 用ioctl()執行BINDER_SET_MAX_THREADS,通知Binder驅動程序最多能設置多少個線 程,MediaPlayerService最多可同時啓動15個線程來處理Client端的請求。把用戶傳進來的參數保存在 proc->max_threads中就完畢了。(注意,這裏再調用binder_get_thread函數的時候,就可以在 proc->threads中找到當前線程對應的struct binder_thread結構了,因爲前面已經創建好並保存在proc->threads紅黑樹中)
-
-
對返回的fd使用mmap,把設備文件/dev/binder映射到內存中(流程見“成爲守護進程mmap"部分)
這樣,ProcessState全局唯一變量gProcess就創建完畢了,回到了frameworks/base/media/mediaserver/main_mediaserver.cpp文件中的main函數
4.3.2 創建IServiceManager對象
DefaultServiceManager函數的實現在之前分析過,則:sp<IServiceManager> sm = defaultServiceManager(); 爲:sp<IServiceManager> sm = new BpServiceManager(new BpBinder(0));
4.3.3 註冊MediaPlayerService
MediaPlayerService::instantiate()調 用:defaultServiceManager()->addService()。這個函數最終會通過 IPCthreadState->transact()和Binder驅動打交道,把數據傳送到SM中,完成MediaPlayerService 的註冊。defaultServiceManager()返回的對象是BpServiceManager,而BpServiceManager是 IServiceManager的後代。IServiceManager是一個抽象類,裏面有我們操作業務層的各種函數。
4.3.3.1 MediaPlayerService::instantiate()
MediaPlayerService::instantiate();的實現如下:
這裏,實際上是調用的BpServiceManger::addService()這個函數實現在frameworks/base/libs /binder/IServiceManager.cpp文件中的addService()。addService是一個業務層的函數,調用 remote()->transact();remote()返回的是mRemote,也就是BpBinder對象。在addService函數 中,把請求數據打包成data後,傳遞給了BpBinder的transact函數,把通信任務交給了BpBinder;即交給了通信層去處理。
4.3.3.2 transact()通信層的工作
BpBinder::transact()調用了:status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
這裏的mHandle爲0,code爲ADD_SERVICE_TRANSACTION。ADD_SERVICE_TRANSACTION是上面以參數形 式傳進來的,這裏表示的是Service Manager遠程接口,mHandle的句柄值一定是0。即,把transact工作交給了IPCThreadState。 IPCThreadState::self()中,TLS: Thread Local Storage,每個線程都有,且不共享。通過pthread_getspecific/pthread_setspecific函數可以獲得/設置這些
空間中的內容。
流程如下:
-
pthread_getspecific()從線程本地存儲空間中獲得保存在其中的IPCThreadState對象
-
new一個IPCThreadState對象,調用構造函數,構造函數中會調用pthread_setspecific函數。則上面的調用變爲: new IPCThreadState()->transact(mHandle, code, data, reply, flags);
-
err = writeTransactionData(BC_TRANSACTION,...); 函數裏會創建一個binder_transaction_data tr,這個就是等下要傳給Binder驅動的。發送的消息碼爲:BC_XX
-
err = waitForResponse(reply); binder設備嚮應用程序回覆消息,BR_XX爲回覆的消息碼
-
其中函數中定義的binder_transaction_data是和binder設備通信的數據結構 binder_transaction_data tr;
-
handle的值傳遞給了target用來標識目的端,其中0爲SM的標誌。tr.target.handle = handle;
-
cmd:發送的命令消息碼 BC_XXX,此處爲BC_TRANSACTION
-
code: 用來switch/case的消息碼
-
把命令寫到mOut中,並不直接發出去。mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr));
-
該函數原型爲:IPCTheadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
-
這時,已經把addService的請求信息”tr”寫到mOut中了,寫入的內容爲:
-
-
寫流程:
-
讀流程:
-
其中定義了binder_write_read bwr; 一個與binder設備交換數據的結構;這裏調用了驅動的ioctl()與驅動交互:
-
executeCommand(int32_t cmd)收到cmd後,switch(cmd):
-
sp<BBinder>b((BBinder*)tr.cookie); 設置BnServiceXXX的對象b,BnServiceXXX是從BBinder派生
-
b->transact(); 調用transact函數,發送binder_transaction_data和Parcel類型的數據
-
收到Binder驅動發來的service死掉的消息,只有Bp端能收到
-
收到來自驅動的指示以創建一個新線程,用於和Binder通信
-
接收回復的數據waitForResponse(Rarcel *reply, status_t *acquireResult)。在無限循環中(數據讀完或異常,則退出)做了如下事情:
-
構造函數 IPCThreadState()的流程:
-
IPCThreadState::transact()調用:
-
調用talkWithDriver();
-
把數據讀到mIn中
-
把命令(BR_XXX)讀出並switch/case
-
executeCommand(cmd)執行命令
-
請求命令填充
-
調用ioctl,由binder驅動實現具體操作
-
接收數據緩衝區信息的填充,如果以後收到數據,就填到mIn中
-
調用ioctl,由binder驅動實現具體操作
-
case BR_ERROR:
-
case BR_TRANSACTION:
-
case BR_DEAD_BINDER:
-
case BR_SPAWN_LOOPER:
-
pthread_setspecific() 把自己設置到線程本地存儲中
-
設置mIn和mOut搜法命令的緩衝區
-
4.3.4 StartThreadPool()
StartThreadPool()調用spawnPooledThread()函數:sp<Thread> t = new PoolThread(isMain); isMain參數是true; PoolThread是在IPCThreadState中定義了一個Thread子類。PoolThread類中,調用threadLoop()。 threadLoop()中,在這個線程中又創建了一個IPCThreadState: IPCThreadState::self()->joinThreadPool(mIsMain)。
joinThreadPool()流程:
-
mOut.writeInt32(isMain?BC_ENTER_LOOPER: BC_REGISTER_LOOPER); 如果isMain爲true,則需要循環處理。把請求寫到mOut中,過會一起發出
-
處理已經死亡的BBinder對象
-
發送命令,讀取請求:調用talkWithDriver();
4.3.5 MS中的joinThreadPool()
MediaServer進程一共註冊了4個服務。MS中目前有兩個線程在talkWithDriver():
-
一個是StartThreadPool啓動新線程通過joinThreadPool,調用talkWithDriver(),讀取binder設備;
-
另一個是MS主線程調用joinThreadPool,調用talkWithDriver(),讀取binder設備
BnService和BpService負責業務的交互;BBinder和BpBinder負責通信的交互
4.3.6 MediaServer註冊服務到SM流程圖
4.4 Client從SM獲得服務
client從SM獲得服務,也就是從SM獲得 BpMediaPlayerService。BpMediaPlayerService的構造函數有一個參數impl,它的類型爲const sp<IBinder>&,從上面的描述中,這個實際上就是一個BpBinder對象。 這樣,要創建一個BpMediaPlayerService對象,首先就要有一個BpBinder對象。再來看BpBinder類的構造函數,它有一個參 數handle,類型爲int32_t,這個參數的意義就是請求MediaPlayerService這個遠程接口的進程對 MediaPlayerService這個Binder實體的引用了。因此,獲取MediaPlayerService這個遠程接口的本質問題就變爲從 Service Manager中獲得MediaPlayerService的一個句柄了。
4.4.1 詳細分析:
這裏我們以MediaServer中的MediaPlayService與Client交互爲例,來了解請求數據是如何從通信層傳遞到業務層並進行處理的:
client想要獲得某個Service的信息,就得先和SM交互,通過調用getService()來獲得對應的Service信息,這裏用到的是IMediaDeathNotifier::getMeidaPlayerService()
-
通過defaultServiceManager()獲得SM的遠程接口BpServiceManager的IServiceManager接口
-
用while循環通過binder= sm->getService()不斷嘗試獲得名字爲”media.player”的service;向SM查詢對應服務的信息,返回一個與MediaPlayerService通信的BpBinder;如果SM上還沒有註冊對應的服務,則睡0.5秒再嘗試,直到對應服務註冊到SM上才中止
-
通過interface_cast,將這個binder轉換成一個BpMediaPlayerService
有了BpMediaPlayerService,client就能夠使用任何IMediaPlayerService提供的業務邏輯函數 了,e.g: createMediaRecorder和createMetadataRetriever等。調用這些函數都將把請求數據打包發給Binder驅動,並 由BpBinder中handle知道對應端的處理者來處理,包括
-
通信層接收到請求
-
遞交給業務層處理
4.4.2 BpServiceManager::getService()
BpServiceManager::getService通過BpServiceManager::checkService執行操作。
在BpServiceManager::checkService中:
-
首先是通過Parcel::writeInterfaceToken往data寫入一個RPC頭;就是寫往data裏面寫入了一個整數和一個字符 串“android.os.IServiceManager”, Service Manager來處理CHECK_SERVICE_TRANSACTION請求之前,會先驗證一下這個RPC頭,看看是否正確。接着再往data寫入一個 字符串name,這裏就是“media.player”了
-
調用remote()返回的是一個BpBinder,於是,就進行到 BpBinder::transact函數了。這裏的mHandle = 0,code = CHECK_SERVICE_TRANSACTION,flags = 0。進入到IPCThread::transact函數中:
-
首先是調用函數writeTransactionData寫入將要傳輸的數據到IPCThreadState的成員變量mOut中去
-
調 用waitForResponse(reply),這個函數通過IPCThreadState::talkWithDriver與驅動程序進行交互,這裏 的needRead爲true,因此,bwr.read_size大於0;outAvail也大於0,因此,bwr.write_size也大於0;
-
最後ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
-
4.5 c/s Native層通信小結
-
通信層
-
首先server和client都調用了ProcessState的構造函數從而都向驅動申請了一塊物理內存用於通信數據的存放
-
server 調用SM的addService函數傳遞一個字符串和實際Binder對象在自己虛擬地址空間的地址到Binder驅動,Binder驅動記錄下該地址 值,在SM申請的物理內存中分配一個虛擬地址並連同字符串一起傳遞給SM,而且Binder驅動會記錄下兩個地址之間的對應關係.
-
client 調用SM的getService函數傳遞一個字符串給SM,SM將相對應的虛擬地址值傳遞給Binder驅動,Binder驅動查詢出實際對象的地址,在 client申請的物理內存中分配一個虛擬地址並傳遞給client,而且Binder驅動會記錄下這個地址和實際Binder對象地址之間的對應關 系,client這裏得到的就是實際Binder的引用了。到了這一步,真正的Binder對象就擁有兩個引用,一個在SM,一個client.
-
client通過得到的Binder引用調用server中的函數,驅動會根據傳遞過來引用值找到應該處理該請求的進程,並喚醒其中的Binder線程,調用BBinder對象的onTransaction函數,最終調用到實際的函數
-
-
從通信層到業務層
-
從bpxxxService的構造函數可以看出,在Client進程,每一個BpxxxService對象都封裝了一個BpBinder對象,因 此,確切來說,Client進程緩存的是BpBinder對象,每一個BpBinder對象都與一個Binder句柄值對應。每當Client進程需要創 建一個BpxxxService對象時,就會檢查本地緩存中是否已經存在對應的BpBinder對象。如果存在的話,就可以直接使用它來創建一個 BpxxxService對象,否則的話,就要通過Binder驅動程序來獲得一個Binder句柄值,再以這個句柄值來創建一個BpBinder對象, 最後再根據這個BpBinder對象來創建一個BpxxxService對象。
-
-
業務層
-
由於BpMediaPlayerService繼承了IMediaPlayerService,IXXService有比如createMediaRecord(), CreateMetaDataRetrive()等業務層方法,則可以完成相應業務需要
-