根据gityuan大神总结再次理解IPC通信流程。
http://gityuan.com/2016/09/04/binder-start-service/
那么就从启动一个远程服务来分析整个IPC流程,最为应用开发者,底层的很多通信细节我不了解,但是
整个流程上特别是底层和framework层的衔接上要有个清晰的人是。 下面就根据gityuan的总结 我再次
总结加深一下。
初始化本进程的aidl对象(代理对象)
Activity -->startService()
ContextWrapper -->startService()
ContextImpl -->startServiceCommon()
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
调用aidl对象的业务方法
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeString(callingPackage);
data.writeInt(userId);
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
在业务方法中调用mRemote.transact,并将数据写入底层。
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
底层判断是否需要返回值,如果需要,就等待远程进程的执行结果。
是否需要返回值 例如:
unbroadcastIntent{ // 不需要返回值。 mRemote.transact(FINISH_RECEIVER_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); } finishReceiver{ // 需要返回值。 mRemote.transact(UNBROADCAST_INTENT_TRANSACTION, data, reply, 0); }
转入C++层,通过binder驱动来远程调用AMS服务(在远程进程)
调用BpBinder.transact
BpBinder.cpp
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
//继续调用
status_t status = IPCThreadState::self()->transact
-------------------------------------------------------------------------------------------------------------
继续调用IPC.transact
IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
//.....写入binder驱动数据
if (err == NO_ERROR) {
// 将数据写入mOut ,准备数据传输
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
// 如果写入有异常情况,直接返回异常
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
// 等待服务端返回结果
// 默认情况下,都是采用非oneway的方式, 也就是需要等待服务端的返回结果
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
//reply对象不为空
err = waitForResponse(reply);
}else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
如果需要返回值,则等待远程进程返回数据。
跨进程调用时:
如果需要返回结果,就等待远程进程当中的方法执行,然后再发送命令获取结果。
如果不需要返回结果,直接返送命令 获取远程进程的执行结果。
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
int32_t cmd;
int32_t err;
while (1) {
//1:★★★ talkWithDriver: 真正与Binder驱动进行数据读写交互的过程。
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break; //当存在error则退出循环
//每当跟Driver交互一次,若mIn收到数据则往下执行一次BR命令
//2:★★★ 读取远程进程的执行结果。
if (mIn.dataAvail() == 0) continue;
//3:★★★ 读完之后 再次发送命令,确认最终执行结果。
cmd = mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
//★★★ 只有当不需要reply, 也就是oneway时 才会跳出循环,否则还需要等待.
if (!reply && !acquireResult) goto finish; break;
case BR_DEAD_REPLY:
// 远程返回失败
err = DEAD_OBJECT; goto finish;
case BR_FAILED_REPLY:
//远程返回失败
err = FAILED_TRANSACTION; goto finish;
//Binder驱动向Client端发送回应消息; 对于非oneway transaction时,当收到该消息,
则完整地完成本次Binder通信;
case BR_REPLY: ... goto finish;
default:
//3:★★★ 读完远程进程中方法执行结果之后, 再次发送命令最终确认结果。
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (reply) reply->setError(err); //将发送的错误代码返回给最初的调用者
}
return err;
}
//Binder驱动向Server端发送消息,确定最终远程进程 的执行结果。
status_t IPCThreadState::executeCommand(int32_t cmd)
{
switch ((uint32_t)cmd) {
...
case BR_TRANSACTION:
...
//对于非oneway, 需要reply通信过程,则向Binder驱动发送BC_REPLY命令 .
//★★★ 发起进程需要返回值的情况,这里最后通知发起进程, 远程进程执行完毕,并将结果返回了。
sendReply(reply, 0);
...
}
}
------------------------------------------------------------------------------------------------------------------
底层调用远程进程的方法。
// 以上进过处理以后,底层经过一系列处理,最终调用到 目标进程
/***/
BBinder.transact
Binder.cpp ::BBinder
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
.....
//★
err = onTransact(code, data, reply, flags);
......
}
以上进过处理以后,底层经过一系列处理,最终调用到 目标进程
------------------------------------------------------------------------------------------------------------------
/***/
BBinder.transact
Binder.cpp ::BBinder
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
.....
err = onTransact(code, data, reply, flags);
......
}
-----------------------------------------------------------------------------------------------------------------
调用到远程进程当中
/*底层回调到 远程进程当中 ,最先执行binder中的execTransact方法*/
JavaBBinder
android_util_Binder.cpp
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
//调用Binder.execTransact
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
}
-----------------------------------------------------------------------------------------------------------------
Binder.execTransact
Binder.java
private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
// 调用子类AMN.onTransact方法
res = onTransact(code, data, reply, flags);
}
-----------------------------------------------------------------------------------------------------------------
/*接着 执行aidl对象的 onTransact 方法(也就是Stub中的onTransact)*/
执行远程进程当中的业务方法
ActivityManagerNative.java
//重要两部:1:执行本进程中的 目标业务方法。这里的方法就是发起进程要的
2:返回结果给发起进程。(作为远程服务(目标进程) 将客户端需要的 执行结果返回。)
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
...
case START_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
//生成ApplicationThreadNative的代理对象,即ApplicationThreadProxy对象
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
String callingPackage = data.readString();
int userId = data.readInt();
//调用ActivityManagerService的startService()方法
//★★★ 执行本进程中的 目标业务方法。这里的方法就是发起进程要的。
ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
//★★★ 告诉给发起端进程
// 作为远程服务(目标进程) 将客户端需要的 执行结果返回。
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
}
}
将执行结果返回给发起进程
ComponentName.writeToParcel(cn, reply);
// 经过sendReply调用
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags){
......
}
// 经过一系列过程后.....
binder_thread_read{
//★★★将cmd和 远程进程返回的 数据 写回用户空间
put_user(cmd, (uint32_t __user *)ptr))
}
最后调用到java层aidl对象(代理对象)的方法中。
ActivityManagerNative.ActivityManagerProxy -->startService(){
//远程进程方法执行后 ,底层将结果写入到reply 对象中。
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
// 读取 远程进程的执行结果。
// String result = reply.readString();
// return reslult;
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
IPC调用完毕。