Audio policy basic:https://www.cnblogs.com/CoderTian/p/5705742.htmlhtml
Set volume flow:https://blog.csdn.net/axlecho/article/details/78510496java
https://blog.csdn.net/u014702999/article/details/52488803api
audio policy config xml:https://blog.csdn.net/u012188065/article/details/84104275app
AudioPolicy在Android系统中主要负责Audio"策略"相关的问题。它和AudioFlinger一块儿组成了Android Audio系统的两个服务。一个负责管理audio的“路由”,一个负责管理audio“设备”。这两个服务都是在系统启动的过程当中,经过MediaServer来加载的。ui
AudioPolicyService在Android Audio系统中主要完成如下几个任务:this
①管理输入输出设备,包括设备的链接、断开状态,设备的选择和切换等spa
②管理系统的音频策略,好比通话时播放音乐、或者播放音乐时来电话的一系列处理.net
③管理系统的音量线程
④上层的一些音频参数也能够经过AudioPolicyService设置到底层去指针
Audio Policy初始化:
AudioPolicyService是继承自BnAudioPolicyService的,一步步往上推,最终发现它的祖先是RefBase,根据强指针的特性,目标对象在第一次被引用时会调用onFirstRef()。
在第一次被强引用时AudioPolicyService建立了3个AudioCommandThread和AudioPolicyManager。
三个AudioCommandThread线程分别是ApmTone、ApmAudio、ApmOutput
ApmTone用于播放tone音;
ApmAudio用于执行audio命令;
ApmOutput用于执行输出命令;
1.loadconfig
void AudioPolicyManager::loadConfig() { #ifdef USE_XML_AUDIO_POLICY_CONF if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) { #else if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, getConfig()) != NO_ERROR) && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, getConfig()) != NO_ERROR)) { #endif ALOGE("could not load audio policy configuration file, setting defaults"); getConfig().setDefault(); } }
1)若是没有define USE_XML_AUDIO_POLICY_CONF,加载audio_policy.conf配置文件 /system/etc/audio_policy.conf(对于模拟器而言走的是defaultAudioPolicyConfig())
在AudioPolicyManager建立过程当中会经过加载audio_policy.conf配置文件来加载音频设备,Android为每种音频接口定义了对应的硬件抽象层。硬件抽象层代码参考写法
hardware/libhardware/modules/audio
external/bluetooth/bluedroid/audio_a2dp_hw/ |
audio.a2dp.default.so |
hardware/libhardware/modules/audio/ |
audio.primary.default.so |
hardware/libhardware/modules/usbaudio/ |
audio.usb.default.so |
每种音频接口定义了不一样的输入输出,一个接口能够具备多个输入或者输出,每一个输入输出能够支持不一样的设备,经过读取audio_policy.conf文件能够获取系统支持的音频接口参数,在AudioPolicyManager中会优先加载/vendor/etc/audio_policy.conf配置文件, 若是该配置文件不存在, 则加载/system/etc/audio_policy.conf配置文件。AudioPolicyManager加载完全部音频接口后,就知道了系统支持的全部音频接口参数,能够为音频输出提供决策。
audio_policy.conf同时定义了多个audio接口,每个audio接口包含若干output和input,而每一个output和input又同时支持多种输入输出模式,每种输入输出模式又支持若干种设备.
ConfigParsingUtils::loadAudioPolicyConfig(....);
分红两部分,第一部分是解析全局标签,第二部分是解析audio_hw_modules标签,其子标签都表示hardware module,有primary和r_submix两种hardware module都被解析到mHwModules,hardware module的子标签有outputs和inputs,outputs的各个子标签被解析到mHwModules 的 mOutputProfiles,inputs的各个子标签被解析到mHwModules 的 mInputProfiles。
2)若是有define USE_XML_AUDIO_POLICY_CONF,则解析audio_policy_configure.xml
<!-- Modules section: There is one section per audio HW module present on the platform. Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”. The module names are the same as in current .conf file: “primary”, “A2DP”, “remote_submix”, “USB” Each module will contain the following sections: “devicePorts”: a list of device descriptors for all input and output devices accessible via this module. This contains both permanently attached devices and removable devices. “mixPorts”: listing all output and input streams exposed by the audio HAL “routes”: list of possible connections between input and output devices or between stream and devices. "route": is defined by an attribute: -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix) -"sink": the sink involved in this route -"sources": all the sources than can be connected to the sink via vis route “attachedDevices”: permanently attached devices. The attachedDevices section is a list of devices names. The names correspond to device names defined in <devicePorts> section. “defaultOutputDevice”: device to be used by default when no policy rule applies -->
<modules> <!-- Primary Audio HAL --> <module name="primary" halVersion="3.0"> <attachedDevices> <item>Speaker</item> <item>Built-In Mic</item> <item>Built-In Back Mic</item> </attachedDevices> <defaultOutputDevice>Speaker</defaultOutputDevice> <mixPorts> <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="deep_buffer" role="source" flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="compressed_offload" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING"> <profile name="" format="AUDIO_FORMAT_MP3" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/> <profile name="" format="AUDIO_FORMAT_AAC" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/> <profile name="" format="AUDIO_FORMAT_AAC_LC" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/> </mixPort> <mixPort name="voice_tx" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/> </mixPort> <mixPort name="primary input" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/> </mixPort> <mixPort name="voice_rx" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </mixPort> </mixPorts> <devicePorts> <!-- Output devices declaration, i.e. Sink DEVICE PORT --> <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </devicePort> <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address=""> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> <gains> <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT" minValueMB="-8400" maxValueMB="4000" defaultValueMB="0" stepValueMB="100"/> </gains> </devicePort> <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </devicePort> <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </devicePort> <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/> </devicePort> <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/> </devicePort> <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/> </devicePort> <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/> </devicePort> <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/> </devicePort> <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/> </devicePort> <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/> </devicePort> <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </devicePort> <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </devicePort> </devicePorts> <!-- route declaration, i.e. list all available sources for a given sink --> <routes> <route type="mix" sink="Earpiece" sources="primary output,deep_buffer,BT SCO Headset Mic"/> <route type="mix" sink="Speaker" sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/> <route type="mix" sink="Wired Headset" sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/> <route type="mix" sink="Wired Headphones" sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/> <route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/> <route type="mix" sink="Telephony Tx" sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic, voice_tx"/> <route type="mix" sink="voice_rx" sources="Telephony Rx"/> </routes> </module> <!-- A2dp Audio HAL --> <xi:include href="a2dp_audio_policy_configuration.xml"/> <!-- Usb Audio HAL --> <xi:include href="usb_audio_policy_configuration.xml"/> <!-- Remote Submix Audio HAL --> <xi:include href="r_submix_audio_policy_configuration.xml"/> <!-- Hearing aid Audio HAL --> <xi:include href="hearing_aid_audio_policy_configuration.xml"/> </modules> <!-- End of Modules section --> <!-- Volume section --> <xi:include href="audio_policy_volumes.xml"/> <xi:include href="default_volume_tables.xml"/> <!-- End of Volume section --> </audioPolicyConfiguration>
每一个 <module>都是一个 audio hal(对应代码中的HwModule类)。
<mixPort>(对应代码中AudioPort的子类IOProfile), 共有两大类role, 一类是"source", 一类是 “sink”。
"source"类的<mixPort> 共同组成了 HwModule 中的mOutputProfiles, "sink"类的<mixPort> 共同组成了 HwModule 中的mInputProfiles, mOutputProfiles + mInputProfiles 共同组成了 HwModule 中的mPorts。
<devicePort>(对应代码中AudioPort和AudioPortConfig的子类DeviceDescriptor),共同组成了 HwModule中的 mDeclaredDevices, 里面的各个device成员也会加载到先前HwModule类中的mPort。
<route>(对应代码中的AudioRoute类),顾名思义,是通路的意思,其链接port和device的做用. 每一个<route>实质上是一个MIX或者MUX, 以MIX为例,一个MIX包含一个sink(即AudioRoute的mSink)和多个source(分别add到AudioRoute的mSurce),此时已经将sink和source创建了简单的关系。
2)initialize
load_audio_interface()用来audio hal so,而后打开设备并建立一个audio_hw_device_t实例,音频设备接口所对应的so名称是有必定格式的,如a2dp的模块名多是audio.a2dp.so或audio.a2dp.default.so等,查找路径主要有两个/system/lib/hw和/vendor/lib/hw
load()dlopen hal so,dlsym返回audio_module:
struct audio_module HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = AUDIO_MODULE_API_VERSION_0_1, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = AUDIO_HARDWARE_MODULE_ID, .name = "QCOM Audio HAL", .author = "Code Aurora Forum", .methods = &hal_module_methods, }, };
open返回audio_hw_device_t。这样audio policy完成了对Hal module的加载
对于每一个outputProfile,建立1个outputDescription, 每一个outputDescription调用open来openOutput,返回audio_io_handle_t类型的output handle.并把output handle add到mOutput.而后调用setOutputDevice(在里面createAudioPatch)。
setDeviceConnectionState:当有设备(好比耳机)接入或者断开时 ,会由java层通知audio system来更改输出设备。
设置音量:
getOutput flow:
setForceUse & create patch flow:
Audio policy 与Audio Flinger control block: