Binder算是Android中比較難懂的一部分內(nèi)容了,但是非常的重要,要想研究Framework層無論如何也繞不開Binder诀蓉。網(wǎng)上也有很多講解Binder的文章浸遗,有的很深入涉及到底層C層面,理解起來難度較大驾胆,要完全理解還需要Linux驅(qū)動(dòng)的知識(shí)涣澡,看了還也是似懂非懂,我認(rèn)為也不需要理解那么深入丧诺。寫這篇博客主要是我從最學(xué)習(xí)理解Binder的過程的角度出發(fā)入桂,也來談?wù)凚inder。
Binder是什么
Binder是android中用于進(jìn)程間通信IPC的重要機(jī)制驳阎,ActivityManagerService抗愁、WinderManagerService等系統(tǒng)服務(wù)的背后都是Binder。
Binder架構(gòu)包括服務(wù)器接口呵晚、Binder驅(qū)動(dòng)蜘腌、客戶端接口三個(gè)模塊。
Binder服務(wù)端:一個(gè)Binder服務(wù)端實(shí)際上就是Binder類的對(duì)象饵隙,該對(duì)象一旦創(chuàng)建撮珠,內(nèi)部則會(huì)啟動(dòng)一個(gè)隱藏線程,會(huì)接收Binder驅(qū)動(dòng)發(fā)送的消息金矛,收到消息后芯急,會(huì)執(zhí)行Binder對(duì)象中的onTransact()函數(shù)倘潜,并按照該函數(shù)的參數(shù)執(zhí)行不同的服務(wù)器端代碼。onTransact函數(shù)的參數(shù)是客戶端調(diào)用transact函數(shù)的輸入志于。
Binder驅(qū)動(dòng):任意一個(gè)服務(wù)端Binder對(duì)象被創(chuàng)建時(shí)涮因,同時(shí)會(huì)在Binder驅(qū)動(dòng)中創(chuàng)建一個(gè)mRemote對(duì)象,該對(duì)象也是一個(gè)Binder類伺绽⊙荩客戶端訪問遠(yuǎn)程服務(wù)端都是通過該mRemote對(duì)象。
客戶端:獲取遠(yuǎn)程服務(wù)在Binder驅(qū)動(dòng)中對(duì)應(yīng)的mRemote引用奈应,然后調(diào)用它的transact方法即可向服務(wù)端發(fā)送消息澜掩。
這幅圖展現(xiàn)了Binder框架的大致構(gòu)成,至于里面有一些內(nèi)容需要看完這篇博客才能看懂杖挣。
需要注意的一個(gè)問題:既然客戶端要通過mRemote引用調(diào)用它的transact方法向服務(wù)端發(fā)送消息肩榕,那么客戶端獲取遠(yuǎn)程服務(wù)在Binder中的mRemote引用?
客戶端獲取遠(yuǎn)程服務(wù)在Binder中的mRemote引用有兩種方式:系統(tǒng)服務(wù)和自定義的服務(wù)端程序不一樣惩妇,對(duì)于系統(tǒng)服務(wù)使用Binder就可以實(shí)現(xiàn)服務(wù)端株汉,而我們自定義的服務(wù)必須借助Service來編寫。
》》系統(tǒng)服務(wù)是在系統(tǒng)啟動(dòng)的時(shí)候在SystemServer進(jìn)程的init2函數(shù)中啟動(dòng)ServerThread線程歌殃,在這個(gè)線程中啟動(dòng)了各種服務(wù)乔妈,并且通過調(diào)用ServerManager.addService(String name, IBinder service)將其加入保存起來。ServerManager就相當(dāng)于DNS服務(wù)器氓皱,在查找某個(gè)服務(wù)時(shí)通過調(diào)用ServerManager.getService(String name)函數(shù)就可以獲得遠(yuǎn)程服務(wù)的Binder路召,至于它的具體細(xì)節(jié)可以查看Android啟動(dòng)相關(guān)的源代碼。
》》自定義的服務(wù)必須通過Service來實(shí)現(xiàn)波材。
通過bind函數(shù)綁定一個(gè)遠(yuǎn)程服務(wù)
[java] view plaincopy
public boolean bindService(Intent service, ServiceConnection conn, int flags)
其中第二個(gè)參數(shù)是一個(gè)回調(diào)接口股淡,onServiceConnected的參數(shù)service即為遠(yuǎn)程服務(wù)在Binder驅(qū)動(dòng)中的binder引用。
[java] view plaincopy
public interface ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service);
public void onServiceDisconnected(ComponentName name);
}
使用Binder進(jìn)行IPC通信
實(shí)現(xiàn)如下效果:Activity‘中有一個(gè)按鈕廷区,點(diǎn)擊該按鈕唯灵,將abc和def三個(gè)字母拼接起來,拼接的函數(shù)在另一個(gè)進(jìn)程中躲因。
客戶端
[java] view plaincopy
public class MainActivity extends Activity {
private boolean isBound;
private Button btn_add;
private IBinder mRemote = null;
private ServiceConnection serviceConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemote = service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bind();
btn_add = (Button)findViewById(R.id.btn_add);
btn_add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String result = null;
try {
result = strcat("abc", "def");
} catch (RemoteException e) {
Toast.makeText(MainActivity.this, "error", 0).show();
e.printStackTrace();
}
Toast.makeText(MainActivity.this, result, 0).show();
}
});
}
private void bind() {
Intent intent = new Intent(MainActivity.this, ComputeService.class);
isBound = bindService(intent, serviceConn, Context.BIND_AUTO_CREATE);
}
private void unbind() {
if (isBound) {
MainActivity.this.unbindService(serviceConn);
isBound = false;
}
}
private String strcat(String x, String y) throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
String _result;
try {
_data.writeString(x);
_data.writeString(y);
mRemote.transact(1, _data, _reply, 0);
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
protected void onDestroy() {
unbind();
super.onDestroy();
}
}
遠(yuǎn)程服務(wù)端
[java] view plaincopy
public class ComputeService extends Service {
private IBinder binder = new Binder(){
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
if (code == 1) {
String _arg0;
_arg0 = data.readString();
String _arg1;
_arg1 = data.readString();
String _result = this.strcat(_arg0, _arg1);
reply.writeString(_result);
return true;
}
return super.onTransact(code, data, reply, flags);
};
public String strcat(String x, String y){
return x + y;
}
};
@Override
public IBinder onBind(Intent arg0) {
return binder;
}
}
將該service配置在一個(gè)新的進(jìn)程中
[html] view plaincopy
<service android:name = "org.qhyuan.binder.ComputeService"
android:process=":remote"/>
點(diǎn)擊按鈕如圖所示彈出提示
接下來分析上面的代碼:
客戶端通過bindService啟動(dòng)遠(yuǎn)程服務(wù)早敬。最終會(huì)由系統(tǒng)回調(diào)傳入的ServiceConnection接口忌傻,因此可以在onServiceConnected函數(shù)中獲得該遠(yuǎn)程服務(wù)所對(duì)應(yīng)的Binder驅(qū)動(dòng)中的引用大脉,接下來想要和遠(yuǎn)程服務(wù)端通信只需調(diào)用該mRemote的transact方法即可。
[java] view plaincopy
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
code標(biāo)識(shí)要執(zhí)行的動(dòng)作水孩,其實(shí)就是指調(diào)用服務(wù)端的哪個(gè)函數(shù)镰矿。
data是對(duì)輸入?yún)?shù)的打包
reply是對(duì)返回值的打包
writeString<--->readString 客戶端打包一個(gè)Parcel對(duì)象,在服務(wù)端讀取該P(yáng)arcel對(duì)象中打包的數(shù)據(jù)俘种,客戶端的寫入和服務(wù)端的讀取時(shí)對(duì)應(yīng)的秤标。
這里存在的問題:要統(tǒng)一客戶端寫入和服務(wù)端讀取的順序绝淡,當(dāng)然對(duì)于一個(gè)程序員來說,保證這一點(diǎn)是很簡單的苍姜。
接下來調(diào)用mRemote的transact方法會(huì)陷入內(nèi)核態(tài)牢酵,也就是說剩下的都是由系統(tǒng)完成的,binder驅(qū)動(dòng)會(huì)掛起當(dāng)前線程衙猪,將參數(shù)包裹發(fā)給服務(wù)端程序馍乙,在服務(wù)端的onTransact(code, data, reply, flags)函數(shù)里面讀取出包裝的數(shù)據(jù)進(jìn)行處理(數(shù)據(jù)處理的過程也就是根據(jù)code執(zhí)行指定的服務(wù)函數(shù)),然后把執(zhí)行的結(jié)果放入客戶端提供的reply包裹中垫释,然后服務(wù)端向Binder驅(qū)動(dòng)發(fā)送一個(gè)notify消息丝格,喚醒客戶端線程,繼續(xù)執(zhí)行使得客戶端線程從Binder驅(qū)動(dòng)返回到客戶端代碼區(qū)棵譬,再次回到用戶態(tài)显蝌。
使用AIDL
我們也看到了上面使用Binder進(jìn)行IPC通信的時(shí)候代碼比較繁瑣,尤其是客戶端給服務(wù)端發(fā)送消息的打包過程中要保證順序的一致性订咸。當(dāng)然android也給我們提供了一個(gè)比較好的方式曼尊,那就是使用android提供的aidl工具。
AIDL(Android Interface Definition Language)脏嚷,編譯器通過*.aidl文件的描述信息生成符合通信協(xié)議的Java代碼涩禀,我們不需要自己寫這些繁雜的代碼,使用非常方便然眼。只需要建立一個(gè)xxx.aidl文件艾船,這時(shí)在gen目錄下就會(huì)生成對(duì)應(yīng)的java文件
[java] view plaincopy
package org.qhyuan.aidl;
interface ICompute {
String strcat (String x,String y);
}
這樣使用aidl來實(shí)現(xiàn)上面的功能就可以很簡單了。于是客戶端代碼
[java] view plaincopy
public class MainActivity extends Activity {
private ICompute compute = null;
private boolean isBound;
private Button btn_add;
private ServiceConnection serviceConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
compute = ICompute.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bind();
btn_add = (Button)findViewById(R.id.btn_add);
btn_add.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String result = null;
try {
result = compute.strcat("abc", "def");
} catch (RemoteException e) {
Toast.makeText(MainActivity.this, "error", 0).show();
e.printStackTrace();
}
Toast.makeText(MainActivity.this, result, 0).show();
}
});
}
private void bind() {
Intent intent = new Intent(MainActivity.this, ComputeService.class);
isBound = bindService(intent, serviceConn, Context.BIND_AUTO_CREATE);
}
private void unbind() {
if (isBound) {
MainActivity.this.unbindService(serviceConn);
isBound = false;
}
}
@Override
protected void onDestroy() {
unbind();
super.onDestroy();
}
}
服務(wù)端代碼
[java] view plaincopy
public class ComputeService extends Service {
private IBinder binder = new ICompute.Stub() {
@Override
public String strcat(String x, String y) throws RemoteException {
return x+y;
}
};
@Override
public IBinder onBind(Intent arg0) {
return binder;
}
}
其他的都不需要改變高每,是不是簡單了很多屿岂?封裝了底層的細(xì)節(jié),使得程序?qū)懫饋砗軆?yōu)美鲸匿。之前手動(dòng)寫的transact函數(shù)和重寫的onTransact函數(shù)也不見蹤影了爷怀。
接下來分析上面的代碼,看看aidl文件到底做了什么带欢,能使得我們編寫程序簡化很多运授。
[java] view plaincopy
/*
- This file is auto-generated. DO NOT MODIFY.
- Original file: E:\EclipseProject\Binder\src\org\qhyuan\aidl\ICompute.aidl
*/
package org.qhyuan.aidl;
public interface ICompute extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements
org.qhyuan.aidl.ICompute {
private static final java.lang.String DESCRIPTOR = "org.qhyuan.aidl.ICompute";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an org.qhyuan.aidl.ICompute interface,
* generating a proxy if needed.
*/
public static org.qhyuan.aidl.ICompute asInterface(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof org.qhyuan.aidl.ICompute))) {
return ((org.qhyuan.aidl.ICompute) iin);
}
return new org.qhyuan.aidl.ICompute.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_strcat: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _arg1;
_arg1 = data.readString();
java.lang.String _result = this.strcat(_arg0, _arg1);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements org.qhyuan.aidl.ICompute {
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 java.lang.String strcat(java.lang.String x,
java.lang.String y) 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(x);
_data.writeString(y);
mRemote.transact(Stub.TRANSACTION_strcat, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_strcat = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public java.lang.String strcat(java.lang.String x, java.lang.String y)
throws android.os.RemoteException;
}
為了看起來方便,這里存在幾個(gè)類及每個(gè)類中的屬性和方法大致簡化如下乔煞。
[java] view plaincopy
interface ICompute extends IInterface
{
strcat();
static abstract class Stub extends Binder implements ICompute {
static final int TRANSACTION_strcat;
static final String DESCRIPTOR;
static asInterface();
asBinder();
onTransact();
static class Proxy implements ICompute {
IBinder binder;
asBinder();
getInterfaceDescriptor();
strcat();
}
}
}
首先要明白AIDL的主要設(shè)計(jì)思想吁朦。產(chǎn)生的這個(gè)類的思想是抽象出了一個(gè)接口,接口里面包含我們想實(shí)現(xiàn)的strcat方法渡贾,于是服務(wù)端的Binder來實(shí)現(xiàn)這個(gè)接口逗宜,其實(shí)就是這里的Stub類。然后客戶端在獲得了服務(wù)端在Binder驅(qū)動(dòng)中的Binder引用mRemote后,通過該引用給遠(yuǎn)程服務(wù)端發(fā)送消息纺讲,這是包含在Proxy類的strcat函數(shù)中擂仍。由于有aidl工具生成的代碼所以包裹中的打包數(shù)據(jù)的順序都是一致的。
ICompute類中的strcat函數(shù)不需要實(shí)現(xiàn)熬甚,僅僅是提供接口而已逢渔,具體的在Stub的子類類和Proxy類中實(shí)現(xiàn)。
在Stub子類中具體實(shí)現(xiàn)乡括,一般是在服務(wù)端程序中的复局。
在Proxy類中的strcat函數(shù)包括對(duì)參數(shù)的打包和通過Binder驅(qū)動(dòng)中的mRemote調(diào)用transact函數(shù)向服務(wù)端發(fā)送包裹,再從reply包裹中讀取出返回值返回粟判。
》》TRANSACTION_strcat:是對(duì)函數(shù)的編號(hào)亿昏,由于這里只有一個(gè)函數(shù)stract,所以只有這一個(gè)整型值档礁。
》》DESCRIPTOR:每個(gè)Stub類有一個(gè)描述符角钩,與它實(shí)現(xiàn)的接口有關(guān)。
》》onTransact:收到Binder驅(qū)動(dòng)發(fā)來的包裹呻澜,進(jìn)行解包递礼,這里面調(diào)用了this.strcat(_arg0, _arg1);是非常重要的,實(shí)際上是在服務(wù)器端實(shí)現(xiàn)的類的strcat函數(shù)羹幸。
》》asInterface:是最重要的一個(gè)函數(shù)脊髓,這是一個(gè)靜態(tài)方法,是用在客戶端將一個(gè)IBinder對(duì)象轉(zhuǎn)化為它實(shí)現(xiàn)的接口栅受。
如果能根據(jù)DESCRIPTION通過queryLocalInterface查找到的值将硝,就直接返回該值,(如果不是因?yàn)槭莝tatic的屏镊,是不是返回this就可以了依疼?)這對(duì)應(yīng)的情況是服務(wù)端自己調(diào)用該Binder中的服務(wù)程序。返回的就是服務(wù)端的Binder而芥,接下來的調(diào)用就是直接用服務(wù)端的Binder調(diào)用服務(wù)端的程序律罢,不存在IPC。否則就將該IBinder包裝成一個(gè)新的類Proxy類棍丐,接下來調(diào)用Proxy的stract方法實(shí)質(zhì)上是用的Binder驅(qū)動(dòng)中的遠(yuǎn)程Binder的引用mRemote來調(diào)用的误辑,是IPC。這里歌逢,Proxy顧名思義是代理的意思巾钉,本地調(diào)用就直接返回ICompute接口實(shí)際上是當(dāng)前服務(wù)器端的Binder,否則就返回一個(gè)代理類趋翻,該代理類實(shí)現(xiàn)了ICompute睛琳,里面封裝的是Binder驅(qū)動(dòng)中的mRemote引用盒蟆,這樣保證接下來的操作是一致的踏烙。
一句話就是說asInterface函數(shù)的存在將本地調(diào)用和進(jìn)程間調(diào)用綜合在一起了师骗。看到這里有沒有覺得三個(gè)類組織的非常巧妙代碼很優(yōu)美呢讨惩。
另辟癌,上面三個(gè)類如果寫成三個(gè)類而不是寫成嵌套類的形式會(huì)好理解很多。并且和最開始手工寫的Binder本質(zhì)上是一致的荐捻。
代碼中出現(xiàn)的如下幾個(gè)打包的數(shù)據(jù)可以認(rèn)為是增加安全性和處理一些其他的問題黍少,沒有也是可以可以的。writeInterfaceToken<--->enforceInterface 客戶端封裝一個(gè)String標(biāo)識(shí)处面,在服務(wù)端收到后對(duì)比確保該Binder驅(qū)動(dòng)確實(shí)是想訪問我厂置。類似的還有writeException<--->readException。
再此基礎(chǔ)上去看系統(tǒng)中一些XXXManager代碼魂角,就會(huì)容易很多昵济,里面使用Binder的部分都類似于AIDL產(chǎn)生的那些代碼,本質(zhì)上就是上面講的Binder進(jìn)行IPC通信野揪,下面舉例子說明源代碼中使用Binder的地方访忿。
系統(tǒng)服務(wù)中的Binder分析
下面以ServiceManager和ActivityManagerService為例來分析。ServiceManager:
前面已經(jīng)提到過ServiceManager可以認(rèn)為是DNS斯稳,用來查找系統(tǒng)服務(wù)海铆。保存了已經(jīng)開啟的系統(tǒng)服務(wù)。他有兩個(gè)主要的方法
[java] view plaincopy
public static IBinder getService(String name)
public static void addService(String name, IBinder service)
實(shí)際上ServerManager既是系統(tǒng)服務(wù)的管理者挣惰,同時(shí)也是一個(gè)系統(tǒng)服務(wù)卧斟。因此它肯定是基于Binder實(shí)現(xiàn)的。
接下來的分析中憎茂,時(shí)刻記得使用aidl工具生成那三個(gè)類:IXXX唆涝、IXXX.Stub和IXXX.Stub.Proxy,并做好對(duì)應(yīng)唇辨。這樣看ServiceManager的相關(guān)的代碼就容易多了廊酣。1.與IXXX相對(duì)應(yīng)的類就是IServiceManager類,封裝了遠(yuǎn)程調(diào)用的幾個(gè)主要函數(shù)赏枚。
[java] view plaincopy
public interface IServiceManager extends IInterface
{
public IBinder getService(String name) throws RemoteException;
public IBinder checkService(String name) throws RemoteException;
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException;
public String[] listServices() throws RemoteException;
public void setPermissionController(IPermissionController controller)
throws RemoteException;
static final String descriptor = "android.os.IServiceManager";
int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
int CHECK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
int ADD_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
int LIST_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
int CHECK_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
int SET_PERMISSION_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5;
}
2.與IXXX.Stub對(duì)應(yīng)的類就是ServiceManagerNative亡驰。[java] view plaincopy
public abstract class ServiceManagerNative extends Binder implements IServiceManager{
static public IServiceManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
public ServiceManagerNative() {
attachInterface(this, descriptor);
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
try {
switch (code) {
case IServiceManager.GET_SERVICE_TRANSACTION: {
data.enforceInterface(IServiceManager.descriptor);
String name = data.readString();
IBinder service = getService(name);
reply.writeStrongBinder(service);
return true;
}
case IServiceManager.ADD_SERVICE_TRANSACTION: {
data.enforceInterface(IServiceManager.descriptor);
String name = data.readString();
IBinder service = data.readStrongBinder();
boolean allowIsolated = data.readInt() != 0;
addService(name, service, allowIsolated);
return true;
}
// ...
} catch (RemoteException e) {
}
return false;
}
public IBinder asBinder() {
return this;
}
}
3.與IXXX.Stub.Proxy對(duì)應(yīng)的類ServiceManagerProxy[java] view plaincopy
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
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);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
// ....
private IBinder mRemote;
}
觀察上面的代碼,實(shí)際上和使用adil生成的代碼沒什么兩樣饿幅。僅僅是類命名不一樣凡辱,將三個(gè)類分開寫了而已。
不用看源代碼也知道接下來該怎么做了吧栗恩?透乾!當(dāng)然就是在服務(wù)端繼承ServiceManagerNative類實(shí)現(xiàn)里面的相關(guān)方法就能實(shí)現(xiàn)服務(wù)端,然后在客戶端將遠(yuǎn)程服務(wù)端所對(duì)應(yīng)的的Binder封裝成IServiceManager iSm = ServiceManagerNative.asInterface(binder)即可,正常情況下確實(shí)是這樣的乳乌。實(shí)際上捧韵,在源碼中找不到繼承自ServiceManagerNative類的遠(yuǎn)程服務(wù)端類,比如說ServiceManagerService汉操,根本就找不到這樣一個(gè)類再来。原因是SMS在native層被實(shí)現(xiàn)成一個(gè)獨(dú)立的進(jìn)程,是在啟動(dòng)后解析init.rc腳本啟動(dòng)服務(wù)的磷瘤。native層的代碼沒必要去研究芒篷,那么這個(gè)遠(yuǎn)程的Binder怎么獲得呢?系統(tǒng)提供的函數(shù)BinderInternal.getContextObject()來獲得對(duì)應(yīng)的Binder引用采缚。還是ServiceManager比較特殊嘛针炉,畢竟對(duì)于“DNS”來說不得一開機(jī)就啟動(dòng),還與其他“主機(jī)”有點(diǎn)差別扳抽,但是其他的系統(tǒng)服務(wù)就和上面我們想象的那樣是一樣的了篡帕。
這里要說明一點(diǎn),雖然SMS服務(wù)時(shí)在native層摔蓝,獲取遠(yuǎn)程服務(wù)卻并不一定非要在native層實(shí)現(xiàn)赂苗,使用Binder構(gòu)架與是用什么語言沒必然關(guān)系。
當(dāng)然了贮尉,這里的ServiceManagerNative確實(shí)沒什么用拌滋,如果要說有用,就是他的靜態(tài)方法asInterface吧猜谚。但不知道為什么android源碼中還有這個(gè)類的存在败砂,至少這樣讓我們隱約感覺Binder通信的框架就是這樣的,提高了一致性魏铅。
接下來我們看ServiceManager類
[java] view plaincopy
public final class ServiceManager {
private static final String TAG = "ServiceManager";
private static IServiceManager sServiceManager;
// 本地有緩存
private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
// 其實(shí)是IPC調(diào)用昌犹,具體會(huì)調(diào)用
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
// ...
}
ServiceManager類其實(shí)就是對(duì)遠(yuǎn)程的SMS服務(wù)的Binder的封裝。使用ServiceManagerNative.asInterface(BinderInternal.getContextObject());將其轉(zhuǎn)化為sServiceManager接口览芳,接下來使用該對(duì)象即可完成IPC調(diào)用斜姥。
舉個(gè)例子比如調(diào)用ServiceManager的getService方法,實(shí)際上會(huì)ServiceManagerProxy走到ServiceManagerProxy類的getService方法里面去沧竟,然后就是向服務(wù)端發(fā)消息铸敏。當(dāng)然這些細(xì)節(jié)就不用考慮了,因?yàn)閍ndroid的Binder機(jī)制封裝的就是這么完美悟泵,你不用關(guān)注底層細(xì)節(jié)杈笔。
ActivityManager:
再看看ActivityManager中的Binder。
IActivityManager對(duì)應(yīng)IXXX接口
ActivityManagerNative對(duì)應(yīng)IXXX.Stub類糕非,繼承自Binder類蒙具。
ActivityManagerProxy對(duì)應(yīng)IXXX.Stub.Proxy類球榆。
那么AMS的服務(wù)端是那個(gè)類呢?沒錯(cuò)禁筏,就是ActivityManagerService類持钉,這個(gè)類繼承自ActivityManagerNative,實(shí)現(xiàn)了IActivityManager接口中的方法用來進(jìn)行IPC融师。
那么只要在客戶端得到了這個(gè)遠(yuǎn)程服務(wù)端的Binder引用就可以進(jìn)行IPC通信了右钾,事實(shí)確實(shí)是這樣的蚁吝。舉個(gè)栗子旱爆,在ActivityThread的attach方法里有下面兩行代碼
[java] view plaincopy
IActivityManager mgr = ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread);
而getDefault方法代碼如下
[java] view plaincopy
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
// 這里可以看到通過調(diào)用getService方法得到Binder
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
顯然,ActivityManagerNative.getDefault()就可以得到遠(yuǎn)程的activity的服務(wù)AMS對(duì)應(yīng)的Binder引用窘茁,并且調(diào)用asInterface將其轉(zhuǎn)化為IActivityManager怀伦,接下來調(diào)用接口中的函數(shù)即可和遠(yuǎn)端的AMS通信。一般來說山林,對(duì)于其他的Service一般就是通過ServiceManager來獲取對(duì)應(yīng)的Binder房待。
當(dāng)然,如果還想弄的更清楚點(diǎn)還需要知道這個(gè)系統(tǒng)服務(wù)是在哪里啟動(dòng)和將Binder添加到SystemServer中的驼抹。
在SystemServerr進(jìn)程的init2函數(shù)中啟動(dòng)ServerThread線程桑孩,這個(gè)線程中啟動(dòng)了很多系統(tǒng)服務(wù),而每個(gè)系統(tǒng)服務(wù)都是一個(gè)線程框冀。ServerThread的run方法大概有1000行流椒,里面啟動(dòng)了系統(tǒng)服務(wù),不同的服務(wù)有不同的啟動(dòng)方法明也。
比如這里的AMS是通過調(diào)用context = ActivityManagerService.main(factoryTest)實(shí)現(xiàn)的宣虾。main函數(shù)里面啟動(dòng)了AThread線程。
接下來又調(diào)用了ActivityManagerService.setSystemProcess();
[java] view plaincopy
public static void setSystemProcess() {
ActivityManagerService m = mSelf;
ServiceManager.addService("activity", m, true);
ServiceManager.addService("meminfo", new MemBinder(m));
ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
ServiceManager.addService("dbinfo", new DbBinder(m));
// ....
}
這里的m是在AThread線程中new出來的ActivityManagerService實(shí)例温数。至此绣硝,就完成了服務(wù)的啟動(dòng)和向ServiceManager中的添加。當(dāng)然里面有很多細(xì)節(jié)撑刺,這里主要是跟蹤Binder通信的過程鹉胖。