Pmcs类图理解
1. 名词定义
名词 | 含义 |
---|---|
BBinder | 服务端接口 |
BpBinder | 客户端接口 |
2. 使用Binder流程
- 开发native service
- 定义服务端接口文件,即IPmcsService类,其继承于IInterface类
- 定义BnPmcsService类,继承于BnInterface
- 实现一个PmcsService类,继承于BnPmcsService类,并实现响应客户端请求onTransact()
- 开发client
BpBinder(客户端)如何把请求发送给BBinder(服务端),BBinder又如何将响应传回给客户端的呢?
3. BBinder服务端
- BBinder 实现了大部分的IBinder 接口,除了onTransact() 和 queryLocalInterface(), getInterfaceDescriptor()
- IInterface
- 实现queryLocalInterface(),该函数可查询服务端提供的服务
- INTERFACE模板继承和实现IInterface
- BnInterface
- BnInterface
对象将自己强制转换成 IInterface对象返回给客户端 - BnInterface是一个模板类,继承了BBinder和模板INTERFACE
- BnInterface 实现了IBinder的queryLocalInterface()和getInterfaceDescriptor()
- BnInterface
- BnPmcsServer同时继承IInterface和IBinder,定义了onTransact(),没有实现
- PmcsService里具体实现了onTransact()
4. BpBinder客户端
目标:找到一个类,它必须同时拥有IBinder 和 IIterface的特性
- BpRefBase里有IBinder成员变量
- BpInterface
- BpInterface继承于BpRefBase,而BpRefBase里有IBinder成员变量,从而获取到IBinder特性
- BpInterface继承于INTRFACE,这里INTRFACE就是IPmcsService
- IInterface中函数asBinder()->BpInterface::onAsBinder()->BpInterface::remote(),返回得到mRemote
- BpPmcsService为客户端,具体向服务端发起请求
- PmcsProxy为客户端的回调,服务端响应完请求后,调用回调向调用发起者通知执行结果
BpRefbase的mRemote是如何被赋值的?
最后追溯到 IPmcsService.cpp
1 | interface_cast<IMediaPlayer>(reply.readStrongBinder()); //reply里读出IBinder,然后转成IMediaPlayer接口对象 |
通过子类一级一级注入,即new一个BpPmcsService,然后将其转换为父父类IPmcsService
客户端流程
客户端从远端生成一个IBinder对象,再生成BpPmcsService,将其转换为IpmcsService接口对象,调用其接口方法,最终调用到BpBinder的transact()
而客户端的transact()函数通过Binder Driver获取到BBinder对象(IBinder的实现),并调用onTransact()
5. 总流程
- 应用程序的角度
- 已知服务名,APP通过getService() 从ServiceManager 获取存储在Parcel对象的服务的信息
- APP收到Parcel对象 (通过kernel),获取到服务对应的服务号,mHandle
- 以mHandle作为参数输入生成一个IBinder对象(实际是BpBinder)
- APP获取到IBinder对象,通过asInterface(IBinder)生成服务对应的Proxy对象(BpPmcsService),将其强转到*IPmcsService,调用接口函数
- 所有的接口对象调用最终会走到BpBinder->transact()函数,这个函数调用IPCThreadState->transact()并以Service号作为参数之一
- 最终通过系统调用ioctrl() 进入内核空间,Binder驱动根据传进来的Service 号寻找该Service正处于等待状态的Binder Thread, 唤醒它并在该线程内执行相应的函数,并返回结果给APP