IPC理解2



根据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;
    }
}

将执行结果返回给发起进程

        //java层

    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调用完毕。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值