xref: /aosp_15_r20/hardware/interfaces/audio/aidl/default/EngineConfigXmlConverter.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2022 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 <fcntl.h>
18 #include <inttypes.h>
19 #include <unistd.h>
20 #include <functional>
21 #include <unordered_map>
22 
23 #define LOG_TAG "AHAL_Config"
24 #include <aidl/android/media/audio/common/AudioFlag.h>
25 #include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
26 #include <aidl/android/media/audio/common/AudioProductStrategyType.h>
27 #include <android-base/logging.h>
28 
29 #include "core-impl/CapEngineConfigXmlConverter.h"
30 #include "core-impl/EngineConfigXmlConverter.h"
31 #include "core-impl/XsdcConversion.h"
32 
33 using aidl::android::hardware::audio::core::internal::CapEngineConfigXmlConverter;
34 using aidl::android::hardware::audio::core::internal::convertAudioUsageToAidl;
35 using aidl::android::media::audio::common::AudioAttributes;
36 using aidl::android::media::audio::common::AudioContentType;
37 using aidl::android::media::audio::common::AudioFlag;
38 using aidl::android::media::audio::common::AudioHalAttributesGroup;
39 using aidl::android::media::audio::common::AudioHalCapCriterion;
40 using aidl::android::media::audio::common::AudioHalCapCriterionType;
41 using aidl::android::media::audio::common::AudioHalCapCriterionV2;
42 using aidl::android::media::audio::common::AudioHalEngineConfig;
43 using aidl::android::media::audio::common::AudioHalProductStrategy;
44 using aidl::android::media::audio::common::AudioHalVolumeCurve;
45 using aidl::android::media::audio::common::AudioHalVolumeGroup;
46 using aidl::android::media::audio::common::AudioProductStrategyType;
47 using aidl::android::media::audio::common::AudioSource;
48 using aidl::android::media::audio::common::AudioStreamType;
49 using aidl::android::media::audio::common::AudioUsage;
50 
51 using ::android::BAD_VALUE;
52 using ::android::base::unexpected;
53 
54 namespace eng_xsd = android::audio::policy::engine::configuration;
55 
56 namespace aidl::android::hardware::audio::core::internal {
57 
58 /** Default path of audio policy cap engine configuration file. */
59 static constexpr char kCapEngineConfigFileName[] =
60         "/parameter-framework/Settings/Policy/PolicyConfigurableDomains.xml";
61 
initProductStrategyMap()62 void EngineConfigXmlConverter::initProductStrategyMap() {
63 #define STRATEGY_ENTRY(name) {"STRATEGY_" #name, static_cast<int>(AudioProductStrategyType::name)}
64 
65     mProductStrategyMap = {STRATEGY_ENTRY(MEDIA),
66                            STRATEGY_ENTRY(PHONE),
67                            STRATEGY_ENTRY(SONIFICATION),
68                            STRATEGY_ENTRY(SONIFICATION_RESPECTFUL),
69                            STRATEGY_ENTRY(DTMF),
70                            STRATEGY_ENTRY(ENFORCED_AUDIBLE),
71                            STRATEGY_ENTRY(TRANSMITTED_THROUGH_SPEAKER),
72                            STRATEGY_ENTRY(ACCESSIBILITY)};
73 #undef STRATEGY_ENTRY
74 }
75 
convertProductStrategyNameToAidl(const std::string & xsdcProductStrategyName)76 ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyNameToAidl(
77         const std::string& xsdcProductStrategyName) {
78     const auto [it, success] = mProductStrategyMap.insert(
79             std::make_pair(xsdcProductStrategyName, mNextVendorStrategy));
80     if (success) {
81         mNextVendorStrategy++;
82     }
83     return it->second;
84 }
85 
convertProductStrategyIdToAidl(int xsdcId)86 ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyIdToAidl(int xsdcId) {
87     if (xsdcId < AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) {
88         return unexpected(BAD_VALUE);
89     }
90     return xsdcId;
91 }
92 
isDefaultAudioAttributes(const AudioAttributes & attributes)93 bool isDefaultAudioAttributes(const AudioAttributes& attributes) {
94     return ((attributes.contentType == AudioContentType::UNKNOWN) &&
95             (attributes.usage == AudioUsage::UNKNOWN) &&
96             (attributes.source == AudioSource::DEFAULT) && (attributes.flags == 0) &&
97             (attributes.tags.empty()));
98 }
99 
convertAudioAttributesToAidl(const eng_xsd::AttributesType & xsdcAudioAttributes)100 ConversionResult<AudioAttributes> EngineConfigXmlConverter::convertAudioAttributesToAidl(
101         const eng_xsd::AttributesType& xsdcAudioAttributes) {
102     if (xsdcAudioAttributes.hasAttributesRef()) {
103         if (mAttributesReferenceMap.empty()) {
104             mAttributesReferenceMap =
105                     generateReferenceMap<eng_xsd::AttributesRef, eng_xsd::AttributesRefType>(
106                             getXsdcConfig()->getAttributesRef());
107         }
108         return convertAudioAttributesToAidl(
109                 *(mAttributesReferenceMap.at(xsdcAudioAttributes.getAttributesRef())
110                           .getFirstAttributes()));
111     }
112     AudioAttributes aidlAudioAttributes;
113     if (xsdcAudioAttributes.hasContentType()) {
114         aidlAudioAttributes.contentType = VALUE_OR_FATAL(convertAudioContentTypeToAidl(
115                 xsdcAudioAttributes.getFirstContentType()->getValue()));
116     }
117     if (xsdcAudioAttributes.hasUsage()) {
118         aidlAudioAttributes.usage = VALUE_OR_FATAL(
119                 convertAudioUsageToAidl(xsdcAudioAttributes.getFirstUsage()->getValue()));
120     }
121     if (xsdcAudioAttributes.hasSource()) {
122         aidlAudioAttributes.source = VALUE_OR_FATAL(
123                 convertAudioSourceToAidl(xsdcAudioAttributes.getFirstSource()->getValue()));
124     }
125     if (xsdcAudioAttributes.hasFlags()) {
126         std::vector<eng_xsd::FlagType> xsdcFlagTypeVec =
127                 xsdcAudioAttributes.getFirstFlags()->getValue();
128         aidlAudioAttributes.flags = VALUE_OR_FATAL(convertAudioFlagsToAidl(xsdcFlagTypeVec));
129     }
130     if (xsdcAudioAttributes.hasBundle()) {
131         const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
132         aidlAudioAttributes.tags.reserve(1);
133         aidlAudioAttributes.tags.push_back(xsdcBundle->getKey() + "_" + xsdcBundle->getValue());
134     }
135     if (isDefaultAudioAttributes(aidlAudioAttributes)) {
136         mDefaultProductStrategyId = std::optional<int>{-1};
137     }
138     return aidlAudioAttributes;
139 }
140 
convertAttributesGroupToAidl(const eng_xsd::AttributesGroup & xsdcAttributesGroup)141 ConversionResult<AudioHalAttributesGroup> EngineConfigXmlConverter::convertAttributesGroupToAidl(
142         const eng_xsd::AttributesGroup& xsdcAttributesGroup) {
143     AudioHalAttributesGroup aidlAttributesGroup;
144     static const int kStreamTypeEnumOffset =
145             static_cast<int>(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
146             static_cast<int>(AudioStreamType::VOICE_CALL);
147     aidlAttributesGroup.streamType = xsdcAttributesGroup.hasStreamType()
148                                              ? VALUE_OR_FATAL(convertAudioStreamTypeToAidl(
149                                                        xsdcAttributesGroup.getStreamType()))
150                                              : AudioStreamType::INVALID;
151     aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
152     if (xsdcAttributesGroup.hasAttributes_optional()) {
153         aidlAttributesGroup.attributes =
154                 VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::AttributesType, AudioAttributes>(
155                         xsdcAttributesGroup.getAttributes_optional(),
156                         std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this,
157                                   std::placeholders::_1))));
158     } else if (xsdcAttributesGroup.hasContentType_optional() ||
159                xsdcAttributesGroup.hasUsage_optional() ||
160                xsdcAttributesGroup.hasSource_optional() ||
161                xsdcAttributesGroup.hasFlags_optional() ||
162                xsdcAttributesGroup.hasBundle_optional()) {
163         aidlAttributesGroup.attributes.push_back(VALUE_OR_FATAL(convertAudioAttributesToAidl(
164                 eng_xsd::AttributesType(xsdcAttributesGroup.getContentType_optional(),
165                                         xsdcAttributesGroup.getUsage_optional(),
166                                         xsdcAttributesGroup.getSource_optional(),
167                                         xsdcAttributesGroup.getFlags_optional(),
168                                         xsdcAttributesGroup.getBundle_optional(), std::nullopt))));
169 
170     } else {
171         LOG(ERROR) << __func__ << " Review Audio Policy config: no audio attributes provided for "
172                    << aidlAttributesGroup.toString();
173         return unexpected(BAD_VALUE);
174     }
175     return aidlAttributesGroup;
176 }
177 
convertProductStrategyToAidl(const eng_xsd::ProductStrategies::ProductStrategy & xsdcProductStrategy)178 ConversionResult<AudioHalProductStrategy> EngineConfigXmlConverter::convertProductStrategyToAidl(
179         const eng_xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
180     AudioHalProductStrategy aidlProductStrategy;
181 
182     aidlProductStrategy.id =
183             VALUE_OR_FATAL(convertProductStrategyIdToAidl(xsdcProductStrategy.getId()));
184     aidlProductStrategy.name = xsdcProductStrategy.getName();
185 
186     if (xsdcProductStrategy.hasAttributesGroup()) {
187         aidlProductStrategy.attributesGroups = VALUE_OR_FATAL(
188                 (convertCollectionToAidl<eng_xsd::AttributesGroup, AudioHalAttributesGroup>(
189                         xsdcProductStrategy.getAttributesGroup(),
190                         std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this,
191                                   std::placeholders::_1))));
192     }
193     if ((mDefaultProductStrategyId != std::nullopt) && (mDefaultProductStrategyId.value() == -1)) {
194         mDefaultProductStrategyId = aidlProductStrategy.id;
195     }
196     return aidlProductStrategy;
197 }
198 
convertVolumeCurveToAidl(const eng_xsd::Volume & xsdcVolumeCurve)199 ConversionResult<AudioHalVolumeCurve> EngineConfigXmlConverter::convertVolumeCurveToAidl(
200         const eng_xsd::Volume& xsdcVolumeCurve) {
201     AudioHalVolumeCurve aidlVolumeCurve;
202     aidlVolumeCurve.deviceCategory =
203             static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
204     if (xsdcVolumeCurve.hasRef()) {
205         if (mVolumesReferenceMap.empty()) {
206             mVolumesReferenceMap = generateReferenceMap<eng_xsd::VolumesType, eng_xsd::VolumeRef>(
207                     getXsdcConfig()->getVolumes());
208         }
209         aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
210                 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
211                         mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
212                         &convertCurvePointToAidl)));
213     } else {
214         aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
215                 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
216                         xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl)));
217     }
218     return aidlVolumeCurve;
219 }
220 
convertVolumeGroupToAidl(const eng_xsd::VolumeGroupsType::VolumeGroup & xsdcVolumeGroup)221 ConversionResult<AudioHalVolumeGroup> EngineConfigXmlConverter::convertVolumeGroupToAidl(
222         const eng_xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) {
223     AudioHalVolumeGroup aidlVolumeGroup;
224     aidlVolumeGroup.name = xsdcVolumeGroup.getName();
225     aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin();
226     aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax();
227     aidlVolumeGroup.volumeCurves =
228             VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::Volume, AudioHalVolumeCurve>(
229                     xsdcVolumeGroup.getVolume(),
230                     std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
231                               std::placeholders::_1))));
232     return aidlVolumeGroup;
233 }
234 
getAidlEngineConfig()235 AudioHalEngineConfig& EngineConfigXmlConverter::getAidlEngineConfig() {
236     return mAidlEngineConfig;
237 }
238 
init()239 void EngineConfigXmlConverter::init() {
240     initProductStrategyMap();
241     if (getXsdcConfig()->hasProductStrategies()) {
242         mAidlEngineConfig.productStrategies = VALUE_OR_FATAL(
243                 (convertWrappedCollectionToAidl<eng_xsd::ProductStrategies,
244                                                 eng_xsd::ProductStrategies::ProductStrategy,
245                                                 AudioHalProductStrategy>(
246                         getXsdcConfig()->getProductStrategies(),
247                         &eng_xsd::ProductStrategies::getProductStrategy,
248                         std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this,
249                                   std::placeholders::_1))));
250         if (mDefaultProductStrategyId) {
251             mAidlEngineConfig.defaultProductStrategyId = mDefaultProductStrategyId.value();
252         }
253     }
254     if (getXsdcConfig()->hasVolumeGroups()) {
255         mAidlEngineConfig.volumeGroups = VALUE_OR_FATAL(
256                 (convertWrappedCollectionToAidl<eng_xsd::VolumeGroupsType,
257                                                 eng_xsd::VolumeGroupsType::VolumeGroup,
258                                                 AudioHalVolumeGroup>(
259                         getXsdcConfig()->getVolumeGroups(),
260                         &eng_xsd::VolumeGroupsType::getVolumeGroup,
261                         std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this,
262                                   std::placeholders::_1))));
263     }
264     if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
265         AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
266         capSpecificConfig.criteriaV2 =
267                 std::make_optional<>(VALUE_OR_FATAL((convertCapCriteriaCollectionToAidl(
268                         getXsdcConfig()->getCriteria(), getXsdcConfig()->getCriterion_types()))));
269         internal::CapEngineConfigXmlConverter capEngConfigConverter{
270                 ::android::audio_find_readable_configuration_file(kCapEngineConfigFileName)};
271         if (capEngConfigConverter.getStatus() == ::android::OK) {
272             capSpecificConfig.domains = std::move(capEngConfigConverter.getAidlCapEngineConfig());
273         }
274         mAidlEngineConfig.capSpecificConfig = capSpecificConfig;
275     }
276 }
277 }  // namespace aidl::android::hardware::audio::core::internal
278