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/
目錄替換到平臺即可