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