blob: 631cdce1a0cb2672b87014174239f3a04e8edc30 [file] [log] [blame]
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +00001/*
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
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000023#define LOG_TAG "AHAL_Config"
Lorena Torres-Huerta0f4d6892022-12-14 20:00:26 +000024#include <aidl/android/media/audio/common/AudioFlag.h>
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000025#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
Lorena Torres-Huerta0f4d6892022-12-14 20:00:26 +000026#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000027#include <android-base/logging.h>
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000028
29#include "core-impl/EngineConfigXmlConverter.h"
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000030#include "core-impl/XsdcConversion.h"
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000031
32using aidl::android::media::audio::common::AudioAttributes;
33using aidl::android::media::audio::common::AudioContentType;
34using aidl::android::media::audio::common::AudioFlag;
35using aidl::android::media::audio::common::AudioHalAttributesGroup;
36using aidl::android::media::audio::common::AudioHalCapCriterion;
37using aidl::android::media::audio::common::AudioHalCapCriterionType;
38using aidl::android::media::audio::common::AudioHalEngineConfig;
39using aidl::android::media::audio::common::AudioHalProductStrategy;
40using aidl::android::media::audio::common::AudioHalVolumeCurve;
41using aidl::android::media::audio::common::AudioHalVolumeGroup;
42using aidl::android::media::audio::common::AudioProductStrategyType;
43using aidl::android::media::audio::common::AudioSource;
44using aidl::android::media::audio::common::AudioStreamType;
45using aidl::android::media::audio::common::AudioUsage;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000046using ::android::BAD_VALUE;
47using ::android::base::unexpected;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000048
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000049namespace eng_xsd = android::audio::policy::engine::configuration;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000050
51namespace aidl::android::hardware::audio::core::internal {
52
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000053void 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
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000067ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyNameToAidl(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000068 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
77bool 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
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000084ConversionResult<AudioAttributes> EngineConfigXmlConverter::convertAudioAttributesToAidl(
85 const eng_xsd::AttributesType& xsdcAudioAttributes) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000086 if (xsdcAudioAttributes.hasAttributesRef()) {
87 if (mAttributesReferenceMap.empty()) {
88 mAttributesReferenceMap =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000089 generateReferenceMap<eng_xsd::AttributesRef, eng_xsd::AttributesRefType>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000090 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()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000110 std::vector<eng_xsd::FlagType> xsdcFlagTypeVec =
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000111 xsdcAudioAttributes.getFirstFlags()->getValue();
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000112 for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
113 if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000114 aidlAudioAttributes.flags |= 1 << (static_cast<int>(xsdcFlagType) - 1);
115 }
116 }
117 }
118 if (xsdcAudioAttributes.hasBundle()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000119 const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000120 aidlAudioAttributes.tags[0] = xsdcBundle->getKey() + "=" + xsdcBundle->getValue();
121 }
122 if (isDefaultAudioAttributes(aidlAudioAttributes)) {
123 mDefaultProductStrategyId = std::optional<int>{-1};
124 }
125 return aidlAudioAttributes;
126}
127
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000128ConversionResult<AudioHalAttributesGroup> EngineConfigXmlConverter::convertAttributesGroupToAidl(
129 const eng_xsd::AttributesGroup& xsdcAttributesGroup) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000130 AudioHalAttributesGroup aidlAttributesGroup;
131 static const int kStreamTypeEnumOffset =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000132 static_cast<int>(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000133 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 =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000139 VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::AttributesType, AudioAttributes>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000140 xsdcAttributesGroup.getAttributes_optional(),
141 std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000142 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000143 } else if (xsdcAttributesGroup.hasContentType_optional() ||
144 xsdcAttributesGroup.hasUsage_optional() ||
145 xsdcAttributesGroup.hasSource_optional() ||
146 xsdcAttributesGroup.hasFlags_optional() ||
147 xsdcAttributesGroup.hasBundle_optional()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000148 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))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000154
155 } else {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000156 LOG(ERROR) << __func__ << " Review Audio Policy config: no audio attributes provided for "
157 << aidlAttributesGroup.toString();
158 return unexpected(BAD_VALUE);
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000159 }
160 return aidlAttributesGroup;
161}
162
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000163ConversionResult<AudioHalProductStrategy> EngineConfigXmlConverter::convertProductStrategyToAidl(
164 const eng_xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000165 AudioHalProductStrategy aidlProductStrategy;
166
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000167 aidlProductStrategy.id =
168 VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName()));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000169
170 if (xsdcProductStrategy.hasAttributesGroup()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000171 aidlProductStrategy.attributesGroups = VALUE_OR_FATAL(
172 (convertCollectionToAidl<eng_xsd::AttributesGroup, AudioHalAttributesGroup>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000173 xsdcProductStrategy.getAttributesGroup(),
174 std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000175 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000176 }
177 if ((mDefaultProductStrategyId != std::nullopt) && (mDefaultProductStrategyId.value() == -1)) {
178 mDefaultProductStrategyId = aidlProductStrategy.id;
179 }
180 return aidlProductStrategy;
181}
182
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000183ConversionResult<AudioHalVolumeCurve> EngineConfigXmlConverter::convertVolumeCurveToAidl(
184 const eng_xsd::Volume& xsdcVolumeCurve) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000185 AudioHalVolumeCurve aidlVolumeCurve;
186 aidlVolumeCurve.deviceCategory =
187 static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
188 if (xsdcVolumeCurve.hasRef()) {
189 if (mVolumesReferenceMap.empty()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000190 mVolumesReferenceMap = generateReferenceMap<eng_xsd::VolumesType, eng_xsd::VolumeRef>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000191 getXsdcConfig()->getVolumes());
192 }
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000193 aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
194 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000195 mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000196 &convertCurvePointToAidl)));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000197 } else {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000198 aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
199 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
200 xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl)));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000201 }
202 return aidlVolumeCurve;
203}
204
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000205ConversionResult<AudioHalVolumeGroup> EngineConfigXmlConverter::convertVolumeGroupToAidl(
206 const eng_xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000207 AudioHalVolumeGroup aidlVolumeGroup;
208 aidlVolumeGroup.name = xsdcVolumeGroup.getName();
209 aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin();
210 aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax();
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000211 aidlVolumeGroup.volumeCurves =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000212 VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::Volume, AudioHalVolumeCurve>(
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000213 xsdcVolumeGroup.getVolume(),
214 std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000215 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000216 return aidlVolumeGroup;
217}
218
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000219AudioHalEngineConfig& EngineConfigXmlConverter::getAidlEngineConfig() {
220 return mAidlEngineConfig;
221}
222
223void EngineConfigXmlConverter::init() {
224 initProductStrategyMap();
225 if (getXsdcConfig()->hasProductStrategies()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000226 mAidlEngineConfig.productStrategies = VALUE_OR_FATAL(
227 (convertWrappedCollectionToAidl<eng_xsd::ProductStrategies,
228 eng_xsd::ProductStrategies::ProductStrategy,
229 AudioHalProductStrategy>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000230 getXsdcConfig()->getProductStrategies(),
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000231 &eng_xsd::ProductStrategies::getProductStrategy,
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000232 std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000233 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000234 if (mDefaultProductStrategyId) {
235 mAidlEngineConfig.defaultProductStrategyId = mDefaultProductStrategyId.value();
236 }
237 }
238 if (getXsdcConfig()->hasVolumeGroups()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000239 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))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000247 }
248 if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
249 AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000250 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)));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000262 }
263}
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000264} // namespace aidl::android::hardware::audio::core::internal