赞
踩
AudioPolicyService(APS)和AudioFlinger(AF)是Android音频系统的两大服务,今天主要梳理一下AudioPolicyService的启动过程,
注:文章代码为Android P版本代码
一、main_audioserver.cpp 启动音频两大服务:
AudioPolicyService的启动主要位于main_audioserver.cpp当中,它由Android 系统启动 init.rc中去执行,
代码位置:/frameworks/av/media/audioserver/main_audioserver.cpp
int main(int argc __unused, char **argv){
android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
**在main函数当中依次调用AF和APS的instantiate函数**
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
// AAudioService should only be used in OC-MR1 and later.
// And only enable the AAudioService if the system MMAP policy explicitly allows it.
}
}
这里有个问题为什么会先去启动AF而不是APS呢? 其实是因为APS的启动过程中需要用到AF,因为之前的文章有提到过AF是音频系统的引擎,真正去做事情的就是它,
接下来看看
AudioPolicyService::instantiate();都做了些什么,
注意APS其实是继承的BinderServer类,所以会调用到BinderService::instantiate(),
BinderService:
static void instantiate() { publish(); }
可以看到publish 内部的实现,其实就是一个Android通用的启动服务的方式,通过getServiceName函数去获取服务的名称:
1.SERVICE::getServiceName():
因为BinderService是类模板,又因为AudioPolicyService::instantiate(),所以此处的SERVICE就是类AudioPolicyService类。
因此SERVICE::getServiceName()实际上调用了AudioPolicyService类中的成员函数getServiceName.
2、new Service() -------->new AudioPolicyService 接下来就开始到APS的内容了:
由于sm是sp强引用类型的指针,所以在第一次调用AudioPolicyService模块时,会调用AudioPolicyService::onFirstRef(),从上面的代码图中可以看到再onFristRef函数中主要做了如下三件事:
二、new APS对象:
1、创建AudioCommandThread对象,可以理解为是用于去执行音频播放过程中的一些指令的thread,比如播放声音的过程中调节音量等操作,上层用AudioManager 通过APS的这个Thread 最终 去调用APM的接口做对应的处理
为什么这里会创建三个AudioCommand对象呢?个人理解是因为音频系统比较复杂,所以进行了分类(ApmTone、ApmAudio、ApmOutput),方便去做管理,
可以大致看一下这个Thread 的代码,了解一下,后面可以单独开篇小文章,在深入研究一下里面的内容
提问:那么系统是如何处理这些command的呢?比如同时刻有很多command需要执行,先执行哪一个command呢?可以研究一下
2、在创建完AudioThread对象后,接着会实例化AudioPolicyClient及createAudioPolicyManager:
看看AudioPolicyManager:
可以看到APM的构造函数里主要做两件事情:
1、loadConfig()
loadConfig 主要是解析APM需要的一些参数,将这些参数保存到Audioconfig中
通过**serializer.deserialize()**去解析 audio_policy_configuration.xml 保存到config中
xml配置文件如下:
module name:支持“primary”、“A2DP”、“remote_submix”和“USB”。模块名称和相应音频驱动程序应编译到audio.primary.$(variant).so 中,后续就是通过APM的initialize(),去根据解析到的module得到对应的 hal 库。
devicePorts: 包含可从此模块访问的所有输入和输出设备(包括永久连接的设备和可移除设备)的设备描述符列表。
mixPorts: 包含由音频 HAL 提供的所有输出流和输入流的列表。每个 mixPort 实例都可被视为传输到 Android AudioService 的物理音频流。
routes: 定义输入和输出设备之间或音频流和设备之间可能存在的连接的列表。
对于手机来说,应用相对较多的output有primary output、fast output 、deepbuffer output及 compressed_offload等:
primary output:主输出流设备,用于铃声类声音输出,对应着标识为 AUDIO_OUTPUT_FLAG_PRIMARY 的音频流和一个 MixerThread 回放线程实例,这个MixerThread 后面会提到,可以先有一个印象
fast output:低延迟输出流设备,用于按键音、游戏背景音等对时延要求高的声音输出,对应着标识为 AUDIO_OUTPUT_FLAG_FAST 的音频流和一个 MixerThread 回放线程实例
deepbuffer output:音乐音轨输出流设备,用于音乐等对时延要求不高的声音输出,对应着标识为 AUDIO_OUTPUT_FLAG_DEEP_BUFFER 的音频流和一个 MixerThread 回放线程实例
compressed_offload:硬解输出流设备,用于需要硬件解码的数据输出,对应着标识为 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 的音频流和一个 OffloadThread 回放线程实例,有在上面的图中标识,
XML配置文件中的内容大致就介绍这么多了,接下来看看是如何解析的:
这里调用deserializeCollection,先后去解析modules volume配置,这个函数里面又去通过模板依次调用对应的deserialize函数,去依次去解析XML内容
依次解析将配置项保存起来,以便接下来的APM:: initialize去使用,解析配置文件这一块就不详细介绍了,感兴趣的同学可以深入研究下
总结:
本文主要介绍了APS服务启动过程中创建APM去解析AuidoPolicyconfig.xml文件部分,大体就是系统启动通过解析init.rc文件,去调用main_audioserver.cpp文件的main函数,去创建一个APS对象,然后去实例化一个AudioPolicyManager对象,去解析AuidoPolicyconfig.xml,然后在通过APM::initialize()去使用得到的配置参数去初始化;initialize部分下篇在分析;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。