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