前言
稍微看過(guò)Android FrameWork層的人應(yīng)該都知道Binder究驴,因?yàn)閍pp與系統(tǒng)服務(wù)之間的通信基本上都是建立在Binder的基礎(chǔ)上泽谨。之前對(duì)Binder也是云里霧里狸演,似懂非懂蕉斜,于是花了不少時(shí)間鸟辅,看了很多資料和源碼茅糜,才大致了解了Binder通信的原理橄杨,總結(jié)出來(lái)秘症,如有錯(cuò)誤,還望指正式矫。
簡(jiǎn)介
Binder是什么乡摹?Binder是為跨進(jìn)程通信而生的產(chǎn)物。眾所周知采转,我們的app都是由Zygote進(jìn)程fork出來(lái)的聪廉,每個(gè)app都運(yùn)行在單獨(dú)的進(jìn)程中,一個(gè)app想與另外一個(gè)app進(jìn)行通信故慈,只能采用跨進(jìn)程的方式板熊,傳統(tǒng)的Linux跨進(jìn)程方式有如下幾種:管道、信號(hào)量察绷、共享內(nèi)存及Socket等干签,Android系統(tǒng)建立在Linux的基礎(chǔ)上,但其采用的是Binder來(lái)進(jìn)行IPC的拆撼。
接下來(lái)讓我們用一個(gè)小Demo展示一下如何用Binder進(jìn)行跨進(jìn)程通信容劳。
實(shí)例
既然是跨進(jìn)程通信,那么至少得有兩個(gè)進(jìn)程闸度,最簡(jiǎn)單的方式就是指定activity的process屬性竭贩,但是本文為了更清楚的講解binder,采用的方式是建立兩個(gè)app莺禁,一個(gè)作為服務(wù)端留量,一個(gè)作為客戶端。服務(wù)端提供一個(gè)簡(jiǎn)單的生詞本功能,客戶端可以向服務(wù)端插入和查詢生詞肪获。
使用Binder通信主要有以下幾個(gè)步驟:
Step1:編寫AIDL文件
想要使用Binder寝凌,必須要先了解AIDL(Android Interface Definition Language)柒傻,也就是接口定義語(yǔ)言孝赫,提供接口給遠(yuǎn)程調(diào)用者。
為了給客戶端提供生詞本的調(diào)用接口红符,我們?cè)?src/main目錄下先新建一個(gè)文件夾aidl,并新建一個(gè)aidl文件IDictionaryManager.aidl青柄。
// IDictionaryManager.aidl
package com.wanginbeijing.dictionaryserver;
interface IDictionaryManager {
void add(String chinese,String english);
String query(String chinese);
}
接口中提供了兩個(gè)方法:add()和query(),分別作為插入和查詢操作预侯。Build一下工程致开,android studio會(huì)自動(dòng)為我們生成一個(gè)java類:IDictionaryManager.java。
我們來(lái)看看這個(gè)java類里面都寫了什么
public interface IDictionaryManager extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements com.wanginbeijing.dictionaryserver.IDictionaryManager {
private static final java.lang.String DESCRIPTOR = "com.wanginbeijing.dictionaryserver.IDictionaryManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.wanginbeijing.dictionaryserver.IDictionaryManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.wanginbeijing.dictionaryserver.IDictionaryManager))) {
return ((com.wanginbeijing.dictionaryserver.IDictionaryManager) iin);
}
return new com.wanginbeijing.dictionaryserver.IDictionaryManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_add: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _arg1;
_arg1 = data.readString();
this.add(_arg0, _arg1);
reply.writeNoException();
return true;
}
case TRANSACTION_query: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.query(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.wanginbeijing.dictionaryserver.IDictionaryManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void add(java.lang.String chinese, java.lang.String english) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(chinese);
_data.writeString(english);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public java.lang.String query(java.lang.String chinese) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(chinese);
mRemote.transact(Stub.TRANSACTION_query, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_query = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void add(java.lang.String chinese, java.lang.String english) throws android.os.RemoteException;
public java.lang.String query(java.lang.String chinese) throws android.os.RemoteException;
}
這個(gè)接口類比較長(zhǎng)萎馅,繼承了android.os.IInterface這個(gè)接口双戳。這個(gè)類簡(jiǎn)化的結(jié)構(gòu)大致如下:
public interface IDictionaryManager extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements com.wanginbeijing.dictionaryserver.IDictionaryManager {
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.wanginbeijing.dictionaryserver.IDictionaryManager asInterface(android.os.IBinder obj)
@Override
public android.os.IBinder asBinder()
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
private static class Proxy implements com.wanginbeijing.dictionaryserver.IDictionaryManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
@Override
public android.os.IBinder asBinder()
public java.lang.String getInterfaceDescriptor()
@Override
public void add(java.lang.String chinese, java.lang.String english)
@Override
public java.lang.String query(java.lang.String chinese)
}
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_query = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void add(java.lang.String chinese, java.lang.String english)
public java.lang.String query(java.lang.String chinese)
}
該類首先包含了一個(gè)抽象內(nèi)部類:Stub, 該類繼承自Binder并實(shí)現(xiàn)了IDictionary接口。在Stub的內(nèi)部糜芳,又包含了一個(gè)靜態(tài)內(nèi)部類:Proxy飒货,Proxy類同樣實(shí)現(xiàn)了IDictionary接口。
Step2:定義一個(gè)Service峭竣,用于客戶端連接
public class DictionaryManagerService extends Service {
private Map<String, String> mMap = new HashMap<>();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new IDictionaryManager.Stub() {
@Override
public void add(String chinese, String english) throws RemoteException {
mMap.put(chinese, english);
Log.e("DictionaryManager", "add new word");
}
@Override
public String query(String chinese) throws RemoteException {
return mMap.get(chinese);
}
};
}
}
該類中定義了一個(gè)HashMap用來(lái)保存生詞塘辅,并重寫了Service中的onBind方法,在onBinder方法中皆撩,返回了一個(gè)繼承自IDictionaryManager.Stub的匿名內(nèi)部類扣墩,并重寫了IDictionaryManager接口中add和query方法,實(shí)現(xiàn)真正的生詞本業(yè)務(wù)邏輯扛吞。
Step3:客戶端連接服務(wù)端Service
客戶端要調(diào)用服務(wù)端接口呻惕,先要將服務(wù)端定義好的aidl文件拷貝到客戶端相同目錄下,并build生成java文件滥比。然后開始連接服務(wù)器端:
public class MainActivity extends Activity {
private IDictionaryManager mDictionaryManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setAction("android.intent.action.DictionaryManagerService");
intent.setPackage("com.wanginbeijing.dictionaryserver");
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
//添加一個(gè)新單詞
findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
mDictionaryManager.add("你好", "Hello");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
//查詢單詞
findViewById(R.id.btn_query).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
String english = mDictionaryManager.query("你好");
Toast.makeText(MainActivity.this, english, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
IDictionaryManager dictionaryManager = IDictionaryManager.Stub.asInterface(iBinder);
try {
mDictionaryManager = dictionaryManager;
Toast.makeText(MainActivity.this, "connect success", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "connect failed", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
客戶端的MainActivty的onCreate()方法中亚脆,首先自動(dòng)連接遠(yuǎn)程service,拿到遠(yuǎn)程service傳回的Binder對(duì)象后守呜,強(qiáng)轉(zhuǎn)為IDictionaryService類型的變量mDictionaryManager型酥。然后在add按鈕和query按鈕的監(jiān)聽事件中分別添加和查詢單詞(你好,Hello)查乒。下面展示一下操作Demo.
可以看見弥喉,在連接遠(yuǎn)端service成功后,首先點(diǎn)擊add按鈕插入單詞玛迄,接著調(diào)用query接口由境,可以成功查詢到剛剛插入的單詞。
以上就是使用Binder進(jìn)行IPC的主要過(guò)程,但是僅僅掌握了使用方法怎么能滿足我們的好奇心呢虏杰,我們還必須要挖挖它的原理讥蟆。
原理
java層
說(shuō)到原理,還得先從代碼看起纺阔,回到上述所說(shuō)的Android Studio自動(dòng)生成的那個(gè)java類:IDictionaryManager瘸彤。剛才已經(jīng)說(shuō)過(guò),該類中有一個(gè)繼承自Binder的Stub類笛钝,它實(shí)現(xiàn)了我們所需要的IDictionaryManager接口质况。我們先來(lái)看看它的幾個(gè)方法:
public static IDictionaryManager asInterface(IBinder obj)
這方法將一個(gè)IBinder對(duì)象轉(zhuǎn)換成實(shí)現(xiàn)了IDictionaryManager。如果請(qǐng)求調(diào)用的客戶端在同一進(jìn)程玻靡,就直接返回Stub對(duì)象本身结榄,如果不在同一進(jìn)程,就返回Stub類中的Proxy對(duì)象囤捻。Proxy類同樣實(shí)現(xiàn)了IDictionaryManager接口臼朗。
asBinder
這個(gè)方法很簡(jiǎn)單,就直接返回了Stub對(duì)象自己蝎土。
onTransact
這個(gè)方法主要是進(jìn)行用來(lái)調(diào)用其他函數(shù)的视哑,它會(huì)根據(jù)傳入的參數(shù)code,選擇調(diào)用add方法還是query方法瘟则。
接下來(lái)看看Stub.Proxy類中的方法
asBinder
這個(gè)方法返回了Proxy對(duì)象中的mRemote變量黎炉,mRemote變量的賦值發(fā)生在Proxy類的構(gòu)造函數(shù)中,而在Stub類的asInterface()方法中調(diào)用了該構(gòu)造函數(shù)Proxy()醋拧,并傳入了一個(gè)Binder對(duì)象慷嗜,將mRemote指向了這個(gè)Binder對(duì)象。
add
該add方法繼承自IDictionary接口丹壕。里面主要是將客戶端傳參寫入_data中,然后調(diào)用transact()方法庆械,在transact方法中,會(huì)回調(diào)Stub類中的onTransact()菌赖。
query
同上述add方法一樣缭乘,只不過(guò)多了一個(gè)返回值。
介紹完這些方法之后琉用,我們?cè)賮?lái)將這些方法串起來(lái)堕绩,講一下完整的IPC過(guò)程∫厥保客戶端連接遠(yuǎn)程Service時(shí)奴紧,Service會(huì)返回一個(gè)Binder對(duì)象,即我們?cè)贒ictionaryManagerService.onBind()中返回的繼承自Stub的匿名對(duì)象晶丘,該類實(shí)現(xiàn)了生詞本邏輯黍氮。
客戶端調(diào)用有兩種情況:
1:客戶端和服務(wù)端在同一個(gè)進(jìn)程
服務(wù)器端就直接將該Stub對(duì)象返回唐含,即我們?cè)趏nBind()中返回的Stub對(duì)象,客戶端調(diào)用返回對(duì)象的asInterface()方法沫浆,將Stub對(duì)象強(qiáng)轉(zhuǎn)為IDictionManager對(duì)象捷枯,直接調(diào)用IDictionManager對(duì)象中的方法,就像調(diào)用本地對(duì)象的方法一樣专执。
2:客戶端和服務(wù)端不在同一個(gè)進(jìn)程
因?yàn)槭强邕M(jìn)程淮捆,兩端的內(nèi)存資源是不能共享的,服務(wù)器端不可能將真正的Stub對(duì)象返回他炊,它只能將Stub中的代理類Prxoy對(duì)象返回争剿∫鸭瑁客戶端同樣調(diào)用返回對(duì)象的asInterface()方法痊末,將Proxy對(duì)象強(qiáng)轉(zhuǎn)為IDictionManager對(duì)象,所以這次調(diào)用IDictionManager中add方法的時(shí)候哩掺,調(diào)用的實(shí)際上是Prxoy.add()凿叠。這次調(diào)用發(fā)生在客戶端進(jìn)程,然后在Proxy.add()方法中嚼吞,將參數(shù)和目標(biāo)函數(shù)code寫入Binder驅(qū)動(dòng)中盒件,并通過(guò)回調(diào)服務(wù)端Stub.onTransact()方法,實(shí)現(xiàn)調(diào)用真正的Stub.add()方法舱禽。
C++層
我們開發(fā)時(shí)所見到的Binder是Android系統(tǒng)提供給我們的java接口炒刁,java層的Binder對(duì)象只是Android對(duì)底層Binder的一個(gè)封裝,提供給上層開發(fā)人員使用誊稚,真正的Binder其實(shí)隱藏在系統(tǒng)底層翔始,默默的替我們進(jìn)行著跨進(jìn)程通信。
Java層的服務(wù)端Binder對(duì)象在C++層對(duì)應(yīng)的對(duì)象為BBinder里伯,而客戶端拿到的BinderProxy對(duì)象對(duì)應(yīng)的則為BpBinder城瞎,BBindder和BpBinder都繼承自IBinder,上層Binder和BinderProxy之間的通信其實(shí)是BBinder和BpBinder之間的通信疾瓮。
Binder的核心是Binder Driver脖镀,即Binder驅(qū)動(dòng),雖然各個(gè)進(jìn)程不能共享自己的內(nèi)存空間狼电,但是系統(tǒng)的內(nèi)核空間是共享的蜒灰,每個(gè)進(jìn)程都可以訪問(wèn),而Binder Driver即存在于內(nèi)核空間肩碟,BBinder和BpBinder都是通過(guò)它來(lái)通信的强窖,所以可以把Binder驅(qū)動(dòng)當(dāng)作是BBinder和BpBinder之間的一座橋梁。當(dāng)然BBinder和BpBinder也不是直接和Binder驅(qū)動(dòng)打交道腾务,它們中間還隔著一個(gè)IPCThreadState毕骡。每一個(gè)進(jìn)程都有一個(gè)ProcessState對(duì)象,它負(fù)責(zé)打開Binder驅(qū)動(dòng),這樣該進(jìn)程中的所有線程都可以通過(guò)Binder驅(qū)動(dòng)通信未巫,而每個(gè)線程都會(huì)有一個(gè)IPCThreadState對(duì)象窿撬,它才是真正讀寫B(tài)inder驅(qū)動(dòng)的主角,它通過(guò)talkWithDriver()和驅(qū)動(dòng)打交道叙凡,將IPC數(shù)據(jù)寫入驅(qū)動(dòng)中劈伴。
Java-->C++對(duì)象轉(zhuǎn)換
回到我們上面的Demo,客戶端連接成功后拿到了BinderProxy對(duì)象握爷,那么這個(gè)服務(wù)端的Binder對(duì)象是如何轉(zhuǎn)為BinderPrxoy的呢跛璧?這點(diǎn)我們要看bindService的源碼,bindService流程很長(zhǎng)新啼,感興趣的讀者可以自己去看后者直接看老羅的分析追城,我這里直接告訴讀者大致過(guò)程:
1.客戶端請(qǐng)求bindService,先會(huì)請(qǐng)求ActivityManagerService;
2.ActvityManagerService再去找到對(duì)應(yīng)的Service燥撞,讓Service所在進(jìn)程創(chuàng)建并啟動(dòng)Service;
3.Service調(diào)用AMS.publishService()將Binder對(duì)象傳遞給AMS;
4.AMS拿到的Binder對(duì)象同樣為BinderProxy對(duì)象座柱,然后調(diào)用 c.conn.connected(r.name, service)方法,將BinderProxy對(duì)象傳遞給客戶端物舒。
這里要知道的是色洞,AMS也是處在一個(gè)單獨(dú)的進(jìn)程中,所以Binder對(duì)象不是直接返回給AMS冠胯,AMS也不是直接返回給客戶端的火诸,而是經(jīng)過(guò)了Binder驅(qū)動(dòng)。服務(wù)端Service將Binder對(duì)象傳遞給AMS時(shí)荠察,會(huì)調(diào)用AMS在服務(wù)端的代理對(duì)象ActivityManagerProxy.publishService()方法置蜀,準(zhǔn)確的說(shuō),Service端在此時(shí)成了AMS的客戶端割粮。
public void publishService(IBinder token,
Intent intent, IBinder service) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
intent.writeToParcel(data, 0);
data.writeStrongBinder(service);
mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
該方法中通過(guò)Parcel.writeStrongBinder()盾碗,將服務(wù)端的Binder對(duì)象轉(zhuǎn)化成C++中的flat_binder_object對(duì)象,并將Binder對(duì)象的地址賦值給flat_binder_object對(duì)象中的cookie舀瓢。
struct flat_binder_object {
unsigned long type;
unsigned long flags;
union {
void *binder; /* local object */
signed long handle; /* remote object */
};
void *cookie;
};
flat_binder_object對(duì)象最終被包裝在了data中廷雅,然后通過(guò)mRemote.transact(),將data數(shù)據(jù)傳送到IPCThreadState, IPCThreadState再次將data包裝成binder_transaction_data,并調(diào)用talkWithDriver(),將包裝好的數(shù)據(jù)傳遞給Binder驅(qū)動(dòng)京髓。
Binder驅(qū)動(dòng)收到數(shù)據(jù)后航缀,并不會(huì)急著將數(shù)據(jù)傳給AMS,因?yàn)閭魉偷臄?shù)據(jù)中有flat_binder_object堰怨,所以它會(huì)查詢flat_binder_object對(duì)應(yīng)的Binder對(duì)象在驅(qū)動(dòng)中是否有Binder節(jié)點(diǎn)芥玉,如果沒有,則會(huì)利用flat_binder_object中的cookie值(指向BBinder)創(chuàng)建一個(gè)Binder節(jié)點(diǎn)备图,并為該節(jié)點(diǎn)生成一個(gè)索引值灿巧,將索引值賦給flat_binder_object的handle赶袄。
然后AMS就可以取數(shù)據(jù)了,AMS同樣有一個(gè)IPCThreadState對(duì)象抠藕,Binder驅(qū)動(dòng)將數(shù)據(jù)傳遞給該對(duì)象饿肺,接收端拿到了數(shù)據(jù)后,會(huì)調(diào)用Parcel.readStrongBinder()盾似,這在java層是一個(gè)jni方法敬辣,該方法會(huì)先調(diào)用Native層的readStrongBinder(),利用flat_binder_object中的handle值創(chuàng)建BpBinder對(duì)象零院,然后該Native方法返回BpBinder的指針溉跃,jni方法再根據(jù)BpBinder指針創(chuàng)建java層的BinderProxy對(duì)象并返回給java層。至此BpBinder和BinderProxy對(duì)象都已經(jīng)創(chuàng)建完畢告抄。
BpBinder與BBinder的通信
上面我們已經(jīng)拿到了BpBinder撰茎,那BpBinder又將如何與BBinder通信呢?這里不得不提一個(gè)重要的變量:handle玄妈。還記得在創(chuàng)建BpBiner的時(shí)候乾吻,需要傳入flat_binder_object的handle嗎,而這個(gè)handle是Binder節(jié)點(diǎn)在驅(qū)動(dòng)中的索引拟蜻,即位置。這樣當(dāng)BpBinder通過(guò)transact()調(diào)用BBinder時(shí)枯饿,Binder驅(qū)動(dòng)就可以根據(jù)BpBinder提供的handle值找到Binder在驅(qū)動(dòng)中的節(jié)點(diǎn)酝锅,Binder節(jié)點(diǎn)保存了BBinder的地址,從而找到了BBinder奢方,實(shí)現(xiàn)對(duì)BBinder的調(diào)用搔扁。
系統(tǒng)服務(wù)的注冊(cè)
上面的例子展示的匿名Binder的通信,為什么說(shuō)是匿名蟋字,因?yàn)锽inder對(duì)象并沒有在ContextManager中實(shí)名注冊(cè)稿蹲。
ContextManager又是什么?它是系統(tǒng)服務(wù)的管理者鹊奖,它在java層和C++層的代理對(duì)象都為ServiceManager苛聘,系統(tǒng)服務(wù)可以通過(guò)ServiceManager.addService()將自己實(shí)名注冊(cè)到ContextManager中。為什么要實(shí)名注冊(cè)忠聚?如果不采用實(shí)名的方法设哗,系統(tǒng)服務(wù)那么多,你難道一個(gè)個(gè)的去記得它的handle两蟀?
ServiceManager.addService()會(huì)將服務(wù)的Binder對(duì)象傳到Binder Driver网梢,Binder Driver為其生成Binder節(jié)點(diǎn)后,ContextManager就會(huì)將服務(wù)的實(shí)名和其Binder節(jié)點(diǎn)的索引handle保存到自身赂毯。當(dāng)客戶端需要找一個(gè)系統(tǒng)服務(wù)時(shí)战虏,只需將服務(wù)名ServiceManager.getService()拣宰,ServiceManager就可以找到服務(wù)的索引handle,并創(chuàng)建對(duì)應(yīng)的BpBinder對(duì)象烦感,從而建立通信徐裸。比如java層的ActivityManagerService就是一個(gè)Binder類,我們就可以通過(guò)ServiceManager.getService("activity")啸盏,拿到它的代理對(duì)象重贺,從而進(jìn)行Activity生命周期的調(diào)度。
上面說(shuō)到ServiceManager是ContextManager的代理回懦,因?yàn)镃ontextManager本身也就是一個(gè)服務(wù)气笙,服務(wù)端和客戶端想調(diào)用它的addService或getService時(shí),也必須通過(guò)ServiceManager來(lái)跨進(jìn)程怯晕∏逼裕可是我該怎么拿到這個(gè)代理呢?我總不能調(diào)用它的getService來(lái)獲取它自己吧舟茶。Binder這一點(diǎn)設(shè)計(jì)的很奇妙谭期,ContextManager在BinderDriver中的節(jié)點(diǎn)索引為0,誰(shuí)讓它是老大呢吧凉。這樣大家都知道了隧出,我想調(diào)用ContextManger,直接根據(jù)handle=0就可以生成它的代理對(duì)象BpBinder了阀捅,從而創(chuàng)建代理對(duì)象ServiceManager胀瞪。
總結(jié)
系統(tǒng)中每個(gè)app和系統(tǒng)服務(wù)都活在自己的進(jìn)程中,無(wú)法訪問(wèn)彼此的內(nèi)存空間饲鄙,正是因?yàn)橄嗷ネㄐ诺膹?qiáng)烈需求凄诞,從而誕生了Binder。Binder驅(qū)動(dòng)就像所有進(jìn)程共同的地盤忍级,系統(tǒng)服務(wù)可以這里留下自己的地址帆谍,而客戶端可以可以根據(jù)這些地址找到對(duì)應(yīng)的服務(wù),相互通信轴咱,從而千里姻緣一線牽汛蝙,百年恩愛雙心結(jié)。
(轉(zhuǎn)載請(qǐng)注明ID:半棧工程師嗦玖,歡迎訪問(wèn)個(gè)人博客:https://halfstackdeveloper.github.io/)
歡迎關(guān)注我的知乎專欄:https://zhuanlan.zhihu.com/halfstack