Parameter Framework - Android AudioPolicy Engine
使用 libengineconfigurable.so
来取缔默认安卓音频引擎 libenginedefault.so
,因为默认安卓音频引擎是通过代码来决定策略,然而 libengineconfigurable 采用读取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)
不同的audio_source_t使用什么样的输入设备
<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>
3.2 输出设备优先级(product_strategies)
不同的product_strategy_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.3 音量曲线切换(streams)
不同的audio_stream_type_t使用哪个stream type的音量曲线
<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>
4. 配置pfw文件
4.1 supDomain
- supDomain定义是对Strategy进行分类命名,可以任意修改
- 可以定义多级supDomain,生成的xml中是以"."分隔
(eg: DeviceForProductStrategy.Media)
supDomain: DeviceForProductStrategysupDomain: Mediadomain: Device1conf: ForceUseBtA2dpSpeakerAvailableOutputDevices Includes BLUETOOTH_A2DP_SPEAKERForceUseForMedia Is BT_A2DPcomponent: /Policy/policy/product_strategies/vx_1005/selected_output_devices/maskspeaker = 0spdif = 0bluetooth_a2dp_speaker = 1
...
4.2 domain
- supDomain下面可以配置多个domain
- 多个domain的device是共存的
- 同一supDomain中不同的domain中不能配置相同的device
eg:下面Assistant的Strategy中配置了2个domain(Device1、Device2),ARC可以跟其他device共存
supDomain: DeviceForProductStrategysupDomain: Assistantdomain: Device1conf: RemoteSubmixAvailableOutputDevices Includes REMOTE_SUBMIXAvailableOutputDevicesAddresses Includes 0component: /Policy/policy/product_strategies/assistant/selected_output_devices/maskspeaker = 0remote_submix = 1
...domain: Device2## these following domains consists in device(s) that can co-exist with others# e.g. ARC, SPDIF, AUX_LINE#conf: SelectedAvailableOutputDevices Includes HDMI_ARCcomponent: /Policy/policy/product_strategies/assistant/selected_output_devices/maskhdmi_arc = 1conf: NotSelectedcomponent: /Policy/policy/product_strategies/assistant/selected_output_devices/maskhdmi_arc = 0
...
4.3 config
- 每一个domain下面的config相当于代码中的switch-case语句。放在前面的config先被执行到。
- 满足config条件才会被使用,之后不再执行同一domain下的config。如果不满足条件则进行下一个config条件检查。
domain: Device1conf: ForceUseBtA2dpSpeakerAvailableOutputDevices Includes BLUETOOTH_A2DP_SPEAKERForceUseForMedia Is BT_A2DPcomponent: /Policy/policy/product_strategies/vx_1005/selected_output_devices/maskspeaker = 0spdif = 0hdmi = 0hdmi_arc = 0bluetooth_a2dp_speaker = 1usb_device = 0conf: UsbDeviceAvailableOutputDevices Includes USB_DEVICEcomponent: /Policy/policy/product_strategies/vx_1005/selected_output_devices/maskspeaker = 0spdif = 0hdmi = 0hdmi_arc = 0bluetooth_a2dp_speaker = 0usb_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: UsbDeviceAvailableOutputDevices Includes USB_DEVICEAvailableOutputDevices Excludes WIRED_HEADPHONEANYForceUseForCommunication Is BT_SCOALLForceUseForCommunication Is SPEAKERTelephonyMode IsNot IN_CALLcomponent: /Policy/policy/product_strategies/vx_1000/selected_output_devices/mask
...usb_accessory = 0usb_device = 1usb_headset = 0speaker = 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 layeraddSubsystemObjectFactory(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文件之后
device/amlogic/common/audio
路径下mm -j
,将/vendor/etc/parameter-framework/
目录替换到平台即可