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