一 、类图扩充
图1
Binder代理,本地接口
类图中加入了Bp<Interface>的代理类:BpMediaPlayer,BpMediaPlayerService。这些类和相应的Bn<Interface>互相配对,Bp<Interface>客户端代理接口,而Bn<Interface>实现服务端本地接口。
拿BxMediaPlayer来举例:BpMediaPlayer继承BpInterface<IMediaPlayer>,并重载实现IMediaPlayer接口的所有方法,这些方法包括start(), stop(),pause()等等。在这些重载方法中,实现client<->server的服务协议,利用remote()->transact()发送请求ID(enum结构),请求附带数据并获得调用结果(reply)。然后由宏IMPLEMENT_META_INTERFACE(MediaPlayer,"android.hardware.IMediaPlayer”) 将BpMediaPlayer和静态方法IMediaPlayer::asInterface(constsp<IBinder>& obj)相关联。你在代码里看不到有代码去实例化BpMediaPlayer,其实是在asInterface里做的,并且由interface_cast模板函数实现:
- Template<typename INTERFACE>
- inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
- {
- return INTERFACE::asInterface(obj);
- }
- <SPAN style="WHITE-SPACE: pre"> </SPAN>
Template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
- 具体的interface_cast的用法,可以在BpMediaPlayerService::create()里看到:
- virtual sp<IMediaPlayer> create(pid_t pid, constsp<IMediaPlayerClient>& client, const char* url
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
- data.writeInt32(pid);
- data.writeStrongBinder(client->asBinder());
- data.writeCString(url);
- remote()->transact(CREATE_URL,data, &reply);
- returninterface_cast<IMediaPlayer>(reply.readStrongBinder());
- }
具体的interface_cast的用法,可以在BpMediaPlayerService::create()里看到:
virtual sp<IMediaPlayer> create(pid_t pid, constsp<IMediaPlayerClient>& client, const char* url
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(pid);
data.writeStrongBinder(client->asBinder());
data.writeCString(url);
remote()->transact(CREATE_URL,data, &reply);
returninterface_cast<IMediaPlayer>(reply.readStrongBinder());
}
该create函数,实际是mediaplayer client实例在请求MediaPlayerService获取一个MediaPlayer服务接口时,BpMediaPlayerService代理返回的interface_cast过后得到的BpMediaPlayer实例。
因此,如果某个service需要走IPC层(也就是服务提供者和请求者不在同一个进程里),那么这个服务需要暴露的IXXXXInterface必然被BpXX/BnXX两个类实现(继承),Bp用在客户端,Bn用在服务端。客户端获取服务接口类的类型虽然是IXXXX,但实际上利用C++的多态机制,得到的是BpXX的类型。
各个类之间关系
MediaPlayer(MediaPlayerClient)对象从MediaPlayerService获取的player,实际上是BpMediaPlayer实例,并保存在它的mPlayer成员变量中。对应的在MediaPlayerService实例中,MediaPlayerClient申请,并创建的player对象会被放入clients成员向量中,该向量实际上是BnMediaPlayer的对象容器。每个client对象都有自己的mPlayer成员变量,保存的则是OpenCORE创建的PVPlayer对象。这里有两个mPlayer成员变量,各自代表不同类型,不要混淆。二、通过MediaPlayer获得service player时序图
以setDataSource接口为例:
三、使用serviceplayer时序图
以上的时序图,描述的是之前获得的mPlayer的使用时序。这个时序比较简单,这里不做详细说明,需要注意的是图最右侧,Client对象实际要通过创建和调用OpenCORE里的PVPlayer来最终实现多媒体播放功能。