MediaPlayer(三)--C++|MediaPlayer(三)--C++ binder框架

在看这篇文章前,建议先阅读
C++ Binder机制学习(转载)
只是介绍c++层binder通讯的使用流程,并未涉及binder原理机制
结构框架 【MediaPlayer(三)--C++|MediaPlayer(三)--C++ binder框架】上一篇文章MediaPlayer--MediaPlayer基本框架没有将C++的mediaplayer binder通讯展开,这篇文章主要展开这一部分。
大概画了下C++ MediaPlayer的uml图,不是很满意,请高手指教

MediaPlayer(三)--C++|MediaPlayer(三)--C++ binder框架
文章图片
MediaPlayerBinder.png
这里面主要的client和service实现类是以下两个文件(Android8.1 路径)
frameworks/av/media/libmedia/mediaplayer.cpp
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
这里面涉及了三对IPC的通讯,即
IMediaPlayerClient
IMediaPlayerService
IMediaPlayer
其中 IMediaPlayerService , IMediaPlayer 的服务端在MediaPlayerService.cpp, 客户端在mediaplayer.cpp。IMediaPlayerClient 的服务端在mediaplayer.cpp, 客户端在MediaPlayerService.cpp, 这是MediaPlayerService回调mediaplayer使用的。 IMediaPlayerService会创建IMediaPlayer的实例
流程 MediaPlayer 同MediaPlayerService通讯 是通过变量 sp mPlayer, mPlayer赋值是在setDataSource

status_t MediaPlayer::setDataSource( const sp &httpService, const char *url, const KeyedVector *headers) { ALOGV("setDataSource(%s)", url); status_t err = BAD_VALUE; if (url != NULL) { const sp service(getMediaPlayerService()); if (service != 0) { sp player(service->create(this, mAudioSessionId)); if ((NO_ERROR != doSetRetransmitEndpoint(player)) || (NO_ERROR != player->setDataSource(httpService, url, headers))) { player.clear(); } err = attachNewPlayer(player); } } return err; }

关于创建mPlayer这块主要分3步:
1 const sp service(getMediaPlayerService()); 这一步其实是获取了BpMediaPlayerService
2 sp player(service->create(this, mAudioSessionId)); 这一步是通过BpMediaPlayerService 的create方法返回了BpMediaPlayer
3 attachNewPlayer 将player赋值给mPlayer
看一下 1 和 2 的两个函数的实现
/*static*/const sp IMediaDeathNotifier::getMediaPlayerService() { ALOGV("getMediaPlayerService"); Mutex::Autolock _l(sServiceLock); if (sMediaPlayerService == 0) { sp sm = defaultServiceManager(); sp binder; do { binder = sm->getService(String16("media.player")); if (binder != 0) { break; } ALOGW("Media player service not published, waiting..."); usleep(500000); // 0.5 s } while (true); if (sDeathNotifier == NULL) { sDeathNotifier = new DeathNotifier(); } binder->linkToDeath(sDeathNotifier); sMediaPlayerService = interface_cast(binder); } ALOGE_IF(sMediaPlayerService == 0, "no media player service!?"); return sMediaPlayerService; }

这里简单讲一下
1 sp sm = defaultServiceManager(); 获取到ServiceManager
2 sm->getService(String16("media.player")); 通过ServiceManager获取到 MediaPlayerService,MediaPlayerService在android初始化时就向ServiceManager注册了
3 interface_cast(binder); 这里实际是new BpMediaPlayerService(binder)
class BpMediaPlayerService: public BpInterface { public: virtual sp create( const sp& 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(reply.readStrongBinder()); }

create方法做了两件事
1 remote()->transact(CREATE, data, &reply) 通过 IMediaPlayerService binder通讯,将IMediaPlayerClient的IBinder传给了MediaPlayerService, MediaPlayerServcie后面可以通过IMediaPlayerClient 回调MediaPlayer
2 interface_cast(reply.readStrongBinder()); 上一步binder通讯MeidaPlayer的binder对象, 同过binder是创建了 BpMediaPlayer 实例
Binder可分为实名binder和匿名binder, 实名binder是在ServiceManager注册的servce,可以通过ServiceManager的getService获取,而匿名binder没在ServiceManager中注册,没法通过ServiceManager获取,需要想办法获取service的binder实例才能通讯。对于MediaPlayer的结构,MediaPlayerServcie 属于实名binder, IMediaPlayer 和 IMediaPlayerClient 属于匿名binder。MediaPlayer 通过 MediaPlayerServcie实名binder, 将IMediaPlayerClient binder 传递给MediaPlayerServcie,同时MediaPlayerServcie将IMediaPlayer binder返回MediaPlayer。 这样MediaPlayer 就能通过 IMediaPlayer 调用 MediaPlayerServcie::client接口, MediaPlayerServcie可以通过IMediaPlayerClient调用MediaPlayer接口

MediaPlayer(三)--C++|MediaPlayer(三)--C++ binder框架
文章图片
MediaPlayerBinderSeque.png

    推荐阅读