Android Multimedia序列7(框架总结 )

Android Multimedia序列7(框架总结 )---C++中MediaPlayer的C/S架构补充及MediaService介绍

一、前言


(1)C/S模型中的三角关系流程图
(2)MediaPlayerService相关联的类图
(3)MediaPlayerService的产生过程
(4)MediaPlayerService添加服务过程
(5)MediaPlayerService通过BinderDriver和MediaPlayer通信过程

二、C/S模型中的三角关系流程图

上图总结如下几点:

  1. MediaPlayer是客户端,也就是我们说的C/S中的C端。

  2. MediaPlayerService和MediaPlayerService::Client是服务器端。也就是我们说的C/S中的S端。

  3. MediaPlayerService实现IMediaPlayerService定义的业务逻辑,其主要功能是根据MediaPlayer::setDataSource输入的URL调用create函数创建对应的Player。

  4. MediaPlayerService::Client实现IMediaPlayer定义的业务逻辑,其主要功能包括start, stop, pause, resume…,其实现方法是调用MediaPlayerService create的Player中的对应方法来实现具体功能。

此前在第四篇那个图中已经画了个整体,今天再把MediaPlayerService,MediaPlayerService::Client,MediaPlayer放大看下他们在实际业务中交互关系。

三、MediaPlayerService相关联的类图

 

以上类关系图,总结如下几点:

  1. 在一个BnXXX或BpXXX都派生于两个类,具体情况如下:
    class BpXXX : public IXXX, public BpRefBase
    class BnXXX : public IXXX, public BBinder

  2. BpXXX和BnXXX都派生于IXXX,哪IXXX又是做什么的呢?
    这里可以理解为,定义业务逻辑,我们此前分析IMediaPlayerClient在作用时,也说过。但在BpXXX与BnXXX中的实现方式不同:

    在BpXXX中,把对应的binder_transaction_data打包之后通过BpRefBase中的mRemote(BpBinder)发送出去,并等待结果
    在BnXXX中,实现对应的业务逻辑,通过调用BnXXX派生类中的方法来实现,如MediaPlayerService::Client

  3. 从上图可以看出,IBinder是用来进行进程间通信用的。
    BpRefBase中有一个mRemote(BpBinder)用来与Binder驱动交互用的。
    Binder是用来从Binder驱动中接收相关请求,并进行相关处理的。

四、MediaPlayerService的产生过程

在了解MediaPlayerService之前,先了解下IMediaPlayerService.cpp,
6.0源码中是在frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp中:





可以看出这里定义一些常规业务相关,接下来开始了解MediaPlayerService
先找到入口,在frameworks/base/media/mediaserver/main_mediaserver.cpp



首先看下defaultServiceManager函数,如下:



用的是一个单例,每个进程只需要一个BpServiceManager代理,ProcessState::self()->getContextObject(NULL),接下来看下getContextObject(NULL)函数,接着看看ProcessState::self()->getContextObject(NULL)。


以上代码总结为:根据传入的句柄handle值为0,表示ServiceManager,new一个BpBinder所以现在相当于:
gDefaultServiceManager = interface_cast(new BpBinder(0));
然后我们看看interface_cast做了什么操作?
位于frameworks/base/include/binder/IInterface.h中,有如下代码:



继续跟到IServiceManager里面去:
位于frameworks/base/include/binder/IServiceManager.h中,有如下代码:


总结上述代码:根据句柄handle(0)创建一个new BpBinder(0),根据这个BpBinder创建了一个BpServiceManager代理。
下面来看看BpServiceManager代理:
在这里插入图片描述
这里BpInterface是一个模板类,表示这里BpServiceManager同时继承与BpInterface和IServiceManager类
在这里插入图片描述
调用了基类BpInterface构造函数:
在这里插入图片描述
MediaPlayerService::instantiate();//实例化MediaPlayerService
frameworks/base/media/libmediaplayerservice/MediaPlayerService.cpp

在这里插入图片描述
defaultServiceManager()返回的是刚创建的BpServiceManager,调用add函数。
BpMediaPlayService作为服务代理端,那么BnMediaPlayerService一定是实现端,MediaPlayerService继承于BnMediaPlayerService,实现了真正的业务函数,用于处理客户端传递的信息。
 

五、MediaPlayerService添加服务过程

来看看BpServiceManager的addService()函数:



这里remote()就是前面创建的BpBinder(0)对象。



接着看一个有意思的名字,talkWithDriver的实现,顾名思义,和driver谈话:


IPCThreadState::joinThreadPool(), ProcessState::self()->startThreadPool()
进入线程循环talkWithDriver 等待客户端Client请求,从Binder读取命令请求进行处理。

到现在为止MediaPlayerService的服务端已经向服务总管ServiceManager注册了。

六、MediaPlayerService通过BinderDriver和MediaPlayer通信过程

下面看看客户端是如何获得服务的代理并和服务端通信的。
以MediaPlayer的业务函数decode解析播放一个网络视频的url为例
在这里插入图片描述
这里主要分析getMediaPlayerService,客户端是如何向ServiceManager总管查询服务并获得代理的。


首先获得BpServiceManager的代理,然后调用getService()函数向服务总管ServiceManager查询名叫String16(“media.player”)的服务。
位于frameworks/base/libs/binder/IServiceManager.cpp中:


这里首先将请求打包成Parcel各式,然后调用remote()->transact()函数,
前面我们分析过BpServiceManager::remote()返回 的就是前面new BpBinder(0)对应句柄为ServiceManager。
继续去BpBinder中寻找实现代码:
在frameworks/base/libs/binder/BpBinder.cpp中
在这里插入图片描述

最后调用的IPCThreadState的transact()函数,IPCThreadState是专门提供通过Binder进程间通信的接口的。

在这里插入图片描述
在这一步,首先通过writeTransactionData函数来填充mOut结构体,mOut里面内容为:
在这里插入图片描述
这里binder_transaction_data tr内容为:
在这里插入图片描述
tr.data内容为:
在这里插入图片描述
这个waitForResponse()函数是等待ProcessState返回信息:



最后返回的是:return reply.readStrongBinder();进入到Parcel的readStrongBinder()函数



这里flat->type是BINDER_TYPE_HANDLE,所以调用ProcessState::getStrongProxyForHandle()函数



这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄,这个ProcessState根据这个句柄new 了一个BpBinder,并将其保存起来,这样下次需要从ServiceManager请求获取到相同句柄的时候就可以直接返回了。

最后根据这个返回的BpBinder获得MediaPlayerService的代理:
sMediaPlayerService = interface_cast(binder);根据前面ServiceManager一样,最后调用的是IMediaPlayerService的asInterface()宏函数


这样就获得了一个代理BpMediaPlayerService对象,它的remote()为BpBinder(handle),这个handle就是向服务总管ServiceManager查询到的MediaPlayerService对应的Binder句柄。

七、总结

实际业务中,如MediaPlayer::setDataSource返回时,会创建一个与MediaPlayerService::Client对应的BpMediaPlayer,用于获取MediaPlayerService::Client的各项功能。

MediaPlayer又是如何找到MediaPlayerService::Client的呢?
只有MediaPlayerService才向ServiceManager进行了注册,所以MediaPlayer必须先获取BpMediaPlayerService,然后通过BpMediaService的管理功能create,来创建一个MediaPlayerService::Client.

为什么不直接定义一个MediaPlayer向ServiceManager注册呢?
MediaPlayerService包含的功能不只是Client, 还有AudioOutput,AudioCache,MediaConfigClient功能。MediaPlayerService就是一个媒体服务的窗口(Driver有点类似一个场地,在这个场地,沟通好信息),MediaPlayerService把生意谈好,合同签回来,再根据合同上的要求,安排不同的开人发员去做。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值