android binder study
可以看到,在这个接口类中定义了IMediaPlayerService需要提供的6个函数接口,因为是接口类,所以定义为纯虚函数。需要注意这个接口类的名称有严格要求,必须是以大写字母I开始。
重点关注在这些函数前面的一个宏定义:DECLARE_META_INTERFACE(MediaPlayerService)。这个宏定义必须要有,其中封装了实现binder所需要的一些类成员变量和成员函数, 通过这些成员函数可以为一个binder实现创建proxy。这个宏定义在文件frameworks\base\include \utils\IInterface.h里,在后面还会讲到。这个宏定义的参数必须是接口类的名称去除字母I后剩下的部分。
另外说明一下,可以看到接口类中所定义的函数的返回值都是sp
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>这个类的写法是标准的写法,下次如果写一个代理类,就可以这样写。BpInterface是实现接口代理类的继承的模板类,而这个类的参数也就是IMediaPlayerService,最后的结果就是这个类BpMediaPlayerService实现了IMediaPlayerService所有实现的接口。
IMediaPlayerService的接口代理实现类,BpInterface是接口代理实现类的模块,再加一个IMediaPlayerService是要2边实现的类的接口,一边是接口ap的代理类,一边是server的实现类。
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
{
public:
DECLARE_DYNAMIC(BpMediaPlayerService);
BpMediaPlayerService(const sp<IBinder>& impl)
: BpInterface<IMediaPlayerService>(impl),
PREINIT_DYNAMIC()
{
}
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());/*第一个写入的是接口的
一个描述字符串,binder的实现类中会用这个字符串来对接口做验证,防止调用错误。这个字符串也可以不写,如果不写,在binder实现类中相应的也就不要做验证了*/
data.writeInt32(pid);
remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
}
这些bp类的实现的原理都是一样的,Parcel是为了专门给binder实现而设计的类,为了在bp和bn之间传送数据。量data是用于封装create()函数调用所需要的输入参数,而reply则是用于封装调用的返回数据(包括输出参数的值和函数返回值)。Pacel提供一种先入先出的数据存储方式,即数据的写入顺序和读取顺序必须严格一致,否则将会出错。
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
{
public:
DECLARE_DYNAMIC(BpMediaPlayerService);
BpMediaPlayerService(const sp<IBinder>& impl)
: BpInterface<IMediaPlayerService>(impl),
PREINIT_DYNAMIC()
{
}
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(pid);
remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
}
//imediaplayerservice.cpp
。。。都是这样的写法,通过binder操作之后,应该在BnMediaPlayerService中有个ontransact函数,这个函数会调用server端实现MediaPlayerService的接口,以后要找这样的接口就直接搜名字即可。因为接口叫IMediaPlayerService。那么代理端叫BpMediaPlayerService,服务端叫BnMediaPlayerService,只要搜谁实现了BnMediaPlayerService这个类,那么在bp端通过binder调用的就是这个函数。具体这个例子如下:
BnMediaPlayerService::BnMediaPlayerService() //imediaplayservices.cpp
: PREINIT_DYNAMIC()
{
}
BnMediaPlayerService::~BnMediaPlayerService()
{
}
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
pid_t pid = data.readInt32();
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
int audioSessionId = data.readInt32();
sp<IMediaPlayer> player = create(pid, client, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
case DECODE_URL: {
…
而查这个类的bn端找到实现:
class MediaPlayerService : public BnMediaPlayerService 位于mediaplayservices.h中。则可以找到具体bp端的接口实现了。
具体参考:http://blog.mcuol.com/User/AT91RM9200/article/20878_1.htm