首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android学习札记-Binder

2012-09-24 
Android学习笔记--Binderandroid mediaplayer?????android的媒体播放功能分成两部分,一部分是媒体播放应用

Android学习笔记--Binder

android mediaplayer



??

???android的媒体播放功能分成两部分,一部分是媒体播放应用,一部分是媒体播放服务(MediaServer,在系统启动时由init所启动,具可参考init.rc文件)。这两部分分别跑在不同的进程中。媒体播放应用包括Java程序和部分C++代码,媒体播放服务是C++代码,并且需要调用外部模块opencore来实现真正的媒体播放。媒体播放应用和媒体播放服务之间需要通过binder机制来进行相互调用,这些调用包括:

???(1)媒体播放应用向媒体播放服务发控制指令
???(2)媒体播放服务向媒体播放应用发事件通知(notify)

???媒体播放服务对外提供多个接口,在上面得图中包括其中的2个接口:IMediaService和IMediaPlayer,IMediaplayer用于创建和管理播放实例,而IMediaplayer接口则是播放接口,用于实现指定媒体文件的播放以及播放过程的控制。

???上面的图中还有媒体播放应用向媒体播放服务提供的1个接口:IMediaPlayerClient,用于接收notify。

???这些接口因为需要跨进程调用,因此需要用到binder机制。每个接口包括两部分实现,一部分是接口功能的真正实现(BnInterface),这部分运行在接口提供进程中;另一部分是接口的proxy(BpInterface),这部分运行在调用接口的进程中。binder的作用就是让这两部分之间建立联系。下图是整个播放器的一个概要说明。?

???

binder Ip


?????媒体播放器比较复杂一些,总共实现了3个接口,不过要了解binder的机制,只需要研究其中一个接口就足够了。在这里选择IMediaPlayerService接口来看一下。

?????IMediaPlayerService接口包括六个功能函数:create(url)、create(fd)、decode(url)、?decode(fd)、createMediaRecord()、createMetadataRetriever()。在这里不介绍这些函数是做什么的,我们只关注如何通过binder还提供这些函数接口。




(二)?接口定义

(1)?定义接口类


?????首先定义IMediaPlayerService类,这是一个接口类(C++的术语应该叫纯虚类)。该接口类定义在文件frameworks\base\include\media\IMediaPlayerService.h。代码如下:


class?IMediaPlayerService:?public?IInterface
{
public:
????DECLARE_META_INTERFACE(MediaPlayerService);

????virtual?sp??createMediaRecorder(pid_t?pid)?=?0;
????virtual?sp?createMetadataRetriever(pid_t?pid)?=?0;
????virtual?sp????create(pid_t?pid,?const?sp&?client,?const?char*?url)?=?0;
????virtual?sp????create(pid_t?pid,?const?sp&?client,?int?fd,?int64_t?offset,?int64_t?length)?=?0;
????virtual?sp?????????decode(const?char*?url,?uint32_t?*pSampleRate,?int*?pNumChannels,?int*?pFormat)?=?0;
????virtual?sp?????????decode(int?fd,?int64_t?offset,?int64_t?length,?uint32_t?*pSampleRate,?int*?pNumChannels,?int*?pFormat)?=?0;
};

?
?
????可以看到,在这个接口类中定义了IMediaPlayerService需要提供的6个函数接口,因为是接口类,所以定义为纯虚函数。需要注意这个接口类的名称有严格要求,必须是以大写字母I开始。?
????重点关注在这些函数前面的一个宏定义:?DECLARE_META_INTERFACE(MediaPlayerService)。这个宏定义必须要有,其中封装了实现binder所需要的一些类成员变量和成员函数通过这些成员函数可以为一个binder实现创建proxy。这个宏定义在问价frameworks\base\include?\utils\IInterface.h里,在后面还会讲到。这个宏定义的参数必须是接口类的名称去除字母I后剩下的部分。

????另外说明一下,可以看到接口类中所定义的函数的返回值都是sp的形式,看起来有点怪异。sp是android中定义的一个模板类,用于实现智能指针功能。sp就是IMediaPlayer的智能指针,可以简单地把它看成是标准C++中的指针定义即?IMediaPlayer*?即可。

(2)?定义和实现binder类


????binder类包括两个,一个是接口实现类,一个接口代理类。接口代理类继承自BpInterface,接口实现类继承自BnInterface。这两个基类都是模板类,封装了binder的进程间通信机制,这样使用者无需关注底层通信实现细节。

????对于IMediaPlayerService接口,其binder接口实现类为BnMediaPlayerService,接口代理类为?BpMediaPlayerService。需注意这两个类的名称有严格要求,必须以Bn和Bp开头,并且后面的部分必须是前面所定义的接口类的名称去除字母''''I’。比如前面所定义的接口类为IMediaPlayerService,去除字母I后是MediaPlayerService,所以两个?binder类的名称分别是BnMediaPlayerService和BpMediaPlayerService。为什么有这样的要求?原因就在前面提到的宏定义DECLARE_META_INTERFACE()和另一个宏定义IMPLEMENT_META_INTERFACE()里面。有兴趣的话可以去看一下,这两个宏定义都在文件frameworks\base\include\utils\IInterface.h里。

????BpMediaPlayerService是一个最终实现类。定义并且实现在在文件frameworks\base\media\libmidia?\IMediaPlayerService.cpp中。在看BpMediaPlayerService的代码之前,先看一下在?IMediaPlayerService.cpp文件的开始部分的一个枚举定义:

enum?{
????CREATE_URL?=?IBinder::FIRST_CALL_TRANSACTION,
????CREATE_FD,
????DECODE_URL,
????DECODE_FD,
????CREATE_MEDIA_RECORDER,
????CREATE_METADATA_RETRIEVER,
};

????这些6个枚举定义对应于IMediaPlayerService接口所提供的6个功能函数,可以称为这些功能函数的功能代码,用于在进程之间进行RPC是标识需要调用哪个函数。如果不想定义这些枚举值,在后面需要用到这些值的地方直接写上1,2,3,4,5,6也是可以的,不过……一个合适的程序员会这么干吗?

????下面看一下BpMediaPlayerService的代码。

(3)?BpMediaPlayerService代码分析


class?BpMediaPlayerService:?public?BpInterface
{
public:
????BpMediaPlayerService(const?sp&?impl)
????????:?BpInterface(impl)
????{
????}

????virtual?sp?createMetadataRetriever(pid_t?pid)
????{
????????Parcel?data,?reply;
????????data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
????????data.writeInt32(pid);
????????remote()->transact(CREATE_METADATA_RETRIEVER,?data,?&reply);
????????return?interface_cast(reply.readStrongBinder());
????}

????virtual?sp?create(pid_t?pid,?const?sp&?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);
????????return?interface_cast(reply.readStrongBinder());
????}

????virtual?sp?createMediaRecorder(pid_t?pid)
????{
????????Parcel?data,?reply;
????????data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
????????data.writeInt32(pid);
????????remote()->transact(CREATE_MEDIA_RECORDER,?data,?&reply);
????????return?interface_cast(reply.readStrongBinder());
????}

????virtual?sp?create(pid_t?pid,?const?sp&?client,?int?fd,?int64_t?offset,?int64_t?length)
????{
????????Parcel?data,?reply;
????????data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
????????data.writeInt32(pid);
????????data.writeStrongBinder(client->asBinder());
????????data.writeFileDescriptor(fd);
????????data.writeInt64(offset);
????????data.writeInt64(length);
????????remote()->transact(CREATE_FD,?data,?&reply);
????????return?interface_cast(reply.readStrongBinder());
????}

????virtual?sp?decode(const?char*?url,?uint32_t?*pSampleRate,?int*?pNumChannels,?int*?pFormat)
????{
????????Parcel?data,?reply;
????????data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
????????data.writeCString(url);
????????remote()->transact(DECODE_URL,?data,?&reply);
????????*pSampleRate?=?uint32_t(reply.readInt32());
????????*pNumChannels?=?reply.readInt32();
????????*pFormat?=?reply.readInt32();
????????return?interface_cast(reply.readStrongBinder());
????}

????virtual?sp?decode(int?fd,?int64_t?offset,?int64_t?length,?uint32_t?*pSampleRate,?int*?pNumChannels,?int*?pFormat)
????{
????????Parcel?data,?reply;
????????data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
????????data.writeFileDescriptor(fd);
????????data.writeInt64(offset);
????????data.writeInt64(length);
????????remote()->transact(DECODE_FD,?data,?&reply);
????????*pSampleRate?=?uint32_t(reply.readInt32());
????????*pNumChannels?=?reply.readInt32();
????????*pFormat?=?reply.readInt32();
????????return?interface_cast(reply.readStrongBinder());
????}
};
????首先可以看到,这个类继承自模板类BpInterface,指定类型为接口类IMediaPlayerService。BpInterface模板类定义在文件IInterface.h。看一下BpInterface的定义就可以发现,BpMediaPlayerService这样定义了以后,事实上间接继承了IMediaPlayerService,从而可以提供IMediaPlayerService接口所定义的接口函数。?BpMediaPlayerService需要实现这些接口函数。在一个简单的构造函数之后,就是这些接口函数的实现。可以看到,所有的接口函数的实现方法都是一致的,都是通过binder所提供的机制将参数仍给binder的实现类,并获取返回值。这也就是这个类之所以成为代理类的原因。下面具体看一下一个接口函数。这里选的是函数create(url)。

????virtual?sp?create(pid_t?pid,?const?sp&?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);
????????return?interface_cast(reply.readStrongBinder());
????}

????这个接口函数的参数指定了一个URL,函数将为这个URL创建一个播放器实例用于播放该URL。
????函数首先定义了两个局部变量data和reply,变量的类型都是Parcel。Parcel是一个专为binder通信的数据传送而定义的类,该类提供了对多种类型的数据的封装功能,同时提供多个数据读取和写入函数,用于多种类型的数据的写入和读取,支持的数据类型既包括简单数据类型,也包括对象。这里定义的变量data是用于封装create()函数调用所需要的输入参数,而reply则是用于封装调用的返回数据(包括输出参数的值和函数返回值)。
????函数首先向data中写入各种数据。第一个写入的是接口的一个描述字符串,binder的实现类中会用这个字符串来对接口做验证,防止调用错误。这个字符串也可以不写,如果不写,在binder实现类中相应的也就不要做验证了。跟在描述字符串后面写入的是该接口函数所需要的各种的输入参数。需要说明的是,Pacel提供一种先入先出的数据存储方式,即数据的写入顺序和读取顺序必须严格一致,否则将会出错。
????完成数据写入后,函数调用remote()->transact()用于完成binder通信。transact()函数的第一个参数就是前面提到过的功能代码。transact()的功能是将data中的数据传给binder的实现类,函数调用结束后,reply中将包含返回数据。首先来看看?remote()成员函数。前面讲到过BpMediaPlayerService通过继承BpInterface模板类间接继承了?IMediaPlayerService接口类,其实BpInterface类是一个有两个父类的多重继承子类,另一个父类是?BpRefbase(frameworks\base\include\utils\Binder.h)。remote()就是继承自BpRefBase?类的一个成员函数,该函数返回BpRefBase类中定义的一个私有属性mRemote。mRemote是对IBinder接口类的子类BpBinder?的一个对象的引用(参考前面的类关系图)。transact()函数在IBinder接口类中定义(frameworks\base\include?\utils\Binder.h),并在BpBinder类中实现(frameworks\base\include\utils?\BpBinder.h、frameworks\base\libs\utils\BpBinder.cpp)。在transact()函数中将调用?IPCThreadState类的transact()函数,并进而通过Lniux内核中的android共享内存驱动来实现进程间通信。不过这些细节这里就不多说了。在这里BpBinder类对象是一个关键,是实现Binder代理的核心之一。BpBinder类可以看成是一个通信handle(类似于网络编程中的socket),用于实现进程间通信。接下来需要研究的是这个BpBinder类对象(即mRemote成员变量的值)是从哪里来的。
????回过头来BpMediaPlayerService的构造函数(看前面的代码)。该构造函数的参数是一个IBinder对象的引用。mRemote的值就是在这里传进来的这个对象。那么这个对象又是怎么来的呢?要搞清楚这一点就需要找到创建BpMediaPlayerService类的实例的代码,这个代码就就跟在该类的定义代码的下面。继续看IMediaPlayerService.cpp文件,在BpMediaPlayerService类定义的后面,是下面这样一行代码:


????IMPLEMENT_META_INTERFACE(MediaPlayerService,?"android.hardware.IMediaPlayerService");


????这行代码调用了一个宏定义IMPLEMENT_META_INTERFACE()。这个宏定义与前面提到过的?DECLARE_META_INTERFACE()相呼应。看名字就知道,IMPLEMENT_META_INTERFACE()宏是对?DECLARE_META_INTERFACE()所定义的成员函数的具体实现。这个宏的第一个参数与DECLARE_META_INTERFACE()?的参数需完全一样,第二参数是接口的描述字符串(这个字符串前面也已经讲到过了)。描述字符串不重要,重要的是宏里面定义的一个静态成员函数?asInterface()。BpMediaPlayerService的类实例是在IMediaPlayerService的静态成员函数?asInterface()中创建的,在IInterface.h中定义了一个内联函数interface_cast(),对这个成员函数进行了封装。通过看代码容易知道,BpMediaPlayerService的构造函数的参数是通过interface_cast()的参数传进来的。
????好,下面就该看看这个interface_cast()是在哪里调用的,它的参数到底是什么。找到frameworks\base\media?\libmedia\mediaplayer.cpp文件,其中的MediaPlayer::getMediaPlayerService()的实现代码:

const?sp&?MediaPlayer::getMediaPlayerService()
{
????Mutex::Autolock?_l(sServiceLock);
????if?(sMediaPlayerService.get()?==?0)?{
????????sp?sm?=?defaultServiceManager();
????????sp?binder;
????????do?{
????????????binder?=?sm->getService(String16("media.player"));
????????????if?(binder?!=?0)
????????????????break;
????????????LOGW("MediaPlayerService?not?published,?waiting...");
????????????usleep(500000);?//?0.5?s
????????}?while(true);
????????if?(sDeathNotifier?==?NULL)?{
????????????sDeathNotifier?=?new?DeathNotifier();
????????}
????????binder->linkToDeath(sDeathNotifier);
????????sMediaPlayerService?=?interface_cast(binder);
????}
????LOGE_IF(sMediaPlayerService==0,?"no?MediaPlayerService!?");
????return?sMediaPlayerService;
}

????看一下上面这段代码中的红色字体部分。结合前面的分析,可知BpBinder类的对象实例是从android的服务管理器的getService()函数中获取,进一步追进去,会发现下面这样一段代码:


{
????????Parcel?data,?reply;
????????data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
????????data.writeString16(name);
????????remote()->transact(CHECK_SERVICE_TRANSACTION,?data,?&reply);
????????return?reply.readStrongBinder();
}


????Android的服务管理器是一个单独的进程,也向外提供接口。这段代码的含义,是通过Android的服务管理器的接口代理,请求调用服务管理器的?checkService()接口函数,查找指定的服务(上面就是查找media.player服务),查找成功后返回一个BpBinder类的对象实例,用于供IMediaPlayerService代理使用。这个对象BpBinder是在Parcel::readStrongBinder()函数里面创建的。那么到底是怎么创建出来的呢?在这里没有必要追到ServiceManager的实现代码里去,毕竟我们只是想知道BpBinder的对象是如何创建的,我们可以换一个例子来看。回到前面的BpMediaPlayerService::create()函数的实现,是不是很眼熟。没错,在那个函数里也创建了一个BpBinder类对象,那个对象是是给IMediaPlayer接口代理使用的。虽然接口不同,但是创建原理是一样的。我们继续,下面该到binder的另一个类——实现类的代码了。

(3)?BnMediaPlayerService代码分析
????BnMediaPlayerService类的定义在文件frameworks\base\include\media?\IMediaPlayService.h,实现则与BpMediaPlayerService一样是在文件frameworks\base\media?\libmidia\IMediaPlayerService.cpp中。类定义的代码如下:

class?BnMediaPlayerService:?public?BnInterface
{
public:
????virtual?status_t????onTransact(?uint32_t?code,
????????????????????????????????????const?Parcel&?data,
????????????????????????????????????Parcel*?reply,
????????????????????????????????????uint32_t?flags?=?0);
};

????这个类继承自BnInterface模板类,约束类型为IMediaPlayerService。看一下BnInterface模板类的定义(IInterface.h)就可以知道,BnMediaPlayerService间接继承了IMediaPlayerService接口类。不过?BnInterface类并没有实现IMediaPlayerService所定义的6个接口函数,因此BnInterface还是一个纯虚类。这些接口需要在BnMediaPlayerService的子类中真正实现,这个子类就是MediaPlayerService(frameworks\base?\media\libmidiaservice\MediaPlayerService.h,frameworks\base\media?\libmidiaservice\MediaPlayerService.cpp)。在BnMediaPlayerService的成员函数?onTransact()中,需要调用这6个接口函数。BnMediaPlayerService中主要就是定义并实现了onTransact()函数。当在代理那边调用了transact()函数后,这边的onTransact()函数就会被调用。BnMediaPlayerService的实现代码如下:

#define?CHECK_INTERFACE(interface,?data,?reply)?\
????????do?{?if?(!data.enforceInterface(interface::getInterfaceDescriptor()))?{?\
????????????LOGW("Call?incorrectly?routed?to?"?#interface);?\
????????????return?PERMISSION_DENIED;?\
????????}?}?while?(0)

status_t?BnMediaPlayerService::onTransact(
????uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags)
{
????switch(code)?{
????????case?CREATE_URL:?{
????????????CHECK_INTERFACE(IMediaPlayerService,?data,?reply);
????????????pid_t?pid?=?data.readInt32();
????????????sp?client?=?interface_cast(data.readStrongBinder());
????????????const?char*?url?=?data.readCString();
????????????sp?player?=?create(pid,?client,?url);
????????????reply->writeStrongBinder(player->asBinder());
????????????return?NO_ERROR;
????????}?break;
????????case?CREATE_FD:?{
????????????CHECK_INTERFACE(IMediaPlayerService,?data,?reply);
????????????pid_t?pid?=?data.readInt32();
????????????sp?client?=?interface_cast(data.readStrongBinder());
????????????int?fd?=?dup(data.readFileDescriptor());
????????????int64_t?offset?=?data.readInt64();
????????????int64_t?length?=?data.readInt64();
????????????sp?player?=?create(pid,?client,?fd,?offset,?length);
????????????reply->writeStrongBinder(player->asBinder());
????????????return?NO_ERROR;
????????}?break;
????????case?DECODE_URL:?{
????????????CHECK_INTERFACE(IMediaPlayerService,?data,?reply);
????????????const?char*?url?=?data.readCString();
????????????uint32_t?sampleRate;
????????????int?numChannels;
????????????int?format;
????????????sp?player?=?decode(url,?&sampleRate,?&numChannels,?&format);
????????????reply->writeInt32(sampleRate);
????????????reply->writeInt32(numChannels);
????????????reply->writeInt32(format);
????????????reply->writeStrongBinder(player->asBinder());
????????????return?NO_ERROR;
????????}?break;
????????case?DECODE_FD:?{
????????????CHECK_INTERFACE(IMediaPlayerService,?data,?reply);
????????????int?fd?=?dup(data.readFileDescriptor());
????????????int64_t?offset?=?data.readInt64();
????????????int64_t?length?=?data.readInt64();
????????????uint32_t?sampleRate;
????????????int?numChannels;
????????????int?format;
????????????sp?player?=?decode(fd,?offset,?length,?&sampleRate,?&numChannels,?&format);
????????????reply->writeInt32(sampleRate);
????????????reply->writeInt32(numChannels);
????????????reply->writeInt32(format);
????????????reply->writeStrongBinder(player->asBinder());
????????????return?NO_ERROR;
????????}?break;
????????case?CREATE_MEDIA_RECORDER:?{
????????????CHECK_INTERFACE(IMediaPlayerService,?data,?reply);
????????????pid_t?pid?=?data.readInt32();
????????????sp?recorder?=?createMediaRecorder(pid);
????????????reply->writeStrongBinder(recorder->asBinder());
????????????return?NO_ERROR;
????????}?break;
????????case?CREATE_METADATA_RETRIEVER:?{
????????????CHECK_INTERFACE(IMediaPlayerService,?data,?reply);
????????????pid_t?pid?=?data.readInt32();
????????????sp?retriever?=?createMetadataRetriever(pid);
????????????reply->writeStrongBinder(retriever->asBinder());
????????????return?NO_ERROR;
????????}?break;
????????default:
????????????return?BBinder::onTransact(code,?data,?reply,?flags);
????}
}

????首先是一个宏定义CHECK_INTERFACE(),这个宏定义的作用是检查接口的描述字符串,这个前面也提到过,不需细说。然后就是?onTrasact()函数的实现。这个函数的结构也很简单,就是根据参数code的值分别执行不同的功能调用。code的取值就是前面提到过的接口功能代码。函数的参数除了code,还包括Parcel类的两个对象data和reply,分别用于传送输入参数和返回数据,与transact()函数的参数相对应。还有一个参数flag在这里用不上,不讨论。对应我们前面所选择的接口函数的例子create(url),看看这边对应的实现:

case?CREATE_URL:?{
?????CHECK_INTERFACE(IMediaPlayerService,?data,?reply);
?????pid_t?pid?=?data.readInt32();
?????sp?client?=?interface_cast(data.readStrongBinder());
?????const?char*?url?=?data.readCString();
?????sp?player?=?create(pid,?client,?url);
?????reply->writeStrongBinder(player->asBinder());
?????return?NO_ERROR;
}

????首先是从data对象中依次取出各项输入参数,然后调用接口函数create()(将在子类MediaPlayerService中实现),最后向reply中写入返回数据。这个函数返回后,代理那边的transact()也会跟着返回。
????那么onTransact()函数是怎么被调用的呢?通过查看BnInterface模板类的定义可以看到,这个类也是一个多重继承类,另一个父类是?BBinder(frameworks\base\include\utils\Binder.h,frameworks\base\libs?\utils\Binder.cpp)。BBinder类继承自IBinder,也实现了transact()函数,在这个函数中调用?onTransact()函数。而BBinder对象的transact()函数则是在IPCThreadState类的?executeCommand()成员函数中调用的。这已经涉及到较底层的实现,在这里不再多说。
????上面这部分代码还与前面提到过的BpBinder对象的创建有关系。看其中的红色字体部分,通过create()函数调用会创建一个?IMediaPlayer接口类的子类的对象,这个对象其实是MediaPlayerService::Client类(可以看一下?MediaPlayerService的定义)的对象实例,而MediaPlayerService::Client类是继承自?BnMediaPlayer类的,与BnMediaPlayerService类类似,BnMediaPlayer其实也是一个binder实现类(是?BBinder的子类,进而也是IBinder的子类)。在上述代码中,通过Parcel的writeStrongBinder()函数将这个对象写入?reply,而在代理侧,通过Parcel的readStrongBinder()函数读取则可以得到一个BpBinder的对象。至于类的具体创建过程已经封装在Parcel类的定义中,这里就不再多说了。

(4)?接口功能的真正实现
????到这里两个binder类就已经定义完了,下面就是IMediaPlayerService接口函数的真正实现。前面已经说过这些函数在类?MediaPlayerService中实现。这个类继承自BnMediaPlayerService,也间接地继承了?IMediaPlayerService接口类定义的6个功能函数,只需要按照正常方式实现这6个功能函数即可,当然为了实现这6个函数就需要其它一大堆的东西,不过这些具体的实现方法已经与binder机制无关,不再多说。
???在MediaPlayerService类中定义了一个静态函数instantiate(),在这个函数中创建MediaPlayerService的对象实例,并将这个对象注册到服务管理器中。这样需要使用的时候就可以从服务管理器获取IMediaPlayerService的代理对象。这个?instantiate()是在MediaServer程序的main()函数中调用的。?
void?MediaPlayerService::instantiate()?{
????defaultServiceManager()->addService(
????????????String16("media.player"),?new?MediaPlayerService());
}



(三)?总结一下
????说了这么多,总结一下。下图是binder机制的层次模型。


binder frame
????如果一个服务需要通过binder机制对外提供跨进程的接口,需要做下面这些事情。
????(1)?第一步,需要为这个接口定义一个继承自IInterface的接口类,假设叫做IMyService。
????(2)?第二步,需要定义两个binder类,其中一个是代理类BpMyService,需继承自BpInterface;另一个是实现类BnMyService,需继承自BnInterface。
????(3)?第三步,定义BnMyService的子类,这个子类可以是任何名字,比如就叫MyService,在其中真正实现接口所提供的各个函数。
????(4)?第四步,创建MyService的实例,注册到服务管理器(如IMediaPlayerService),也可以在其它接口的函数中创建(如上面的IMediaPlayer)。

热点排行