談到android進(jìn)程間通信,就不得不想到Binder,那么他到底是何方圣神呢?話不多說(shuō),咱們下面一起來(lái)解密一番!
IBinder
首先我們來(lái)看一下Binder的聲明:
public class Binder implements IBinder {...}
喲,那么IBinder又是什么呢?
public interface IBinder {
int FIRST_CALL_TRANSACTION = 0x00000001;
int LAST_CALL_TRANSACTION = 0x00ffffff;
int PING_TRANSACTION = ('_'<<24)|('P'<<16)|('N'<<8)|'G';
int DUMP_TRANSACTION = ('_'<<24)|('D'<<16)|('M'<<8)|'P';
int SHELL_COMMAND_TRANSACTION = ('_'<<24)|('C'<<16)|('M'<<8)|'D';
int INTERFACE_TRANSACTION = ('_'<<24)|('N'<<16)|('T'<<8)|'F';
int TWEET_TRANSACTION = ('_'<<24)|('T'<<16)|('W'<<8)|'T';
int LIKE_TRANSACTION = ('_'<<24)|('L'<<16)|('I'<<8)|'K';
int SYSPROPS_TRANSACTION = ('_'<<24)|('S'<<16)|('P'<<8)|'R';
int FLAG_ONEWAY = 0x00000001;
public static final int MAX_IPC_SIZE = 64 * 1024;
public @Nullable String getInterfaceDescriptor() throws RemoteException;
public boolean pingBinder();
public boolean isBinderAlive();
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor);
public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException;
public void dumpAsync(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException;
public void shellCommand(@Nullable FileDescriptor in,
@Nullable FileDescriptor out, @Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback shellCallback,
@NonNull ResultReceiver resultReceiver) throws RemoteException;
public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException;
public interface DeathRecipient {
public void binderDied();
}
public void linkToDeath(@NonNull DeathRecipient recipient, int flags) throws RemoteException;
public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags);
}
哦,原來(lái)IBinder 是一個(gè)定義了跨進(jìn)程傳輸能力的接口。只要實(shí)現(xiàn)了這個(gè)接口,就能將這個(gè)對(duì)象進(jìn)行跨進(jìn)程傳遞。
這些方法中重點(diǎn)關(guān)注 transact(),Binder里面與它對(duì)應(yīng)的是 Binder.onTransact()。
Binder
Binder是官方提供的實(shí)現(xiàn)了IBinder接口的操作,它是 Android IPC 的基礎(chǔ),平常接觸到的各種 Manager(ActivityManager, ServiceManager 等),以及綁定 Service 時(shí)都在使用它進(jìn)行跨進(jìn)程操作。
下面介紹幾個(gè)關(guān)鍵方法:
- transact()
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
連接Binder驅(qū)動(dòng),發(fā)起IPC請(qǐng)求。
- onTransact()
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
if (code == INTERFACE_TRANSACTION) {
......
} else if (code == DUMP_TRANSACTION) {
......
} else if (code == SHELL_COMMAND_TRANSACTION) {
......
}
return false;
}
根據(jù) code 對(duì)傳入的參數(shù) data 做相應(yīng)的處理,然后寫(xiě)入 reply,這樣就能返回操作后的數(shù)據(jù)。
- attachInterface()
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
這個(gè)方法的作用是將一個(gè)描述符、特定的 IInterface 與當(dāng)前 Binder 綁定起來(lái),這樣后續(xù)調(diào)用 queryLocalInterface 就可以拿到這個(gè) IInterface,那 IInterface 又是什么呢?
public interface IInterface{
public IBinder asBinder();
}
IInterface 里只定義了一個(gè) asBinder() 方法,這個(gè)方法可以返回當(dāng)前接口關(guān)聯(lián)的 Binder 對(duì)象。
Binder通信機(jī)制
上面只是簡(jiǎn)單介紹了Binder類相關(guān)的信息,具體的詳細(xì)信息可以去查看源碼,但這只是Binder通信機(jī)制的基礎(chǔ)。
要理解Binder通信機(jī)制,首先我們要先來(lái)了解一下Android的內(nèi)存空間:

用戶空間:用戶空間的進(jìn)程是相互獨(dú)立的,彼此之間不能共享
內(nèi)核空間:內(nèi)核空間的內(nèi)存是可以共享的,其大小可以通過(guò)參數(shù)來(lái)配置
Android進(jìn)程間通信其實(shí)質(zhì)就是利用內(nèi)核空間共享來(lái)完成的。
下面我們來(lái)看Binder進(jìn)程間通信的四個(gè)重要角色:

- Client:用戶端進(jìn)程
- Server:服務(wù)端進(jìn)程
- Service Manager:運(yùn)行在用戶空間,它負(fù)責(zé)管理 Service 注冊(cè)與查詢等操作
- Binder驅(qū)動(dòng):負(fù)責(zé)進(jìn)程之間Binder通信的建立,進(jìn)程間通信的核心
下面我們來(lái)總結(jié)一下Binder機(jī)制的整個(gè)運(yùn)行過(guò)程:
- ServiceManager 初始化
- Server 向 ServiceManager 注冊(cè)自己
- Client 獲取遠(yuǎn)程服務(wù)
- Client 向 Server 發(fā)起 IPC 請(qǐng)求
- Binder 驅(qū)動(dòng)將該請(qǐng)求轉(zhuǎn)發(fā)給 ServiceManager 進(jìn)程,
- ServiceManager 查找到 對(duì)應(yīng)的 Server 的 Binder 引用后通過(guò) Binder 驅(qū)動(dòng)反饋給 Client(并不是實(shí)際真實(shí)的遠(yuǎn)程Binder對(duì)象,而是Binder驅(qū)動(dòng)里的一個(gè)映射)
- Client 收到 Server 對(duì)應(yīng)的 Binder 引用后,會(huì)創(chuàng)建一個(gè) Server 對(duì)應(yīng)的遠(yuǎn)程服務(wù)(即 Server 在當(dāng)前進(jìn)程的代理)
- Client 通過(guò)代理調(diào)用 Server
- Client 會(huì)先將請(qǐng)求數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間,然后調(diào)用transact去連接Binder驅(qū)動(dòng)
- 接著B(niǎo)inder驅(qū)動(dòng)會(huì)去連接遠(yuǎn)程進(jìn)程,并通知遠(yuǎn)程進(jìn)程執(zhí)行onTransact()函數(shù)
- Server 返回結(jié)果
- 執(zhí)行完成后將結(jié)果寫(xiě)入內(nèi)核空間
- Binder驅(qū)動(dòng)再喚醒客戶端線程獲取數(shù)據(jù)
注意:這個(gè)過(guò)程中客戶端當(dāng)前線程會(huì)被掛起!因此,如果遠(yuǎn)程進(jìn)程是執(zhí)行長(zhǎng)時(shí)間的運(yùn)算,請(qǐng)不要使用主線程去調(diào)用遠(yuǎn)程函數(shù),以防止ANR。
示例分析
上面講了一些理論上的Binder進(jìn)程間通信的知識(shí),可以清晰的看出Binder采用的是C/S架構(gòu)的模式來(lái)進(jìn)行進(jìn)程間通信的,而其核心點(diǎn)也就是內(nèi)核空間的Binder驅(qū)動(dòng)。下面呢,我們會(huì)通過(guò)一個(gè)具體的實(shí)例從源碼的角度來(lái)解析Binder的進(jìn)程間通信。
首先我們這里給出一副價(jià)值200萬(wàn)的圖(一點(diǎn)也不夸張哈?。?/p>

- AIDL(Android Interface Definition Language),即Android接口定義語(yǔ)言。通俗來(lái)講就是定義一個(gè)大家都懂的語(yǔ)言,這樣進(jìn)程間交流才不會(huì)有障礙。
- Stub:接收底層C/C++Binder引用的回調(diào)。
- function:就是我們定義的一些接口方法。
- Proxy:用來(lái)訪問(wèn)底層的Binder驅(qū)動(dòng)。
- 本地服務(wù):就是在我們當(dāng)前進(jìn)程里的服務(wù)(后面會(huì)有具體的涉及)。
- Binder驅(qū)動(dòng):這里看圖就行了,不做過(guò)多解釋。
OK!價(jià)值200萬(wàn)的圖大家趕緊收好。接下來(lái)我們就具體來(lái)分析源碼。
一、AIDL創(chuàng)建
- 新建com.wf.testaidl.bean.Person類,并實(shí)現(xiàn)Parcelable
public class Person implements Parcelable {...}
- 在main下面新建aidl文件夾并創(chuàng)建aidl文件(注意:包名和類名必須相同)

- 編寫(xiě)aidl接口
// Person.aidl
package com.wf.testaidl.bean;
// Declare any non-default types here with import statements
parcelable Person;
Preson.aidl做一下映射避免下面文件編譯的時(shí)候報(bào)錯(cuò)。
// PersonAidl.aidl
package com.wf.testaidl;
// Declare any non-default types here with import statements
import com.wf.testaidl.bean.Person;
interface PersonAidl {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
/*void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);*/
void addPerson(in Person person);
List<Person> getPersonList();
}
這個(gè)文件就具體定義了我們需要的接口。
- Make Project
編譯成功后會(huì)生成app\build\generated\source\aidl\debug\com\wf\testaidl\PersonAidl.java文件。
二、解析PersonAidl.java源碼
package com.wf.testaidl;
public interface PersonAidl extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.wf.testaidl.PersonAidl {
...
private static class Proxy implements com.wf.testaidl.PersonAidl {...}
...
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*//*void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);*/
public void addPerson(com.wf.testaidl.bean.Person person) throws android.os.RemoteException;
public java.util.List<com.wf.testaidl.bean.Person> getPersonList() throws android.os.RemoteException;
}
是不是很熟悉,沒(méi)錯(cuò)就是我們上面那幅200萬(wàn)的圖。這里可以很清晰的看出PersonAidl里面包含了我們定義的接口方法和一個(gè)靜態(tài)內(nèi)部抽象類Stub,這個(gè)Stub繼承了Binder并且實(shí)現(xiàn)了PersonAidl接口,這個(gè)Stub里面又定義了一個(gè)Proxy同樣實(shí)現(xiàn)了PersonAidl接口。
Stub
ok!接下來(lái)我們來(lái)看看這個(gè)神奇Stub。
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.wf.testaidl.PersonAidl {
private static final java.lang.String DESCRIPTOR = "com.wf.testaidl.PersonAidl";
public Stub() {...}
/**
* Cast an IBinder object into an com.wf.testaidl.PersonAidl interface,
* generating a proxy if needed.
*/
public static com.wf.testaidl.PersonAidl 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) throws android.os.RemoteException {...}
private static class Proxy implements com.wf.testaidl.PersonAidl {...}
static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getPersonList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
上面就是這個(gè)Stub的整個(gè)的一個(gè)結(jié)構(gòu),這里有兩個(gè)方法名映射的int常量,這個(gè)后面我們會(huì)用到。
下面我們就來(lái)一步一步的分析它里面的代碼。
- DESCRIPTOR
private static final java.lang.String DESCRIPTOR = "com.wf.testaidl.PersonAidl";
這個(gè)很簡(jiǎn)單吧,就是用一個(gè)靜態(tài)常量來(lái)存儲(chǔ)了我們AIDL的類名,有什么用呢?后面你就知道了。
- Stub() 構(gòu)造函數(shù)
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
構(gòu)造函數(shù)里面就調(diào)了一個(gè)方法,而這個(gè)attachInterface自己沒(méi)有,那么是誰(shuí)的呢?沒(méi)錯(cuò),是它爹Binder的。
private IInterface mOwner;
private String mDescriptor;
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
那么,這個(gè)方法干了一個(gè)什么事兒呢?它就是把自己和這個(gè)DESCRIPTOR保存在了當(dāng)前這個(gè)類里,做了一個(gè)關(guān)聯(lián)關(guān)系,那么有什么用呢?我們繼續(xù)往后面看。
- asInterface()
public static com.wf.testaidl.PersonAidl asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.wf.testaidl.PersonAidl))) {
return ((com.wf.testaidl.PersonAidl) iin);
}
return new com.wf.testaidl.PersonAidl.Stub.Proxy(obj);
}
這個(gè)方法主要就干了一個(gè)事兒,那就是當(dāng)發(fā)起IPC請(qǐng)求時(shí)把我們從Binder驅(qū)動(dòng)拿到的這個(gè)IBinder描述轉(zhuǎn)換成一個(gè)具體的AIDL接口對(duì)象,后面才能調(diào)用相應(yīng)的接口方法。這里面首先調(diào)用了一個(gè)queryLocalInterface,我們來(lái)看看為什么要先調(diào)用這個(gè)方法呢?
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
這里可以看出它是拿這個(gè)descriptor去判斷是不是調(diào)用的自己,是就直接返回自己(明白了上面那個(gè)attachInterface的作用了吧)。這又是為什么呢?這里就有一個(gè)要注意的點(diǎn)了,上面我們給出的那個(gè)200萬(wàn)的圖是不是有一個(gè)本地服務(wù),那么為什么會(huì)有一個(gè)本地服務(wù)呢?這里我就要反問(wèn)一個(gè)問(wèn)題了:是不是我們需要訪問(wèn)的服務(wù)一定是在不同的進(jìn)程呢?答案是不是的,我們也有可能會(huì)訪問(wèn)自己的服務(wù),對(duì)吧!好了,那么我想你應(yīng)該明白了這里為什么會(huì)有一個(gè)queryLocalInterface了吧。
好了,我們接著往下看,如果我們?cè)L問(wèn)的不是自己就需要拿這個(gè)IBinder描述去創(chuàng)建一個(gè)遠(yuǎn)程的AIDL接口對(duì)象。
- onTransact()
@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_addPerson: {
data.enforceInterface(DESCRIPTOR);
com.wf.testaidl.bean.Person _arg0;
if ((0 != data.readInt())) {
_arg0 = com.wf.testaidl.bean.Person.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getPersonList: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.wf.testaidl.bean.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
這個(gè)方法就是來(lái)處理我們的IPC請(qǐng)求的,根據(jù)不同的code值最終會(huì)調(diào)到它的實(shí)現(xiàn)類的對(duì)應(yīng)的接口方法,然后將處理后的結(jié)果寫(xiě)入replay返回給客戶端。這里面的代碼都很簡(jiǎn)單,就不一一分析了,相信大家自己也能看明白。
- class Proxy這個(gè)我們單獨(dú)放到下一節(jié)來(lái)講。
- 此刻我想你一定有一個(gè)問(wèn)題:服務(wù)不是要注冊(cè)到ServiceManager嘛,上面沒(méi)有哪里講到注冊(cè)了啊?其實(shí)它在我們上面講的構(gòu)造函數(shù)里面就已經(jīng)完成了注冊(cè),無(wú)參構(gòu)造函數(shù)的初始化首先會(huì)調(diào)用父類的無(wú)參構(gòu)造函數(shù),那我們就來(lái)看看它的父類Binder的無(wú)參構(gòu)造函數(shù):
public Binder() {
init();
...
}
private native final void init();
從上面我們可以看出它調(diào)用了一個(gè)native方法,就是在這里進(jìn)行注冊(cè)的。那么你又會(huì)問(wèn)了:這里沒(méi)有傳任何數(shù)據(jù)???其實(shí)這里native方法它會(huì)隱式的把this傳過(guò)去,那我們之定義的DESCRIPTOR就注冊(cè)過(guò)去了。
到這里我們的Stub服務(wù)端就基本講完了。
Proxy
上面我們剖析了一下Stub的源碼,理解到了Stub其實(shí)是作為一個(gè)服務(wù)端注冊(cè)到ServiceManager來(lái)響應(yīng)我們的請(qǐng)求的。接下來(lái)我們就來(lái)看我么是怎么樣發(fā)起請(qǐng)求的呢?首先我們來(lái)看一下這個(gè)Proxy是什么。
private static class Proxy implements com.wf.testaidl.PersonAidl {
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 addPerson(com.wf.testaidl.bean.Person person) throws android.os.RemoteException {...}
@Override
public java.util.List<com.wf.testaidl.bean.Person> getPersonList() throws android.os.RemoteException { ...}
}
Proxy作為一個(gè)Stub的靜態(tài)內(nèi)部類主要用來(lái)發(fā)起跨進(jìn)程的請(qǐng)求,那一個(gè)進(jìn)程為什么既有Stub又有Proxy呢?因?yàn)橐粋€(gè)進(jìn)程它既可以是客戶端也可以是服務(wù)端。好了,接下來(lái)我們一步步分析Proxy的源碼,看看它是怎么工作的。
- 構(gòu)造函數(shù)
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
初始化的時(shí)候傳入一需要訪問(wèn)的進(jìn)程的IBinder描述,也就是我們發(fā)起IPC請(qǐng)求的時(shí)候從ServiceManager里面查詢尋到的IBinder,這樣我們才知道是要去訪問(wèn)哪個(gè)進(jìn)程。
- 實(shí)現(xiàn)接口方法addPerson()和getPersonList()
@Override
public void addPerson(com.wf.testaidl.bean.Person person) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((person != null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public java.util.List<com.wf.testaidl.bean.Person> getPersonList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.wf.testaidl.bean.Person> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.wf.testaidl.bean.Person.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
首先初始化兩個(gè)Parcel對(duì)象,都是通過(guò)Parcel.obtain()去Parcel池(隊(duì)列)里面拿的(節(jié)約內(nèi)存)。然后將我們要訪問(wèn)的進(jìn)程(DESCRIPTOR)和傳遞的參數(shù)寫(xiě)入Parcel。接下來(lái)就調(diào)用IBinder引用的transact()去連接 Binder驅(qū)動(dòng)。
mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
這里有一個(gè)很有意思也是最簡(jiǎn)單的做法,它把要訪問(wèn)的方法定義成了一個(gè)int類型的常量TRANSACTION_addPerson和TRANSACTION_getPersonList,這兩個(gè)常量是定義在它外部類stub里面的,這樣IBinder引用拿到后就知道是要去調(diào)用哪個(gè)方法了。
接下來(lái)我們看看這個(gè)transact()做了些什么事情?
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
當(dāng)Binder驅(qū)動(dòng)拿到我們的請(qǐng)求和數(shù)據(jù)后,它就會(huì)去連接我們要訪問(wèn)的服務(wù)端進(jìn)程,然后通知它回調(diào)onTransact()方法。到這里我們的整個(gè)請(qǐng)求就算完成了。
小結(jié)
- 一個(gè)進(jìn)程既可以是服務(wù)端Stub,也可以是客戶端Proxy。
- 一個(gè)IPC請(qǐng)求發(fā)起時(shí),首先會(huì)調(diào)用Proxy去連接Binder驅(qū)動(dòng),然后Binder驅(qū)動(dòng)再去連接Stub
- 要實(shí)現(xiàn)跨進(jìn)程通信,兩個(gè)進(jìn)程必須要有相同的AIDL接口
三、調(diào)用流程分析
- ServiceManager的注冊(cè)和獲取
上面我們講到了Binder進(jìn)程間通信時(shí)所有的Server都時(shí)由ServiceManager來(lái)管理的,那么你可能會(huì)問(wèn)了ServiceManager也是一個(gè)獨(dú)立進(jìn)程,那么它是什么時(shí)候啟動(dòng)?又是什么時(shí)候注冊(cè)的呢?
系統(tǒng)啟動(dòng)的時(shí)候會(huì)去執(zhí)行\(zhòng)system\core\rootdir\init.rc,在這里面就啟動(dòng)了ServiceManager,啟動(dòng)之后會(huì)去執(zhí)行service_manager.c,那這里面干了什么呢?
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
打開(kāi)bind驅(qū)動(dòng),并且分配128K大小,緊接著把自己注冊(cè)為Service 大管家,然后就開(kāi)啟loop來(lái)讀取Binder驅(qū)動(dòng)的消息處理各種服務(wù)請(qǐng)求。
- 客戶端發(fā)起IPC請(qǐng)求
private PersonAidl mPersonAidl;
//綁定服務(wù)
Intent intent = new Intent(this, AidlService.class);
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mPersonAidl = PersonAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mPersonAidl = null;
}
}, BIND_AUTO_CREATE);
//請(qǐng)求接口
mPersonAidl.addPerson(person);
List<Person> personList = mPersonAidl.getPersonList();
上面我們是通過(guò)顯示意圖來(lái)綁定的,因?yàn)槲覀兪菍?xiě)在一起然后配置在不同進(jìn)程的,當(dāng)然你也可以用隱式意圖來(lái)綁定服務(wù),那么接下來(lái)我們就來(lái)看看bindService做了什么?
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}
那我們就來(lái)看看mBase.bindService又是干了什么?
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
我們可以看到它調(diào)用的是一個(gè)抽象方法,那么我們就自然要去找到它的實(shí)現(xiàn)類,最終我們找到了ContextImpl.java里面。
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags){
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}
那么我再來(lái)看看 bindServiceCommon又干了些啥?
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user){
...
int res = ActivityManager.getService().bindService(...)
...
}
好,到這里就開(kāi)始跨進(jìn)程訪問(wèn)了,通過(guò)ActivityManagerService去獲取遠(yuǎn)程服務(wù),最終會(huì)在ActivityThread.java的handleBindService()方法里回調(diào)遠(yuǎn)程服務(wù)的onBind方法返回一個(gè)IBinder引用,這樣我們就能通過(guò)這個(gè)IBinder引用去調(diào)用相應(yīng)的接口來(lái)進(jìn)程跨進(jìn)程訪問(wèn)。后面具體的底層源碼這里就不貼出來(lái)了,感興趣的話可以自己去翻閱源碼。
- 自定義服務(wù)端注冊(cè)
public class AidlService extends Service {
private List<Person> mPersons = new ArrayList<>();
private IBinder mIBinder = new PersonAidl.Stub() {
@Override
public void addPerson(Person person) throws RemoteException {
mPersons.add(person);
}
@Override
public List<Person> getPersonList() throws RemoteException {
return mPersons;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mIBinder;
}
}
上面的代碼就是我們自定義的一個(gè)服務(wù),它里面實(shí)現(xiàn)了我們的PersonAidl.Stub,上一節(jié)我們分析的Stub源碼里的onTransact最終會(huì)回調(diào)到這里我們具體的實(shí)現(xiàn)。并且這里可以看到它里面實(shí)現(xiàn)了一個(gè)onBind方法來(lái)返回這個(gè)IBinder引用。
<service
android:name=".service.AidlService"
android:exported="true"
android:enabled="true"
android:process=":aidl"/>
上面這段代碼就是把我們的服務(wù)聲明到aidl進(jìn)程,這里沒(méi)有什么要說(shuō)的,都是很標(biāo)準(zhǔn)的寫(xiě)法。
總結(jié)
好了,到這里呢,我們這次的Binder進(jìn)程間通信機(jī)制的探索就告一段落了。主要掌握以下幾點(diǎn):
- Linux內(nèi)存空間分為用戶空間和內(nèi)核空間,用戶空間不能共享,內(nèi)核空間可以共享;
- Binder機(jī)制的四個(gè)重要角色:Client、Server、ServiceManager、Binder驅(qū)動(dòng);
- Binder機(jī)制采用的是C/S架構(gòu),Binder驅(qū)動(dòng)是他們之間的橋梁亦是整個(gè)架構(gòu)的核心。
- Android中Binder主要的表現(xiàn)形式就是AIDL,重點(diǎn)理解Stub和Proxy模式。
以上就是我個(gè)人對(duì)Binder機(jī)制的一個(gè)理解,如果有說(shuō)錯(cuò)的或者理解不到位的地方都可以指出來(lái),我們一起學(xué)習(xí)改正,謝謝!
最后我們給出舉例的源碼地址:https://github.com/WangFion/TestAidl