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实现而设计的类,为了在bpbn之间传送数据。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

posted @ 2013-06-14 16:05  Colourman  阅读(231)  评论(0编辑  收藏  举报