在看这篇文章前,建议先阅读
C++ Binder机制学习(转载)
只是介绍c++层binder通讯的使用流程,并未涉及binder原理机制
结构框架
上一篇文章MediaPlayer--MediaPlayer基本框架没有将C++的mediaplayer binder通讯展开,这篇文章主要展开这一部分。
大概画了下C++ MediaPlayer的uml图,不是很满意,请高手指教
这里面主要的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
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
2 sp
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
2 sm->getService(String16("media.player")); 通过ServiceManager获取到 MediaPlayerService,MediaPlayerService在android初始化时就向ServiceManager注册了
3 interface_cast
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
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接口