Binder系列7—framework層分析

一起愈、概述

1.1 Binder架構(gòu)

binder在framework層球昨,采用JNI技術(shù)來(lái)調(diào)用native(C/C++)層的binder架構(gòu)画舌,從而為上層應(yīng)用程序提供服務(wù)。 看過(guò)binder系列之前的文章翻斟,我們知道native層中,binder是C/S架構(gòu)说铃,分為Bn端(Server)和Bp端(Client)访惜。對(duì)于java層在命名與架構(gòu)上非常相近,同樣實(shí)現(xiàn)了一套IPC通信架構(gòu)腻扇。


圖解:

圖中紅色代表整個(gè)framework層 binder架構(gòu)相關(guān)組件债热;

Binder類代表Server端,BinderProxy類代碼Client端幼苛;

圖中藍(lán)色代表Native層Binder架構(gòu)相關(guān)組件窒篱;

上層framework層的Binder邏輯是建立在Native層架構(gòu)基礎(chǔ)之上的,核心邏輯都是交予Native層方法來(lái)處理蚓峦。

framework層的ServiceManager類與Native層的功能并不完全對(duì)應(yīng)舌剂,framework層的ServiceManager類的實(shí)現(xiàn)最終是通過(guò)BinderProxy傳遞給Native層來(lái)完成的,后面會(huì)詳細(xì)說(shuō)明暑椰。

1.2 Binder類圖

下面列舉framework的binder類關(guān)系圖


圖解:(圖中淺藍(lán)色都是Interface霍转,其余都是Class)

ServiceManager:通過(guò)getIServiceManager方法獲取的是ServiceManagerProxy對(duì)象; ServiceManager的addService, getService實(shí)際工作都交由ServiceManagerProxy的相應(yīng)方法來(lái)處理一汽;

ServiceManagerProxy:其成員變量mRemote指向BinderProxy對(duì)象避消,ServiceManagerProxy的addService, getService方法最終是交由mRemote來(lái)完成。

ServiceManagerNative:其方法asInterface()返回的是ServiceManagerProxy對(duì)象召夹,ServiceManager便是借助ServiceManagerNative類來(lái)找到ServiceManagerProxy岩喷;

Binder:其成員變量mObject和方法execTransact()用于native方法

BinderInternal:內(nèi)部有一個(gè)GcWatcher類,用于處理和調(diào)試與Binder相關(guān)的垃圾回收监憎。

IBinder:接口中常量FLAG_ONEWAY:客戶端利用binder跟服務(wù)端通信是阻塞式的纱意,但如果設(shè)置了FLAG_ONEWAY,這成為非阻塞的調(diào)用方式鲸阔,客戶端能立即返回偷霉,服務(wù)端采用回調(diào)方式來(lái)通知客戶端完成情況。另外IBinder接口有一個(gè)內(nèi)部接口DeathDecipient(死亡通告)褐筛。

1.3 Binder類分層

整個(gè)Binder從kernel至类少,native,JNI渔扎,F(xiàn)ramework層所涉及的全部類


二硫狞、初始化

在Android系統(tǒng)開(kāi)機(jī)過(guò)程中,Zygote啟動(dòng)時(shí)會(huì)有一個(gè)虛擬機(jī)注冊(cè)過(guò)程,該過(guò)程調(diào)用AndroidRuntime::startReg方法來(lái)完成jni方法的注冊(cè)残吩。

2.1 startReg

==> AndroidRuntime.cpp


注冊(cè)JNI方法财忽,其中g(shù)RegJNI是一個(gè)數(shù)組蔗怠,記錄所有需要注冊(cè)的jni方法治拿,其中有一項(xiàng)便是REG_JNI(register_android_os_Binder),下面說(shuō)說(shuō)register_android_os_Binder過(guò)程淳玩。

2.2 register_android_os_Binder

==> android_util_Binder.cpp


2.3 注冊(cè)Binder

==> android_util_Binder.cpp


注冊(cè) Binder類的jni方法旁瘫,其中:

FindClassOrDie(env, kBinderPathName) 基本等價(jià)于 env->FindClass(kBinderPathName)

MakeGlobalRefOrDie() 等價(jià)于 env->NewGlobalRef()

GetMethodIDOrDie() 等價(jià)于 env->GetMethodID()

GetFieldIDOrDie() 等價(jià)于 env->GeFieldID()

RegisterMethodsOrDie() 等價(jià)于 Android::registerNativeMethods();

(1)gBinderOffsets

gBinderOffsets是全局靜態(tài)結(jié)構(gòu)體(struct)祖凫,定義如下:


gBinderOffsets保存了Binder.java類本身以及其成員方法execTransact()和成員屬性mObject,這為JNI層訪問(wèn)Java層提供通道酬凳。另外通過(guò)查詢獲取Java層 binder信息后保存到gBinderOffsets惠况,而不再需要每次查找binder類信息的方式能大幅度提高效率,是由于每次查詢需要花費(fèi)較多的CPU時(shí)間宁仔,尤其是頻繁訪問(wèn)時(shí)稠屠,但用額外的結(jié)構(gòu)體來(lái)保存這些信息,是以空間換時(shí)間的方法翎苫。

(2)gBinderMethods


通過(guò)RegisterMethodsOrDie()权埠,將為gBinderMethods數(shù)組中的方法建立了一一映射關(guān)系,從而為Java層訪問(wèn)JNI層提供通道煎谍。

總之攘蔽,int_register_android_os_Binder方法的主要功能:

通過(guò)gBinderOffsets,保存Java層Binder類的信息呐粘,為JNI層訪問(wèn)Java層提供通道满俗;

通過(guò)RegisterMethodsOrDie,將gBinderMethods數(shù)組完成映射關(guān)系作岖,從而為Java層訪問(wèn)JNI層提供通道唆垃。

也就是說(shuō)該過(guò)程建立了Binder類在Native層與framework層之間的相互調(diào)用的橋梁。

2.4 注冊(cè)BinderInternal

==> android_util_Binder.cpp

注冊(cè)BinderInternal類的jni方法痘儡,gBinderInternalOffsets保存了BinderInternal的forceBinderGc()方法辕万。

下面是BinderInternal類的JNI方法注冊(cè):

該過(guò)程其【2.3】非常類似,也就是說(shuō)該過(guò)程建立了是BinderInternal類在Native層與framework層之間的相互調(diào)用的橋梁沉删。

2.5 注冊(cè)BinderProxy

==> android_util_Binder.cpp

注冊(cè)BinderProxy類的jni方法蓄坏,gBinderProxyOffsets保存了BinderProxy的構(gòu)造方法,sendDeathNotice(), mObject, mSelf, mOrgue信息丑念。

下面BinderProxy類的JNI方法注冊(cè)

該過(guò)程其【2.3】非常類似,也就是說(shuō)該過(guò)程建立了是BinderProxy類在Native層與framework層之間的相互調(diào)用的橋梁结蟋。

三脯倚、注冊(cè)服務(wù)

3.1 SM.addService

[-> ServiceManager.java]


先來(lái)看看getIServiceManager()過(guò)程,如下:

3.2 getIServiceManager

[-> ServiceManager.java]


采用了單例模式獲取ServiceManager getIServiceManager()返回的是ServiceManagerProxy(簡(jiǎn)稱SMP)對(duì)象

3.2.1 getContextObject()

[-> android_util_binder.cpp]


BinderInternal.java中有一個(gè)native方法getContextObject(),JNI調(diào)用執(zhí)行上述方法推正。

對(duì)于ProcessState::self()->getContextObject()恍涂,在獲取ServiceManager的第3節(jié)已詳細(xì)解決,即ProcessState::self()->getContextObject()等價(jià)于?new BpBinder(0);

3.2.2 javaObjectForIBinder

[-> android_util_binder.cpp]


根據(jù)BpBinder(C++)生成BinderProxy(Java)對(duì)象. 主要工作是創(chuàng)建BinderProxy對(duì)象,并把BpBinder對(duì)象地址保存到BinderProxy.mObject成員變量. 到此植榕,可知ServiceManagerNative.asInterface(BinderInternal.getContextObject()) 等價(jià)于


3.3 SMN.asInterface

[-> ServiceManagerNative.java]


由此再沧,可知ServiceManagerNative.asInterface(new BinderProxy()) 等價(jià)于new ServiceManagerProxy(new BinderProxy()). 為了方便,ServiceManagerProxy簡(jiǎn)稱為SMP尊残。

3.3.1 ServiceManagerProxy初始化

[-> ServiceManagerNative.java ::ServiceManagerProxy]


mRemote為BinderProxy對(duì)象炒瘸,該BinderProxy對(duì)象對(duì)應(yīng)于BpBinder(0),其作為binder代理端寝衫,指向native層大管家service Manager顷扩。

ServiceManager.getIServiceManager最終等價(jià)于new ServiceManagerProxy(new BinderProxy()),意味著【3.1】中的getIServiceManager().addService(),等價(jià)于SMP.addService().

framework層的ServiceManager的調(diào)用實(shí)際的工作確實(shí)交給SMP的成員變量BinderProxy慰毅;而BinderProxy通過(guò)jni方式隘截,最終會(huì)調(diào)用BpBinder對(duì)象;可見(jiàn)上層binder架構(gòu)的核心功能依賴native架構(gòu)的服務(wù)來(lái)完成的汹胃。

3.4 SMP.addService

[-> ServiceManagerNative.java ::ServiceManagerProxy]

3.5 writeStrongBinder(Java)

[-> Parcel.java]


3.5.1 android_os_Parcel_writeStrongBinder

[-> android_os_Parcel.cpp]

3.5.2 ibinderForJavaObject

[-> android_util_Binder.cpp]


根據(jù)Binde(Java)生成JavaBBinderHolder(C++)對(duì)象. 主要工作是創(chuàng)建JavaBBinderHolder對(duì)象,并把JavaBBinderHolder對(duì)象地址保存到Binder.mObject成員變量.

3.5.3 JavaBBinderHolder.get()

[-> android_util_Binder.cpp]


JavaBBinderHolder有一個(gè)成員變量mBinder婶芭,保存當(dāng)前創(chuàng)建的JavaBBinder對(duì)象,這是一個(gè)wp類型的着饥,可能會(huì)被垃圾回收器給回收犀农,所以每次使用前,都需要先判斷是否存在贱勃。

3.5.4 JavaBBinder初始化

==> [-> android_util_Binder.cpp]


創(chuàng)建JavaBBinder井赌,該對(duì)象繼承于BBinder對(duì)象。

data.writeStrongBinder(service)最終等價(jià)于parcel->writeStrongBinder(new JavaBBinder(env, obj));

3.6 writeStrongBinder(C++)

[-> parcel.cpp]


3.6.1 flatten_binder

[-> parcel.cpp]


將Binder對(duì)象扁平化贵扰,轉(zhuǎn)換成flat_binder_object對(duì)象仇穗。

對(duì)于Binder實(shí)體,則cookie記錄Binder實(shí)體的指針戚绕;

對(duì)于Binder代理纹坐,則用handle記錄Binder代理的句柄;

關(guān)于localBinder舞丛,代碼見(jiàn)Binder.cpp耘子。


3.6.2 finish_flatten_binder


再回到小節(jié)3.4的addService過(guò)程,則接下來(lái)進(jìn)入transact球切。

3.7 BinderProxy.transact

[-> Binder.java ::BinderProxy]


回到ServiceManagerProxy.addService谷誓,其成員變量mRemote是BinderProxy。transactNative經(jīng)過(guò)jni調(diào)用吨凑,進(jìn)入下面的方法

3.8 android_os_BinderProxy_transact

[-> android_util_Binder.cpp]


Java層的BinderProxy.transact()最終交由Native層的BpBinder::transact()完成捍歪。Native Binder的注冊(cè)服務(wù)(addService)中有詳細(xì)說(shuō)明BpBinder執(zhí)行過(guò)程户辱。另外,該方法可拋出RemoteException糙臼。

3.9 小結(jié)

addService的核心過(guò)程:

四庐镐、獲取服務(wù)

4.1 SM.getService

[-> ServiceManager.java]


關(guān)于getIServiceManager(),在前面小節(jié)3.2已經(jīng)講述了变逃,等價(jià)于new ServiceManagerProxy(new BinderProxy())必逆。 其中sCache = new HashMap()以hashmap格式緩存已組成的名稱。請(qǐng)求獲取服務(wù)過(guò)程中揽乱,先從緩存中查詢是否存在名眉,如果緩存中不存在的話,再通過(guò)binder交互來(lái)查詢相應(yīng)的服務(wù)锤窑。

4.2 SMP.getService

[-> ServiceManagerNative.java ::ServiceManagerProxy]


4.3 BinderProxy.transact

[-> Binder.java]

4.4 android_os_BinderProxy_transact

[-> android_util_Binder.cpp]


0

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末璧针,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子渊啰,更是在濱河造成了極大的恐慌探橱,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绘证,死亡現(xiàn)場(chǎng)離奇詭異隧膏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嚷那,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門胞枕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人魏宽,你說(shuō)我怎么就攤上這事腐泻。” “怎么了队询?”我有些...
    開(kāi)封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵派桩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蚌斩,道長(zhǎng)铆惑,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任送膳,我火速辦了婚禮员魏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘叠聋。我一直安慰自己撕阎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布碌补。 她就那樣靜靜地躺著闻书,像睡著了一般名斟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上魄眉,一...
    開(kāi)封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音闷袒,去河邊找鬼坑律。 笑死,一個(gè)胖子當(dāng)著我的面吹牛囊骤,可吹牛的內(nèi)容都是我干的晃择。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼也物,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宫屠!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起滑蚯,我...
    開(kāi)封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤浪蹂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后告材,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坤次,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年斥赋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缰猴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疤剑,死狀恐怖滑绒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情隘膘,我是刑警寧澤疑故,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站棘幸,受9級(jí)特大地震影響焰扳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜误续,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一吨悍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蹋嵌,春花似錦育瓜、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)恋脚。三九已至,卻和暖如春焰手,著一層夾襖步出監(jiān)牢的瞬間糟描,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工书妻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留船响,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓躲履,卻偏偏與公主長(zhǎng)得像见间,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子工猜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容