1.先从调用者说起
AudioSystemsetPhoneState中:
aps->setPhoneState(state),
aps类型:
sp<IAudioPolicyService>
2.IAudioPolicyService是一个抽象类,找子类,共两位
BnAudioPolicyServicepublic BnInterface<IAudioPolicyService>
BpAudioPolicyServicepublic BpInterface<IAudioPolicyService>
3.BnInterfaceBpInterface是什么鬼?
原来是C++模板类
template<typenameINTERFACE>
class BnInterface :public INTERFACE。。。
class BpInterface :public INTERFACE。。。
当前的情况尖括号里是IAudioPolicyService。
所以上面这个就相当于classBnInterface : public IAudioPolicyService
也就是说BnInterfaceBpInterface都是继承自IAudioPolicyService
4.调用者AudioSystem调用之后需要找实现,那真实调用的setPhoneState的实现,就在BnAudioPolicyService,BpAudioPolicyService这两者中间,很明显,BnAudioPolicyService没实现任何来自爷爷类IAudioPolicyService的成员函数,但是BpAudioPolicyService中是有实现的,
virtual status_tsetPhoneState(audio_mode_t state)
{
Parcel data,reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(state);
remote()->transact(SET_PHONE_STATE, data, &reply);
returnstatic_cast <status_t> (reply.readInt32());
}
6.而BnAudioPolicyService实现了来自爸爸的onTransact函数。函数的实现就是根据各种code做一些对应的操作,比如setPhoneState对应的:
caseSET_PHONE_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
reply->writeInt32(static_cast <uint32_t>(setPhoneState(
(audio_mode_t) data.readInt32())));
returnNO_ERROR;
} break;
这就很明显,又很关键了,
一个transact,一个onTransact,一发一收,一唱一和,就用一个码来完成通信。
7.onTransact里很明显调用了setPhoneState()方法,而这个类本身并没有实现setPhoneState(),所以往下找,找它的子类吧
AudioPolicyServicepublic BnAudioPolicyService
AudioPolicyService中:(实现在AudioPolicyInterfaceImp.cpp中,惊讶!)
mAudioPolicyManager->setPhoneState(state);
虽然可能你已经很兴奋地要喊出来了,实现就在AudioPolicyManager中,但是请别着急!
请看:
AudioPolicyInterface*mAudioPolicyManager;
这个变量的赋值根本不在AudioPolicyInterfaceImp.cpp中,害我找了好几分钟,AudioPolicyService类的实现,除了AudioPolicyInterfaceImp.cpp文件,还有个纯正的AudioPolicyService.cpp。作者请给我打电话跟我解释一下这件事情,是不是有毛病?
mAudioPolicyManager= createAudioPolicyManager(mAudioPolicyClient);
这行代码出自voidAudioPolicyService::onFirstRef()
是不是明白什么了,我擦,开机启动时mediaserver直接会启动AudioPolicy和AudioFlinger两大服务。这个变量在时候被初始化了!
8.上面说到的这个createAudioPolicyManager函数又是一个”虚“函数,给人一种无处不在的赶脚。这样就能让各家手机厂商,芯片厂商自己实现自己的AudioPolicyManager了。总之我们知道这时候函数调用进入到了AudioPolicyManger里就好了。再往下扯,各位看官又该吐槽我写的东西又长又臭了,而且还离题千里。
9.话说前面说到BnAudioPolicyService,BpAudioPolicyService这两货一唱一和就实现了Binder调用。在我展开说之前你肯定也像第一次看的我一样不信。实现就在同一个文件里。直接调用不就完了吗?为嘛非得通过这种transact,onTransact的方式呢?
你别忘了现在讲的是Binder.应用场景是跨进程的。也就是说BnAudioPolicyService,BpAudioPolicyService代码文件写在同一个文件里是方便你看,其实他们运行的时候完全是两个进程。BnAudioPolicyService咱们前面分析过了,真正的实现在服务端,mediaserver进程。BpAudioPolicyService是什么进程呢?取决与调用者,AudioSystem的调用者。全局搜索一下,不难发现,来自java层的AudioSystem类通过jni调用过来(我说的是setPhoneState函数,不是所有),最终能追述到AudioService。而对应到用户端能掉用的就是AudioManager接口了。
10.把废话整理一下,就是第三方应用通过AudioManager层层调用的一个函数,通过Binder调用到mediaserver进程中实现的函数。正所谓跨进程啦。
11.至于中间这个binder是怎么通过code进行调用的呢?
binder又是一个进程了,一个服务进程。你想想你在淘宝上买东西的时候,是不是淘宝给你送货的?都是快递帮你们进行转发的。也许binder就是一个送快递的呢!哈哈
具体细节我也不知道呢,毕竟,本文的标题是用法,而不是原理!!!hahaha
原理请看:
http://blog.csdn.net/coding_glacier/article/details/7520199