1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "AHAL_Config"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/media/audio/common/AudioProductStrategyType.h>
20*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*4d7e907cSAndroid Build Coastguard Worker #include <media/AidlConversionCppNdk.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <media/TypeConverter.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <media/convert.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <utils/FastStrcmp.h>
25*4d7e907cSAndroid Build Coastguard Worker
26*4d7e907cSAndroid Build Coastguard Worker #include "core-impl/CapEngineConfigXmlConverter.h"
27*4d7e907cSAndroid Build Coastguard Worker #include "core-impl/XsdcConversion.h"
28*4d7e907cSAndroid Build Coastguard Worker
29*4d7e907cSAndroid Build Coastguard Worker using aidl::android::hardware::audio::common::iequals;
30*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioDeviceAddress;
31*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioDeviceDescription;
32*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioHalCapConfiguration;
33*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioHalCapCriterionV2;
34*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioHalCapDomain;
35*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioHalCapParameter;
36*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioHalCapRule;
37*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioPolicyForceUse;
38*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioSource;
39*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioStreamType;
40*4d7e907cSAndroid Build Coastguard Worker
41*4d7e907cSAndroid Build Coastguard Worker using ::android::BAD_VALUE;
42*4d7e907cSAndroid Build Coastguard Worker using ::android::base::unexpected;
43*4d7e907cSAndroid Build Coastguard Worker using ::android::utilities::convertTo;
44*4d7e907cSAndroid Build Coastguard Worker
45*4d7e907cSAndroid Build Coastguard Worker namespace eng_xsd = android::audio::policy::capengine::configuration;
46*4d7e907cSAndroid Build Coastguard Worker
47*4d7e907cSAndroid Build Coastguard Worker namespace aidl::android::hardware::audio::core::internal {
48*4d7e907cSAndroid Build Coastguard Worker
49*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gStrategiesParameter = "product_strategies";
50*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gInputSourcesParameter = "input_sources";
51*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gStreamsParameter = "streams";
52*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gOutputDevicesParameter = "selected_output_devices";
53*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gOutputDeviceAddressParameter = "device_address";
54*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gStrategyPrefix = "vx_";
55*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gLegacyOutputDevicePrefix = "AUDIO_DEVICE_OUT_";
56*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gLegacyInputDevicePrefix = "AUDIO_DEVICE_IN_";
57*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gLegacyStreamPrefix = "AUDIO_STREAM_";
58*4d7e907cSAndroid Build Coastguard Worker static constexpr const char* gLegacySourcePrefix = "AUDIO_SOURCE_";
59*4d7e907cSAndroid Build Coastguard Worker
60*4d7e907cSAndroid Build Coastguard Worker std::optional<std::vector<std::optional<AudioHalCapDomain>>>&
getAidlCapEngineConfig()61*4d7e907cSAndroid Build Coastguard Worker CapEngineConfigXmlConverter::getAidlCapEngineConfig() {
62*4d7e907cSAndroid Build Coastguard Worker return mAidlCapDomains;
63*4d7e907cSAndroid Build Coastguard Worker }
64*4d7e907cSAndroid Build Coastguard Worker
convertCriterionRuleToAidl(const eng_xsd::SelectionCriterionRuleType & xsdcRule)65*4d7e907cSAndroid Build Coastguard Worker ConversionResult<AudioHalCapRule::CriterionRule> convertCriterionRuleToAidl(
66*4d7e907cSAndroid Build Coastguard Worker const eng_xsd::SelectionCriterionRuleType& xsdcRule) {
67*4d7e907cSAndroid Build Coastguard Worker using Tag = AudioHalCapCriterionV2::Tag;
68*4d7e907cSAndroid Build Coastguard Worker AudioHalCapRule::CriterionRule rule{};
69*4d7e907cSAndroid Build Coastguard Worker std::string criterionName = xsdcRule.getSelectionCriterion();
70*4d7e907cSAndroid Build Coastguard Worker std::string criterionValue = xsdcRule.getValue();
71*4d7e907cSAndroid Build Coastguard Worker if (iequals(criterionName, toString(Tag::availableInputDevices))) {
72*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::AvailableDevices value;
73*4d7e907cSAndroid Build Coastguard Worker value.values.emplace_back(VALUE_OR_RETURN(
74*4d7e907cSAndroid Build Coastguard Worker convertDeviceTypeToAidl(gLegacyInputDevicePrefix + criterionValue)));
75*4d7e907cSAndroid Build Coastguard Worker rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::availableInputDevices>(value);
76*4d7e907cSAndroid Build Coastguard Worker
77*4d7e907cSAndroid Build Coastguard Worker } else if (iequals(criterionName, toString(Tag::availableOutputDevices))) {
78*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::AvailableDevices value;
79*4d7e907cSAndroid Build Coastguard Worker value.values.emplace_back(VALUE_OR_RETURN(
80*4d7e907cSAndroid Build Coastguard Worker convertDeviceTypeToAidl(gLegacyOutputDevicePrefix + criterionValue)));
81*4d7e907cSAndroid Build Coastguard Worker rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(value);
82*4d7e907cSAndroid Build Coastguard Worker } else if (iequals(criterionName, toString(Tag::availableInputDevicesAddresses))) {
83*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::AvailableDevicesAddresses value;
84*4d7e907cSAndroid Build Coastguard Worker value.values.emplace_back(criterionValue);
85*4d7e907cSAndroid Build Coastguard Worker rule.criterionAndValue =
86*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(value);
87*4d7e907cSAndroid Build Coastguard Worker } else if (iequals(criterionName, toString(Tag::availableOutputDevicesAddresses))) {
88*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::AvailableDevicesAddresses value;
89*4d7e907cSAndroid Build Coastguard Worker value.values.emplace_back(criterionValue);
90*4d7e907cSAndroid Build Coastguard Worker rule.criterionAndValue =
91*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(value);
92*4d7e907cSAndroid Build Coastguard Worker } else if (iequals(criterionName, toString(Tag::telephonyMode))) {
93*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::TelephonyMode value;
94*4d7e907cSAndroid Build Coastguard Worker value.values.emplace_back(VALUE_OR_RETURN(convertTelephonyModeToAidl(criterionValue)));
95*4d7e907cSAndroid Build Coastguard Worker rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::telephonyMode>(value);
96*4d7e907cSAndroid Build Coastguard Worker } else if (!fastcmp<strncmp>(criterionName.c_str(), kXsdcForceConfigForUse,
97*4d7e907cSAndroid Build Coastguard Worker strlen(kXsdcForceConfigForUse))) {
98*4d7e907cSAndroid Build Coastguard Worker AudioHalCapCriterionV2::ForceConfigForUse value;
99*4d7e907cSAndroid Build Coastguard Worker value.values.emplace_back(
100*4d7e907cSAndroid Build Coastguard Worker VALUE_OR_RETURN(convertForceUseToAidl(criterionName, criterionValue)));
101*4d7e907cSAndroid Build Coastguard Worker rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(value);
102*4d7e907cSAndroid Build Coastguard Worker } else {
103*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << " unrecognized criterion " << criterionName;
104*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
105*4d7e907cSAndroid Build Coastguard Worker }
106*4d7e907cSAndroid Build Coastguard Worker if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Excludes) {
107*4d7e907cSAndroid Build Coastguard Worker rule.matchingRule = AudioHalCapRule::MatchingRule::EXCLUDES;
108*4d7e907cSAndroid Build Coastguard Worker } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Includes) {
109*4d7e907cSAndroid Build Coastguard Worker rule.matchingRule = AudioHalCapRule::MatchingRule::INCLUDES;
110*4d7e907cSAndroid Build Coastguard Worker } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Is) {
111*4d7e907cSAndroid Build Coastguard Worker rule.matchingRule = AudioHalCapRule::MatchingRule::IS;
112*4d7e907cSAndroid Build Coastguard Worker } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::IsNot) {
113*4d7e907cSAndroid Build Coastguard Worker rule.matchingRule = AudioHalCapRule::MatchingRule::IS_NOT;
114*4d7e907cSAndroid Build Coastguard Worker } else {
115*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Unsupported match when rule.";
116*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
117*4d7e907cSAndroid Build Coastguard Worker }
118*4d7e907cSAndroid Build Coastguard Worker return rule;
119*4d7e907cSAndroid Build Coastguard Worker }
120*4d7e907cSAndroid Build Coastguard Worker
convertRule(const eng_xsd::CompoundRuleType & xsdcCompoundRule)121*4d7e907cSAndroid Build Coastguard Worker ConversionResult<AudioHalCapRule> convertRule(const eng_xsd::CompoundRuleType& xsdcCompoundRule) {
122*4d7e907cSAndroid Build Coastguard Worker AudioHalCapRule rule{};
123*4d7e907cSAndroid Build Coastguard Worker bool isPreviousCompoundRule = true;
124*4d7e907cSAndroid Build Coastguard Worker if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::Any) {
125*4d7e907cSAndroid Build Coastguard Worker rule.compoundRule = AudioHalCapRule::CompoundRule::ANY;
126*4d7e907cSAndroid Build Coastguard Worker } else if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::All) {
127*4d7e907cSAndroid Build Coastguard Worker rule.compoundRule = AudioHalCapRule::CompoundRule::ALL;
128*4d7e907cSAndroid Build Coastguard Worker } else {
129*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Unsupported compound rule type.";
130*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
131*4d7e907cSAndroid Build Coastguard Worker }
132*4d7e907cSAndroid Build Coastguard Worker for (const auto& childXsdcCoumpoundRule : xsdcCompoundRule.getCompoundRule_optional()) {
133*4d7e907cSAndroid Build Coastguard Worker if (childXsdcCoumpoundRule.hasCompoundRule_optional()) {
134*4d7e907cSAndroid Build Coastguard Worker rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule)));
135*4d7e907cSAndroid Build Coastguard Worker } else if (childXsdcCoumpoundRule.hasSelectionCriterionRule_optional()) {
136*4d7e907cSAndroid Build Coastguard Worker rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule)));
137*4d7e907cSAndroid Build Coastguard Worker }
138*4d7e907cSAndroid Build Coastguard Worker }
139*4d7e907cSAndroid Build Coastguard Worker if (xsdcCompoundRule.hasSelectionCriterionRule_optional()) {
140*4d7e907cSAndroid Build Coastguard Worker for (const auto& xsdcRule : xsdcCompoundRule.getSelectionCriterionRule_optional()) {
141*4d7e907cSAndroid Build Coastguard Worker rule.criterionRules.push_back(VALUE_OR_FATAL(convertCriterionRuleToAidl(xsdcRule)));
142*4d7e907cSAndroid Build Coastguard Worker }
143*4d7e907cSAndroid Build Coastguard Worker }
144*4d7e907cSAndroid Build Coastguard Worker return rule;
145*4d7e907cSAndroid Build Coastguard Worker }
146*4d7e907cSAndroid Build Coastguard Worker
getAudioProductStrategyId(const std::string & path)147*4d7e907cSAndroid Build Coastguard Worker ConversionResult<int> getAudioProductStrategyId(const std::string& path) {
148*4d7e907cSAndroid Build Coastguard Worker std::vector<std::string> strings;
149*4d7e907cSAndroid Build Coastguard Worker std::istringstream pathStream(path);
150*4d7e907cSAndroid Build Coastguard Worker std::string stringToken;
151*4d7e907cSAndroid Build Coastguard Worker while (getline(pathStream, stringToken, '/')) {
152*4d7e907cSAndroid Build Coastguard Worker std::size_t pos = stringToken.find(gStrategyPrefix);
153*4d7e907cSAndroid Build Coastguard Worker if (pos != std::string::npos) {
154*4d7e907cSAndroid Build Coastguard Worker std::string strategyIdLiteral = stringToken.substr(pos + std::strlen(gStrategyPrefix));
155*4d7e907cSAndroid Build Coastguard Worker int strategyId;
156*4d7e907cSAndroid Build Coastguard Worker if (!convertTo(strategyIdLiteral, strategyId)) {
157*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid strategy " << stringToken << " from path " << path;
158*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
159*4d7e907cSAndroid Build Coastguard Worker }
160*4d7e907cSAndroid Build Coastguard Worker return strategyId;
161*4d7e907cSAndroid Build Coastguard Worker }
162*4d7e907cSAndroid Build Coastguard Worker }
163*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
164*4d7e907cSAndroid Build Coastguard Worker }
165*4d7e907cSAndroid Build Coastguard Worker
getAudioSource(const std::string & path)166*4d7e907cSAndroid Build Coastguard Worker ConversionResult<AudioSource> getAudioSource(const std::string& path) {
167*4d7e907cSAndroid Build Coastguard Worker std::vector<std::string> strings;
168*4d7e907cSAndroid Build Coastguard Worker std::istringstream pathStream(path);
169*4d7e907cSAndroid Build Coastguard Worker std::string stringToken;
170*4d7e907cSAndroid Build Coastguard Worker while (getline(pathStream, stringToken, '/')) {
171*4d7e907cSAndroid Build Coastguard Worker if (stringToken.find(gInputSourcesParameter) != std::string::npos) {
172*4d7e907cSAndroid Build Coastguard Worker getline(pathStream, stringToken, '/');
173*4d7e907cSAndroid Build Coastguard Worker std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(),
174*4d7e907cSAndroid Build Coastguard Worker [](char c) { return std::toupper(c); });
175*4d7e907cSAndroid Build Coastguard Worker std::string legacySourceLiteral = "AUDIO_SOURCE_" + stringToken;
176*4d7e907cSAndroid Build Coastguard Worker audio_source_t legacySource;
177*4d7e907cSAndroid Build Coastguard Worker if (!::android::SourceTypeConverter::fromString(legacySourceLiteral, legacySource)) {
178*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid source " << stringToken << " from path " << path;
179*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
180*4d7e907cSAndroid Build Coastguard Worker }
181*4d7e907cSAndroid Build Coastguard Worker return legacy2aidl_audio_source_t_AudioSource(legacySource);
182*4d7e907cSAndroid Build Coastguard Worker }
183*4d7e907cSAndroid Build Coastguard Worker }
184*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
185*4d7e907cSAndroid Build Coastguard Worker }
186*4d7e907cSAndroid Build Coastguard Worker
getAudioStreamType(const std::string & path)187*4d7e907cSAndroid Build Coastguard Worker ConversionResult<AudioStreamType> getAudioStreamType(const std::string& path) {
188*4d7e907cSAndroid Build Coastguard Worker std::vector<std::string> strings;
189*4d7e907cSAndroid Build Coastguard Worker std::istringstream pathStream(path);
190*4d7e907cSAndroid Build Coastguard Worker std::string stringToken;
191*4d7e907cSAndroid Build Coastguard Worker
192*4d7e907cSAndroid Build Coastguard Worker while (getline(pathStream, stringToken, '/')) {
193*4d7e907cSAndroid Build Coastguard Worker if (stringToken.find(gStreamsParameter) != std::string::npos) {
194*4d7e907cSAndroid Build Coastguard Worker getline(pathStream, stringToken, '/');
195*4d7e907cSAndroid Build Coastguard Worker std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(),
196*4d7e907cSAndroid Build Coastguard Worker [](char c) { return std::toupper(c); });
197*4d7e907cSAndroid Build Coastguard Worker std::string legacyStreamLiteral = std::string(gLegacyStreamPrefix) + stringToken;
198*4d7e907cSAndroid Build Coastguard Worker audio_stream_type_t legacyStream;
199*4d7e907cSAndroid Build Coastguard Worker if (!::android::StreamTypeConverter::fromString(legacyStreamLiteral, legacyStream)) {
200*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid stream " << stringToken << " from path " << path;
201*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
202*4d7e907cSAndroid Build Coastguard Worker }
203*4d7e907cSAndroid Build Coastguard Worker return legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStream);
204*4d7e907cSAndroid Build Coastguard Worker }
205*4d7e907cSAndroid Build Coastguard Worker }
206*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
207*4d7e907cSAndroid Build Coastguard Worker }
208*4d7e907cSAndroid Build Coastguard Worker
toUpperAndAppendPrefix(const std::string & capName,const std::string & legacyPrefix)209*4d7e907cSAndroid Build Coastguard Worker ConversionResult<std::string> toUpperAndAppendPrefix(const std::string& capName,
210*4d7e907cSAndroid Build Coastguard Worker const std::string& legacyPrefix) {
211*4d7e907cSAndroid Build Coastguard Worker std::string legacyName = capName;
212*4d7e907cSAndroid Build Coastguard Worker std::transform(legacyName.begin(), legacyName.end(), legacyName.begin(),
213*4d7e907cSAndroid Build Coastguard Worker [](char c) { return std::toupper(c); });
214*4d7e907cSAndroid Build Coastguard Worker return legacyPrefix + legacyName;
215*4d7e907cSAndroid Build Coastguard Worker }
216*4d7e907cSAndroid Build Coastguard Worker
convertParamToAidl(const eng_xsd::ConfigurableElementSettingsType & element)217*4d7e907cSAndroid Build Coastguard Worker ConversionResult<AudioHalCapParameter> CapEngineConfigXmlConverter::convertParamToAidl(
218*4d7e907cSAndroid Build Coastguard Worker const eng_xsd::ConfigurableElementSettingsType& element) {
219*4d7e907cSAndroid Build Coastguard Worker const auto& path = element.getPath();
220*4d7e907cSAndroid Build Coastguard Worker
221*4d7e907cSAndroid Build Coastguard Worker AudioHalCapParameter parameterSetting;
222*4d7e907cSAndroid Build Coastguard Worker if (path.find(gStrategiesParameter) != std::string::npos) {
223*4d7e907cSAndroid Build Coastguard Worker int strategyId = VALUE_OR_FATAL(getAudioProductStrategyId(path));
224*4d7e907cSAndroid Build Coastguard Worker if (path.find(gOutputDevicesParameter) != std::string::npos) {
225*4d7e907cSAndroid Build Coastguard Worker // Value is 1 or 0
226*4d7e907cSAndroid Build Coastguard Worker if (!element.hasBitParameter_optional()) {
227*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid strategy value type";
228*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
229*4d7e907cSAndroid Build Coastguard Worker }
230*4d7e907cSAndroid Build Coastguard Worker // Convert name to output device type
231*4d7e907cSAndroid Build Coastguard Worker const auto* xsdcParam = element.getFirstBitParameter_optional();
232*4d7e907cSAndroid Build Coastguard Worker std::string outputDevice = VALUE_OR_FATAL(toUpperAndAppendPrefix(
233*4d7e907cSAndroid Build Coastguard Worker eng_xsd::toString(xsdcParam->getName()), gLegacyOutputDevicePrefix));
234*4d7e907cSAndroid Build Coastguard Worker audio_devices_t legacyType;
235*4d7e907cSAndroid Build Coastguard Worker if (!::android::OutputDeviceConverter::fromString(outputDevice, legacyType)) {
236*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid strategy device type " << outputDevice;
237*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
238*4d7e907cSAndroid Build Coastguard Worker }
239*4d7e907cSAndroid Build Coastguard Worker AudioDeviceDescription aidlDevice =
240*4d7e907cSAndroid Build Coastguard Worker VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
241*4d7e907cSAndroid Build Coastguard Worker bool isSelected;
242*4d7e907cSAndroid Build Coastguard Worker if (!convertTo(xsdcParam->getValue(), isSelected)) {
243*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid strategy device selection value " << xsdcParam->getValue();
244*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
245*4d7e907cSAndroid Build Coastguard Worker }
246*4d7e907cSAndroid Build Coastguard Worker parameterSetting =
247*4d7e907cSAndroid Build Coastguard Worker AudioHalCapParameter::StrategyDevice(aidlDevice, strategyId, isSelected);
248*4d7e907cSAndroid Build Coastguard Worker } else if (path.find(gOutputDeviceAddressParameter) != std::string::npos) {
249*4d7e907cSAndroid Build Coastguard Worker // Value is the address
250*4d7e907cSAndroid Build Coastguard Worker if (!element.hasStringParameter_optional()) {
251*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
252*4d7e907cSAndroid Build Coastguard Worker }
253*4d7e907cSAndroid Build Coastguard Worker std::string address = element.getFirstStringParameter_optional()->getValue();
254*4d7e907cSAndroid Build Coastguard Worker parameterSetting = AudioHalCapParameter::StrategyDeviceAddress(
255*4d7e907cSAndroid Build Coastguard Worker AudioDeviceAddress(address), strategyId);
256*4d7e907cSAndroid Build Coastguard Worker }
257*4d7e907cSAndroid Build Coastguard Worker } else if (path.find(gInputSourcesParameter) != std::string::npos) {
258*4d7e907cSAndroid Build Coastguard Worker // Value is 1 or 0
259*4d7e907cSAndroid Build Coastguard Worker if (!element.hasBitParameter_optional()) {
260*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid source value type";
261*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
262*4d7e907cSAndroid Build Coastguard Worker }
263*4d7e907cSAndroid Build Coastguard Worker AudioSource audioSourceAidl = VALUE_OR_FATAL(getAudioSource(path));
264*4d7e907cSAndroid Build Coastguard Worker const auto* xsdcParam = element.getFirstBitParameter_optional();
265*4d7e907cSAndroid Build Coastguard Worker std::string inputDeviceLiteral = VALUE_OR_FATAL(toUpperAndAppendPrefix(
266*4d7e907cSAndroid Build Coastguard Worker eng_xsd::toString(xsdcParam->getName()), gLegacyInputDevicePrefix));
267*4d7e907cSAndroid Build Coastguard Worker audio_devices_t inputDeviceType;
268*4d7e907cSAndroid Build Coastguard Worker if (!::android::InputDeviceConverter::fromString(inputDeviceLiteral, inputDeviceType)) {
269*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid source device type " << inputDeviceLiteral;
270*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
271*4d7e907cSAndroid Build Coastguard Worker }
272*4d7e907cSAndroid Build Coastguard Worker AudioDeviceDescription aidlDevice =
273*4d7e907cSAndroid Build Coastguard Worker VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(inputDeviceType));
274*4d7e907cSAndroid Build Coastguard Worker
275*4d7e907cSAndroid Build Coastguard Worker bool isSelected;
276*4d7e907cSAndroid Build Coastguard Worker if (!convertTo(xsdcParam->getValue(), isSelected)) {
277*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid source value type " << xsdcParam->getValue();
278*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
279*4d7e907cSAndroid Build Coastguard Worker }
280*4d7e907cSAndroid Build Coastguard Worker parameterSetting =
281*4d7e907cSAndroid Build Coastguard Worker AudioHalCapParameter::InputSourceDevice(aidlDevice, audioSourceAidl, isSelected);
282*4d7e907cSAndroid Build Coastguard Worker } else if (path.find(gStreamsParameter) != std::string::npos) {
283*4d7e907cSAndroid Build Coastguard Worker AudioStreamType audioStreamAidl = VALUE_OR_FATAL(getAudioStreamType(path));
284*4d7e907cSAndroid Build Coastguard Worker if (!element.hasEnumParameter_optional()) {
285*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid stream value type";
286*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
287*4d7e907cSAndroid Build Coastguard Worker }
288*4d7e907cSAndroid Build Coastguard Worker const auto* xsdcParam = element.getFirstEnumParameter_optional();
289*4d7e907cSAndroid Build Coastguard Worker std::string profileLiteral =
290*4d7e907cSAndroid Build Coastguard Worker VALUE_OR_FATAL(toUpperAndAppendPrefix(xsdcParam->getValue(), gLegacyStreamPrefix));
291*4d7e907cSAndroid Build Coastguard Worker audio_stream_type_t profileLegacyStream;
292*4d7e907cSAndroid Build Coastguard Worker if (!::android::StreamTypeConverter::fromString(profileLiteral, profileLegacyStream)) {
293*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid stream value " << profileLiteral;
294*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
295*4d7e907cSAndroid Build Coastguard Worker }
296*4d7e907cSAndroid Build Coastguard Worker AudioStreamType profileStreamAidl = VALUE_OR_FATAL(
297*4d7e907cSAndroid Build Coastguard Worker legacy2aidl_audio_stream_type_t_AudioStreamType(profileLegacyStream));
298*4d7e907cSAndroid Build Coastguard Worker parameterSetting =
299*4d7e907cSAndroid Build Coastguard Worker AudioHalCapParameter::StreamVolumeProfile(audioStreamAidl, profileStreamAidl);
300*4d7e907cSAndroid Build Coastguard Worker }
301*4d7e907cSAndroid Build Coastguard Worker return parameterSetting;
302*4d7e907cSAndroid Build Coastguard Worker }
303*4d7e907cSAndroid Build Coastguard Worker
304*4d7e907cSAndroid Build Coastguard Worker ConversionResult<std::vector<AudioHalCapParameter>>
convertSettingToAidl(const eng_xsd::SettingsType::Configuration & xsdcSetting)305*4d7e907cSAndroid Build Coastguard Worker CapEngineConfigXmlConverter::convertSettingToAidl(
306*4d7e907cSAndroid Build Coastguard Worker const eng_xsd::SettingsType::Configuration& xsdcSetting) {
307*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioHalCapParameter> aidlCapParameterSettings;
308*4d7e907cSAndroid Build Coastguard Worker for (const auto& element : xsdcSetting.getConfigurableElement()) {
309*4d7e907cSAndroid Build Coastguard Worker aidlCapParameterSettings.push_back(VALUE_OR_FATAL(convertParamToAidl(element)));
310*4d7e907cSAndroid Build Coastguard Worker }
311*4d7e907cSAndroid Build Coastguard Worker return aidlCapParameterSettings;
312*4d7e907cSAndroid Build Coastguard Worker }
313*4d7e907cSAndroid Build Coastguard Worker
convertConfigurationToAidl(const eng_xsd::ConfigurationsType::Configuration & xsdcConfiguration,const eng_xsd::SettingsType::Configuration & xsdcSettingConfiguration)314*4d7e907cSAndroid Build Coastguard Worker ConversionResult<AudioHalCapConfiguration> CapEngineConfigXmlConverter::convertConfigurationToAidl(
315*4d7e907cSAndroid Build Coastguard Worker const eng_xsd::ConfigurationsType::Configuration& xsdcConfiguration,
316*4d7e907cSAndroid Build Coastguard Worker const eng_xsd::SettingsType::Configuration& xsdcSettingConfiguration) {
317*4d7e907cSAndroid Build Coastguard Worker AudioHalCapConfiguration aidlCapConfiguration;
318*4d7e907cSAndroid Build Coastguard Worker aidlCapConfiguration.name = xsdcConfiguration.getName();
319*4d7e907cSAndroid Build Coastguard Worker if (xsdcConfiguration.hasCompoundRule()) {
320*4d7e907cSAndroid Build Coastguard Worker if (xsdcConfiguration.getCompoundRule().size() != 1) {
321*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
322*4d7e907cSAndroid Build Coastguard Worker }
323*4d7e907cSAndroid Build Coastguard Worker aidlCapConfiguration.rule =
324*4d7e907cSAndroid Build Coastguard Worker VALUE_OR_FATAL(convertRule(xsdcConfiguration.getCompoundRule()[0]));
325*4d7e907cSAndroid Build Coastguard Worker aidlCapConfiguration.parameterSettings =
326*4d7e907cSAndroid Build Coastguard Worker VALUE_OR_FATAL(convertSettingToAidl(xsdcSettingConfiguration));
327*4d7e907cSAndroid Build Coastguard Worker }
328*4d7e907cSAndroid Build Coastguard Worker return aidlCapConfiguration;
329*4d7e907cSAndroid Build Coastguard Worker }
330*4d7e907cSAndroid Build Coastguard Worker
getConfigurationByName(const std::string & name,const std::vector<eng_xsd::SettingsType> & xsdcSettingsVec)331*4d7e907cSAndroid Build Coastguard Worker ConversionResult<eng_xsd::SettingsType::Configuration> getConfigurationByName(
332*4d7e907cSAndroid Build Coastguard Worker const std::string& name, const std::vector<eng_xsd::SettingsType>& xsdcSettingsVec) {
333*4d7e907cSAndroid Build Coastguard Worker for (const auto& xsdcSettings : xsdcSettingsVec) {
334*4d7e907cSAndroid Build Coastguard Worker for (const auto& xsdcConfiguration : xsdcSettings.getConfiguration()) {
335*4d7e907cSAndroid Build Coastguard Worker if (xsdcConfiguration.getName() == name) {
336*4d7e907cSAndroid Build Coastguard Worker return xsdcConfiguration;
337*4d7e907cSAndroid Build Coastguard Worker }
338*4d7e907cSAndroid Build Coastguard Worker }
339*4d7e907cSAndroid Build Coastguard Worker }
340*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << " failed to find configuration " << name;
341*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
342*4d7e907cSAndroid Build Coastguard Worker }
343*4d7e907cSAndroid Build Coastguard Worker
344*4d7e907cSAndroid Build Coastguard Worker ConversionResult<std::vector<AudioHalCapConfiguration>>
convertConfigurationsToAidl(const std::vector<eng_xsd::ConfigurationsType> & xsdcConfigurationsVec,const std::vector<eng_xsd::SettingsType> & xsdcSettingsVec)345*4d7e907cSAndroid Build Coastguard Worker CapEngineConfigXmlConverter::convertConfigurationsToAidl(
346*4d7e907cSAndroid Build Coastguard Worker const std::vector<eng_xsd::ConfigurationsType>& xsdcConfigurationsVec,
347*4d7e907cSAndroid Build Coastguard Worker const std::vector<eng_xsd::SettingsType>& xsdcSettingsVec) {
348*4d7e907cSAndroid Build Coastguard Worker if (xsdcConfigurationsVec.empty() || xsdcSettingsVec.empty()) {
349*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << " empty configurations/settings";
350*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
351*4d7e907cSAndroid Build Coastguard Worker }
352*4d7e907cSAndroid Build Coastguard Worker std::vector<AudioHalCapConfiguration> aidlConfigurations;
353*4d7e907cSAndroid Build Coastguard Worker for (const auto& xsdcConfigurations : xsdcConfigurationsVec) {
354*4d7e907cSAndroid Build Coastguard Worker for (const auto& xsdcConfiguration : xsdcConfigurations.getConfiguration()) {
355*4d7e907cSAndroid Build Coastguard Worker auto xsdcSettingConfiguration = VALUE_OR_FATAL(
356*4d7e907cSAndroid Build Coastguard Worker getConfigurationByName(xsdcConfiguration.getName(), xsdcSettingsVec));
357*4d7e907cSAndroid Build Coastguard Worker aidlConfigurations.push_back(VALUE_OR_FATAL(
358*4d7e907cSAndroid Build Coastguard Worker convertConfigurationToAidl(xsdcConfiguration, xsdcSettingConfiguration)));
359*4d7e907cSAndroid Build Coastguard Worker }
360*4d7e907cSAndroid Build Coastguard Worker }
361*4d7e907cSAndroid Build Coastguard Worker return aidlConfigurations;
362*4d7e907cSAndroid Build Coastguard Worker }
363*4d7e907cSAndroid Build Coastguard Worker
convertConfigurableDomainToAidl(const eng_xsd::ConfigurableDomainType & xsdcConfigurableDomain)364*4d7e907cSAndroid Build Coastguard Worker ConversionResult<AudioHalCapDomain> CapEngineConfigXmlConverter::convertConfigurableDomainToAidl(
365*4d7e907cSAndroid Build Coastguard Worker const eng_xsd::ConfigurableDomainType& xsdcConfigurableDomain) {
366*4d7e907cSAndroid Build Coastguard Worker AudioHalCapDomain aidlConfigurableDomain;
367*4d7e907cSAndroid Build Coastguard Worker
368*4d7e907cSAndroid Build Coastguard Worker aidlConfigurableDomain.name = xsdcConfigurableDomain.getName();
369*4d7e907cSAndroid Build Coastguard Worker if (xsdcConfigurableDomain.hasSequenceAware() && xsdcConfigurableDomain.getSequenceAware()) {
370*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "sequence aware not supported.";
371*4d7e907cSAndroid Build Coastguard Worker return unexpected(BAD_VALUE);
372*4d7e907cSAndroid Build Coastguard Worker }
373*4d7e907cSAndroid Build Coastguard Worker if (xsdcConfigurableDomain.hasConfigurations() && xsdcConfigurableDomain.hasSettings()) {
374*4d7e907cSAndroid Build Coastguard Worker aidlConfigurableDomain.configurations = VALUE_OR_FATAL(convertConfigurationsToAidl(
375*4d7e907cSAndroid Build Coastguard Worker xsdcConfigurableDomain.getConfigurations(), xsdcConfigurableDomain.getSettings()));
376*4d7e907cSAndroid Build Coastguard Worker }
377*4d7e907cSAndroid Build Coastguard Worker return aidlConfigurableDomain;
378*4d7e907cSAndroid Build Coastguard Worker }
379*4d7e907cSAndroid Build Coastguard Worker
init()380*4d7e907cSAndroid Build Coastguard Worker void CapEngineConfigXmlConverter::init() {
381*4d7e907cSAndroid Build Coastguard Worker if (getXsdcConfig()->hasConfigurableDomain()) {
382*4d7e907cSAndroid Build Coastguard Worker mAidlCapDomains = std::make_optional<>(VALUE_OR_FATAL(
383*4d7e907cSAndroid Build Coastguard Worker (convertCollectionToAidlOptionalValues<eng_xsd::ConfigurableDomainType,
384*4d7e907cSAndroid Build Coastguard Worker AudioHalCapDomain>(
385*4d7e907cSAndroid Build Coastguard Worker getXsdcConfig()->getConfigurableDomain(),
386*4d7e907cSAndroid Build Coastguard Worker std::bind(&CapEngineConfigXmlConverter::convertConfigurableDomainToAidl,
387*4d7e907cSAndroid Build Coastguard Worker this, std::placeholders::_1)))));
388*4d7e907cSAndroid Build Coastguard Worker } else {
389*4d7e907cSAndroid Build Coastguard Worker mAidlCapDomains = std::nullopt;
390*4d7e907cSAndroid Build Coastguard Worker }
391*4d7e907cSAndroid Build Coastguard Worker }
392*4d7e907cSAndroid Build Coastguard Worker
393*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl::android::hardware::audio::core::internal
394