作者:wangle12138 鏈接:http://www.cnblogs.com/wangle12138/p/8087709.html 聲明:本文是 wangle12138 原創(chuàng)投稿,,轉(zhuǎn)發(fā)等請(qǐng)聯(lián)系原作者授權(quán)。
前言我們?cè)谏弦黄斜容^詳盡的介紹了 Android 的消息機(jī)制,,不過有一些內(nèi)容我們?cè)诓焕斫釧ndroid Binder 的話是無法講解清楚的。對(duì)于初學(xué) Android 的朋友而言,,最難卻又最想掌握的恐怕就是 Binder 機(jī)制了,,因?yàn)?Android 系統(tǒng)基本上可以看作是一個(gè)基于 Binder 通信的 C/S 架構(gòu)。 Binder 就像網(wǎng)絡(luò)一樣,,把系統(tǒng)的各個(gè)部分連接在了一起,,因此它是非常重要的,。我們下面會(huì) Android Binder 機(jī)制進(jìn)行從上到下從易到難的分層次講解,從而既能讓初學(xué)者對(duì) Binder 有一定認(rèn)識(shí),,也能讓有一定Android基礎(chǔ)的人獲得收獲,。 注:下文中的源碼均出自android-6.0.0_r5 Binder概述對(duì)于初學(xué)者來說,深入 Android Binder 機(jī)制是非常不明智的,。Android Binder機(jī)制大都涉及Java層,、Native層、驅(qū)動(dòng)層這三三個(gè)方面,,對(duì)于初學(xué)者來說想啃這三塊硬骨頭很容易磕著牙,。我們這這一節(jié)概述從以下幾個(gè)方面讓你從比較宏觀的角度理解Android Binder。 進(jìn)程在該系列博客中的第一章我們就說起了Android進(jìn)程相關(guān)問題,,Android故意弱化了進(jìn)程的概念,,而用相對(duì)容易理解的四大組件??墒俏覀?cè)谏晕⑸钊階ndroid的時(shí)候,,那么進(jìn)程是繞不過的。默認(rèn)情況下,,同一個(gè)應(yīng)用程序中的所有組件運(yùn)行在同一個(gè)進(jìn)程中,,而且絕大多數(shù)的應(yīng)用程序也都是這樣的。這個(gè)默認(rèn)進(jìn)程是用這個(gè)應(yīng)用的包名來命名的,。 進(jìn)程間通信我們?cè)谶\(yùn)行App的時(shí)候經(jīng)常需要使用一些系統(tǒng)服務(wù),,比如剪切板服務(wù),而剪切板服務(wù)是運(yùn)行在SystemServer進(jìn)程中的,。那我們的App是怎么使用剪切板服務(wù)的呢,,我們都知道進(jìn)程是相互獨(dú)立的,靜態(tài)變量等等都無法共用,。這就涉及到進(jìn)程間的通信了,,即IPC。我們都知道Android是基于Linux內(nèi)核的,,那我們簡(jiǎn)單介紹下Linux下的幾種IPC機(jī)制,。 管道(Pipe)管道是由內(nèi)核管理的一個(gè)緩沖區(qū),相當(dāng)于我們放入內(nèi)存中的一個(gè)紙條,。管道的一端連接一個(gè)進(jìn)程的輸出,。這個(gè)進(jìn)程會(huì)向管道中放入信息。管道的另一端連接一個(gè)進(jìn)程的輸入,,這個(gè)進(jìn)程取出被放入管道的信息,。 管道是半雙工的,數(shù)據(jù)只能向一個(gè)方向流動(dòng);需要雙方通信時(shí),,需要建立起兩個(gè)管道 只能用于父子進(jìn)程或者兄弟進(jìn)程之間(具有親緣關(guān)系的進(jìn)程),。比如fork或exec創(chuàng)建的新進(jìn)程,在使用exec創(chuàng)建新進(jìn)程時(shí),,需要將管道的文件描述符作為參數(shù)傳遞給exec創(chuàng)建的新進(jìn)程,。當(dāng)父進(jìn)程與使用fork創(chuàng)建的子進(jìn)程直接通信時(shí),發(fā)送數(shù)據(jù)的進(jìn)程關(guān)閉讀端,,接受數(shù)據(jù)的進(jìn)程關(guān)閉寫端,。 管道只能在本地計(jì)算機(jī)中使用,而不可用于網(wǎng)絡(luò)間的通信,。
命名管道(FIFO)命名管道是一種特殊類型的文件,,它在系統(tǒng)中以文件形式存在。這樣克服了管道的弊端,,他可以允許沒有親緣關(guān)系的進(jìn)程間通信,。 共享內(nèi)存(Share Memory)共享內(nèi)存是在多個(gè)進(jìn)程之間共享內(nèi)存區(qū)域的一種進(jìn)程間的通信方式,由IPC為進(jìn)程創(chuàng)建的一個(gè)特殊地址范圍,,它將出現(xiàn)在該進(jìn)程的地址空間中,。其他進(jìn)程可以將同一段共享內(nèi)存連接到自己的地址空間中。所有進(jìn)程都可以訪問共享內(nèi)存中的地址,,如果一個(gè)進(jìn)程向共享內(nèi)存中寫入了數(shù)據(jù),,所做的改動(dòng)將立刻被其他進(jìn)程看到。 共享內(nèi)存是IPC最快捷的方式,,共享內(nèi)存方式直接將某段內(nèi)存段進(jìn)行映射,多個(gè)進(jìn)程間的共享內(nèi)存是同一塊的物理空間,,僅僅映射到各進(jìn)程的地址不同而已,,因此不需要進(jìn)行復(fù)制,可以直接使用此段空間,。 共享內(nèi)存本身并沒有同步機(jī)制,,需要程序員自己控制。
內(nèi)存映射(Memory Map)內(nèi)存映射是由一個(gè)文件到一塊內(nèi)存的映射,,在此之后進(jìn)程操作文件,,就像操作進(jìn)程空間里的內(nèi)存地址一樣了。 套接字(Socket)套接字機(jī)制不但可以單機(jī)的不同進(jìn)程通信,,而且使得跨網(wǎng)機(jī)器間進(jìn)程可以通信,。 套接字的創(chuàng)建和使用與管道是有區(qū)別的,套接字明確地將客戶端與服務(wù)器區(qū)分開來,,可以實(shí)現(xiàn)多個(gè)客戶端連到同一服務(wù)器,。 Binder作為Android系統(tǒng)下的一種IPC機(jī)制,其本質(zhì)上與上面羅列出的IPC機(jī)制并無本質(zhì)上的不同,都是作為進(jìn)程間通信的一種手段,。并且在Android系統(tǒng)中也不是只存在Binder這一種進(jìn)程間通信的方式,,在有些地方也使用了Socket。既然Linux已經(jīng)提供了眾多IPC機(jī)制,,那么Android 為何還要使用Binder作為主要的進(jìn)程間通信的方式呢,,那么當(dāng)然有他的優(yōu)點(diǎn)存在。 采用C/S的通信模式,。而在linux通信機(jī)制中,,目前只有socket支持C/S的通信模式,但socket有其劣勢(shì),,具體參看第二條,。 有更好的傳輸性能。對(duì)比于Linux的通信機(jī)制,,socket:是一個(gè)通用接口,,導(dǎo)致其傳輸效率低,開銷大,;管道和消息隊(duì)列:因?yàn)椴捎么鎯?chǔ)轉(zhuǎn)發(fā)方式,,所以至少需要拷貝2次數(shù)據(jù),效率低,;共享內(nèi)存:雖然在傳輸時(shí)沒有拷貝數(shù)據(jù),,但其控制機(jī)制復(fù)雜(比如跨進(jìn)程通信時(shí),需獲取對(duì)方進(jìn)程的pid,,得多種機(jī)制協(xié)同操作),。 安全性更高。Linux的IPC機(jī)制在本身的實(shí)現(xiàn)中,,并沒有安全措施,,得依賴上層協(xié)議來進(jìn)行安全控制。而Binder機(jī)制的UID/PID是由Binder機(jī)制本身在內(nèi)核空間添加身份標(biāo)識(shí),,安全性高,;并且Binder可以建立私有通道,這是linux的通信機(jī)制所無法實(shí)現(xiàn)的(Linux訪問的接入點(diǎn)是開放的),。 對(duì)用戶來說,,通過binder屏蔽了client的調(diào)用server的隔閡,client端函數(shù)的名字,、參數(shù)和返回值和server的方法一模一樣,,對(duì)用戶來說猶如就在本地(也可以做得不一樣),這樣的體驗(yàn)或許其他ipc方式也可以實(shí)現(xiàn),,但binder出生那天就是為此而生,。
Java層BinderJava層Binder的功能,依賴于Native層Binder來實(shí)現(xiàn),可以認(rèn)為Java層Binder架構(gòu)是Native層Binder架構(gòu)的一個(gè)鏡像,。但是這并不影響我們分析Android Java層Binder的功能,。我們用一個(gè)例子來說明這個(gè)過程。 我們?cè)诘谝黄芯椭v解了SystemServer這個(gè)進(jìn)程,,這個(gè)進(jìn)程和zygote進(jìn)程一起撐起了Android 世界,,他們之中有一個(gè)崩潰,Android世界就會(huì)砰然倒塌,。Android許多的重要的系統(tǒng)服務(wù)如AMS,、PMS等都運(yùn)行在SystemServer進(jìn)程中。但是還有一個(gè)比較重要的進(jìn)程ServiceManager進(jìn)程(簡(jiǎn)稱SM)跟zygote是兄弟進(jìn)程,。這個(gè)進(jìn)程的作用是用來統(tǒng)一管理服務(wù),,如AMS。它們之間的關(guān)系如下,。 我們的AMS需要向SM進(jìn)程中注冊(cè)信息,,其他進(jìn)程如果想使用AMS,那么先和ServiceManager進(jìn)程進(jìn)行通信查詢,,接著再和AMS所在SystemServer進(jìn)程通信,。這部分關(guān)系圖如下 我們這里僅上圖分析①②③中的一條道路,我們來分析③,,即我們的應(yīng)用進(jìn)程(Client)如何與服務(wù)進(jìn)程(Server)交互,。 Java層的Binder,我們來看涉及的類的結(jié)構(gòu)圖
[IBinder.java] public interface IBinder { //交互函數(shù) public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException; }
我們接著來看Binder和BinderProxy 他們都聲明在Binder.java中 [Binder.java] /** Binder類 */ public class Binder implements IBinder { public final boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { ...... //這里調(diào)用了onTransact函數(shù)進(jìn)行處理,一般情況下這個(gè)函數(shù)都會(huì)被它的子類重寫 boolean r = onTransact(code, data, reply, flags); if (reply != null) { reply.setDataPosition(0); } return r; } } /** BinderProxy類 */ final class BinderProxy implements IBinder { public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { //直接以JNI的方式調(diào)用Native層的transact函數(shù) return transactNative(code, data, reply, flags); } public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException; }
通用的IPC流程如下 現(xiàn)在假設(shè)下面一個(gè)場(chǎng)景,,我們的應(yīng)用進(jìn)程即我們的App想要使用ActivityManagerService的startActivity函數(shù)(這種場(chǎng)景肯定有的,,當(dāng)我們拿到手機(jī)的時(shí)候,手機(jī)已經(jīng)預(yù)裝了許多App,其中Launcher App(桌面管理App)是在Android系統(tǒng)啟動(dòng)完成之后啟動(dòng)的第一個(gè)App,,我們安裝好一個(gè)應(yīng)用后,,點(diǎn)擊應(yīng)用圖標(biāo)即發(fā)出Intent,想要啟動(dòng)另一個(gè)App中的Activity,,我們?cè)贏ndroidManifest.xml中注冊(cè)了Main Activity)。Launcher App所在的進(jìn)程要與AMS所在的進(jìn)程SystemServer進(jìn)程交互,。 我們來看這個(gè)例子,。按照上面的通用流程我們猜測(cè)Launcher進(jìn)程與SystemServer進(jìn)程交互過程也如上圖所示,那么按照這個(gè)思路我們來看,。分為3點(diǎn): 是否存在業(yè)務(wù)函數(shù)的統(tǒng)一聲明,?這一部分是我們的上圖中的test函數(shù)所聲明的類或者接口,我們的Client端代理和Server端服務(wù)都要實(shí)現(xiàn)這個(gè)函數(shù),。果然有 [IActivityManager.java] public interface IActivityManager extends IInterface { public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException; ...... }
這里聲明了我們將要調(diào)用的業(yè)務(wù)函數(shù)startActivity,,那么接著第二點(diǎn) 是否存在Server端服務(wù)代理?ActivityManagerProxy是在ActivityManagerNative.java中聲明的內(nèi)部類 class ActivityManagerProxy implements IActivityManager { public ActivityManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeString(callingPackage); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeStrongBinder(resultTo); data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); if (profilerInfo != null) { data.writeInt(1); profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } if (options != null) { data.writeInt(1); options.writeToParcel(data, 0); } else { data.writeInt(0); } //看這里果然是通過mRemote.transact函數(shù),,這里的mRemote是BinderProxy類,,關(guān)于這一點(diǎn)我們?cè)贜ative層分析的時(shí)候再給出 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); reply.readException(); int result = reply.readInt(); reply.recycle(); data.recycle(); return result; } ...... }
是否存在Server端服務(wù)ActivityManagerNative是繼承于Binder的抽象類,,并重寫了onTransact方法 public abstract class ActivityManagerNative extends Binder implements IActivityManager{ @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { //根據(jù)code處理相應(yīng)的業(yè)務(wù)邏輯,,我們這里是START_ACTIVITY_TRANSACTION switch (code) { case START_ACTIVITY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); IApplicationThread app = ApplicationThreadNative.asInterface(b); String callingPackage = data.readString(); Intent intent = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); IBinder resultTo = data.readStrongBinder(); String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); ProfilerInfo profilerInfo = data.readInt() != 0 ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int result = startActivity(app, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options); reply.writeNoException(); reply.writeInt(result); return true; } } }
既然ActivityManagerNative是個(gè)抽象類,,那么誰(shuí)真正實(shí)現(xiàn)了呢 [ActivityManagerService.java]
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { //重寫了onTransact函數(shù) @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { ...... try { //調(diào)用父類即ActivityManagerNative的onTransact函數(shù) return super.onTransact(code, data, reply, flags); } catch (RuntimeException e) { throw e; } } }
Launcher進(jìn)程與SystemServer進(jìn)程交互過程如下 本節(jié)小結(jié)關(guān)于Java層的Binder機(jī)制,,我們只需要理解以BinderProxy代表的代理端和Binder代表的服務(wù)端的概念即可,,例如我們本例中的AMS,,AMS是運(yùn)行在SystemServer進(jìn)程中的服務(wù)端,,它間接繼承于Binder,,在得到相關(guān)請(qǐng)求后,會(huì)調(diào)用AMS重寫的onTransact函數(shù)進(jìn)行邏輯處理,。那么這個(gè)請(qǐng)求就是是AMS的客戶端ActivityManagerProxy通過Binder的方式發(fā)給它的,,ActivityManagerProxy發(fā)送這個(gè)請(qǐng)求的方式,是通過調(diào)用其內(nèi)部的成員變量mRemote,這個(gè)mRemote其實(shí)是BinderProxy的對(duì)象,,然后BinderProxy通過JNI調(diào)用Native層對(duì)應(yīng)函數(shù),,最終通過Binder驅(qū)動(dòng)達(dá)到與SystemServer交互的目的。 那么還遺留下以下幾個(gè)問題: 1. 服務(wù)器端的代理怎么獲得的 2. 位于代理類中的mRemote這個(gè)變量 要想理解好上面的個(gè)問題,,我們必須向Native層進(jìn)軍,。 Native層Binder我們依然以AMS分析,我們先來想一下我們?cè)谟脩暨M(jìn)程中即我們的App中想使用AMS或者其他剪切板之類的系統(tǒng)服務(wù)函數(shù)了怎么辦,?,?按照上面的分析我們要獲得AMS的代理ActivityManagerProxy [ActivityManagerNative.java] //這里我們的App進(jìn)程從SM進(jìn)程得到AMS服務(wù)對(duì)應(yīng)的客戶端代理BinderProxy IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); //以BinderProxy為參數(shù)得到我們ActivityManagerProxy,并把BinderProxy對(duì)象存儲(chǔ)在mRemote變量中 IActivityManager am = asInterface(b); return am;
到這里我們就有以下問題,,本小節(jié)分析1,2 1. 既然可以通過SM獲得對(duì)應(yīng)的客戶端代理,,那么AMS必定已經(jīng)注冊(cè)在SM中了,那么怎么注冊(cè)的呢,? 2. AMS代理是如何獲得的,? 3. AMS代理是如何與Binder通信的? 我們來一一分析,,在分析問題之前我們先做一個(gè)假設(shè),,這個(gè)假設(shè)至關(guān)重要,那就是不管我們的SystemServer進(jìn)程與SM進(jìn)程交互也好還是我們的App進(jìn)程與SM進(jìn)程也好,,SM的代理已經(jīng)事先創(chuàng)建完畢,,即不管我們?cè)赟ystemServer端還是App端,在與SM進(jìn)程交互的時(shí)候不用考慮代理怎么獲得的,。為什么會(huì)有如此假設(shè),,因?yàn)槲易约荷钍芷浜Γ捎谏鲜鋈齻€(gè)過程均是通過Binder,,很容易陷入思維混亂,。 AMS是如何注冊(cè)的,?我們SystemServer進(jìn)程中的AMS通過SM的代理與SM進(jìn)程交互(讀者也可以把這個(gè)過程想象為你所能理解的進(jìn)程間通信方式,例如管道,、Socket等),,并把自己注冊(cè)在SM中 SystemServer創(chuàng)建出ActivityManagerService后,最終將調(diào)用其setSystemProcess方法: [SystemServer.java] public void setSystemProcess() { try { //注冊(cè)服務(wù),,第二個(gè)參數(shù)為this,,這里假設(shè)SystemServer通過“socket”與SM交互 ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); .......... } catch (PackageManager.NameNotFoundException e) { ........ } }
上面的請(qǐng)求最終是通過SM服務(wù)代理發(fā)送的() [ServiceManagerNative.java] public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException { //將數(shù)據(jù)打包寫入Parcel對(duì)象 Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); //注意這個(gè)地方,后文分析,,此時(shí)的service為ActivityManagerService data.writeStrongBinder(service); data.writeInt(allowIsolated ? 1 : 0); //調(diào)用BindProxy的transact函數(shù) mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); reply.recycle(); data.recycle(); }
上面的過程已經(jīng)分析過了,, 這里我們主要看一下哪個(gè)對(duì)應(yīng)的native層的transact函數(shù) [android_ util_Binder.cpp] static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) { ........ //將java對(duì)象轉(zhuǎn)化為native對(duì)象 Parcel* data = parcelForJavaObject(env, dataObj); ......... Parcel* reply = parcelForJavaObject(env, replyObj); ........ //得到native層的BpBinder IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); ........ //通過BpBinder利用IPCThreadState,將請(qǐng)求通過Binder驅(qū)動(dòng)發(fā)送給SM進(jìn)程 status_t err = target->transact(code, *data, reply, flags); ........ }
SM進(jìn)程收到信息后便處理這個(gè)消息(這個(gè)說法并不準(zhǔn)確,,準(zhǔn)確的說法是,,SM進(jìn)程中主線程一直在與binder設(shè)備交互,想必讀者也猜到了for(;;)),有消息時(shí)便通過預(yù)先定義好的函數(shù)進(jìn)行處理 [service_manager.c] switch(txn->code) { case SVC_MGR_ADD_SERVICE: s = bio_get_string16(msg, &len); if (s == NULL) { return -1; } handle = bio_get_ref(msg); allow_isolated = bio_get_uint32(msg) ? 1 : 0; //do_add_service if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, txn->sender_pid)) return -1; break; } int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, uid_t uid, int allow_isolated, pid_t spid) { //結(jié)構(gòu)體si,用來存儲(chǔ)服務(wù)信息 struct svcinfo *si; //判斷服務(wù)有沒有權(quán)限注冊(cè),,并不是所有的服務(wù)都能注冊(cè) if (!svc_can_register(s, len, spid)) { return -1; } //查詢服務(wù)有沒有注冊(cè)過 si = find_svc(s, len); if (si) {//已經(jīng)注冊(cè)過 if (si->handle) { ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n", str8(s, len), handle, uid); svcinfo_death(bs, si); } si->handle = handle; } else {//還沒有注冊(cè)過,,我們進(jìn)入這個(gè)分支 si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); if (!si) { ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n", str8(s, len), handle, uid); return -1; } //保存一些handle等信息 si->handle = handle; si->len = len; memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); si->name[len] = '\0'; si->death.func = (void*) svcinfo_death; si->death.ptr = si; si->allow_isolated = allow_isolated; si->next = svclist; svclist = si; } binder_acquire(bs, handle); binder_link_to_death(bs, handle, &si->death); return 0; }
看到這里SM貌似只保留了一些AMS的信息而已,實(shí)際上并不只是如此,,我們來看一下上面的保留問題 [Parcel.java] data.writeStrongBinder(service); public final void writeStrongBinder(IBinder val) { //調(diào)用了native函數(shù) nativeWriteStrongBinder(mNativePtr, val); }
跟進(jìn)[android_os_Parcel.cpp] static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { //native層的parcel const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } } } sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) { if (obj == NULL) return NULL; //obj為Binder類 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject); //調(diào)用了JavaBBinderHolder的get方法 return jbh != NULL ? jbh->get(env, obj) : NULL; } //obj為BinderProxy類 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { return (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); } ALOGW("ibinderForJavaObject: %p is not a Binder object", obj); return NULL; }
跟進(jìn)[Pacel.cpp] status_t Parcel::writeStrongBinder(const sp<IBinder>& val) { return flatten_binder(ProcessState::self(), val, this); } status_t flatten_binder(const sp<ProcessState>& /*proc*/, const sp<IBinder>& binder, Parcel* out) { flat_binder_object obj; obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; if (binder != NULL) {//binder不為空 IBinder *local = binder->localBinder();//是不是本地binder,,本地的意思是同一個(gè)進(jìn)程中的調(diào)用 if (!local) { BpBinder *proxy = binder->remoteBinder(); if (proxy == NULL) { ALOGE("null proxy"); } const int32_t handle = proxy ? proxy->handle() : 0; obj.type = BINDER_TYPE_HANDLE; obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */ obj.handle = handle; obj.cookie = 0; } else {//我們這里明顯不是 obj.type = BINDER_TYPE_BINDER; obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); obj.cookie = reinterpret_cast<uintptr_t>(local); } } else {//錯(cuò)誤信息 obj.type = BINDER_TYPE_BINDER; obj.binder = 0; obj.cookie = 0; } return finish_flatten_binder(binder, obj, out); }
通過上面的代碼,我們可以看到當(dāng)一個(gè)服務(wù)進(jìn)行注冊(cè)時(shí),,會(huì)將Java層的Binder對(duì)象和Native層的BBinder關(guān)聯(lián)起來,,于是服務(wù)端綁定到了Native層的Binder架構(gòu)。 此外,,addService中打包傳入的其實(shí)不是ActivityManagerService本身,,而是對(duì)應(yīng)的JavaBBinder對(duì)象。 這里對(duì)應(yīng)的結(jié)構(gòu)如下圖所示: AMS代理是如何獲得的,?我們上面SystemServer中的AMS已經(jīng)在SM中準(zhǔn)備好了,,那我們ServiceManager.getService(Context.ACTIVITY_SERVICE); 一樣的過程,我們知道最終會(huì)在service_manager.c中處理 switch(txn->code) { //這里有個(gè)case穿透,,,,好吧 case SVC_MGR_GET_SERVICE: case SVC_MGR_CHECK_SERVICE: s = bio_get_string16(msg, &len); if (s == NULL) { return -1; } //查詢AMS保存在SM中對(duì)應(yīng)的的那個(gè)handle handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); if (!handle) break; bio_put_ref(reply, handle); return 0; } 把寫入數(shù)據(jù)后的reply返回 bio_put_uint32(reply, 0);
回到我們的調(diào)用處 [ServiceManagerNative.java] public IBinder getService(String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); //看這里readStrongBinder,是不是感覺跟我們上面的writeStrongBinder感覺是一對(duì)的 IBinder binder = reply.readStrongBinder(); reply.recycle(); data.recycle(); return binder; }
Parcel的readStrongBinder還是個(gè)JNI調(diào)用 [android_ os_Parcel.cpp] static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { //這里我們看到了什么,,,,看函數(shù)名字應(yīng)該是為Binder生成一個(gè)java對(duì)象吧 return javaObjectForIBinder(env, parcel->readStrongBinder()); } return NULL; }
我們先看Pacel的readStrongBinder方法 [Parcel.cpp] sp<IBinder> Parcel::readStrongBinder() const { sp<IBinder> val; //看到這里,還記得writeStrongBinder中的flatten_binder,,這里是unflatten_binder unflatten_binder(ProcessState::self(), *this, &val); return val; } status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out) { const flat_binder_object* flat = in.readObject(false); if (flat) { switch (flat->type) { case BINDER_TYPE_BINDER: *out = reinterpret_cast<IBinder*>(flat->cookie); return finish_unflatten_binder(NULL, *flat, in); case BINDER_TYPE_HANDLE: //到這里我們也清楚了進(jìn)入這個(gè)分支 //調(diào)用ProcessState的getStrongProxyForHandle函數(shù) *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in); } } return BAD_TYPE; }
繼續(xù)跟進(jìn)[ProcessState.cpp] sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { if (handle == 0) {//這里handle為0的情況是為SM準(zhǔn)備的, Parcel data; status_t status = IPCThreadState::self()->transact( 0, IBinder::PING_TRANSACTION, data, NULL, 0); if (status == DEAD_OBJECT) return NULL; } //我們的不為0,,在這里創(chuàng)建了BpBinder b = new BpBinder(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result; }
好了剩下最后一個(gè)了javaObjectForIBinder [android_ util_Binder.cpp] jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) { if (val == NULL) return NULL; //如果val是Binder對(duì)象,,進(jìn)入下面分支,,此時(shí)val是BpBinder if (val->checkSubclass(&gBinderOffsets)) { // One of our own! jobject object = static_cast<JavaBBinder*>(val.get())->object(); LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object); return object; } ......... //調(diào)用BpBinder的findObject函數(shù) //在Native層的BpBinder中有一個(gè)ObjectManager,它用來管理在Native BpBinder上創(chuàng)建的Java BinderProxy對(duì)象 //findObject用于判斷gBinderProxyOffsets中,,是否存儲(chǔ)了已經(jīng)被ObjectManager管理的Java BinderProxy對(duì)象 jobject object = (jobject)val->findObject(&gBinderProxyOffsets); if (object != NULL) { jobject res = jniGetReferent(env, object); ............ //如果該Java BinderProxy已經(jīng)被管理,,則刪除這個(gè)舊的BinderProxy android_atomic_dec(&gNumProxyRefs); val->detachObject(&gBinderProxyOffsets); env->DeleteGlobalRef(object); } //創(chuàng)建一個(gè)新的BinderProxy對(duì)象 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); if (object != NULL) { // The proxy holds a reference to the native object. env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get()); val->incStrong((void*)javaObjectForIBinder); // The native object needs to hold a weak reference back to the // proxy, so we can retrieve the same proxy if it is still active. jobject refObject = env->NewGlobalRef( env->GetObjectField(object, gBinderProxyOffsets.mSelf)); //新創(chuàng)建的BinderProxy對(duì)象注冊(cè)到BpBinder的ObjectManager中,同時(shí)注冊(cè)一個(gè)回收函數(shù)proxy_cleanup //當(dāng)BinderProxy對(duì)象detach時(shí),,proxy_cleanup函數(shù)將被調(diào)用,,以釋放一些資源 val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup); // Also remember the death recipients registered on this proxy sp<DeathRecipientList> drl = new DeathRecipientList; drl->incStrong((void*)javaObjectForIBinder); //將死亡通知list和BinderProxy聯(lián)系起來 env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get())); // Note that a new object reference has been created. android_atomic_inc(&gNumProxyRefs); //垃圾回收相關(guān);利用gNumRefsCreated記錄創(chuàng)建出的BinderProxy數(shù)量 //當(dāng)創(chuàng)建出的BinderProxy數(shù)量大于200時(shí),,該函數(shù)將利用BinderInternal的ForceGc函數(shù)進(jìn)行一個(gè)垃圾回收 incRefsCreated(env); return object; } }
到這里總算都打通了總體流程如下 驅(qū)動(dòng)層BinderAMS代理是如何與Binder通信的,?通過Java層的服務(wù)端代理最終調(diào)用到BpBinder.transact函數(shù) [BpBinder.cpp] status_t BpBinder:transact(uint32_t code,const Parcel&data,Parcel*reply,uint32_t flags){ 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,; } return DEAD_OBJECT,; }
[IPCThreadState.cpp] IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mMyThreadId(gettid()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { pthread_setspecific(gTLS, this); clearCaller(); //mIn和mOut是兩個(gè)Parcel。 把它看成是發(fā)送和接收命令的緩沖區(qū)即可,。 mIn.setDataCapacity(256); mOut.setDataCapacity(256); } status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { ...... /* 注意這里的第一個(gè)參數(shù)BC_TRANSACTION,,它是應(yīng)用程序向binder設(shè)備發(fā)送消息的消 息碼,而binder設(shè)備向應(yīng)用程序回復(fù)消息的消息碼以BR_開頭,。 消息碼的定義在 binder_module.h中,,請(qǐng)求消息碼和回應(yīng)消息碼的對(duì)應(yīng)關(guān)系,需要查看Binder驅(qū)動(dòng)的實(shí) 現(xiàn)才能將其理清楚,,我們這里暫時(shí)用不上,。 */ err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); ...... err = waitForResponse(NULL, NULL); ...... return err; } status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, 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,用來標(biāo)識(shí)目的端,,其中0是ServiceManager的標(biāo)志,。 tr.target.handle=handle; //code是消息碼,,是用來switch/case的,! tr.code = code; tr.flags = binderFlags; tr.cookie = 0; tr.sender_pid = 0; tr.sender_euid = 0; const status_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(binder_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 = reinterpret_cast<uintptr_t>(statusBuffer); tr.offsets_size = 0; tr.data.ptr.offsets = 0; } else { return (mLastError = err); } //把命令寫到mOut中,而不是直接發(fā)出去,,可見這個(gè)函數(shù)有點(diǎn)名不副實(shí)。 mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr)); return NO_ERROR; } status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { uint32_t cmd; int32_t err; while (1) { if ((err=talkWithDriver()) <NO_ERROR) break; err = mIn.errorCheck(); if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; //看見沒,?這里開始操作mIn了,,看來talkWithDriver中 //把mOut發(fā)出去,,然后從driver中讀到數(shù)據(jù)放到mIn中了。 cmd = mIn.readInt32(); } } status_t IPCThreadState::talkWithDriver(bool doReceive) { binder_write_read bwr; //中間東西太復(fù)雜了,,不就是把mOut數(shù)據(jù)和mIn接收數(shù)據(jù)的處理后賦值給bwr嗎,? status_t err; do { //用ioctl來讀寫 if (ioctl(mProcess->mDriverFD,BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else err = -errno; } while (err == -EINTR); //到這里,回復(fù)數(shù)據(jù)就在bwr中了,,bmr接收回復(fù)數(shù)據(jù)的buffer就是mIn提供的 if (bwr.read_consumed > 0) { mIn.setDataSize(bwr.read_consumed); mIn.setDataPosition(0); } return NO_ERROR; }
本篇總結(jié)我們本篇詳細(xì)分析了Binder機(jī)制,,從概述->Java層Binder->Native層Binder->Binder驅(qū)動(dòng),位于各層次的讀者都能獲得收獲,。
下篇預(yù)告不好意思各位,,下周有個(gè)比較重要的面試,所以暫時(shí)不會(huì)更新該系列的博客,,但是也會(huì)更新其他博客,。記錄準(zhǔn)備面試的過程中需要用到的比較容易錯(cuò)誤的知識(shí)。
此致,,敬禮
|