android在native層實作了程序間的binder通信,但是上層應用程式的開發及framework的實作都是java,用java層再實作一次肯定是不合理的,java可以通過jni調用native code,是以通過jni複用binder在native層的實作就是一個順理成章的事情。
在init程序的init2階段,系統啟動了serverthread,在serverthread中會啟動很多用java實作的系統服務,比如說powerservice:
建立server端實體,然後向servicemanager注冊,從代碼表面看是和native層binder一樣的。powermanagerservice繼承自java層的binder類:
是以在new powermanagerservice時會調用binder的構造函數,binder的構造函數中調用了init(),init是native方法,執行jni的android_os_binder_init:
在android_os_binder_init,建立了一個javabbinderholder對角,并将其指針儲存在了obj即binder的gbinderoffsets.mobject域中,而gbinderoffsets.mobject又是個什麼東西?看一下它的定義:
在androidruntine::startreg中會調用register_android_os_binder,register_android_os_binder會調用int_register_android_os_binder等函數建立java層binder、binderproxy、binderinternal、log等與native層的映射關系。比如在int_register_android_os_binder中會通過jni标準的方法getmethodid等初始化gbinderoffsets:
在android_os_binder_init中new了一個javabbinderholder,javabbinderholder new了一個javabbinder儲存到了自己的成員wp<javabbinder> mbinder中。
javabbinder繼承自native層的bbinder,并且将java層的binder對象(此處即powermanagerservice)儲存到了成員mobject中,并通過object()方法傳回。
現在我們發現,javabinder,binderbbinderholder,javabbinder存在互相引用關系:
powermanagerservice.mobject->javabbinderholder
javabbinderholder.mbinder->javabbinder
javabbinder.mobject->powermanagerservice
binder是一種client-server類型的ipc,powermanagerservice屬于server端,從native binder中我們知道,client通過bpbinder經由binder driver、bbinder與serverr通信,powermanagerservice通過javabbinderholder引用javabbinder,而javabbinder繼承自bbinder,符合了server的條件,server實體有了,接下來就要向servicemanager注冊,通過以下方法:
binderinternal.getcontextobject是一個native方法,調用jniandroid_os_binderinternal_getcontextobject:
processstate::self()->getcontextobject就很熟悉了,在binder in native中可以知道,這個調用傳回new bpbinder(0)。
javaobjectforibinder的作用就是,建立一個java層的binderproxy對象,将native層的bpbinder儲存到binderproxy.mobject,并将binderproxy的弱引用通過attachobject儲存到native層的bpbinder(成員mobjects中),這樣java層的binderproxy與native層的bpbinder就可以互相引用了。java層的binderproxy及其在native層的表示間的映射關系同binder類一樣也是在register_android_os_binder中建立的。
上面紅色的部分就等效于:
servicemanagernative繼承自iservicemanager與java層的binder類,binderproxy可以引用bpbinder。asinterface就像native binder中的interface_cast的,asinterface實作可以簡化為:
obj是binderproxy對象。servicemanagerproxy直接将這個binderproxy對象儲存在了成員mremote中,并通過asbinder傳回。
servicemanagerproxy同時實作了iservicemanager,而且由其名字可知,servicemanagerproxy是作為servicemanager在client端的代理的,看下它的addservice的實作:
writestrongbinder是native方法,調用android_os_parcel_writestrongbinder,在android_os_parcel_writestrongbinder将java parcel轉換成native parcel(native parcel的指針儲存在java parcel的成員變量中),然後調用以下語句:
sp<ibinder> ibinderforjavaobject(jnienv* env, jobject obj)根據obj傳回javabbinder或native bpbinder,在這裡傳入的obj 是powermanagerservice,傳回javabbinder。接下來調用了mremote.transact,mremote是binderproxy的對象。
binderproxy的transact是native方法,調用jniandroid_os_binderproxy_transact,在android_os_binderproxy_transact中通過:
擷取到binderproxy中儲存的bpbinder,然後調用bpbinder的transact,到這裡就和native binder的調用流程一樣了,native servicemanager會注冊我們的service,在這裡是powermanagerservice。
service已經向servicemanager注冊了,那麼我們怎麼獲得所注冊的service,或者更準确地說,怎麼獲得所注冊的service的代理呢?
回想下我們在apk中是怎麼擷取系統服務的:
看一下getsystemservice的實作,位于contextimpl中:
1. servicemanager.getservice獲得ibinder對象
同servicemanager.addservice一樣,servicemanager.getservice首先獲得一個servicemanagerproxy的對象,然後調用它的getservice方法:
mremote是binderproxy對象,内部引用了bpbinder,調用binderproxy的native方法transact與binder通信,然後通過readstrongbinder()讀取傳回的資料,一個ibinder對象。
readstrongbinder中通過javaobjectforibinder傳回了binderproxy對象,前面已經說過。
2. 通過asinterface将獲得的ibinder對象轉換成ipowermanager對象
ipowermanager.stub.asinterface可以簡化為:
proxy隻是将傳入的參數(binderproxy)儲存到了成員mremote中并通過asbinder傳回。
proxy與stub都是ipowermanager.aidl編譯後生成的類,都位于ipowermanager.java中。關于aidl網上有很多資料。
3. ipowermanager對象是不向外暴露的,構造一個powermanager封裝ipowermanager傳回。
powermanager隻是将ipowermanager儲存在了成員變量中,powermanager中儲存了binderproxy,binderproxy中引用了native bpbinder,就可以與server進行通信了。
server端接收到client的請求後會調用bbinder的transact處理請求,transact會調用虛函數ontransact,javabbinder繼承自bbinder,是以會調用javabbinder::ontransact,在javabbinder::ontransact中有以下一句:
通過jni反向調用了java類的方法。前面我們知道了,java實作的service中,service對象,javabbinderholder,javabbinder存在互相引用關系,javabbinder的成員mobject引用了java中的service對象,比如此處的powermanagerservice,而且在int_register_android_os_binder中通過
将service的exectransact方法(其實是binder的方法)儲存在了gbinderoffsets.mexectransact中,所在以javabbinder::ontransact中會調用binder.exectransact。在binder.exectransact中調用了ontransact,執行子類即stub類的ontransact方法,在ontransact中根據code值執行相應的方法,最終是調用service類(繼承自stub)中相應的方法。
java層通過jni利用了native層的binder,在jni函數注冊時會建立java層binder,binderproxy,binderproxy等類與native層的映射關系。java層service實體繼承自java層的binder類,在binder類初始化時會建立一個javabbinderholder作為javabbinder的容器,javabbinder繼承自bbinder,java層binder類引用javabbinderholder,javabbinderholder引用javabbinder,javabbinder繼承自bbinder并引用java層的binder類,這三者互相引用,這樣java層的service實體就可以通過bbinder與驅動進行通信了。
程序向java層的servicemanager代理發送get_service請求,然後通過jni向native層的servicemanager請求服務,native層的servicemanager傳回請求的服務的代理對象bpbinder,通過javaobjectforibinder函數将native的bpbinder轉化為java層對應的binderproxy,然後通過aidl生成的stub類asinterface方法将binderproxy封閉到請求的服務的代理對象中,這個代理對象引用了binderproxy,binderproxy内部儲存了native層的bpbinder,這樣就可以與驅動進行通信了。
當server端接收到client的請求時會通過bbinder的transact調用server的服務,bbinder的transact調用虛函數ontransact,這樣就會調到bbinder的子類javabbinder的ontransact,而javabinder::ontransact會通過jni反向調用到java層binder類的exectransact,binder.exectransact調用ontransact即子類stub的ontransact,然後根據code值調用service實體類(繼承自stub)相應的方法。