常听Android的IPC是Binder机制,之前也看不少别人的博客。但总是似懂非懂。最近自己结合别人的博客和Activity的启动流程分析了一下。大致如下。(只是自己简单的理解,有错误的话希望大神能帮忙指正一下,谢谢)
1:Binder,可以在进程中传递的对象
2:Parcelable类型数据可以通过Binder和Intent传递
Activity启动流程(到Service):
我们从startActivity开始,一直到Instrumentation.execStartActivity都很明确。这个方法中调用到ActivityManagerNative.getDefault().startActivity。
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
看ActivityManagerNative.getDefault()
static public IActivityManager getDefault() {
return gDefault.get();
}
再看gDefault:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity"); //获取服务Binder
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b); //获取Proxy对象
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
通过ServiceManager.getService获取了指定服务的Binder,然后通过asInterface的方法获取到一个Proxy对象
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
那么我们前面的ActivityManagerNative.getDefault().startActivity其实就是调用的proxy的StartActivity方法。
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(START_ACTIVITY_TRANSACTION, data, reply, 0); //传递消息
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
Proxy中先使用Parcel封装了数据,然后拿构造函数中的Binder对象,也就是相关服务的Binder对象执行了transact方法,这里我的理解是这个方法将标识(START_ACTIVITY_TRANSACTION)和封装的数据通过Binder驱动,发送给了相关的服务--ActivityManagerService。完成一次跨进程的消息传递
ActivityManagerService要在自己的onTransact方法中处理接收的消息。因为它是继承自ActivityManagerNative的,自己也没有重写这个方法,所以调用的是ActivityManagerNative的onTransact方法。这个方法调用了startActivity方法,也就是调用了ActivityManagerService的startActivity方法
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
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, //调用服务的startActivity
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
如上,调用到的startActivity其实就是ActivityManagerService的方法。
至此,服务开始执行startActivity方法
Binder机制提到的四个角色上面都找到了:Client,ServiceManager,Service,Binder驱动。
也就是Client通过ServiceManager拿到服务的Binder,创建Proxy对象,再使用proxy对象通过Binder机制传递消息到Service进程。服务进程根据标识,分辨调用自己的哪个方法