音视频 四 看书的笔记 MediaPlayerService

Binder机制看这里 Binde机智 这是一个分割符 Binder机智+ 分割(goutou) Binder机制++

MediaPlayerService多媒体框架中一个非常重要的服务。MediaPlayerService 我原称之为链接之王


图片来源

  • MediaPlayer 是客户端 C/S 中的C
  • MediaPlayerService MediaPlayerService::Client 是服务端 C/S中的S
  • MediaPlayerService 实现 IMediaPlayerService 定义的业务逻辑,主要功能就是MediaPlayer::setDataSource 调用create创建对应的player
  • MediaPlayerService::Client 实现IMediaPlayer 定义业务逻辑 start stop pause...; 是通过MediaPlayerService create的player中对应的方法 实现具体功能。
  • 通过Transact 函数 向 IBinder 发出调用, 通过 onTransact 函数 使远程对象 相应接收到的调用

Binder通信时,需要通过IBinder接口转化具体的实体对象,就会产生可多可多类。

  • 看上图Bp/Bn开头的类。他们都派生自两个类

    · Bp??? : I??? : BpRefBase

    · Bn??? : I??? : BBinder

    · 都派生自 I??? 有嘛不同?

    复制代码
    -  Bp 把对应的 binder_transaction_data 打包,通过BpRefBase的mRemote(BpBinder)发送出去,等待结果
    -  Bn 实现对应的业务逻辑,通过调用Bn派生类中的方法来实现,例如:MediaPlayerService::Client.继承了 BnMediaPlayer。
  • BpRefBase 中 remote函数用来与Binder驱动交互

  • Binder是用来从Binder驱动中接收相关请求并进行相关处理的

  • BpBinder 和 BinderDriver进行互通

    复制代码
    -   BBinder与BpBinder这两者容易混淆。其实这两者是很好区分
    -  对于service来说继承了BBinder(BnInterface)因为BBinder有onTransact消息处理函数
    -  对于与service通信的client来说需要继承BpBinder(BpInterface),因为BpBinder有消息传递函数transcat。
    以cameraService的client为例
    Camera.cpp中getCameraService函数取得远程CameraService的IBinder对象
    然后通过 mCameraService = interface_cast<ICameraService>(binder);
    进行重构得到了BpCameraService对象。而BpCameraService继承了BpInterface。
    cameraService:
        defaultServiceManager()->addService(String16("media.camera"), new CameraService()); 传入了BBinder。
       IPC传递的过程中IBinder指针不可缺少,这个指针对一个进程来说就像是socket的ID一样,唯一的。
       所以不管这个IBinder是BBinder还是BpBinder, 他们的都是在重构BpBinder或者BBinder的时候把IBinder作为参数传入。
    此段文字来自https://blog.csdn.net/RationalGo/article/details/23845085

看MediaPlayerService 先看 MediaPlayerService.cpp

复制代码
class IMediaPlayerService : public IInterface
{
    public:
    DECLARE_META_INTERFACE(MediaPlayerService);
    virtual sp < IMediaPlayer > create (pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) = 0;
    virtual sp < IMediaPlayer > create (pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
    virtual sp < IMemory > decode (const char * url, uint32_t *pSampleRate, int* pNumChannels) = 0;
    virtual sp < IMemory > decode (int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels) = 0;
};
class BnMediaPlayerService : public BnInterface<IMediaPlayerService>
{
    public:
    virtual status_tonTransact (uint32_t code,
    const Parcel & data,
    Parcel * reply,
    uint32_t flags = 0);
};

可以看到这里定义了一些常规播放控制接口。

找到入口

复制代码
int main(int argc __unused, char** argv)
{
    signal(SIGPIPE, SIG_IGN);
    char value[PROPERTY_VALUE_MAX];
    //...
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    //...
    AudioFlinger::instantiate();//AudioFlinger
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();//AudioPolicyService
    SoundTriggerHwService::instantiate();
    registerExtensions();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
	//...
}

找 defaultServiceManager()

defaultServiceManager返回的实际是一个BpServiceManger类实例,并调用add函数;

B p MediaPlayService 作为服务代理端,那么 B n MediaPlayerService 一定是实现端; (注意一个Bp 一个 Bn)

MediaPlayerService 继承自 BnMediaPlayerService,实现了真正的业务函数。

此处省略一堆

最终BpServiceManager 的 addService 的 结果就是 MediaPlayerService的服务器端 已经再ServiceManager注册了。

BinderDriver和MediaPlayer通信的过程

客户端如何获得服务的代理并和服务器端通信?

MediaPlayer为例:

MediaPlayer::decode 方法中:getMediaPlayerService(),客户端向ServiceManager 查询服务并获得代理BpServiceManager,然后调用getService向ServiceManager 查询名叫 String16("media.palyer")的服务;

getService方法内,先将请求打包成Parcel,然后调用remote -> transact函数,最终调用的是IPCThreadStae的transact函数。

每个线程都有一个IPCThreadState ,IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读写,请求处理框架。

IPCThreadState再构造的时候获取进程的ProcessState并记录再自己的成员变量中。

最终调用ProcessState::getStrongProxyForHandle函数。

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

根据返回的BpBinder 获得 MediaPlayerService的代理。

效用IMediaPlayerService的asInterface宏函数,这样就获得了一个代理BpMediaPlayerService对象,它的remote为BpBinder(handle),这个handle就是向ServiceManager查询到的MediaPlayerService对应的Binder句柄。

总结:

  • MediaPlayer::setDataSource 会创建一个 MediaPlayerService::Client对应的BpMediaPlayer,用于获取MediaPlayerService::Client的各项功能。
  • 只有MediaPlayerService向ServiceManager进行注册,MediaPlayer才能找到MediaPlayerService::Client; SO MediaPlayer必须先获取BpMediaPlayerService,然后通过BpMediaPlayerService 创建一个MediaPlayerService::Client。

可以去这里看书 Android 音视频开发

我看的书是 《Android 音视频开发》何俊林 著 公司被别人垫显示器的,不知道放了几年没人看的旧书,也是新书(木有人翻看过),😈

相关推荐
lwewan1 小时前
26考研——栈、队列和数组_数组和特殊矩阵(3)
数据结构·笔记·考研·算法
wei3872452322 小时前
java笔记02
java·开发语言·笔记
一笑的小酒馆2 小时前
Android在ksp中简单使用Room
android
要天天开心啊2 小时前
MyBatis第二天笔记
笔记·tomcat·mybatis
枫林血舞3 小时前
python笔记之函数
笔记·python
meimeiqian3 小时前
flutter android端抓包工具
android·flutter
Android技术之家3 小时前
谷歌决定终止开源Android以及对开发者的影响
android·开源
悄悄敲敲敲4 小时前
C++第13届蓝桥杯省b组习题笔记
c++·笔记·算法·蓝桥杯
每次的天空5 小时前
Android Jetpack学习总结(源码级理解)
android·学习·android jetpack
木子庆五5 小时前
Android设计模式之代理模式
android·设计模式·代理模式