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