xref: /aosp_15_r20/frameworks/av/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cinttypes>
18 #include <cstdint>
19 #include <istream>
20 #include <map>
21 #include <sstream>
22 #include <stdarg.h>
23 #include <string>
24 #include <string>
25 #include <vector>
26 
27 #define LOG_TAG "APM::AudioPolicyEngine/CapConfig"
28 //#define LOG_NDEBUG 0
29 
30 #include "CapEngineConfig.h"
31 #include <TypeConverter.h>
32 #include <Volume.h>
33 #include <cutils/properties.h>
34 #include <media/AidlConversion.h>
35 #include <media/AidlConversionCppNdk.h>
36 #include <media/AidlConversionUtil.h>
37 #include <media/TypeConverter.h>
38 #include <media/convert.h>
39 #include <system/audio_config.h>
40 #include <utils/Log.h>
41 
42 namespace android {
43 
44 using base::unexpected;
45 using media::audio::common::AudioDeviceAddress;
46 using media::audio::common::AudioDeviceDescription;
47 using media::audio::common::AudioHalCapCriterion;
48 using media::audio::common::AudioHalCapCriterionV2;
49 using media::audio::common::AudioHalCapParameter;
50 using media::audio::common::AudioHalCapRule;
51 using media::audio::common::AudioPolicyForceUse;
52 using media::audio::common::AudioSource;
53 using media::audio::common::AudioStreamType;
54 using utilities::convertTo;
55 
56 namespace capEngineConfig {
57 
58 static constexpr const char *gLegacyOutputDevicePrefix = "AUDIO_DEVICE_OUT_";
59 static constexpr const char *gLegacyInputDevicePrefix = "AUDIO_DEVICE_IN_";
60 static constexpr const char *gLegacyForcePrefix = "AUDIO_POLICY_FORCE_";
61 static constexpr const char *gLegacyStreamPrefix = "AUDIO_STREAM_";
62 static constexpr const char *gLegacySourcePrefix = "AUDIO_SOURCE_";
63 static constexpr const char *gPolicyParamPrefix = "/Policy/policy/";
64 
65 namespace {
66 
truncatePrefixToLower(const std::string & legacyName,const std::string & legacyPrefix)67 ConversionResult<std::string> truncatePrefixToLower(const std::string& legacyName,
68                                                     const std::string& legacyPrefix) {
69     std::size_t pos = legacyName.find(legacyPrefix);
70     if (pos == std::string::npos) {
71         return unexpected(BAD_VALUE);
72     }
73     std::string capName = legacyName.substr(pos + legacyPrefix.length());
74     std::transform(capName.begin(), capName.end(), capName.begin(),
75                    [](unsigned char c) { return std::tolower(c); });
76     return capName;
77 }
78 
truncatePrefix(const std::string & name,const std::string & prefix)79 ConversionResult<std::string> truncatePrefix(const std::string& name,  const std::string& prefix) {
80     std::size_t pos = name.find(prefix);
81     if (pos == std::string::npos) {
82         return unexpected(BAD_VALUE);
83     }
84     std::string capName = name.substr(pos + prefix.length());
85     return capName;
86 }
87 
88 ConversionResult<audio_policy_forced_cfg_t>
aidl2legacy_AudioPolicyForceUseCommunicationDeviceCategory_audio_policy_forced_cfg_t(const AudioPolicyForceUse::CommunicationDeviceCategory aidl)89         aidl2legacy_AudioPolicyForceUseCommunicationDeviceCategory_audio_policy_forced_cfg_t(
90         const AudioPolicyForceUse::CommunicationDeviceCategory aidl) {
91     switch (aidl) {
92         case AudioPolicyForceUse::CommunicationDeviceCategory::NONE:
93             return AUDIO_POLICY_FORCE_NONE;
94         case AudioPolicyForceUse::CommunicationDeviceCategory::SPEAKER:
95             return AUDIO_POLICY_FORCE_SPEAKER;
96         case AudioPolicyForceUse::CommunicationDeviceCategory::BT_SCO:
97             return AUDIO_POLICY_FORCE_BT_SCO;
98         case AudioPolicyForceUse::CommunicationDeviceCategory::BT_BLE:
99             return AUDIO_POLICY_FORCE_BT_BLE;
100         case AudioPolicyForceUse::CommunicationDeviceCategory::WIRED_ACCESSORY:
101             return AUDIO_POLICY_FORCE_WIRED_ACCESSORY;
102     }
103     return unexpected(BAD_VALUE);
104 }
105 
106 ConversionResult<audio_policy_forced_cfg_t>
aidl2legacy_AudioPolicyForceUseMediaDeviceCategory_audio_policy_forced_cfg_t(const AudioPolicyForceUse::MediaDeviceCategory aidl)107         aidl2legacy_AudioPolicyForceUseMediaDeviceCategory_audio_policy_forced_cfg_t(
108         const AudioPolicyForceUse::MediaDeviceCategory aidl) {
109     switch (aidl) {
110         case AudioPolicyForceUse::MediaDeviceCategory::NONE:
111             return AUDIO_POLICY_FORCE_NONE;
112         case AudioPolicyForceUse::MediaDeviceCategory::SPEAKER:
113             return AUDIO_POLICY_FORCE_SPEAKER;
114         case AudioPolicyForceUse::MediaDeviceCategory::HEADPHONES:
115             return AUDIO_POLICY_FORCE_HEADPHONES;
116         case AudioPolicyForceUse::MediaDeviceCategory::BT_A2DP:
117             return AUDIO_POLICY_FORCE_BT_A2DP;
118         case AudioPolicyForceUse::MediaDeviceCategory::ANALOG_DOCK:
119             return AUDIO_POLICY_FORCE_ANALOG_DOCK;
120         case AudioPolicyForceUse::MediaDeviceCategory::DIGITAL_DOCK:
121             return AUDIO_POLICY_FORCE_DIGITAL_DOCK;
122         case AudioPolicyForceUse::MediaDeviceCategory::WIRED_ACCESSORY:
123             return AUDIO_POLICY_FORCE_WIRED_ACCESSORY;
124         case AudioPolicyForceUse::MediaDeviceCategory::NO_BT_A2DP:
125             return AUDIO_POLICY_FORCE_NO_BT_A2DP;
126     }
127     return unexpected(BAD_VALUE);
128 }
129 
130 ConversionResult<audio_policy_forced_cfg_t>
aidl2legacy_AudioPolicyForceUseDockType_audio_policy_forced_cfg_t(const AudioPolicyForceUse::DockType aidl)131         aidl2legacy_AudioPolicyForceUseDockType_audio_policy_forced_cfg_t(
132         const AudioPolicyForceUse::DockType aidl) {
133     switch (aidl) {
134         case AudioPolicyForceUse::DockType::NONE:
135             return AUDIO_POLICY_FORCE_NONE;
136         case AudioPolicyForceUse::DockType::BT_CAR_DOCK:
137             return AUDIO_POLICY_FORCE_BT_CAR_DOCK;
138         case AudioPolicyForceUse::DockType::BT_DESK_DOCK:
139             return AUDIO_POLICY_FORCE_BT_DESK_DOCK;
140         case AudioPolicyForceUse::DockType::ANALOG_DOCK:
141             return AUDIO_POLICY_FORCE_ANALOG_DOCK;
142         case AudioPolicyForceUse::DockType::DIGITAL_DOCK:
143             return AUDIO_POLICY_FORCE_DIGITAL_DOCK;
144         case AudioPolicyForceUse::DockType::WIRED_ACCESSORY:
145             return AUDIO_POLICY_FORCE_WIRED_ACCESSORY;
146     }
147     return unexpected(BAD_VALUE);
148 }
149 
150 ConversionResult<audio_policy_forced_cfg_t>
aidl2legacy_AudioPolicyForceUseEncodedSurroundConfig_audio_policy_forced_cfg_t(const AudioPolicyForceUse::EncodedSurroundConfig aidl)151         aidl2legacy_AudioPolicyForceUseEncodedSurroundConfig_audio_policy_forced_cfg_t(
152         const AudioPolicyForceUse::EncodedSurroundConfig aidl) {
153     switch (aidl) {
154         case AudioPolicyForceUse::EncodedSurroundConfig::UNSPECIFIED:
155             return AUDIO_POLICY_FORCE_NONE;
156         case AudioPolicyForceUse::EncodedSurroundConfig::NEVER:
157             return AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER;
158         case AudioPolicyForceUse::EncodedSurroundConfig::ALWAYS:
159             return AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS;
160         case AudioPolicyForceUse::EncodedSurroundConfig::MANUAL:
161             return AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL;
162     }
163     return unexpected(BAD_VALUE);
164 }
165 
166 ConversionResult<std::pair<audio_policy_force_use_t, audio_policy_forced_cfg_t>>
aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t_audio_policy_forced_cfg_t(const AudioPolicyForceUse & aidl)167         aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t_audio_policy_forced_cfg_t(
168         const AudioPolicyForceUse& aidl) {
169     switch (aidl.getTag()) {
170         case AudioPolicyForceUse::forCommunication:
171             return std::make_pair(
172                     AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
173                     VALUE_OR_RETURN(
174                             aidl2legacy_AudioPolicyForceUseCommunicationDeviceCategory_audio_policy_forced_cfg_t(
175                                     aidl.get<AudioPolicyForceUse::forCommunication>())));
176         case AudioPolicyForceUse::forMedia:
177             return std::make_pair(
178                     AUDIO_POLICY_FORCE_FOR_MEDIA,
179                     VALUE_OR_RETURN(
180                             aidl2legacy_AudioPolicyForceUseMediaDeviceCategory_audio_policy_forced_cfg_t(
181                                     aidl.get<AudioPolicyForceUse::forMedia>())));
182         case AudioPolicyForceUse::forRecord:
183             return std::make_pair(
184                     AUDIO_POLICY_FORCE_FOR_RECORD,
185                     VALUE_OR_RETURN(
186                             aidl2legacy_AudioPolicyForceUseCommunicationDeviceCategory_audio_policy_forced_cfg_t(
187                                     aidl.get<AudioPolicyForceUse::forRecord>())));
188         case AudioPolicyForceUse::dock:
189             return std::make_pair(AUDIO_POLICY_FORCE_FOR_DOCK,
190                     VALUE_OR_RETURN(
191                             aidl2legacy_AudioPolicyForceUseDockType_audio_policy_forced_cfg_t(
192                                     aidl.get<AudioPolicyForceUse::dock>())));
193         case AudioPolicyForceUse::systemSounds:
194             return std::make_pair(AUDIO_POLICY_FORCE_FOR_SYSTEM,
195                     aidl.get<AudioPolicyForceUse::systemSounds>() ?
196                     AUDIO_POLICY_FORCE_SYSTEM_ENFORCED : AUDIO_POLICY_FORCE_NONE);
197         case AudioPolicyForceUse::hdmiSystemAudio:
198             return std::make_pair(
199                     AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO,
200                     aidl.get<AudioPolicyForceUse::hdmiSystemAudio>() ?
201                     AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : AUDIO_POLICY_FORCE_NONE);
202         case AudioPolicyForceUse::encodedSurround:
203             return std::make_pair(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, VALUE_OR_RETURN(
204                 aidl2legacy_AudioPolicyForceUseEncodedSurroundConfig_audio_policy_forced_cfg_t(
205                         aidl.get<AudioPolicyForceUse::encodedSurround>())));
206         case AudioPolicyForceUse::forVibrateRinging:
207             return std::make_pair(
208                     AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING,
209                     VALUE_OR_RETURN(
210                             aidl2legacy_AudioPolicyForceUseCommunicationDeviceCategory_audio_policy_forced_cfg_t(
211                                     aidl.get<AudioPolicyForceUse::forVibrateRinging>())));
212     }
213     return unexpected(BAD_VALUE);
214 }
215 
aidl2legacy_AudioHalCapCriterionV2_CapName(const AudioHalCapCriterionV2 & aidl)216 ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2_CapName(
217         const AudioHalCapCriterionV2& aidl) {
218     switch (aidl.getTag()) {
219         case AudioHalCapCriterionV2::availableInputDevices:
220             return gInputDeviceCriterionName;
221         case AudioHalCapCriterionV2::availableOutputDevices:
222             return gOutputDeviceCriterionName;
223         case AudioHalCapCriterionV2::availableInputDevicesAddresses:
224             return gInputDeviceAddressCriterionName;
225         case AudioHalCapCriterionV2::availableOutputDevicesAddresses:
226             return gOutputDeviceAddressCriterionName;
227         case AudioHalCapCriterionV2::telephonyMode:
228             return gPhoneStateCriterionName;
229         case AudioHalCapCriterionV2::forceConfigForUse: {
230             auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>().values[0];
231             const auto [forceUse, _] = VALUE_OR_RETURN(
232                 aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t_audio_policy_forced_cfg_t(
233                         aidlCriterion));
234             return gForceUseCriterionTag[forceUse];
235         }
236     }
237     return unexpected(BAD_VALUE);
238 }
239 
aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(const AudioDeviceDescription & aidl)240 ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
241         const AudioDeviceDescription& aidl) {
242     audio_devices_t legacyDeviceType = VALUE_OR_RETURN(
243             aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl));
244     bool isOut = audio_is_output_devices(legacyDeviceType);
245     std::string legacyTypeLiteral;
246     if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
247         ALOGE("%s Invalid strategy device type %d", __func__, legacyDeviceType);
248         return unexpected(BAD_VALUE);
249     }
250     return truncatePrefix(legacyTypeLiteral,
251             isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix);
252 }
253 
254 ConversionResult<audio_policy_forced_cfg_t>
aidl2legacy_AudioHalCapCriterionV2ForceUse_audio_policy_forced_cfg_t(const AudioPolicyForceUse & aidl)255         aidl2legacy_AudioHalCapCriterionV2ForceUse_audio_policy_forced_cfg_t(
256         const AudioPolicyForceUse& aidl) {
257     const auto [_, legacyForcedCfg] = VALUE_OR_RETURN(
258             aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t_audio_policy_forced_cfg_t(
259                     aidl));
260     return legacyForcedCfg;
261 }
262 
audio_policy_forced_cfg_t_CapCriterionValue(audio_policy_forced_cfg_t legacyForcedCfg)263 ConversionResult<std::string> audio_policy_forced_cfg_t_CapCriterionValue(
264         audio_policy_forced_cfg_t legacyForcedCfg) {
265     std::string legacyForcedCfgLiteral = audio_policy_forced_cfg_to_string(legacyForcedCfg);
266     if (legacyForcedCfgLiteral.empty()) {
267         ALOGE("%s Invalid forced config value %d", __func__, legacyForcedCfg);
268         return unexpected(BAD_VALUE);
269     }
270     return truncatePrefix(legacyForcedCfgLiteral, gLegacyForcePrefix);
271 }
272 
aidl2legacy_AudioHalCapCriterionV2ForceUse_CapCriterionValue(const AudioPolicyForceUse & aidl)273 ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2ForceUse_CapCriterionValue(
274         const AudioPolicyForceUse& aidl) {
275     const audio_policy_forced_cfg_t legacyForcedCfg = VALUE_OR_RETURN(
276             aidl2legacy_AudioHalCapCriterionV2ForceUse_audio_policy_forced_cfg_t(aidl));
277     return audio_policy_forced_cfg_t_CapCriterionValue(legacyForcedCfg);
278 }
279 
aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(const AudioHalCapCriterionV2 & aidl)280 ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
281         const AudioHalCapCriterionV2& aidl) {
282     switch (aidl.getTag()) {
283         case AudioHalCapCriterionV2::availableInputDevices:
284             return aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
285                     aidl.get<AudioHalCapCriterionV2::availableInputDevices>().values[0]);
286         case AudioHalCapCriterionV2::availableOutputDevices:
287             return aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
288                     aidl.get<AudioHalCapCriterionV2::availableOutputDevices>().values[0]);
289         case AudioHalCapCriterionV2::availableInputDevicesAddresses:
290             return aidl.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>().values[0].
291                     template get<AudioDeviceAddress::id>();
292         case AudioHalCapCriterionV2::availableOutputDevicesAddresses:
293             return aidl.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>().values[0].
294                     template get<AudioDeviceAddress::id>();
295         case AudioHalCapCriterionV2::telephonyMode:
296             return toString(aidl.get<AudioHalCapCriterionV2::telephonyMode>().values[0]);
297         case AudioHalCapCriterionV2::forceConfigForUse:
298             return aidl2legacy_AudioHalCapCriterionV2ForceUse_CapCriterionValue(
299                     aidl.get<AudioHalCapCriterionV2::forceConfigForUse>().values[0]);
300     }
301     return unexpected(BAD_VALUE);
302 }
303 
aidl2legacy_AudioHalCapRule_CapRule(const AudioHalCapRule & aidlRule)304 ConversionResult<std::string> aidl2legacy_AudioHalCapRule_CapRule(
305         const AudioHalCapRule& aidlRule) {
306     std::string rule;
307     switch (aidlRule.compoundRule) {
308         case AudioHalCapRule::CompoundRule::ANY:
309             rule += "Any";
310             break;
311         case AudioHalCapRule::CompoundRule::ALL:
312             rule += "All";
313             break;
314         default:
315             return unexpected(BAD_VALUE);
316     }
317     rule += "{";
318     if (!aidlRule.nestedRules.empty()) {
319         for (const auto& nestedRule: aidlRule.nestedRules) {
320             rule += VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(nestedRule));
321         }
322         if (!aidlRule.criterionRules.empty()) {
323             rule += ",";
324         }
325     }
326     bool isFirstCriterionRule = true;
327     for (const auto& criterionRule: aidlRule.criterionRules) {
328         if (!isFirstCriterionRule) {
329             rule += ",";
330         }
331         isFirstCriterionRule = false;
332         std::string selectionCriterion = VALUE_OR_RETURN(
333                 aidl2legacy_AudioHalCapCriterionV2_CapName(criterionRule.criterionAndValue));
334         std::string matchesWhen;
335         std::string value = VALUE_OR_RETURN(
336                 aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
337                         criterionRule.criterionAndValue));
338 
339         switch (criterionRule.matchingRule) {
340             case AudioHalCapRule::MatchingRule::IS:
341                 matchesWhen = "Is";
342                 break;
343             case AudioHalCapRule::MatchingRule::IS_NOT:
344                 matchesWhen = "IsNot";
345                 break;
346             case AudioHalCapRule::MatchingRule::INCLUDES:
347                 matchesWhen = "Includes";
348                 break;
349             case AudioHalCapRule::MatchingRule::EXCLUDES:
350                 matchesWhen = "Excludes";
351                 break;
352             default:
353                 return unexpected(BAD_VALUE);
354         }
355         rule += selectionCriterion + " " + matchesWhen + " " + value;
356     }
357     rule += "}";
358     return rule;
359 }
360 
aidl2legacy_AudioHalCapConfiguration_CapConfiguration(const media::audio::common::AudioHalCapConfiguration & aidl)361 ConversionResult<CapConfiguration> aidl2legacy_AudioHalCapConfiguration_CapConfiguration(
362         const media::audio::common::AudioHalCapConfiguration& aidl) {
363     CapConfiguration legacy;
364     legacy.name = aidl.name;
365     legacy.rule = VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(aidl.rule));
366     return legacy;
367 }
368 
aidl2legacy_ParameterSetting_ConfigurableElementValue(const AudioHalCapParameter & aidl)369 ConversionResult<ConfigurableElementValue> aidl2legacy_ParameterSetting_ConfigurableElementValue(
370         const AudioHalCapParameter& aidl) {
371     ConfigurableElementValue legacy;
372     std::string literalValue;
373     switch (aidl.getTag()) {
374         case AudioHalCapParameter::selectedStrategyDevice: {
375             auto strategyDevice = aidl.get<AudioHalCapParameter::selectedStrategyDevice>();
376             literalValue = std::to_string(strategyDevice.isSelected);
377             audio_devices_t legacyType = VALUE_OR_RETURN(
378                     aidl2legacy_AudioDeviceDescription_audio_devices_t(strategyDevice.device));
379             std::string legacyTypeLiteral;
380             if (!::android::OutputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
381                 ALOGE("%s Invalid device type %d", __func__, legacyType);
382                 return unexpected(BAD_VALUE);
383             }
384             std::string deviceLiteral = VALUE_OR_RETURN(
385                     truncatePrefixToLower(legacyTypeLiteral, gLegacyOutputDevicePrefix));
386             if (deviceLiteral == "default") {
387                 deviceLiteral = "stub";
388             }
389             legacy.configurableElement.path = std::string(gPolicyParamPrefix)
390                     + "product_strategies/vx_" + std::to_string(strategyDevice.id)
391                     + "/selected_output_devices/mask/" + deviceLiteral;
392             break;
393         }
394         case AudioHalCapParameter::strategyDeviceAddress: {
395             auto strategyAddress = aidl.get<AudioHalCapParameter::strategyDeviceAddress>();
396             legacy.configurableElement.path = std::string(gPolicyParamPrefix)
397                     + "product_strategies/vx_" + std::to_string(strategyAddress.id)
398                     + "/device_address";
399             literalValue = strategyAddress.deviceAddress.get<AudioDeviceAddress::id>();
400             break;
401         }
402         case AudioHalCapParameter::selectedInputSourceDevice: {
403             auto inputSourceDevice = aidl.get<AudioHalCapParameter::selectedInputSourceDevice>();
404             literalValue = std::to_string(inputSourceDevice.isSelected);
405             audio_devices_t legacyType = VALUE_OR_RETURN(
406                     aidl2legacy_AudioDeviceDescription_audio_devices_t(inputSourceDevice.device));
407             std::string legacyTypeLiteral;
408             if (!::android::InputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
409                 ALOGE("%s Invalid input source device type %d", __func__, legacyType);
410                 return unexpected(BAD_VALUE);
411             }
412             std::string deviceLiteral = VALUE_OR_RETURN(
413                     truncatePrefixToLower(legacyTypeLiteral, gLegacyInputDevicePrefix));
414             if (deviceLiteral == "default") {
415                 deviceLiteral = "stub";
416             }
417             audio_source_t legacySource = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
418                     inputSourceDevice.inputSource));
419             std::string inputSourceLiteral;
420             if (!::android::SourceTypeConverter::toString(legacySource, inputSourceLiteral)) {
421                 ALOGE("%s Invalid input source  %d", __func__, legacySource);
422                 return unexpected(BAD_VALUE);
423             }
424             inputSourceLiteral = VALUE_OR_RETURN(
425                     truncatePrefixToLower(inputSourceLiteral, gLegacySourcePrefix));
426             legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "input_sources/"
427                     + inputSourceLiteral + "/applicable_input_device/mask/" + deviceLiteral;
428             break;
429         }
430         case AudioHalCapParameter::streamVolumeProfile: {
431             auto streamVolumeProfile = aidl.get<AudioHalCapParameter::streamVolumeProfile>();
432             audio_stream_type_t legacyStreamType = VALUE_OR_RETURN(
433                     aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.stream));
434             std::string legacyStreamLiteral;
435             if (!::android::StreamTypeConverter::toString(legacyStreamType, legacyStreamLiteral)) {
436                 ALOGE("%s Invalid stream type  %d", __func__, legacyStreamType);
437                 return unexpected(BAD_VALUE);
438             }
439             legacyStreamLiteral = VALUE_OR_RETURN(
440                     truncatePrefixToLower(legacyStreamLiteral, gLegacyStreamPrefix));
441 
442             audio_stream_type_t legacyProfile = VALUE_OR_RETURN(
443                     aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.profile));
444             std::string legacyProfileLiteral;
445             if (!::android::StreamTypeConverter::toString(legacyProfile, legacyProfileLiteral)) {
446                 ALOGE("%s Invalid profile %d", __func__, legacyProfile);
447                 return unexpected(BAD_VALUE);
448             }
449             literalValue = VALUE_OR_RETURN(
450                     truncatePrefixToLower(legacyProfileLiteral, gLegacyStreamPrefix));
451             legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "streams/"
452                     + legacyStreamLiteral + "/applicable_volume_profile/volume_profile";
453             break;
454         }
455         default:
456             return unexpected(BAD_VALUE);
457     }
458     legacy.value = literalValue;
459     return legacy;
460 }
461 
aidl2legacy_AudioHalCapConfiguration_CapSetting(const media::audio::common::AudioHalCapConfiguration & aidl)462 ConversionResult<CapSetting> aidl2legacy_AudioHalCapConfiguration_CapSetting(
463         const media::audio::common::AudioHalCapConfiguration& aidl) {
464     CapSetting legacy;
465     legacy.configurationName = aidl.name;
466     legacy.configurableElementValues = VALUE_OR_RETURN(convertContainer<ConfigurableElementValues>(
467             aidl.parameterSettings, aidl2legacy_ParameterSetting_ConfigurableElementValue));
468     return legacy;
469 }
470 
aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(const media::audio::common::AudioHalCapDomain & aidl)471 ConversionResult<CapConfigurableDomain> aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(
472         const media::audio::common::AudioHalCapDomain& aidl) {
473     CapConfigurableDomain legacy;
474     legacy.name = aidl.name;
475     legacy.configurations = VALUE_OR_RETURN(convertContainer<CapConfigurations>(
476             aidl.configurations,
477             aidl2legacy_AudioHalCapConfiguration_CapConfiguration));
478     legacy.settings = VALUE_OR_RETURN(convertContainer<CapSettings>(
479             aidl.configurations,
480             aidl2legacy_AudioHalCapConfiguration_CapSetting));
481     return legacy;
482 }
483 
aidl2legacy_AudioHalCapCriterionV2_Criterion(const AudioHalCapCriterionV2 & aidl)484 ConversionResult<CapCriterion> aidl2legacy_AudioHalCapCriterionV2_Criterion(
485             const AudioHalCapCriterionV2& aidl) {
486     CapCriterion capCriterion;
487     engineConfig::Criterion& criterion = capCriterion.criterion;
488     engineConfig::CriterionType& criterionType = capCriterion.criterionType;
489 
490     auto loadForceUseCriterion = [](const auto& aidlCriterion, auto& criterion,
491                                     auto& criterionType) -> status_t {
492         if (aidlCriterion.values.empty()) {
493             return BAD_VALUE;
494         }
495         const auto [legacyForceUse, _] = VALUE_OR_RETURN_STATUS(
496                 aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t_audio_policy_forced_cfg_t(
497                         aidlCriterion.values[0]));
498         criterion.typeName = criterionType.name;
499         criterionType.name = criterion.typeName + gCriterionTypeSuffix;
500         criterionType.isInclusive =
501                 (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
502         criterion.name = gForceUseCriterionTag[legacyForceUse];
503         criterion.defaultLiteralValue = toString(
504                 aidlCriterion.defaultValue.template get<AudioPolicyForceUse::forMedia>());
505         for (auto &value : aidlCriterion.values) {
506             const audio_policy_forced_cfg_t legacyForcedCfg = VALUE_OR_RETURN_STATUS(
507                     aidl2legacy_AudioHalCapCriterionV2ForceUse_audio_policy_forced_cfg_t(value));
508             const std::string legacyForcedCfgLiteral = VALUE_OR_RETURN_STATUS(
509                     audio_policy_forced_cfg_t_CapCriterionValue(legacyForcedCfg));
510             criterionType.valuePairs.push_back(
511                     {legacyForcedCfg, 0, legacyForcedCfgLiteral});
512         }
513         return NO_ERROR;
514     };
515 
516     auto loadDevicesCriterion = [](const auto &aidlCriterion, auto &criterion,
517             auto &criterionType) -> status_t {
518         criterionType.name = criterion.name + gCriterionTypeSuffix;
519         criterionType.isInclusive =
520                 (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
521         criterion.typeName = criterionType.name;
522         int shift = 0;
523         if (aidlCriterion.values.empty()) {
524             return BAD_VALUE;
525         }
526         for (const auto &value : aidlCriterion.values) {
527             audio_devices_t legacyDeviceType = VALUE_OR_RETURN_STATUS(
528                     aidl2legacy_AudioDeviceDescription_audio_devices_t(value));
529             bool isOut = audio_is_output_devices(legacyDeviceType);
530             std::string legacyTypeLiteral;
531             if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
532                 ALOGE("%s Invalid device type %d", __func__, legacyDeviceType);
533                 return BAD_VALUE;
534             }
535             std::string deviceLiteral = VALUE_OR_RETURN_STATUS(truncatePrefix(legacyTypeLiteral,
536                     isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix));
537             uint64_t pfwCriterionValue = 1 << shift++;
538             criterionType.valuePairs.push_back(
539                     {pfwCriterionValue, static_cast<int32_t>(legacyDeviceType), deviceLiteral});
540             ALOGV("%s: adding %" PRIu64 " %d %s %s", __func__, pfwCriterionValue, legacyDeviceType,
541                     toString(value.type).c_str(), deviceLiteral.c_str());
542         }
543         return NO_ERROR;
544     };
545 
546     auto loadDeviceAddressesCriterion = [](const auto &aidlCriterion, auto &criterion,
547             auto &criterionType) -> status_t {
548         criterionType.name = criterion.name + gCriterionTypeSuffix;
549         criterionType.isInclusive =
550                 (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
551         criterion.typeName = criterionType.name;
552         int shift = 0;
553         for (auto &value : aidlCriterion.values) {
554             uint64_t pfwCriterionValue = 1 << shift++;
555             if (value.getTag() != AudioDeviceAddress::id) {
556                 return BAD_VALUE;
557             }
558             std::string address = value.template get<AudioDeviceAddress::id>();
559             criterionType.valuePairs.push_back({pfwCriterionValue, 0, address});
560         }
561         return NO_ERROR;
562     };
563 
564     switch (aidl.getTag()) {
565         case AudioHalCapCriterionV2::availableInputDevices: {
566             auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableInputDevices>();
567             criterion.name = gInputDeviceCriterionName;
568             if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
569                 return unexpected(BAD_VALUE);
570             }
571             break;
572         }
573         case AudioHalCapCriterionV2::availableOutputDevices: {
574             auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableOutputDevices>();
575             criterion.name = gOutputDeviceCriterionName;
576             if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
577                 return unexpected(BAD_VALUE);
578             }
579             break;
580         }
581         case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
582             auto aidlCriterion =
583                     aidl.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>();
584             criterion.name = gInputDeviceAddressCriterionName;
585             if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
586                 return unexpected(BAD_VALUE);
587             }
588             break;
589         }
590         case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
591             auto aidlCriterion =
592                     aidl.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>();
593             criterion.name = gOutputDeviceAddressCriterionName;
594             if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
595                 return unexpected(BAD_VALUE);
596             }
597             break;
598         }
599         case AudioHalCapCriterionV2::telephonyMode: {
600             auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::telephonyMode>();
601             criterion.name = gPhoneStateCriterionName;
602             criterionType.name = criterion.name  + gCriterionTypeSuffix;
603             criterionType.isInclusive =
604                     (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
605             criterion.typeName = criterionType.name;
606             criterion.defaultLiteralValue = toString( aidlCriterion.defaultValue);
607             if (aidlCriterion.values.empty()) {
608                 return unexpected(BAD_VALUE);
609             }
610             for (auto &value : aidlCriterion.values) {
611                 uint32_t legacyMode =
612                         VALUE_OR_RETURN(aidl2legacy_AudioMode_audio_mode_t(value));
613                 criterionType.valuePairs.push_back({legacyMode, 0, toString(value)});
614             }
615             break;
616         }
617         case AudioHalCapCriterionV2::forceConfigForUse: {
618             auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>();
619             if (loadForceUseCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
620                 return unexpected(BAD_VALUE);
621             }
622             break;
623         }
624         default:
625             return unexpected(BAD_VALUE);
626     }
627     return capCriterion;
628 }
629 
630 }  // namespace
631 
convert(const::android::media::audio::common::AudioHalEngineConfig & aidlConfig)632 ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
633     auto config = std::make_unique<capEngineConfig::CapConfig>();
634 
635     if (!aidlConfig.capSpecificConfig.has_value() ||
636             !aidlConfig.capSpecificConfig.value().domains.has_value()) {
637         ALOGE("%s: no Cap Engine config", __func__);
638         return ParsingResult{};
639     }
640     for (auto& aidlCriteria: aidlConfig.capSpecificConfig.value().criteriaV2.value()) {
641         if (aidlCriteria.has_value()) {
642             if (auto conv = aidl2legacy_AudioHalCapCriterionV2_Criterion(aidlCriteria.value());
643                     conv.ok()) {
644                 config->capCriteria.push_back(std::move(conv.value()));
645             } else {
646                 return ParsingResult{};
647             }
648         }
649     }
650     size_t skippedElement = 0;
651     for (auto& aidlDomain: aidlConfig.capSpecificConfig.value().domains.value()) {
652         if (aidlDomain.has_value()) {
653             if (auto conv = aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(aidlDomain.value());
654                     conv.ok()) {
655                 config->capConfigurableDomains.push_back(std::move(conv.value()));
656             } else {
657                 return ParsingResult{};
658             }
659         } else {
660             skippedElement += 1;
661         }
662     }
663     return {.parsedConfig=std::move(config), .nbSkippedElement=skippedElement};
664 }
665 } // namespace capEngineConfig
666 } // namespace android
667