Android 10 版本对音频政策管理器进行了重大重构,有助于更灵活地支持复杂的车载使用情形:
- 提供了 OEM 专用路由策略。
- 针对使用相同音量曲线的旧版音频流类型组提供了可自定义音量组。
- 路由策略由音频政策引擎声明,而不是采用硬编码格式。
- 音量曲线和组由音频政策引擎管理。
- 进行了内部重构,目的是为将来分离公共代码和可配置代码做准备,并提供更丰富的音频设备管理功能。例如,在政策规则中使用所有设备属性,而不仅仅是其类型。
Android 7.0 引入了音频政策配置文件格式 (XML),用于描述音频拓扑。
以前的 Android 版本需要使用 device/<company>/<device>/audio/audio_policy.conf
来声明您的产品上存在的音频设备(您可以在 device/samsung/tuna/audio/audio_policy.conf
中查看此文件针对 Galaxy Nexus 音频硬件的示例)。但是,CONF 是一种简单的专有格式,有较大的局限性,无法描述电视和汽车等行业的复杂拓扑。
Android 7.0 已废弃 audio_policy.conf
并添加了对使用 XML 文件格式定义音频拓扑的支持,该文件格式更易于阅读,可使用各种修改和解析工具,并且足够灵活,可以描述复杂的音频拓扑。Android 7.0 使用 USE_XML_AUDIO_POLICY_CONF
构建标志来选择 XML 格式的配置文件。
XML 格式的优势
与在 CONF 文件中一样,XML 文件支持定义输出输入流配置文件、可用于播放和捕获的设备以及音频属性的数量和类型。此外,XML 格式还提供以下增强功能:
- 在 Android 10 中,允许同时使用多个正在运行的录音应用。
- 开始录音的请求绝不会因为存在并发情况而遭到拒绝。
registerAudioRecordingCallback(AudioManager.AudioRecordingCallback cb)
回调会将捕获路径更改通知客户端。
- 在以下情况下,客户端会获取无声音频样本:
- 对隐私敏感的用例(例如,
VOICE_COMMUNICATION
)处于活动状态。
- 客户端没有前台服务或前台界面。
- 政策识别到了特殊的角色:
- 无障碍服务:即使对隐私敏感的用例处于活动状态,也可以录音。
- Google 助理:如果相应界面位于顶层,则视为隐私敏感。
- 音频配置文件的结构类似于 HDMI 简单音频描述符,支持每种音频格式使用一组不同的采样率/声道掩码。
- 设备和流之间所有可能的连接都有显式定义。以前,隐式规则可以使连接到同一 HAL 模块的所有设备互连,从而阻止音频政策控制使用音频补丁程序 API 请求的连接。在 XML 格式中,拓扑描述定义了连接限制。
- 对“包含”的支持可避免出现重复的标准 A2DP、USB 或重新导向提交定义。
- 音量曲线可自定义。以前,音量表采用硬编码格式。在 XML 格式中,音量表通过描述来定义,并且可自定义。
frameworks/av/services/audiopolicy/config/audio_policy_configuration.xml
中的模板展示了很多已在使用的上述功能。
新的音频政策配置文件是 audio_policy_configuration.xml
,位于 /system/etc
。以下示例显示了适用于 Android 12 及 Android 12 以下版本且采用 XML 文件格式的简单音频政策配置。
显示适用于 Android 12 的音频政策示例
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioPolicyConfiguration version="7.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>
显示适用于 Android 12 以下版本的音频政策示例
<?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>
顶层结构中包含与各个音频 HAL 硬件模块对应的模块,其中每个模块都有一系列混音端口、设备端口和导向:
- 混音端口描述了可以在音频 HAL 处打开以供播放和捕获的流的可能配置文件。
- 设备端口描述了可以附上其类型(以及(可选)地址和音频属性,如果相关)的设备。
- 导向已从混音端口描述符中分离出来,支持描述从设备到设备或从流到设备的导向。
音量表是定义用于将界面索引转换为音量(以 dB 为单位)的曲线的点的简单列表。单独的包含文件提供默认曲线,但每个对应于指定使用情形和设备类别的曲线都可以被替换。
显示音量表示例
<?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>
显示音量示例
<?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>
文件包含
XML 包含 (XInclude) 方法可用于包含位于其他 XML 文件中的音频政策配置信息。所有包含的文件必须遵循上述结构,同时满足以下限制条件:
- 文件只能包含顶层元素。
- 文件不能包含 XInclude 元素。
使用“包含”可避免将标准 Android 开源项目 (AOSP) 音频 HAL 模块配置信息复制到所有音频政策配置文件(这样做容易出错)。我们为以下音频 HAL 提供了标准音频政策配置 XML 文件:
- A2DP:
a2dp_audio_policy_configuration.xml
- 重新导向子混音:
rsubmix_audio_policy_configuration.xml
- USB:
usb_audio_policy_configuration.xml
音频政策代码组织
平台将 AudioPolicyManager.cpp
拆分为多个模块,使其易于维护和配置。frameworks/av/services/audiopolicy
的组织包括以下模块。
模块 |
说明 |
/managerdefault |
包含所有应用通用的常规接口和行为实现。类似于 AudioPolicyManager.cpp ,其引擎功能和通用概念隐藏在抽象出来的接口中。 |
/common |
定义基类(例如,输入输出音频流配置文件、音频设备描述符、音频补丁程序和音频端口的数据结构)。基类之前在 AudioPolicyManager.cpp 中定义。 |
/engine |
实现相关规则,这些规则定义应将哪些设备和音量用于指定用例。该模块会实现标准接口(包含通用部分),例如,为指定的播放或捕获用例获取适当的设备,或设置可以改变导向选择的已连接设备或外部状态(即强制使用的调用状态)。
该模块有两种版本:可配置版本和默认版本。如需了解如何选择版本,请参阅使用参数框架的配置。 |
/engineconfigurable |
依赖参数框架的政策引擎实现(请参阅下文)。配置基于参数框架,相关政策由 XML 文件定义。 |
/enginedefault |
基于以前的 Android 音频政策管理中心实现的政策引擎实现。这是默认模块,包含 Nexus 和 AOSP 实现对应的硬编码规则。 |
/service |
包含 Binder 接口、线程和锁定实现(包含连接框架其余部分的接口)。 |
使用参数框架的配置
平台对音频策略代码进行了组织,使其易于理解和维护,同时也支持完全由配置文件定义的音频政策。组织和音频政策设计基于 Intel 的参数框架,该框架基于插件和规则,用于处理各种参数。
通过使用可配置音频政策,供应商和原始设备制造商 (OEM) 可以:
- 用 XML 来描述系统的结构及其参数。
- 编写(用 C++ 语言)或重复使用后端(插件)来访问所描述的参数。
- 定义(用 XML 或域特定语言)指定参数必须取指定值所依据的条件/规则。
AOSP 中包含使用参数框架的音频政策配置文件示例,路径为:Frameworks/av/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml
。如需了解详情,请参阅介绍参数框架的 Intel 文档。
在 Android 10 或更低版本中,需使用构建选项 USE_CONFIGURABLE_AUDIO_POLICY
选择可配置的音频政策。在 Android 11 或更高版本中,需在 audio_policy_configuration.xml
文件中选择音频政策引擎的版本。如需选择可配置的音频政策引擎,请将 globalConfiguration
元素的 engine_library
属性的值设置为 configurable
,如以下示例所示:
<audioPolicyConfiguration>
<globalConfiguration engine_library="configurable" />
...
</audioPolicyConfiguration>
音频政策导向 API
Android 6.0 引入了一个公共 Enumeration and Selection API,位于音频补丁程序/音频端口基础架构之上。借助它,应用开发者可以为连接的音频录制或轨道指明特定设备输出或输入的偏好设置。
在 Android 7.0 中,Enumeration and Selection API 通过了 CTS 测试的验证,并经过扩展,可导向原生 C/C++ (OpenSL ES) 音频流。原生流的路由仍然由 Java 完成,另外还添加了 AudioRouting
接口,该接口会取代、合并和废弃特定于 AudioTrack
和 AudioRecord
类的显式路由方法。
如需详细了解 Enumeration and Selection API,请参阅 Android 配置接口和 OpenSLES_AndroidConfiguration.h
。如需详细了解音频导向,请参阅 AudioRouting。
多声道支持
如果您的硬件和驱动程序通过 HDMI 支持多声道音频,则可以将音频流直接输出到音频硬件(这样可以绕过 AudioFlinger 混音器,也就不会被降混成两个声道)。音频 HAL 必须公开输出流配置文件是否支持多声道音频功能。如果 HAL 公开其功能,默认的政策管理中心会允许通过 HDMI 进行多声道播放。如需了解实现详情,请参阅 device/samsung/tuna/audio/audio_hw.c
。
如需指定您的产品包含多声道音频输出,请修改音频政策配置文件,对产品的多声道输出进行描述。以下示例来自 frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration_tv.xml
,它展示了动态声道掩码,这表示音频政策管理中心会在连接后查询 HDMI 接收器支持的声道掩码。
显示 HDMI 设备配置示例
<module name="primary" halVersion="2.0">
<attachedDevices>
<item>Speaker</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="direct" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT" />
<mixPort name="tunnel" role="source"
flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC" />
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink" />
<devicePort tagName="Out Aux Digital" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink"
encodedFormats="AUDIO_FORMAT_AC3 AUDIO_FORMAT_IEC61937" />
</devicePorts>
<routes>
<route type="mix" sink="Speaker" sources="primary output"/>
<route type="mix" sink="Out Aux Digital" sources="primary output,direct,tunnel"/>
</routes>
</module>
您也可以指定静态声道掩码,例如 AUDIO_CHANNEL_OUT_5POINT1
。当将内容发送到不支持多声道音频的音频设备时,AudioFlinger 的混音器会自动将该内容降混成立体声。
媒体编解码器
确保针对您的产品正确声明您的硬件和驱动程序支持的音频编解码器。如需了解详情,请参阅向框架公开编解码器。