Parameter Framework - Android AudioPolicy Engine
使用 libaudiopolicyengineconfigurable.so
来取缔默认安卓音频引擎 libaudiopolicyenginedefault.so
,因为默认安卓音频引擎是通过代码来决定策略,然而 libaudiopolicyengineconfigurable 采用读取pfw
类型的文件来实现音频策略配置。
1. 优势
不需要修改代码,直接修改pfw配置文件就可以修改音频策略
2. 启用Parameter framework
-
Android U之前的版本
-
在
audio_policy_configuration.xml
文件中globalConfiguration
字段增加字段:engine_library="configurable"
<globalConfiguration speaker_drc_enabled="false" engine_library="configurable" />
-
Android U之后的版本
-
使用aidl的hal,读取config的时候检测
audio_policy_engine_criterion_types.xml
和audio_policy_engine_criteria.xml
文件存在就会启用
hardware\interfaces\audio\aidl\default\EngineConfigXmlConverter.cpp
void EngineConfigXmlConverter::init() {
...
if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
capSpecificConfig.criteriaV2 =
std::make_optional<>(VALUE_OR_FATAL((convertCapCriteriaCollectionToAidl(
getXsdcConfig()->getCriteria(), getXsdcConfig()->getCriterion_types()))));
...
3. 功能
当前主要是3大配置
<InstanceDefinition>
<Component Name="streams" Type="Streams"/>
<Component Name="input_sources" Type="InputSources"/>
<Component Name="product_strategies" Type="ProductStrategies"/>
</InstanceDefinition>
3.1 输入(input_sources)
device_for_input_source.pfw
不同的audio_source_t使用什么样的输入设备
<ComponentType Name="InputSources" Description="associated to audio_source_t definition,
identifier mapping must match the value of the enum">
<Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
<Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
<Component Name="voice_uplink" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
<Component Name="voice_downlink" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
<Component Name="voice_call" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
<Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
<Component Name="voice_recognition" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
<Component Name="voice_communication" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
<Component Name="remote_submix" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
<Component Name="unprocessed" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
<Component Name="voice_performance" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_VOICE_PERFORMANCE"/>
<Component Name="echo_reference" Type="InputSource"
Mapping="Name:AUDIO_SOURCE_ECHO_REFERENCE"/>
<Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
<Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
</ComponentType>
3.2 输出设备优先级(product_strategies)
device_for_product_strategy_phone.pfw
、device_for_product_strategy_media.pfw
…
不同的product_strategy_t使用什么样的输出设备
<ComponentType Name="ProductStrategies" Description="">
<Component Name="phone" Type="ProductStrategy" Mapping="Name:STRATEGY_PHONE"/>
<Component Name="sonification" Type="ProductStrategy" Mapping="Name:STRATEGY_SONIFICATION"/>
<Component Name="enforced_audible" Type="ProductStrategy" Mapping="Name:STRATEGY_ENFORCED_AUDIBLE"/>
<Component Name="accessibility" Type="ProductStrategy" Mapping="Name:STRATEGY_ACCESSIBILITY"/>
<Component Name="sonification_respectful" Type="ProductStrategy" Mapping="Name:STRATEGY_SONIFICATION_RESPECTFUL"/>
<Component Name="media" Type="ProductStrategy" Mapping="Name:STRATEGY_MEDIA"/>
<Component Name="dtmf" Type="ProductStrategy" Mapping="Name:STRATEGY_DTMF"/>
<Component Name="transmitted_through_speaker" Type="ProductStrategy" Mapping="Name:STRATEGY_TRANSMITTED_THROUGH_SPEAKER"/>
<Component Name="assistant" Type="ProductStrategy" Mapping="Name:STRATEGY_ASSISTANT"/>
</ComponentType>
3.3 音量曲线切换(streams)
volumes.pfw
不同的audio_stream_type_t使用哪个stream type的音量曲线
eg: system的stream可以使用music的音量曲线
<ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
<Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
<Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
<Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
<Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
<Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
<Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
<Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
<Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
Description="Sounds that cannot be muted by user and must be routed to speaker"/>
<Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
<Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
<Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
Description="For accessibility talk back prompts"/>
<Component Name="assistant" Type="Stream" Mapping="Name:AUDIO_STREAM_ASSISTANT"
Description="used by a virtual assistant like Google Assistant, Bixby, etc."/>
<Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
Description="For dynamic policy output mixes"/>
<Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
Description="For internal audio flinger tracks. Fixed volume"/>
</ComponentType>
4. 配置pfw文件
4.1 supDomain
- supDomain定义是对Strategy进行分类命名,可以任意修改
- 可以定义多级supDomain,生成的xml中是以"."分隔
(eg: DeviceForProductStrategy.Media)
supDomain: DeviceForProductStrategy
supDomain: Media
domain: Device1
conf: ForceUseBtA2dpSpeaker
AvailableOutputDevices Includes BLUETOOTH_A2DP_SPEAKER
ForceUseForMedia Is BT_A2DP
component: /Policy/policy/product_strategies/vx_1005/selected_output_devices/mask
speaker = 0
spdif = 0
bluetooth_a2dp_speaker = 1
...
4.2 domain
- supDomain下面可以配置多个domain
- 多个domain的device是共存的
- 同一supDomain中不同的domain中不能配置相同的device
eg:下面Assistant的Strategy中配置了2个domain(Device1、Device2),ARC可以跟其他device共存
supDomain: DeviceForProductStrategy
supDomain: Assistant
domain: Device1
conf: RemoteSubmix
AvailableOutputDevices Includes REMOTE_SUBMIX
AvailableOutputDevicesAddresses Includes 0
component: /Policy/policy/product_strategies/assistant/selected_output_devices/mask
speaker = 0
remote_submix = 1
...
domain: Device2
#
# these following domains consists in device(s) that can co-exist with others
# e.g. ARC, SPDIF, AUX_LINE
#
conf: Selected
AvailableOutputDevices Includes HDMI_ARC
component: /Policy/policy/product_strategies/assistant/selected_output_devices/mask
hdmi_arc = 1
conf: NotSelected
component: /Policy/policy/product_strategies/assistant/selected_output_devices/mask
hdmi_arc = 0
...
4.3 config
- 每一个domain下面的config相当于代码中的switch-case语句。放在前面的config先被执行到。
- 满足config条件才会被使用,之后不再执行同一domain下的config。如果不满足条件则进行下一个config条件检查。
domain: Device1
conf: ForceUseBtA2dpSpeaker
AvailableOutputDevices Includes BLUETOOTH_A2DP_SPEAKER
ForceUseForMedia Is BT_A2DP
component: /Policy/policy/product_strategies/vx_1005/selected_output_devices/mask
speaker = 0
spdif = 0
hdmi = 0
hdmi_arc = 0
bluetooth_a2dp_speaker = 1
usb_device = 0
conf: UsbDevice
AvailableOutputDevices Includes USB_DEVICE
component: /Policy/policy/product_strategies/vx_1005/selected_output_devices/mask
speaker = 0
spdif = 0
hdmi = 0
hdmi_arc = 0
bluetooth_a2dp_speaker = 0
usb_device = 1
4.3.1 criterion (准则/标准)
每个criterion 定义: pfw中所有能使用的准则类型 audio_policy_engine_criteria.xml
frameworks/av/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criteria.xml
<criteria>
<criterion name="AvailableInputDevices" type="InputDevicesMaskType" default="none"/>
<criterion name="AvailableOutputDevices" type="OutputDevicesMaskType" default="none"/>
<criterion name="ForceUseForMedia" type="ForceUseForMediaType" default="ForceNone"/>
...
</criteria>
4.3.2 每个criterion的值:每个准则类型的值
/vendor/etc/audio_policy_engine_criteria.xml
是audio_policy_engine_criterion_types
python脚本根据audio_policy_engine_criterion_types.xml.in
文件自动生成。
- Android 16使用Google最新的
capBuildPolicyCriterionTypes.py
,之前安卓版本使用buildPolicyCriterionTypes.py
的Python脚本。
frameworks/av/services/audiopolicy/engineconfigurable/tools/
frameworks/av/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types.xml.in
<criterion_types>
<criterion_type name="OutputDevicesMaskType" type="inclusive">
<values>
<value literal="EARPIECE" android_type="0x1"/>
<value literal="SPEAKER" android_type="0x2"/>
<value literal="WIRED_HEADSET" android_type="0x4"/>
<value literal="WIRED_HEADPHONE" android_type="0x8"/>
<value literal="BLUETOOTH_SCO" android_type="0x10"/>
<value literal="BLUETOOTH_SCO_HEADSET" android_type="0x20"/>
<value literal="BLUETOOTH_SCO_CARKIT" android_type="0x40"/>
<value literal="BLUETOOTH_A2DP" android_type="0x80"/>
<value literal="BLUETOOTH_A2DP_HEADPHONES" android_type="0x100"/>
<value literal="BLUETOOTH_A2DP_SPEAKER" android_type="0x200"/>
</values>
</criterion_type>
...
<criterion_type name="ForceUseForMediaType" type="exclusive">
<values>
<value literal="ForceNone" numerical="0"/>
<value literal="ForceSpeaker" numerical="1"/>
<value literal="ForceHeadphones" numerical="2"/>
<value literal="ForceBtA2dp" numerical="4"/>
<value literal="ForceWiredAccessory" numerical="5"/>
<value literal="ForceAnalogDock" numerical="8"/>
<value literal="ForceDigitalDock" numerical="9"/>
<value literal="ForceNoBtA2dp" numerical="10"/>
</values>
</criterion_type>
...
4.3.3 使用criterion
例如:配置输出设备策略
conf: UsbDevice
AvailableOutputDevices Includes USB_DEVICE
AvailableOutputDevices Excludes WIRED_HEADPHONE
ANY
ForceUseForCommunication Is BT_SCO
ALL
ForceUseForCommunication Is SPEAKER
TelephonyMode IsNot IN_CALL
component: /Policy/policy/product_strategies/vx_1000/selected_output_devices/mask
...
usb_accessory = 0
usb_device = 1
usb_headset = 0
speaker = 0
...
上面的config转化为伪代码的case:
if (AvailableOutputDevices 存在 USB_DEVICE) {
if (AvailableOutputDevices 不存在 WIRED_HEADPHONE) {
if (ForceUseForCommunication == BT_SCO ||
(ForceUseForCommunication == SPEAKER && TelephonyMode != IN_CALL)) {
return USB_DEVICE;
}
}
}
当前Google pfw支持3个SubSystem(Stream、InputSource、ProductStrategy)
frameworks\av\services\audiopolicy\engineconfigurable\parameter-framework\plugin\PolicySubsystem.cpp
// Provide creators to upper layer
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Stream>(
mStreamComponentName,
(1 << MappingKeyName))
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<InputSource>(
mInputSourceComponentName,
(1 << MappingKeyName))
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<ProductStrategy>(
mProductStrategyComponentName, (1 << MappingKeyName))
);
分别通过下面3个函数推送到Engine中
frameworks\av\services\audiopolicy\engineconfigurable\parameter-framework\plugin\
/vendor/etc/parameter-framework/Structure/Policy/PolicySubsystem-CommonTypes.xml
5.1 快速debug
修改完对应的pfw文件之后
parameter framework的pfw所在路径下mm -j
,将/vendor/etc/parameter-framework/
目录替换到平台即可