IPCThreadState::executeCommand 解析(Transact如何调用到onTransact)

佐手、 提交于 2020-08-06 09:46:35

status_t IPCThreadState::executeCommand(int32_t cmd) {

 。。。

b->transact(tr.code, buffer, &reply, tr.flags);

。。。

}

这里就是处理不同的请求地方,当此次请求是一个客户端请求时,会走到BR_TRANSACTION的case中。上面的代码我们可以看到这么一句sp<BBinder> b((BBinder*)tr.cookie) 这个是我们从binder驱动中读出的值。在上一节注册service里面,我们是把BnMediaPlayerService指针注册到了binder当中,如果客户端此次请求是对MediaPlayerService服务的 ,那么此处的cookie就是Service代码地址的指针。然后会执行b->transact(tr.code, buffer, &reply, tr.flags); 我们看一下BBinder中transact()的实现

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            reply->writeInt32(pingBinder());
            break;
        default:
            err = onTransact(code, data, reply, flags);
            break;
    }

    if (reply != NULL) {
        reply->setDataPosition(0);
    }

    return err;
}

解析服务请求命令

然后会调用onTransact()函数,onTransact() 是一个纯虚函数,每一个Service会实现 这个函数。对于MediaPlayerService服务,其实现在IMediaPlayerService.cpp文件中。

status_t BnMediaPlayerService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) {

 。。。

。。。

}

当客户端调用不同的函数时,就会发送 对应的cmd请求,服务端就会跟据这个cmd调用不同的具体实现。

这样对于一个Service完整的binder实现,我们这里就分析完了。总结一下:

首选获得managerService的代理,managerService是一个特殊的binder服务,他将自己注册为 binder驱动的主服务。其他客户端直接通过handle=0像binder驱动发送请求,驱动就会把我们的请求发送给manageService。
获得managerService代理之后,我们将自己注册到binder驱动和managerService里面。binder驱动帮我们生成一个handle整型值和我们的Service的引用传送到managerSerice里面。其他进程可以直接通过名字找到我们的服务
注册完服务后,Service开启线程监听binder驱动是否有数据,当有数据读出时,就根据数据中的服务地址和服务的函数对应的名字,执行相应的服务
 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!