1. Hal层类关系图
以MediaPlayer功能为例,我们可以根据Android 8.1 (Oreo)源代码绘制出其类图
2. IMediaPlayerService.h
定义相关API,方便binder进程调用。IMediaPlayerService理论上是MediaPlayerService的接口,故只定义API而把API具体实现都放在class MediaPlayerService中。
2.1 BnMediaPlayerService
IMediaPlayerService主要有两个子类,一个是BpMediaPlayerServcie类,另一个是BnMediaPlayerService类。
IMediaPlayerService.h中,可以看到BnMediaPlayerService继承模板类BnInterface。在IInterface.h中可看到BnInterface的定义如下:
根据模板类的概念,BnMediaPlayerService相当于继承IMediaPlayerService和BBinder。
同理,BpMediaPlayerService类相当于继承了IMediaPlayerService和BpRefBase类。
2.2 DECLARE_META_INTERFACE( )
DECLARE_META_INTERFACE( )同样位于IInterface.h,同样是一个模板函数。
则DECLARE_META_INTERFACE( MediaPlayerService)可以翻译为:
可以总结为IMediaPlayerService主要包含了以下几个虚函数,待子类 class MediaPlayerService实现。
(1) sp<IMediaPlayer> create(...) //纯虚函数
(2) sp<IOMX> getOMX() //纯虚函数
(3) sp<IHDCP> makeHDCP(bool createEncryptionModule) //纯虚函数
(4) sp<IMediaCodecList> getCodecList() const //纯虚函数
3. IMediaPlayerService.cpp
IMediaPlayer.cpp包含了class BpMediaPlayerService和class BnMediaPlayerService。
BpMediaPlayerService的主要设计满足代理模式(proxy),可以视为代理类,隔断客户端(访问对象)和服务端(被访问对象)。客户端对象必须通过代理类才能访问到BnMediaPlayerService中对象。
BpMediaPlayerService代理类的主要代码如下,主要作用是remote->transact( )调用。通知服务端具体调用。
class BpMediaPlayerService: public BpInterface<IMediaPlayerService> { public: explicit BpMediaPlayerService(const sp<IBinder>& impl):BpInterface<IMediaPlayerService>(impl){ } ... ... virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, audio_session_t, audioSessionId) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); data.writeStrongBinder(IInterface::asBinder(client)); data.writeInt32(audioSessionId); remote()->transact(CREATE, data, &reply); return interface_cast<IMediaPlayer>(reply.readStrongBinder()); } virtual sp<IOMX> getOMX() { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); remote()->transact(GET_OMX, data, &reply); return interface_cast<IOMX>(reply.readStrongBinder()); } virtual sp<IHDCP> makeHDCP(bool createEncryptionModule) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); data.writeInt32(createEncryptionModule); remote()->transact(MAKE_HDCP, data, &reply); return interface_cast<IHDCP>(reply.readStrongBinder()); } ... ... virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName, const sp<IRemoteDisplayClient>& client, const String8& iface){ Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); data.writeString16(opPackageName); data.writeStrongBinder(IInterface::asBinder(client)); data.writeString8(iface); remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply); return interface_cast<IRemoteDisplay>(reply.readStrongBinder()); } virtual sp<IMediaCodecList> getCodecList() const { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); remote()->transact(GET_CODEC_LIST, data, &reply); return interface_cast<IMediaCodecList>(reply.readStrongBinder()); } }; |
BnMediaPlayerService作为实现类,重写onTransact( )函数,处理proxy发来的函数调用。
status_t BnMediaPlayerService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case CREATE: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IMediaPlayerClient> client =interface_cast<IMediaPlayerClient(data.readStrongBinder()); audio_session_t audioSessionId = (audio_session_t) data.readInt32(); sp<IMediaPlayer> player = create(client, audioSessionId); reply->writeStrongBinder(IInterface::asBinder(player)); return NO_ERROR; } break; ... ... case GET_OMX: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IOMX> omx = getOMX(); reply->writeStrongBinder(IInterface::asBinder(omx)); return NO_ERROR; } break; case MAKE_HDCP: { CHECK_INTERFACE(IMediaPlayerService, data, reply); bool createEncryptionModule = data.readInt32(); sp<IHDCP> hdcp = makeHDCP(createEncryptionModule); reply->writeStrongBinder(IInterface::asBinder(hdcp)); return NO_ERROR; } break; ... ... case LISTEN_FOR_REMOTE_DISPLAY: { CHECK_INTERFACE(IMediaPlayerService, data, reply); const String16 opPackageName = data.readString16(); sp<IRemoteDisplayClient> client(interface_cast<IRemoteDisplayClient>(data.readStrongBinder())); if (client == NULL) { reply->writeStrongBinder(NULL); return NO_ERROR; } String8 iface(data.readString8()); sp<IRemoteDisplay> display(listenForRemoteDisplay(opPackageName, client, iface)); reply->writeStrongBinder(IInterface::asBinder(display)); return NO_ERROR; } break; case GET_CODEC_LIST: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IMediaCodecList> mcl = getCodecList(); reply->writeStrongBinder(IInterface::asBinder(mcl)); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } |
例如,当proxy发来调用服务端的getCodecList( )函数(getCodecList()函数为获取编码器列表)。则调用
remote()->transact(GET_CODEC_LIST,data,&reply); |
经过binder驱动,会回调至onTransact( ),处理客户端需求。如GET_CODEC_LIST满足case GET_CODEC_LIST,则执行
而IMediaPlayerService类中的create( ),makeDHCP( ),getCodecList( )具体实现不在IMediaPlayerService类中。