通过BinderDriver和MediaPlayer通信的过程
下面看看客户端是如何获得服务的代理并和服务器端通信的。以MediaPlayer的业务函数解码解析播放一个网络视频的URL为例
这里主要分析getMediaPlayerService
,即客户端是如何向ServiceManager总管查询服务并获得代理的
上图先获得BpServiceManager
的代理,然后调用getService
函数向服务总管ServiceManager查询名叫String16("media.player")
的服务,其处于frameworks/base/libs/binder/IServiceManager.cpp
中(仅展示部分代码)
这里首先将请求打包成Parcel
格式,然后调用remote->transact
函数,前面我们分析过BpServiceManager::remote返回的就是new BpBinder(0),对应的句柄为ServiceManager,在frameworks/base/libs/binder/BpBinder.cpp
中可以找到实现代码
最后调用IPCThreadState
的transact
函数,在Android中ProcessState
是客户端和服务器端公共的部分,作为Binder通信的基础,ProcessState是一个singleton
类,每个进程只有一个对象,这个对象负责打开Binder驱动,建立线程池,让其进程里面的所有线程都能通过Binder通信
与之相关的是IPCThreadState,每个线程都有一个IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读取、写入和请求处理框架。IPCThreadState在构造的时候获取进程的ProcessState
并记录在自己的成员变量中
IPCThreadState::transact
中(部分代码)
通过writeTransactionData
函数来填充mOut
结构体,mOut内容如下
tr
内容如下
tr.data
内容如下
waitForResponse
函数是关键
返回的是reply.readStrongBinder()
.在waitForResponse方法中,收到消息以后这个reply不为空,此时进入reply的ipcSetDataReference方法中,这个reply是Parcel对象,调用了Parcel的ipcSetDataReference方法将ServiceManager返回过来的数据设置到parcel对象中。waitForResponse()执行完BR_REPLY
之后,便返回到IPCThreadState::transact()
中;然后返回,到退回到Java层的ServiceManagerProxy.getService
方法时,调用reply的readStrongBinder
方法
这里的flat->type
是BINDER_TYPE_HANDLE
,所以调用ProcessState::getStrongProxyForHandle
函数
这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄
,这个ProcessState根据这个句柄新建了一个BpBinder
,并将其保存起来,这样下次需要从ServiceManager请求获取相同句柄的时候就可以直接返回了
根据这个从getService中返回的BpBinder获得MediaPlayerService
的代理
和前面的ServiceManager一样,调用IMediaPlayerService的asInterface
宏函数,这样就获得了一个代理BpMediaPlayerService
对象,它的remote为BpBinder(handle)
,这个handle就是向服务总管ServiceManager查询到的MediaPlayerServicer对应的Binder句柄
总结
1.在实际业务中,当MediaPlayer::setDataSource返回时,会创建一个与MediaPlayerService::Client对应的BpMediaPlayer
,用于获取MediaPlayerService::Client的各项功能
2.MediaPlayer要想找到MediaPlayerService::Client必须MediaPlayerService向ServiceManager进行注册
才可以,所以MediaPlayer必须先获取BpMediaPlayerService
,然后通过BpMediaPlayerService的管理功能创建一个MediaPlayerService::Client
3.MediaPlayerService包含的功能不仅是Client,还有AudioOutput、AudioCache、MediaConfigClient
功能。MediaPlayerService就是一个媒体服务的窗口(Driver类似一个场地,在场地内沟通好信息),MediaPlayerService把生意谈好,合同签回来,再根据合同上的要求安排不同的开发人员去做
创建播放器
在MediaPlayer的构造函数中,会预先注册一些播放器的Factory
。很多ROM厂商如果要应用自己写的播放器,也需要有一个Factory
通过StagefrightPlayerFactory
创建一个StagefrightPlayer
(高版本中已经没有该播放器了)
通过NuPlayerFactory
可以创建一个NuPlayer
这里没有直接创建一个NuPlayer,而是创建了一个NuPlayerDriver
,实际上是在NuPlayerDriver的构造函数中创建了一个NuPlayer
建立StageFright层交互
前面建立的NuPlayer要和StageFright层进行交互,下图是它们两个的关系
从上图可以看出StagefrightPlayer/StagefrightRecorder以及NuPlayer都属于MediaPlayerService
层,源码libmediaplayerservice
目录如下(没有StagefrightPlayer是因为版本问题)
上面的文件在编译后会生成libmediaplayerservice.so
文件,当要继续处理从MediaPlayer传过来的事件时,就需要到达libstagefright.so
中,如AwesomePlayer、MediaExtractor、MediaMuxer、MediaBuffer、MediaSource、MediaCodec等,可以看出这些都是多媒体框架的核心部分,用于数据解析、解码等
一个数据源会先分离出音视频数据,如果是视频流,通过OMX组件解码,如果是音频流,通过音频解码器解码,如AACDecoder、AC3Decoder等。解码完成后做音视频同步,最终将视频渲染到屏幕上,音频通过音频系统进行播放