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驱动是否有数据,当有数据读出时,就根据数据中的服务地址和服务的函数对应的名字,执行相应的服务
来源:oschina
链接:https://my.oschina.net/u/920274/blog/4295635