5.5 服务代理与服务通信
Client获取到AudioFlingerProxy后,便可以通过其提供的接口使用Service提供的相应服务。服务代理与服务通信的过程如图5-3所示。
图 5-3 服务代理与服务通信的过程
AudioFlingerProxy中定义了很多接口,以setMasterVolume为例,代码如下:
virtual status_t setMasterVolume(float value)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger:getInterfaceDescriptor());
data.writeFloat(value);
remote()->transact(SET_MASTER_VOLUME, data,&reply);
return reply.readInt32();
}
已知remote()返回的是指定服务的BpBinder对象,调用其transact方法的过程与addService和getService是类似的,所不同的是Binder驱动程序将把IPC请求转发给指定Service所在进程,该进程便是mediaserver。
mediaserver运行过程中会启动两个Binder线程用于处理Binder通信。每个线程都会talkWithDriver等待Client请求,接收到请求后会从talkWithDriver返回,进而执行executeCommand这部分内容在joinThreadPool中已经分析过。接下来直接分析executeCommand函数,其位于IPCThreadState.cpp中,代码如下:
status_t IPCThreadState:executeCommand(int32_t cmd)
{
BBinder*obj;
RefBase:weakref_type*refs;
status_t result=NO_ERROR;
switch(cmd){
……
case BR_TRANSACTION:
{
binder_transaction_data tr;
result=mIn.read(&tr, sizeof(tr));
if(result!=NO_ERROR)break;
Parcel buffer;
……
Parcel reply;
if(tr.target.ptr){
//将服务对象存入BBinder类型的变量b中
sp<BBinder>b((BBinder*)tr.cookie);
const status_t error=b->transact(tr.code, buffer,
&reply, tr.flags);//调用b的transact方法
if(error<NO_ERROR)reply.setError(error);
}else{
……
}
if((tr.flags&TF_ONE_WAY)==0){
sendReply(reply,0);
}else{//Client不需要返回数据时
}
……
}
break;
……
case BR_SPAWN_LOOPER://Binder可以请求增加Binder线程池中线程数量
mProcess->spawnPooledThread(false);
break;
……
return result;
}
上述代码的transact方法定义在BBinder中,其代码如下:
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://将执行switch代码块的default分支
err=onTransact(code, data, reply, flags);
break;
}
if(reply!=NULL){
reply->setDataPosition(0);
}
return err;
}
调用BBinder:transact进而调用到onTransact方法,该方法由子类覆盖,代码如下:
status_t AudioFlinger:onTransact(
uint32_t code, const Parcel&data, Parcel*reply, uint32_t flags)
{
return BnAudioFlinger:onTransact(code, data, reply, flags);
}
AudioFlinger在onTransact方法中复用了其父类BnAudioFlinger的onTransact方法,代码如下:
status_t BnAudioFlinger:onTransact(
uint32_t code, const Parcel&data, Parcel*reply, uint32_t flags)
{
switch(code){
……
case SET_MASTER_VOLUME:{
CHECK_INTERFACE(IAudioFlinger, data, reply);
reply->writeInt32(setMasterVolume(data.readFloat()));
return NO_ERROR;
}break;
……
default:
return BBinder:onTransact(code, data, reply, flags);
BnAudioFlinger:onTransact中定义了所有请求码对应的Server端处理函数。因此Client只需要发送请求码便可以通过Binder驱动转发到Server端,Server端根据请求码在onTransact方法中匹配处理函数,最终实现远程方法调用。