本文基于android7.0分析
一、前言
前面我们已经介绍了
audio_policy.conf
的解析全过程,但是,.conf
是一种简单的专有格式,有较大的局限性,无法描述电视和汽车等应用的复杂拓扑。Android 7.0
弃用了audio_policy.conf
,并增加了对使用XML 文件
格式来定义音频拓扑的支持,这种文件格式更通俗易懂,具有多种编辑和解析工具,并且足够灵活,可以描述复杂的音频拓扑。
注意:Android 7.0 仍支持使用 audio_policy.conf
;系统会默认使用这种旧版格式。要使用 XML 文件格式,需要在设备 Makefile 中添加构建选项 USE_XML_AUDIO_POLICY_CONF := 1
。
二、XML 格式的优势
与在 .conf
文件中一样,新的 XML 文件
支持定义输出输入流配置文件、可用于播放和捕获的设备以及音频属性的数量和类型。此外,XML
格式还提供以下增强功能:
- 音频配置文件目前的结构类似于 HDMI 简单音频描述符,支持每种音频格式使用一组不同的采样率/声道掩码。
- 设备和流之间所有可能连接的显式定义。以前,借助隐式规则,可以使连接到同一 HAL 模块的所有设备互连,从而阻止音频政策控制使用音频补丁程序 API 请求的连接。现在,在 XML 格式中,拓扑描述定义了连接限制。
- 对“包含”的支持可避免出现重复的标准 A2DP、USB 或重新导向提交定义。
- 可自定义的音量曲线。以前,音量表采用硬编码格式。在 XML 格式中,音量表通过描述来定义,并且可自定义。
frameworks/av/services/audiopolicy/config/audio_policy_configuration.xml
中的模板展示了很多已在使用的上述功能。
三、文件格式和位置
新的音频政策配置文件是 audio_policy_configuration.xml
,位于 /system/etc
。要查看采用新的 XML 文件
格式的简单音频政策配置,请查看以下示例。
显示音频政策示例
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude"> <globalConfiguration speaker_drc_enabled="true"/> <modules> <module name="primary" halVersion="3.0"> <attachedDevices> <item>Speaker</item> <item>Earpiece</item> <item>Built-In 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="primary input" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </mixPort> </mixPorts> <devicePorts> <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"/> </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="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </devicePort> <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </devicePort> </devicePorts> <routes> <route type="mix" sink="Earpiece" sources="primary output"/> <route type="mix" sink="Speaker" sources="primary output"/> <route type="mix" sink="Wired Headset" sources="primary output"/> <route type="mix" sink="primary input" sources="Built-In Mic,Wired Headset Mic"/> </routes> </module> <xi:include href="a2dp_audio_policy_configuration.xml"/> </modules>
<xi:include href="audio_policy_volumes.xml"/> <xi:include href="default_volume_tables.xml"/>
</audioPolicyConfiguration>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
顶层结构中包含与各个音频 HAL 硬件模块对应的模块,其中每个模块都有一系列混合端口、设备端口和导向:
- 混合端口描述了可以在音频 HAL 处打开以供播放和捕获的流的可能配置文件。
- 设备端口描述了可以附上其类型(以及(可选)地址和音频属性,如果相关)的设备。
- 导向(新)现在已从混合端口描述符中分离出来,支持描述从设备到设备或从流到设备的导向。
显示音量表示例
<?xml version="1.0" encoding="UTF-8"?>
<volumes>
<reference name="FULL_SCALE_VOLUME_CURVE">
<point>0,0</point>
<point>100,0</point>
</reference>
<reference name="SILENT_VOLUME_CURVE">
<point>0,-9600</point>
<point>100,-9600</point>
</reference>
<reference name="DEFAULT_VOLUME_CURVE">
<point>1,-4950</point>
<point>33,-3350</point>
<point>66,-1700</point>
<point>100,0</point>
</reference>
</volumes>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
显示音量示例
<?xml version="1.0" encoding="UTF-8"?> <volumes> <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>
<volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"> <point>1,-5500</point> <point>20,-4300</point> <point>86,-1200</point> <point>100,0</point> </volume> <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="SILENT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="SILENT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/> <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
</volumes>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
XML 包含 (XInclude) 方法可用于包含位于其他 XML 文件中的音频政策配置信息。所有包含的文件必须遵循上述结构,同时满足以下限制条件:
- 文件只能包含顶层元素。
- 文件不能包含 Xinclude 元素。
使用“包含”可避免将标准 Android 开放源代码项目 (AOSP) 音频 HAL 模块配置信息复制到所有音频政策配置文件(这样做容易出错)google为以下音频 HAL 提供了标准音频政策配置 xml 文件:
- A2DP:
a2dp_audio_policy_configuration.xml
- 重新导向子混音:
rsubmix_audio_policy_configuration.xml
- USB:
usb_audio_policy_configuration.xml
四、解析
以如下audio_policy_configuration.xml
为例:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!-- Copyright (c) 2016, The Linux Foundation. All rights reserved Not a Contribution. --> <!-- Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
–>
<audioPolicyConfiguration version=“1.0” xmlns:xi=“http://www.w3.org/2001/XInclude”>
<!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
<!-- Global configuration Decalaration -->
<globalConfiguration speaker_drc_enabled="true"/>
<!-- 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="Telephony Tx"
sources="voice_tx"/>
<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"/>
<route type="mix" sink="voice_rx"
sources="Telephony Rx"/>
</routes>
</module>
<!-- HDMI Audio HAL -->
<module description="HDMI Audio HAL" name="hdmi" version="2.0">
<mixPorts>
<mixPort name="hdmi output" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000"/>
</mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
</devicePorts>
<routes>
<route type="mix" sink="HDMI Out"
sources="hdmi output"/>
</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"/>
</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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
在之前我们已经介绍了的 audio_policy.conf 文章中可以知道,解析音频配置策略文件所处的类文件为 AudioPolicyManager.cpp 构造函数
而本章第一小节说了自Android 7.0
开始出现了.xml
音频配置策略文件,并且兼容老的 .conf
,通过宏定义 USE_XML_AUDIO_POLICY_CONF
控制 ,代码位于 AudioPolicyManager.cpp
构造函数 如下:AudioPolicyManager.cpp
位于 \frameworks\av\services\audiopolicy\managerdefault
#ifdef USE_XML_AUDIO_POLICY_CONF
mVolumeCurves = new VolumeCurvesCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled,
static_cast<VolumeCurvesCollection *>(mVolumeCurves));
PolicySerializer serializer;
if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {
#else
mVolumeCurves = new StreamDescriptorCollection();
AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice, speakerDrcEnabled);
if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
(ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
#endif
ALOGE("could not load audio policy configuration file, setting defaults");
config.setDefault();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
可以看到首先是定义了 PolicySerializer
对象,.xml
通过 PolicySerializer
类实现解析,解析入口函数为 deserialize
PolicySerializer对象
定义于 \frameworks\av\services\audiopolicy\common\managerdefinitions\include\Serializer.h
实现位于\frameworks\av\services\audiopolicy\common\managerdefinitions\src\Serializer.cpp
PolicySerializer 构造函数如下:
PolicySerializer::PolicySerializer() : mRootElementName(rootName)
{
std::ostringstream oss;
oss << gMajor << "." << gMinor;
mVersion = oss.str();
ALOGV("%s: Version=%s Root=%s", __FUNCTION__, mVersion.c_str(), mRootElementName.c_str());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
可以看到构造函数初始化 变量 mRootElementName = rootName
mVersion =oss.str()= oss << gMajor << "." << gMinor;
rootName、gMajor 、gMinor
定义如下:
const char *const PolicySerializer::rootName = "audioPolicyConfiguration";
const uint32_t PolicySerializer::gMajor = 1;
const uint32_t PolicySerializer::gMinor = 0;
- 1
- 2
- 3
audioPolicyConfiguration
我们可以知道是 .xml的根节点元素字段名,因此 mRootElementName
会用来后面判断.xml的根节点元素字段名是否正确,如果不正确,则解析失败。mVersion =1.0、mRootElementName=“audioPolicyConfiguration”
Serializer.h
源码如下
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include “AudioPolicyConfig.h”
#include <utils/StrongPointer.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <string>
#include <sstream>
#include <fstream>
struct _xmlNode;
struct _xmlDoc;
namespace android {
struct AudioGainTraits
{
static const char *const tag;
static const char *const collectionTag;
struct Attributes
{
static const char mode[]; /**< gain modes supported, e.g. AUDIO_GAIN_MODE_CHANNELS. */
/** controlled channels, needed if mode AUDIO_GAIN_MODE_CHANNELS. */
static const char channelMask[];
static const char minValueMB[]; /**< min value in millibel. */
static const char maxValueMB[]; /**< max value in millibel. */
static const char defaultValueMB[]; /**< default value in millibel. */
static const char stepValueMB[]; /**< step value in millibel. */
static const char minRampMs[]; /**< needed if mode AUDIO_GAIN_MODE_RAMP. */
static const char maxRampMs[]; /**< .needed if mode AUDIO_GAIN_MODE_RAMP */
};
typedef AudioGain Element;
typedef sp<Element> PtrElement;
typedef AudioGainCollection Collection;
typedef void *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx serializingContext);
// Gain has no child
};
// A profile section contains a name, one audio format and the list of supported sampling rates
// and channel masks for this format
struct AudioProfileTraits
{
static const char *const tag;
static const char *const collectionTag;
struct Attributes
{
static const char name[];
static const char samplingRates[];
static const char format[];
static const char channelMasks[];
};
typedef AudioProfile Element;
typedef sp<AudioProfile> PtrElement;
typedef AudioProfileVector Collection;
typedef void *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx serializingContext);
};
struct MixPortTraits
{
static const char *const tag;
static const char *const collectionTag;
struct Attributes
{
static const char name[];
static const char role[];
static const char flags[];
};
typedef IOProfile Element;
typedef sp<Element> PtrElement;
typedef IOProfileCollection Collection;
typedef void *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx serializingContext);
// Children are: GainTraits
};
struct DevicePortTraits
{
static const char *const tag;
static const char *const collectionTag;
struct Attributes
{
static const char tagName[]; /**< <device tag name>: any string without space. */
static const char type[]; /**< <device type>. */
static const char role[]; /**< <device role: sink or source>. */
static const char roleSource[]; /**< <attribute role source value>. */
static const char address[]; /**< optional: device address, char string less than 64. */
};
typedef DeviceDescriptor Element;
typedef sp<DeviceDescriptor> PtrElement;
typedef DeviceVector Collection;
typedef void *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx serializingContext);
// Children are: GainTraits (optionnal)
};
struct RouteTraits
{
static const char *const tag;
static const char *const collectionTag;
struct Attributes
{
static const char type[]; /**< <route type>: mix or mux. */
static const char typeMix[]; /**< type attribute mix value. */
static const char sink[]; /**< <sink: involved in this route>. */
static const char sources[]; /**< sources: all source that can be involved in this route. */
};
typedef AudioRoute Element;
typedef sp<AudioRoute> PtrElement;
typedef AudioRouteVector Collection;
typedef HwModule *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx ctx);
};
struct ModuleTraits
{
static const char *const tag;
static const char *const collectionTag;
static const char *const childAttachedDevicesTag;
static const char *const childAttachedDeviceTag;
static const char *const childDefaultOutputDeviceTag;
struct Attributes
{
static const char name[];
static const char version[];
};
typedef HwModule Element;
typedef sp<Element> PtrElement;
typedef HwModuleCollection Collection;
typedef AudioPolicyConfig *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx serializingContext);
// Children are: mixPortTraits, devicePortTraits and routeTraits
// Need to call deserialize on each child
};
struct GlobalConfigTraits
{
static const char *const tag;
struct Attributes
{
static const char speakerDrcEnabled[];
};
static status_t deserialize(const _xmlNode *root, AudioPolicyConfig &config);
};
struct VolumeTraits
{
static const char *const tag;
static const char *const collectionTag;
static const char *const volumePointTag;
struct Attributes
{
static const char stream[];
static const char deviceCategory[];
static const char reference[];
};
typedef VolumeCurve Element;
typedef sp<VolumeCurve> PtrElement;
typedef VolumeCurvesCollection Collection;
typedef void *PtrSerializingCtx;
static status_t deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx serializingContext);
// No Child
};
class PolicySerializer
{
private:
static const char *const rootName;
static const char *const versionAttribute;
static const uint32_t gMajor; /**< the major number of the policy xml format version. */
static const uint32_t gMinor; /**< the minor number of the policy xml format version. */
public:
PolicySerializer();
status_t deserialize(const char *str, AudioPolicyConfig &config);
private:
typedef AudioPolicyConfig Element;
std::string mRootElementName;
std::string mVersion;
// Children are: ModulesTraits, VolumeTraits
};
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
定义了 我们待会解析数据时的对象,
其中有 struct AudioGainTraits、struct AudioProfileTraits、struct MixPortTraits、struct DevicePortTraits、struct RouteTraits、struct ModuleTraits、struct GlobalConfigTraits、struct VolumeTraits
和解析入口类 class PolicySerializer
和 声明了解析 xml
的对象 struct _xmlNode、struct _xmlDoc
紧接着我们继续看到 入口函数
status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig &config) { xmlDocPtr doc; doc = xmlParseFile(configFile);//将文件内容转换为xml文档 if (doc == NULL) { ALOGE("%s: Could not parse %s document.", __FUNCTION__, configFile); return BAD_VALUE; }
/** audioPolicyConfiguration{ ...... } */ xmlNodePtr cur = xmlDocGetRootElement(doc);//得到xml的根节点元素 if (cur == NULL) { ALOGE("%s: Could not parse %s document: empty.", __FUNCTION__, configFile); xmlFreeDoc(doc); return BAD_VALUE; } if (xmlXIncludeProcess(doc) < 0) { ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __FUNCTION__, configFile); } //mRootElementName="audioPolicyConfiguration" if (xmlStrcmp(cur->name, (const xmlChar *) mRootElementName.c_str())) { ALOGE("%s: No %s root element found in xml data %s.", __FUNCTION__, mRootElementName.c_str(), (const char *)cur->name); xmlFreeDoc(doc); return BAD_VALUE; }
//versionAttribute = “version”;
string version = getXmlAttribute(cur, versionAttribute);
if (version.empty()) {
ALOGE("%s: No version found in root node %s", FUNCTION, mRootElementName.c_str());
return BAD_VALUE;
}
//mVersion = 1.0
if (version != mVersion) {
ALOGE("%s: Version does not match; expect %s got %s", __FUNCTION__, mVersion.c_str(),
version.c_str());
return BAD_VALUE;
}
// Lets deserialize children
// Modules
ModuleTraits::Collection modules;
deserializeCollection<ModuleTraits>(doc, cur, modules, &config);
config.setHwModules(modules);
// deserialize volume section
VolumeTraits::Collection volumes;
deserializeCollection<VolumeTraits>(doc, cur, volumes, &config);
config.setVolumes(volumes);
// Global Configuration
GlobalConfigTraits::deserialize(cur, config);
xmlFreeDoc(doc);
return android::OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
deserialize
函数有两个参数
const char *configFile
//文件路径
即#define AUDIO_POLICY_XML_CONFIG_FILE "/system/etc/audio_policy_configuration.xml"
AudioPolicyConfig &config
//用于封装的整个.xml
数据结构的对象。
参数类型跟我们解析.conf
是一样的,
AudioPolicyConfig.h
源码位于: \frameworks\av\services\audiopolicy\common\managerdefinitions\include
源码如下:
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <AudioGain.h>
#include <VolumeCurve.h>
#include <AudioPort.h>
#include <AudioPatch.h>
#include <DeviceDescriptor.h>
#include <IOProfile.h>
#include <HwModule.h>
#include <AudioInputDescriptor.h>
#include <AudioOutputDescriptor.h>
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
#include <SoundTriggerSession.h>
#include <SessionRoute.h>
namespace android {
class AudioPolicyConfig
{
public:
AudioPolicyConfig(HwModuleCollection &hwModules,
DeviceVector &availableOutputDevices,
DeviceVector &availableInputDevices,
sp<DeviceDescriptor> &defaultOutputDevices,
bool &isSpeakerDrcEnabled,
VolumeCurvesCollection *volumes = nullptr)
: mHwModules(hwModules),
mAvailableOutputDevices(availableOutputDevices),
mAvailableInputDevices(availableInputDevices),
mDefaultOutputDevices(defaultOutputDevices),
mVolumeCurves(volumes),
mIsSpeakerDrcEnabled(isSpeakerDrcEnabled)
{}
void setVolumes(const VolumeCurvesCollection &volumes)
{
if (mVolumeCurves != nullptr) {
*mVolumeCurves = volumes;
}
}
void setHwModules(const HwModuleCollection &hwModules)
{
mHwModules = hwModules;
}
void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice)
{
if (audio_is_output_device(availableDevice->type())) {
mAvailableOutputDevices.add(availableDevice);
} else if (audio_is_input_device(availableDevice->type())) {
mAvailableInputDevices.add(availableDevice);
}
}
void addAvailableInputDevices(const DeviceVector &availableInputDevices)
{
mAvailableInputDevices.add(availableInputDevices);
}
void addAvailableOutputDevices(const DeviceVector &availableOutputDevices)
{
mAvailableOutputDevices.add(availableOutputDevices);
}
void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
{
mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
}
const HwModuleCollection getHwModules() const { return mHwModules; }
const DeviceVector &getAvailableInputDevices() const
{
return mAvailableInputDevices;
}
const DeviceVector &getAvailableOutputDevices() const
{
return mAvailableOutputDevices;
}
void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
{
mDefaultOutputDevices = defaultDevice;
}
const sp<DeviceDescriptor> &getDefaultOutputDevice() const { return mDefaultOutputDevices; }
void setDefault(void)
{
mDefaultOutputDevices = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
sp<HwModule> module;
sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
mAvailableOutputDevices.add(mDefaultOutputDevices);
mAvailableInputDevices.add(defaultInputDevice);
module = new HwModule("primary");
sp<OutputProfile> outProfile;
outProfile = new OutputProfile(String8("primary"));
outProfile->attach(module);
outProfile->addAudioProfile(
new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
outProfile->addSupportedDevice(mDefaultOutputDevices);
outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
module->mOutputProfiles.add(outProfile);
sp<InputProfile> inProfile;
inProfile = new InputProfile(String8("primary"));
inProfile->attach(module);
inProfile->addAudioProfile(
new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000));
inProfile->addSupportedDevice(defaultInputDevice);
module->mInputProfiles.add(inProfile);
mHwModules.add(module);
}
private:
HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
DeviceVector &mAvailableOutputDevices;
DeviceVector &mAvailableInputDevices;
sp<DeviceDescriptor> &mDefaultOutputDevices;
VolumeCurvesCollection *mVolumeCurves;
bool &mIsSpeakerDrcEnabled;
};
}; // namespace android
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
之前解析audio_policy.conf
中我们已经知道通过AudioPolicyConfig
类来装载整个音频策略文件数据,这里也是一样,通过AudioPolicyConfig
来封装audio_policy_configuration.xml
所包含的策略数据,包含如下属性变量
HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports.*/ |
.xml 中所有module 模块的集合 |
DeviceVector &mAvailableOutputDevices; |
.xml 中所有output devices 模块的集合 |
DeviceVector &mAvailableInputDevices; |
.xml 中所有input devices 模块的集合 |
sp<DeviceDescriptor> &mDefaultOutputDevices; |
.xml 中默认output device
|
VolumeCurvesCollection *mVolumeCurves; |
.xml 中音量集合 |
接着通过
1、通过 xmlParseFile
函数将整个 .xml
解析后转换成 数据类型为 xmlDocPtr doc
;
2、通过 xmlDocGetRootElement
函数获取到 根节点所有的元素,以数据类型为 xmlNodePtr cur
接收,也就是 audioPolicyConfiguration
开始包含的所有的元素
3、通过 if (xmlStrcmp(cur->name, (const xmlChar *) mRootElementName.c_str())) {}
,判断上面获取所有元素cur->name
是否是以mRootElementName
作为根元素名字,通过前面解析PolicySerializer
构造函数我们知道mRootElementName=“audioPolicyConfiguration”
,如果cur->name!=audioPolicyConfiguratio
的话,则return BAD_VALUE
,否则继续解析
4、接着通过函数 string version = getXmlAttribute(cur, versionAttribute);
获取 versionAttribute
版本号,
const char *const PolicySerializer::versionAttribute = "version";
string getXmlAttribute(const xmlNode *cur, const char attribute)
{
xmlChar xmlValue = xmlGetProp(cur, (const xmlChar)attribute);
if (xmlValue == NULL) {
return “”;
}
string value((const char)xmlValue);
xmlFree(xmlValue);
return value;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
如果version.empty()
则return BAD_VALUE
,
如果version != mVersion
则return BAD_VALUE
,前面在PolicySerializer
构造函数我们已经初始化mVersion =1.0、mRootElementName=“audioPolicyConfiguration”
否则继续解析
5、进过一些列校验进入了正式解析,通过函数
ModuleTraits::Collection modules;
deserializeCollection<ModuleTraits>(doc, cur, modules, &config);
config.setHwModules(modules);
- 1
- 2
- 3
前面我们在介绍 Serializer.h
已经说明了它声明了一些列 ****Traits
,用来解析过程中作为数据类型封装数据,待会我们解析时一个一个再来看他们的实现,首先我们这里用到了ModuleTraits
,在Serializer.cpp
中找到它的实现,源码如下:
const char *const ModuleTraits::childAttachedDevicesTag = "attachedDevices";
const char *const ModuleTraits::childAttachedDeviceTag = "item";
const char *const ModuleTraits::childDefaultOutputDeviceTag = "defaultOutputDevice";
const char *const ModuleTraits::tag = “module”;
const char *const ModuleTraits::collectionTag = “modules”;
const char ModuleTraits::Attributes::name[] = “name”;
const char ModuleTraits::Attributes::version[] = “halVersion”;
/**
root = moudle {} /moudle
module = HwModule
ctx = AudioPolicyConfig*
*/
status_t ModuleTraits::deserialize(xmlDocPtr doc, const xmlNode *root, PtrElement &module,
PtrSerializingCtx ctx)
{
/**
1. name= primary Attributes::name = "name"
*/
string name = getXmlAttribute(root, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
return BAD_VALUE;
}
uint32_t version = AUDIO_DEVICE_API_VERSION_MIN;//AUDIO_DEVICE_API_VERSION_2_0
/**
1. versionLiteral = 3.0 Attributes::version = "halVersion"
*/
string versionLiteral = getXmlAttribute(root, Attributes::version);//3
if (!versionLiteral.empty()) {
uint32_t major, minor;
/**
1. major = 3 minor = 0
*/
sscanf(versionLiteral.c_str(), "%u.%u", &major, &minor);
version = HARDWARE_DEVICE_API_VERSION(major, minor);
ALOGV("%s: mHalVersion = %04x major %u minor %u", __FUNCTION__,
version, major, minor);
}
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
/**
1. Element = HwModule
*/
module = new Element(name.c_str(), version);
// Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
MixPortTraits::Collection mixPorts;
deserializeCollection<MixPortTraits>(doc, root, mixPorts, NULL);
module->setProfiles(mixPorts);
DevicePortTraits::Collection devicePorts;
deserializeCollection<DevicePortTraits>(doc, root, devicePorts, NULL);
module->setDeclaredDevices(devicePorts);
RouteTraits::Collection routes;
deserializeCollection<RouteTraits>(doc, root, routes, module.get());
module->setRoutes(routes);
const xmlNode *children = root->xmlChildrenNode;
while (children != NULL) {
if (!xmlStrcmp(children->name, (const xmlChar *)childAttachedDevicesTag)) {
ALOGV("%s: %s %s found", __FUNCTION__, tag, childAttachedDevicesTag);
const xmlNode *child = children->xmlChildrenNode;
while (child != NULL) {
if (!xmlStrcmp(child->name, (const xmlChar *)childAttachedDeviceTag)) {
xmlChar *attachedDevice = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
if (attachedDevice != NULL) {
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childAttachedDeviceTag,
(const char*)attachedDevice);
sp<DeviceDescriptor> device =
module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
ctx->addAvailableDevice(device);
xmlFree(attachedDevice);
}
}
child = child->next;
}
}
if (!xmlStrcmp(children->name, (const xmlChar *)childDefaultOutputDeviceTag)) {
xmlChar *defaultOutputDevice = xmlNodeListGetString(doc, children->xmlChildrenNode, 1);;
if (defaultOutputDevice != NULL) {
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childDefaultOutputDeviceTag,
(const char*)defaultOutputDevice);
sp<DeviceDescriptor> device =
module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)defaultOutputDevice));
if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
ctx->setDefaultOutputDevice(device);
ALOGV("%s: default is %08x", __FUNCTION__, ctx->getDefaultOutputDevice()->type());
}
xmlFree(defaultOutputDevice);
}
}
children = children->next;
}
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
可以看到初始化了其内部所携带的属性,和实现了 deserialize
函数
我们接着继续看到 deserializeCollection<ModuleTraits>(doc, cur, modules, &config);
函数,源码如下:
/**
1. Collection = HwModuleCollection PtrSerializingCtx = AudioPolicyConfig*
cur = audioPolicyConfiguration {} /audioPolicyConfiguration
2. Collection = IOProfileCollection PtrSerializingCtx = void *
cur = moudle {} /moudle
3. Collection = AudioProfileVector PtrSerializingCtx = void *
cur = mixPort {} /mixPort
4. Collection = AudioGainCollection PtrSerializingCtx = void *
cur = mixPort {} /mixPort
5. Collection = DeviceVector PtrSerializingCtx = void *
cur = moudle {} /moudle
6. Collection = AudioProfileVector PtrSerializingCtx = void *
cur = devicePort {} /devicePort
7. Collection = AudioGainCollection PtrSerializingCtx = void *
cur = devicePort {} /devicePort
*/
template <class Trait>
static status_t deserializeCollection(_xmlDoc doc, const _xmlNode cur,
typename Trait::Collection &collection,
typename Trait::PtrSerializingCtx serializingContext)
{
/
-
Trait == ModuleTraits
-
Trait == MixPortTraits
-
Trait == AudioProfileTraits
-
Trait == AudioGainTraits
-
Trait == DevicePortTraits
-
Trait == AudioProfileTraits
-
Trait == AudioGainTraits
*//**
1.cur->xmlChildrenNode == globalConfiguration {} /globalConfiguration
2.cur->xmlChildrenNode == attachedDevices {} /attachedDevices
3.cur->xmlChildrenNode == profile {} /profile
4.cur->xmlChildrenNode == profile {} /profile
5.cur->xmlChildrenNode == attachedDevices {} /attachedDevices
6.cur->xmlChildrenNode == profile {} /profile
*/const xmlNode *root = cur->xmlChildrenNode;
while (root != NULL) {/**
1. collectionTag = modules tag = moudle
2. collectionTag = mixPorts tag = mixPort
3. collectionTag = profiles tag = profile
4. collectionTag = gains tag = gain
5. collectionTag = devicePorts tag = devicePort
6. collectionTag = profiles tag = profile
*/
if (xmlStrcmp(root->name, (const xmlChar )Trait::collectionTag) &&
xmlStrcmp(root->name, (const xmlChar )Trait::tag)) {
/
1.root->next = moudles {} /moudles
2.root->next = defaultOutputDevice {} /defaultOutputDevice
3.root->next = mixPorts {} /mixPorts
4.root->next = profile {} /profile
5.root->next = defaultOutputDevice {} /defaultOutputDevice
6.root->next = mixPorts {} /mixPorts
7.root->next = devicePorts {} /devicePorts
*/root = root->next; continue; } const xmlNode *child = root;
/**
1. collectionTag = modules child->name = modules
2. collectionTag = mixPorts child->name = mixPorts
3. collectionTag = devicePorts child->name = devicePorts
*/
if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {/** 1. child->xmlChildrenNode = moudle {} /moudle 2. child->xmlChildrenNode = mixPort {} /mixPort 3. child->xmlChildrenNode = devicePort {} /devicePort */ child = child->xmlChildrenNode; } while (child != NULL) { /** 1. tag = moudle 2. tag = mixPort 3. tag = profile 4. tag = devicePort 5. tag = profile */ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::tag)) { /** 1. PtrElement = HwModule 2. PtrElement = IOProfile 3. PtrElement = sp<AudioProfile> 4. PtrElement = sp<DeviceDescriptor> 5. PtrElement = sp<AudioProfile> */ typename Trait::PtrElement element; status_t status = Trait::deserialize(doc, child, element, serializingContext); if (status != NO_ERROR) { return status; } /** 1. element = sp<AudioProfile> 2. element = IOProfile 3. element = sp<AudioProfile> */ if (collection.add(element) < 0) { ALOGE("%s: could not add element to %s collection", __FUNCTION__, Trait::collectionTag); } } child = child->next; } if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) { return NO_ERROR; } root = root->next;
}
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
首先可以看到 deserializeCollection
函数通过模板类定义的 Trait
,因此以后每次解析 ***Trait
都会是通过这个函数去解析,
这个函数中
1、 const xmlNode *root = cur->xmlChildrenNode;
获取到cur
的子节点 root ,对应.xml中的root= <globalConfiguration {} /globalConfiguration>
2、通过root!=NULL
建立一个while
循环,遍历root
中所有child node
3、然后root->name
跟当前的模板类 template <class Trait>
的collectionTag
与tag
值比较,也就是目前传入的ModuleTraits
定义的
const char *const ModuleTraits::tag = "module"; const char *const ModuleTraits::collectionTag = "modules"; /** 1. collectionTag = modules tag = moudle 2. collectionTag = mixPorts tag = mixPort 3. collectionTag = profiles tag = profile 4. collectionTag = gains tag = gain 5. collectionTag = devicePorts tag = devicePort 6. collectionTag = profiles tag = profile */ if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) && xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) { /** 1.root->next = moudles {} /moudles 2.root->next = defaultOutputDevice {} /defaultOutputDevice 3.root->next = mixPorts {} /mixPorts 4.root->next = profile {} /profile 5.root->next = defaultOutputDevice {} /defaultOutputDevice 6.root->next = mixPorts {} /mixPorts 7.root->next = devicePorts {} /devicePorts */
root = root->next; continue; } const xmlNode *child = root;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
如果 root->name
跟两者都不同相等,则进入该判断 root = root->next;
直到 root->next
中 root->name
与 Trait
中的collectionTag
或者tag
相等,此时如果我们这里的ModuleTraits
与我们解析的collectionTag
相等,所以解析到对应.xml
获取到 child=root->next = moudles {} /moudles
就结束这个判断
4、接着又比较 child->name
与 collectionTag
,这个时候相等,则child = child->xmlChildrenNode;
/** 1. collectionTag = modules child->name = modules 2. collectionTag = mixPorts child->name = mixPorts 3. collectionTag = devicePorts child->name = devicePorts */ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {
/** 1. child->xmlChildrenNode = moudle {} /moudle 2. child->xmlChildrenNode = mixPort {} /mixPort 3. child->xmlChildrenNode = devicePort {} /devicePort */ child = child->xmlChildrenNode; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
因为这个时候 collectionTag = moudles = child->name
,所以 这个时候又获取到其子节点进行解析,child = child->xmlChildrenNode = moudle {} /moudle
5、接着又 通过child != NULL
建立一个while
循环,进行解析 moudle {} /moudle
其内部所有子节点
6、接着 child->name
与 tag
比较,跟模板类的 Trait tag
值比较,此时相等,则进入模板类的Trait
的deserialize
进行解析其子模块,
7、循环遍历 child
中所有的 child = child->next;
中 child->name
与 tag
相等的模块,并且添加到 模板类的Trait
的Collection
现在我们总结下这个函数:
1. 首先循环遍历传入的 const _xmlNode * cur
中找到 cur->name
与 传入的 模板类Trait
的collectionTag
相同的模块,
2. 如果找到则循环遍历 child = cur->xmlChildrenNode;
中找到所有 child ->name
与 传入的
模板类Trait
的 tag
相同的模块
3. 如果找到,则将 child
通过 传入的 模板类Trait
的 deserialize
继续进行明确解析,将解析的数据存入
模板类Trait
的 PtrElement
5. 将所有 找到的 child
添加到 模板类Trait
的集合 Collection
通过上面的分析,我们可以知道 ModuleTraits
用来解析 <module {} /moldule>
模块,那现在我们接下看到解析ModuleTraits
的 deserialize
怎么解析 <module {} /moldule>
模块,在回顾到 ModuleTraits
的 deserialize
源码
/**
root = moudle {} /moudle
module = HwModule
ctx = AudioPolicyConfig*
*/
status_t ModuleTraits::deserialize(xmlDocPtr doc, const xmlNode *root, PtrElement &module,
PtrSerializingCtx ctx)
{
/**
1. name= primary Attributes::name = "name"
*/
string name = getXmlAttribute(root, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
return BAD_VALUE;
}
uint32_t version = AUDIO_DEVICE_API_VERSION_MIN;//AUDIO_DEVICE_API_VERSION_2_0
/**
1. versionLiteral = 3.0 Attributes::version = "halVersion"
*/
string versionLiteral = getXmlAttribute(root, Attributes::version);//3
if (!versionLiteral.empty()) {
uint32_t major, minor;
/**
1. major = 3 minor = 0
*/
sscanf(versionLiteral.c_str(), "%u.%u", &major, &minor);
version = HARDWARE_DEVICE_API_VERSION(major, minor);
ALOGV("%s: mHalVersion = %04x major %u minor %u", __FUNCTION__,
version, major, minor);
}
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
/**
1. Element = HwModule
*/
module = new Element(name.c_str(), version);
// Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
MixPortTraits::Collection mixPorts;
deserializeCollection<MixPortTraits>(doc, root, mixPorts, NULL);
module->setProfiles(mixPorts);
DevicePortTraits::Collection devicePorts;
deserializeCollection<DevicePortTraits>(doc, root, devicePorts, NULL);
module->setDeclaredDevices(devicePorts);
RouteTraits::Collection routes;
deserializeCollection<RouteTraits>(doc, root, routes, module.get());
module->setRoutes(routes);
const xmlNode *children = root->xmlChildrenNode;
while (children != NULL) {
if (!xmlStrcmp(children->name, (const xmlChar *)childAttachedDevicesTag)) {
ALOGV("%s: %s %s found", __FUNCTION__, tag, childAttachedDevicesTag);
const xmlNode *child = children->xmlChildrenNode;
while (child != NULL) {
if (!xmlStrcmp(child->name, (const xmlChar *)childAttachedDeviceTag)) {
xmlChar *attachedDevice = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
if (attachedDevice != NULL) {
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childAttachedDeviceTag,
(const char*)attachedDevice);
sp<DeviceDescriptor> device =
module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
ctx->addAvailableDevice(device);
xmlFree(attachedDevice);
}
}
child = child->next;
}
}
if (!xmlStrcmp(children->name, (const xmlChar *)childDefaultOutputDeviceTag)) {
xmlChar *defaultOutputDevice = xmlNodeListGetString(doc, children->xmlChildrenNode, 1);;
if (defaultOutputDevice != NULL) {
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childDefaultOutputDeviceTag,
(const char*)defaultOutputDevice);
sp<DeviceDescriptor> device =
module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)defaultOutputDevice));
if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
ctx->setDefaultOutputDevice(device);
ALOGV("%s: default is %08x", __FUNCTION__, ctx->getDefaultOutputDevice()->type());
}
xmlFree(defaultOutputDevice);
}
}
children = children->next;
}
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
1、首先判断了 <module>{}</module>
中的name
与version
字段,有效的话继续解析,判断这里比较简单,就不仔细说了。
2、然后创建了 module
对象,用来封装每一个 <module>{}</module>
的数据,构造函数传入步骤1 的name
与version
,module
类型为 HwModule
, 声明位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\HwModule.h
源码如下:
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include “DeviceDescriptor.h”
#include “AudioRoute.h”
#include <hardware/audio.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
#include <system/audio.h>
#include <cutils/config_utils.h>
#include <string>
namespace android {
class IOProfile;
class InputProfile;
class OutputProfile;
typedef Vector<sp<IOProfile> > InputProfileCollection;
typedef Vector<sp<IOProfile> > OutputProfileCollection;
typedef Vector<sp<IOProfile> > IOProfileCollection;
class HwModule : public RefBase
{
public:
HwModule(const char *name, uint32_t halVersion = AUDIO_DEVICE_API_VERSION_MIN);
~HwModule();
const char *getName() const { return mName.string(); }
const DeviceVector &getDeclaredDevices() const { return mDeclaredDevices; }
void setDeclaredDevices(const DeviceVector &devices);
const InputProfileCollection &getInputProfiles() const { return mInputProfiles; }
const OutputProfileCollection &getOutputProfiles() const { return mOutputProfiles; }
void setProfiles(const IOProfileCollection &profiles);
void setHalVersion(uint32_t halVersion) { mHalVersion = halVersion; }
uint32_t getHalVersion() const { return mHalVersion; }
sp<DeviceDescriptor> getRouteSinkDevice(const sp<AudioRoute> &route) const;
DeviceVector getRouteSourceDevices(const sp<AudioRoute> &route) const;
void setRoutes(const AudioRouteVector &routes);
status_t addOutputProfile(const sp<IOProfile> &profile);
status_t addInputProfile(const sp<IOProfile> &profile);
status_t addProfile(const sp<IOProfile> &profile);
status_t addOutputProfile(String8 name, const audio_config_t *config,
audio_devices_t device, String8 address);
status_t removeOutputProfile(String8 name);
status_t addInputProfile(String8 name, const audio_config_t *config,
audio_devices_t device, String8 address);
status_t removeInputProfile(String8 name);
audio_module_handle_t getHandle() const { return mHandle; }
sp<AudioPort> findPortByTagName(const String8 &tagName) const
{
return mPorts.findByTagName(tagName);
}
// TODO remove from here (split serialization)
void dump(int fd);
const String8 mName; // base name of the audio HW module (primary, a2dp ...)
audio_module_handle_t mHandle;
OutputProfileCollection mOutputProfiles; // output profiles exposed by this module
InputProfileCollection mInputProfiles; // input profiles exposed by this module
private:
void refreshSupportedDevices();
uint32_t mHalVersion; // audio HAL API version
DeviceVector mDeclaredDevices; // devices declared in audio_policy configuration file.
AudioRouteVector mRoutes;
AudioPortVector mPorts;
};
class HwModuleCollection : public Vector<sp<HwModule> >
{
public:
sp<HwModule> getModuleFromName(const char *name) const;
sp<HwModule> getModuleForDevice(audio_devices_t device) const;
sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
const char *device_address,
const char *device_name,
bool matchAdress = true) const;
status_t dump(int fd) const;
};
}; // namespace android
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
现在我们知道 <module>{}</module>
通过HwModule
对象去封装,
从HwModule
源码我们可以知道 <module>{}</module>
包含
OutputProfileCollection mOutputProfiles; // output profiles exposed by this module
InputProfileCollection mInputProfiles; // input profiles exposed by this module
DeviceVector mDeclaredDevices; // devices declared in audio_policy configuration file.
AudioRouteVector mRoutes;
- 1
- 2
- 3
- 4
3、创建了HwModule
就可以开始解析 <module>{}</module>
,首先解析的是
// Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
MixPortTraits::Collection mixPorts;
deserializeCollection<MixPortTraits>(doc, root, mixPorts, NULL);
module->setProfiles(mixPorts);
- 1
- 2
- 3
- 4
也就是对应.xml
中<module>
,通过
{
<mixPorts>
{
<mixPort>{}</mixPort>
}
</mixPorts>
}
</module>MixPortTraits
去解析MixPortTraits
实现源码如下:
const char *const MixPortTraits::collectionTag = "mixPorts";
const char *const MixPortTraits::tag = "mixPort";
const char MixPortTraits::Attributes::name[] = “name”;
const char MixPortTraits::Attributes::role[] = “role”;
const char MixPortTraits::Attributes::flags[] = “flags”;
/**
child = mixPort {} /mixPort
mixPort = IOProfile
PtrSerializingCtx = void *
*/
status_t MixPortTraits::deserialize(_xmlDoc doc, const _xmlNode child, PtrElement &mixPort,
PtrSerializingCtx /serializingContext/)
{
/
Attributes::name = “name”; name = “primary output”
*/
string name = getXmlAttribute(child, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::name);
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::name, name.c_str());
/**
Attributes::role = "role"; role = "source"
*/
string role = getXmlAttribute(child, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
return BAD_VALUE;
}
ALOGV("%s: Role=%s", __FUNCTION__, role.c_str());
audio_port_role_t portRole = role == "source" ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
/**
mixPort = IOProfile
*/
mixPort = new Element(String8(name.c_str()), portRole);
AudioProfileTraits::Collection profiles;
deserializeCollection<AudioProfileTraits>(doc, child, profiles, NULL);
if (profiles.isEmpty()) {
sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
ChannelsVector(), SampleRateVector());
dynamicProfile->setDynamicFormat(true);
dynamicProfile->setDynamicChannels(true);
dynamicProfile->setDynamicRate(true);
profiles.add(dynamicProfile);
}
mixPort->setAudioProfiles(profiles);
/**
Attributes::flags = "flags"; flags = "AUDIO_OUTPUT_FLAG_PRIMARY"
*/
string flags = getXmlAttribute(child, Attributes::flags);
if (!flags.empty()) {
// Source role
if (portRole == AUDIO_PORT_ROLE_SOURCE) {
mixPort->setFlags(OutputFlagConverter::maskFromString(flags));
} else {
// Sink role
mixPort->setFlags(InputFlagConverter::maskFromString(flags));
}
}
// Deserialize children
AudioGainTraits::Collection gains;
deserializeCollection<AudioGainTraits>(doc, child, gains, NULL);
mixPort->setGains(gains);
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
3.1、MixPortTraits
首先判断了name
和role
的值,这里比较简单,就不细说怎么获取和判断了、
3.2、MixPortTraits
创建了 mixPort
对象,其对象类型为 IOProfile
,将name
和portRole
传入构造函数\frameworks\av\services\audiopolicy\common\managerdefinitions\include\IOProfile.h
IOProfile
继承自AudioPort
,位于\frameworks\av\services\audiopolicy\common\managerdefinitions\src\AudioPort.h
现在我们可以知道 .<mixPort>{}</mixPort>
通过 IOProfile
继承自AudioPort
去封装
3.3 mixPort
对象创建完之后,便可以开始解析 <mixPort>{}</mixPort>
AudioProfileTraits::Collection profiles;
deserializeCollection<AudioProfileTraits>(doc, child, profiles, NULL);
if (profiles.isEmpty()) {
sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
ChannelsVector(), SampleRateVector());
dynamicProfile->setDynamicFormat(true);
dynamicProfile->setDynamicChannels(true);
dynamicProfile->setDynamicRate(true);
profiles.add(dynamicProfile);
}
mixPort->setAudioProfiles(profiles);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
也就是对应.xml
中<module>
,通过
{
<mixPorts>
{
<mixPort>
{
<profile/>
}
</mixPort>
}
</mixPorts>
}
</module>AudioProfileTraits
去解析AudioProfileTraits
实现源码如下:
const char *const AudioProfileTraits::collectionTag = "profiles";
const char *const AudioProfileTraits::tag = "profile";
const char AudioProfileTraits::Attributes::name[] = “name”;
const char AudioProfileTraits::Attributes::samplingRates[] = “samplingRates”;
const char AudioProfileTraits::Attributes::format[] = “format”;
const char AudioProfileTraits::Attributes::channelMasks[] = “channelMasks”;
/**
root = profile {} /profile
profile = sp<AudioProfile>
PtrSerializingCtx = void*
root = profile {} /profile
profile = sp<AudioProfile>
PtrSerializingCtx = void*
*/
status_t AudioProfileTraits::deserialize(_xmlDoc /doc/, const _xmlNode root, PtrElement &profile,
PtrSerializingCtx /serializingContext/)
{
/
Attributes::samplingRates = “samplingRates”; samplingRates = “48000”
Attributes::format = “format”; format = “AUDIO_FORMAT_PCM_16_BIT”
Attributes::channelMasks = “channelMasks”; channels = “AUDIO_CHANNEL_OUT_STEREO”
2.
Attributes::samplingRates = "samplingRates"; samplingRates = "48000"
Attributes::format = "format"; format = "AUDIO_FORMAT_PCM_16_BIT"
Attributes::channelMasks = "channelMasks"; channels = "AUDIO_CHANNEL_IN_MONO"
*/
string samplingRates = getXmlAttribute(root, Attributes::samplingRates);
string format = getXmlAttribute(root, Attributes::format);
string channels = getXmlAttribute(root, Attributes::channelMasks);
profile = new Element(formatFromString(format), channelMasksFromString(channels, ","),
samplingRatesFromString(samplingRates, ","));
profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
profile->setDynamicChannels(profile->getChannels().isEmpty());
profile->setDynamicRate(profile->getSampleRates().isEmpty());
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
通过AudioPort
去封装<mixPort>{<profile/>}</mixPort>
,又接着通过代码获取flag
属性的值
/** Attributes::flags = "flags"; flags = "AUDIO_OUTPUT_FLAG_PRIMARY"
*/ string flags = getXmlAttribute(child, Attributes::flags); if (!flags.empty()) { // Source role if (portRole == AUDIO_PORT_ROLE_SOURCE) { mixPort->setFlags(OutputFlagConverter::maskFromString(flags)); } else { // Sink role mixPort->setFlags(InputFlagConverter::maskFromString(flags)); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
最后通过AudioGainTraits
解析<mixPort>{<gains/>}</mixPort>
// Deserialize children
AudioGainTraits::Collection gains;
deserializeCollection<AudioGainTraits>(doc, child, gains, NULL);
mixPort->setGains(gains);
- 1
- 2
- 3
- 4
AudioGainTraits
实现源码如下:
const char *const AudioGainTraits::tag = "gain";
const char *const AudioGainTraits::collectionTag = "gains";
const char AudioGainTraits::Attributes::mode[] = “mode”;
const char AudioGainTraits::Attributes::channelMask[] = “channel_mask”;
const char AudioGainTraits::Attributes::minValueMB[] = “minValueMB”;
const char AudioGainTraits::Attributes::maxValueMB[] = “maxValueMB”;
const char AudioGainTraits::Attributes::defaultValueMB[] = “defaultValueMB”;
const char AudioGainTraits::Attributes::stepValueMB[] = “stepValueMB”;
const char AudioGainTraits::Attributes::minRampMs[] = “minRampMs”;
const char AudioGainTraits::Attributes::maxRampMs[] = “maxRampMs”;
status_t AudioGainTraits::deserialize(_xmlDoc */doc/, const _xmlNode *root, PtrElement &gain,
PtrSerializingCtx /serializingContext/)
{
static uint32_t index = 0;
gain = new Element(index++, true);
string mode = getXmlAttribute(root, Attributes::mode);
if (!mode.empty()) {
gain->setMode(GainModeConverter::maskFromString(mode));
}
string channelsLiteral = getXmlAttribute(root, Attributes::channelMask);
if (!channelsLiteral.empty()) {
gain->setChannelMask(channelMaskFromString(channelsLiteral));
}
string minValueMBLiteral = getXmlAttribute(root, Attributes::minValueMB);
uint32_t minValueMB;
if (!minValueMBLiteral.empty() && convertTo(minValueMBLiteral, minValueMB)) {
gain->setMinValueInMb(minValueMB);
}
string maxValueMBLiteral = getXmlAttribute(root, Attributes::maxValueMB);
uint32_t maxValueMB;
if (!maxValueMBLiteral.empty() && convertTo(maxValueMBLiteral, maxValueMB)) {
gain->setMaxValueInMb(maxValueMB);
}
string defaultValueMBLiteral = getXmlAttribute(root, Attributes::defaultValueMB);
uint32_t defaultValueMB;
if (!defaultValueMBLiteral.empty() && convertTo(defaultValueMBLiteral, defaultValueMB)) {
gain->setDefaultValueInMb(defaultValueMB);
}
string stepValueMBLiteral = getXmlAttribute(root, Attributes::stepValueMB);
uint32_t stepValueMB;
if (!stepValueMBLiteral.empty() && convertTo(stepValueMBLiteral, stepValueMB)) {
gain->setStepValueInMb(stepValueMB);
}
string minRampMsLiteral = getXmlAttribute(root, Attributes::minRampMs);
uint32_t minRampMs;
if (!minRampMsLiteral.empty() && convertTo(minRampMsLiteral, minRampMs)) {
gain->setMinRampInMs(minRampMs);
}
string maxRampMsLiteral = getXmlAttribute(root, Attributes::maxRampMs);
uint32_t maxRampMs;
if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
gain->setMaxRampInMs(maxRampMs);
}
ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d", __FUNCTION__,
gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
gain->getMaxValueInMb());
if (gain->getMode() == 0) {
return BAD_VALUE;
}
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
通过 AudioGain
去封装<mixPort>{<gains/>}</mixPort>
位于\frameworks\av\services\audiopolicy\common\managerdefinitions\include\AudioGain.h
到这里<mixPorts></mixPorts>
就解析完了。
4、接着回到代码ModuleTraits
DevicePortTraits::Collection devicePorts;
deserializeCollection<DevicePortTraits>(doc, root, devicePorts, NULL);
module->setDeclaredDevices(devicePorts);
- 1
- 2
- 3
开始解析<module>
,
{
<devicePorts>
{}
</devicePorts>
}
</module>
通过DevicePortTraits
去解析,实现源码如下:
const char *const DevicePortTraits::tag = "devicePort";
const char *const DevicePortTraits::collectionTag = "devicePorts";
const char DevicePortTraits::Attributes::tagName[] = “tagName”;
const char DevicePortTraits::Attributes::type[] = “type”;
const char DevicePortTraits::Attributes::role[] = “role”;
const char DevicePortTraits::Attributes::address[] = “address”;
const char DevicePortTraits::Attributes::roleSource[] = “source”;
/**
root = devicePort {} /devicePort
deviceDesc = sp<DeviceDescriptor>
PtrSerializingCtx = void*
*/
status_t DevicePortTraits::deserialize(_xmlDoc doc, const _xmlNode root, PtrElement &deviceDesc,
PtrSerializingCtx /serializingContext/)
{
/
Attributes::tagName = “tagName”; name = “Earpiece”
*/
string name = getXmlAttribute(root, Attributes::tagName);
if (name.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::tagName);
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::tagName, name.c_str());
/**
Attributes::type = "type" typeName = "AUDIO_DEVICE_OUT_EARPIECE"
*/
string typeName = getXmlAttribute(root, Attributes::type);
if (typeName.empty()) {
ALOGE("%s: no type for %s", __FUNCTION__, name.c_str());
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, typeName.c_str());
/**
Attributes::role = "role"; role = "sink"
*/
string role = getXmlAttribute(root, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::role);
return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::role, role.c_str());
audio_port_role_t portRole = (role == Attributes::roleSource) ?
AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
audio_devices_t type = AUDIO_DEVICE_NONE;
if (!DeviceConverter::fromString(typeName, type) ||
(!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
(!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
ALOGW("%s: bad type %08x", __FUNCTION__, type);
return BAD_VALUE;
}
deviceDesc = new Element(type, String8(name.c_str()));
/**
Attributes::address = "address"; address = ""
*/
string address = getXmlAttribute(root, Attributes::address);
if (!address.empty()) {
ALOGV("%s: address=%s for %s", __FUNCTION__, address.c_str(), name.c_str());
deviceDesc->mAddress = String8(address.c_str());
}
AudioProfileTraits::Collection profiles;
deserializeCollection<AudioProfileTraits>(doc, root, profiles, NULL);
if (profiles.isEmpty()) {
sp <AudioProfile> dynamicProfile = new AudioProfile(gDynamicFormat,
ChannelsVector(), SampleRateVector());
dynamicProfile->setDynamicFormat(true);
dynamicProfile->setDynamicChannels(true);
dynamicProfile->setDynamicRate(true);
profiles.add(dynamicProfile);
}
deviceDesc->setAudioProfiles(profiles);
// Deserialize AudioGain children
deserializeCollection<AudioGainTraits>(doc, root, deviceDesc->mGains, NULL);
ALOGV("%s: adding device tag %s type %08x address %s", __FUNCTION__,
deviceDesc->getName().string(), type, deviceDesc->mAddress.string());
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
经过前面那么多的介绍,其实会发现每个Traits
都是类似的,
- 都是开始获取当前节点的一些属性值判断,
- 创建一个特定的父对象,
- 然后再去获取子节点,通过特定的子对象再封装起来,进行解析。
4.1、DevicePortTraits
开始也是获取 tagName
、type
、role
属性的值,
4.2、然后创建了一个deviceDesc
对象,类型为 DeviceDescriptor
去封装<devicePort>
DeviceDescriptor
继承自AudioPort
,声明位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\DeviceDescriptor.h
4.3、获取子节点解析,即<module>
,
{
<devicePorts>
{
<profile>
}
</devicePorts>
}
</module>
这里也是跟前面mixPort
子节点<profile>
一样通过 AudioProfileTraits
去解析,这不在累赘
4.4、再获取子节点解析,即<module>
,
{
<devicePorts>
{
<gains>
}
</devicePorts>
}
</module>
,这里也是跟前面mixPort
子节点<gains>
一样通过 AudioGainTraits
去解析,这不在累赘.
到这里<devicePorts></devicePorts>
就解析完了。
5、接着回到代码ModuleTraits
RouteTraits::Collection routes;
deserializeCollection<RouteTraits>(doc, root, routes, module.get());
module->setRoutes(routes);
- 1
- 2
- 3
接着通过 RouteTraits
解析<module>
,
{
<routes>
{</route>}
</routes>
}
</module>RouteTraits
实现源码如下:
const char *const RouteTraits::tag = "route";
const char *const RouteTraits::collectionTag = "routes";
const char RouteTraits::Attributes::type[] = “type”;
const char RouteTraits::Attributes::typeMix[] = “mix”;
const char RouteTraits::Attributes::sink[] = “sink”;
const char RouteTraits::Attributes::sources[] = “sources”;
status_t RouteTraits::deserialize(_xmlDoc */doc/, const _xmlNode *root, PtrElement &element,
PtrSerializingCtx ctx)
{
string type = getXmlAttribute(root, Attributes::type);
if (type.empty()) {
ALOGE("%s: No %s found", FUNCTION, Attributes::type);
return BAD_VALUE;
}
audio_route_type_t routeType = (type == Attributes::typeMix) ?
AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, Attributes::type, type.c_str());
element = new Element(routeType);
string sinkAttr = getXmlAttribute(root, Attributes::sink);
if (sinkAttr.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::sink);
return BAD_VALUE;
}
// Convert Sink name to port pointer
sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
if (sink == NULL) {
ALOGE("%s: no sink found with name=%s", __FUNCTION__, sinkAttr.c_str());
return BAD_VALUE;
}
element->setSink(sink);
string sourcesAttr = getXmlAttribute(root, Attributes::sources);
if (sourcesAttr.empty()) {
ALOGE("%s: No %s found", __FUNCTION__, Attributes::sources);
return BAD_VALUE;
}
// Tokenize and Convert Sources name to port pointer
AudioPortVector sources;
char *sourcesLiteral = strndup(sourcesAttr.c_str(), strlen(sourcesAttr.c_str()));
char *devTag = strtok(sourcesLiteral, ",");
while (devTag != NULL) {
if (strlen(devTag) != 0) {
sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
if (source == NULL) {
ALOGE("%s: no source found with name=%s", __FUNCTION__, devTag);
return BAD_VALUE;
}
sources.add(source);
}
devTag = strtok(NULL, ",");
}
free(sourcesLiteral);
sink->addRoute(element);
for (size_t i = 0; i < sources.size(); i++) {
sp<AudioPort> source = sources.itemAt(i);
source->addRoute(element);
}
element->setSources(sources);
return NO_ERROR;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
5.1首先获取属性 type
的值,创建 element
对象,其类型为 AudioRoute
,在获取属性 sink
、sources
的值, sources
属性的值可以通过,
分开有多个,</route>
对象通过 AudioRoute
分装起来AudioRoute
声明位于:\frameworks\av\services\audiopolicy\common\managerdefinitions\include\AudioRoute .h
到这里<routes></routes>
就解析完了。
6、接着回到代码ModuleTraits
const xmlNode *children = root->xmlChildrenNode;
while (children != NULL) {
if (!xmlStrcmp(children->name, (const xmlChar *)childAttachedDevicesTag)) {
ALOGV("%s: %s %s found", __FUNCTION__, tag, childAttachedDevicesTag);
const xmlNode *child = children->xmlChildrenNode;
while (child != NULL) {
if (!xmlStrcmp(child->name, (const xmlChar *)childAttachedDeviceTag)) {
xmlChar *attachedDevice = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
if (attachedDevice != NULL) {
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childAttachedDeviceTag,
(const char*)attachedDevice);
sp<DeviceDescriptor> device =
module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
ctx->addAvailableDevice(device);
xmlFree(attachedDevice);
}
}
child = child->next;
}
}
if (!xmlStrcmp(children->name, (const xmlChar *)childDefaultOutputDeviceTag)) {
xmlChar *defaultOutputDevice = xmlNodeListGetString(doc, children->xmlChildrenNode, 1);;
if (defaultOutputDevice != NULL) {
ALOGV("%s: %s %s=%s", __FUNCTION__, tag, childDefaultOutputDeviceTag,
(const char*)defaultOutputDevice);
sp<DeviceDescriptor> device =
module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)defaultOutputDevice));
if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
ctx->setDefaultOutputDevice(device);
ALOGV("%s: default is %08x", __FUNCTION__, ctx->getDefaultOutputDevice()->type());
}
xmlFree(defaultOutputDevice);
}
}
children = children->next;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
6.1首先找到 名字为<childAttachedDevicesTag=attachedDevices>
节点,如果找到再去解析字节点<childAttachedDeviceTag=item>
并获取其值,通过module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
找到其中对用的DeviceDescriptor
6.2找到 名字为<childDefaultOutputDeviceTag=defaultOutputDevice>
节点,并获取其值,通过module->getDeclaredDevices().getDeviceFromTagName(String8((const char*)attachedDevice));
找到其中对用的DeviceDescriptor
最后一个完整的</module>
就解析完成了
我们最后接着回到 PolicySerializer 类的解析入口函数
// deserialize volume section VolumeTraits::Collection volumes; deserializeCollection<VolumeTraits>(doc, cur, volumes, &config); config.setVolumes(volumes);
// Global Configuration GlobalConfigTraits::deserialize(cur, config);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
最后两个一个是解析音量,一个是全局配置,解析的方式都是跟modules
一样,这里就不累赘了,最后我门再跟之前.conf
文章中一样,总结一下,
//AudioPolicyConfig
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
…
//HwModuleCollection—>AudioPolicyConfig.setHwModules(HwModuleCollection);
<modules>
......
<!-- Primary Audio HAL -->
/**
name="primary"
halVersion="2.0"
*/
// HwModule(name,version ) -->HwModuleCollection.add(HwModule)
<module name="primary" halVersion="2.0">
......
<attachedDevices>
// sp<DeviceDescriptor> device=HwModule->getDeclaredDevices().getDeviceFromTagName(Earpiece)
//AudioPolicyConfig->addAvailableDevice(device);
<item>Earpiece</item>
....
</attachedDevices>
//sp<DeviceDescriptor> device=HwModule->getDeclaredDevices().getDeviceFromTagName(Speaker)
//AudioPolicyConfig->setDefaultOutputDevice(device);
<defaultOutputDevice>Speaker</defaultOutputDevice>
//IOProfileCollection-->HwModule->setProfiles(IOProfileCollection);
<mixPorts>
/**
name="primary output"
role="source"
audio_port_role_t portRole = role == "source" ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
*/
//IOProfile(name,portRole) extends AudioPort -->IOProfileCollection.add(IOProfile );
<mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
/**
AudioProfile.setDynamicFormat(format)
AudioProfile->setDynamicChannels(channelMasks);
AudioProfile->setDynamicRate(samplingRates);
*/
//sp <AudioProfile> -->AudioProfileVector.add(AudioProfile); --> IOProfile ->setAudioProfiles(AudioProfileVector);
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
.....
</mixPort>
......
</mixPorts>
//DeviceVector --> HwModule->setDeclaredDevices(DeviceVector)
<devicePorts>
<!-- Output devices declaration, i.e. Sink DEVICE PORT -->
//typeName="AUDIO_DEVICE_OUT_EARPIECE" role="sink"
/**
audio_port_role_t portRole = (role == Attributes::roleSource) ?
AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
audio_devices_t type = AUDIO_DEVICE_NONE;
if (!DeviceConverter::fromString(typeName, type) ||
(!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
(!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
ALOGW("%s: bad type %08x", __FUNCTION__, type);
return BAD_VALUE;
}
*/
//DeviceDescriptor(type,name) extends AudioPort,AudioPortConfig --> DeviceVector.add(DeviceDescriptor)
<devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
/**
AudioProfile.setDynamicFormat(format)
AudioProfile->setDynamicChannels(channelMasks);
AudioProfile->setDynamicRate(samplingRates);
*/
//sp <AudioProfile> -->AudioProfileVector.add(AudioProfile); --> DeviceDescriptor ->setAudioProfiles(profiles);
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
......
</devicePort>
......
</devicePorts>
<!-- route declaration, i.e. list all available sources for a given sink -->
//AudioRouteVector --> HwModule->setRoutes(AudioRouteVector)
<routes>
//type="mix"
//AudioRoute(type) --> AudioRouteVector.add(AudioRoute);
//sink="Earpiece" ---> sp<AudioPort> sink = AudioPolicyConfig->findPortByTagName(sink);
//sink->addRoute(AudioRoute); --> AudioRoute->setSink(AudioPort);
//sources=""primary output,......" -> AudioPortVector.add(sp<AudioPort> source = AudioPolicyConfig->findPortByTagName("primary output");) --> AudioRoute ->setSources(AudioPortVector);
<route type="mix" sink="Earpiece"
sources="primary output,low_latency,compressed_offload,voip_rx,BT SCO Headset Mic"/>
......
</routes>
......
</module>
......
</modules>
…
</audioPolicyConfiguration>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117