在Android IPC之Messenger一文中,對通過Messenger實現IPC的流程做了一個簡單的介紹,在文中曾說到Messenger的底層也是通過AIDL實現的,這裏通過Messenger的源碼來看看AIDL是如何實現Messenger的。
Messenger實現IPC流程分析
Messenger源碼分析
package android.os;
public final class Messenger implements Parcelable {
/**
* IMessenger就是通過聲明一個.aidl文件生成的對應的接口
*/
private final IMessenger mTarget;
/**
* 第一步:在服務端創建Messenger
*
* 通過該方法創建一個Messenger對象,該對象會持有一個Handler的引用,
* 所有要通過Messenger的send()發送的跨進程Message,最終都是通過該Handler發送,
* 所以Handler是Messenger實現跨進程通信的核心類之一
*/
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
/**
* 第二步:將binder對象返回到客戶端
*
* 通過調用該方法返回一個Binder對象,這個一般在Service的onBind()方法中返回IBinder對象時調用。
*/
public IBinder getBinder() {
return mTarget.asBinder();
}
/**
* 第三步:客戶端服務綁定成功後,通過Binder對象創建Messenger
*
* 通過Binder對象創建一個Messenger對象,
* 這個構造方法一般在客戶端調用,當綁定服務成功後,
* 通過返回的binder對象創建的Messenger會和服務端的Messenger對象對應
* 最終在客戶端發送消息在服務端可以接收到。
*
*/
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
/**
* 第四步:在客戶端調用send方法,向服務端發送消息
*
* 通過調用該方法,最終通過Handler的send()方法,發送Message消息
*/
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
public boolean equals(Object otherObj) {
if (otherObj == null) {
return false;
}
try {
return mTarget.asBinder().equals(((Messenger)otherObj)
.mTarget.asBinder());
} catch (ClassCastException e) {
}
return false;
}
public int hashCode() {
return mTarget.asBinder().hashCode();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeStrongBinder(mTarget.asBinder());
}
public static final Parcelable.Creator<Messenger> CREATOR
= new Parcelable.Creator<Messenger>() {
public Messenger createFromParcel(Parcel in) {
IBinder target = in.readStrongBinder();
return target != null ? new Messenger(target) : null;
}
public Messenger[] newArray(int size) {
return new Messenger[size];
}
};
public static void writeMessengerOrNullToParcel(Messenger messenger,
Parcel out) {
out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
: null);
}
public static Messenger readMessengerOrNullFromParcel(Parcel in) {
IBinder b = in.readStrongBinder();
return b != null ? new Messenger(b) : null;
}
}
在上面的源碼中,Messenger定義了一個IMessenger類型的成員變量mTarget,但是在java源碼中看不到IMessenger類的相關信息,這是因爲IMessenger是一個聲明的aidl接口,我們可以通過android系統源碼找到這個aidl接口文件,代碼如下:
/**
*文件路徑:
*
* ../android-6.0.1_r72/frameworks/base/core/java/android/os/IMessenger.aidl
*/
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
在上面的源碼中,我們可以看到IMessenger對象mTarget對象的初始化是通過調用 Handler.getIMessenger()完成的。
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
這裏我們看下Handler中的getIMessenger方法。
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
/**
* 最終,Messenger的send()方法,是在這裏實現的,
* 這裏我們可以確實,Messenger實現IPC是通過Handler實現的
*/
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
// 這是一個本地方法,用於獲取進程的Uid,保證在進程間通信
msg.sendingUid = Binder.getCallingUid();
// 調用handler的sendMessage方法實現IPC
Handler.this.sendMessage(msg);
}
這裏,我們可以得出一個結論Messenger實現IPC的流程,底層是通過aidl文件實現的,同時handler也是Messenger實現IPC的關鍵類。
關於Handler,想必大多數人對於Handler的認識是停留在線程間通信的,至於Handler如何實現IPC這裏只提一句,Handler在Native層中通過管道實現IPC通信
這裏推薦一篇關於Handler Native層的講解: Android消息機制2-Handler(Native層)