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: