blob: 5a8b0a3f0394eeb89c218a35cc50dc2f4dcdc4a5 [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
François Gaffie57ccab72024-04-17 11:47:51 +020029#include "core-impl/CapEngineConfigXmlConverter.h"
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000030#include "core-impl/EngineConfigXmlConverter.h"
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000031#include "core-impl/XsdcConversion.h"
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000032
François Gaffie57ccab72024-04-17 11:47:51 +020033using aidl::android::hardware::audio::core::internal::CapEngineConfigXmlConverter;
34using aidl::android::hardware::audio::core::internal::convertAudioUsageToAidl;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000035using aidl::android::media::audio::common::AudioAttributes;
36using aidl::android::media::audio::common::AudioContentType;
37using aidl::android::media::audio::common::AudioFlag;
38using aidl::android::media::audio::common::AudioHalAttributesGroup;
39using aidl::android::media::audio::common::AudioHalCapCriterion;
40using aidl::android::media::audio::common::AudioHalCapCriterionType;
François Gaffie57ccab72024-04-17 11:47:51 +020041using aidl::android::media::audio::common::AudioHalCapCriterionV2;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000042using aidl::android::media::audio::common::AudioHalEngineConfig;
43using aidl::android::media::audio::common::AudioHalProductStrategy;
44using aidl::android::media::audio::common::AudioHalVolumeCurve;
45using aidl::android::media::audio::common::AudioHalVolumeGroup;
46using aidl::android::media::audio::common::AudioProductStrategyType;
47using aidl::android::media::audio::common::AudioSource;
48using aidl::android::media::audio::common::AudioStreamType;
49using aidl::android::media::audio::common::AudioUsage;
François Gaffie57ccab72024-04-17 11:47:51 +020050
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000051using ::android::BAD_VALUE;
52using ::android::base::unexpected;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000053
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000054namespace eng_xsd = android::audio::policy::engine::configuration;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000055
56namespace aidl::android::hardware::audio::core::internal {
57
François Gaffie57ccab72024-04-17 11:47:51 +020058/** Default path of audio policy cap engine configuration file. */
59static constexpr char kCapEngineConfigFileName[] =
60 "/parameter-framework/Settings/Policy/PolicyConfigurableDomains.xml";
61
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000062void 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
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000076ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyNameToAidl(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000077 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
François Gaffie57ccab72024-04-17 11:47:51 +020086ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyIdToAidl(int xsdcId) {
87 if (xsdcId < AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) {
88 return unexpected(BAD_VALUE);
89 }
90 return xsdcId;
91}
92
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000093bool 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
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000100ConversionResult<AudioAttributes> EngineConfigXmlConverter::convertAudioAttributesToAidl(
101 const eng_xsd::AttributesType& xsdcAudioAttributes) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000102 if (xsdcAudioAttributes.hasAttributesRef()) {
103 if (mAttributesReferenceMap.empty()) {
104 mAttributesReferenceMap =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000105 generateReferenceMap<eng_xsd::AttributesRef, eng_xsd::AttributesRefType>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000106 getXsdcConfig()->getAttributesRef());
107 }
108 return convertAudioAttributesToAidl(
109 *(mAttributesReferenceMap.at(xsdcAudioAttributes.getAttributesRef())
110 .getFirstAttributes()));
111 }
112 AudioAttributes aidlAudioAttributes;
113 if (xsdcAudioAttributes.hasContentType()) {
François Gaffie57ccab72024-04-17 11:47:51 +0200114 aidlAudioAttributes.contentType = VALUE_OR_FATAL(convertAudioContentTypeToAidl(
115 xsdcAudioAttributes.getFirstContentType()->getValue()));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000116 }
117 if (xsdcAudioAttributes.hasUsage()) {
François Gaffie57ccab72024-04-17 11:47:51 +0200118 aidlAudioAttributes.usage = VALUE_OR_FATAL(
119 convertAudioUsageToAidl(xsdcAudioAttributes.getFirstUsage()->getValue()));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000120 }
121 if (xsdcAudioAttributes.hasSource()) {
François Gaffie57ccab72024-04-17 11:47:51 +0200122 aidlAudioAttributes.source = VALUE_OR_FATAL(
123 convertAudioSourceToAidl(xsdcAudioAttributes.getFirstSource()->getValue()));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000124 }
125 if (xsdcAudioAttributes.hasFlags()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000126 std::vector<eng_xsd::FlagType> xsdcFlagTypeVec =
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000127 xsdcAudioAttributes.getFirstFlags()->getValue();
François Gaffie57ccab72024-04-17 11:47:51 +0200128 aidlAudioAttributes.flags = VALUE_OR_FATAL(convertAudioFlagsToAidl(xsdcFlagTypeVec));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000129 }
130 if (xsdcAudioAttributes.hasBundle()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000131 const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
François Gaffie57ccab72024-04-17 11:47:51 +0200132 aidlAudioAttributes.tags.reserve(1);
133 aidlAudioAttributes.tags.push_back(xsdcBundle->getKey() + "_" + xsdcBundle->getValue());
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000134 }
135 if (isDefaultAudioAttributes(aidlAudioAttributes)) {
136 mDefaultProductStrategyId = std::optional<int>{-1};
137 }
138 return aidlAudioAttributes;
139}
140
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000141ConversionResult<AudioHalAttributesGroup> EngineConfigXmlConverter::convertAttributesGroupToAidl(
142 const eng_xsd::AttributesGroup& xsdcAttributesGroup) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000143 AudioHalAttributesGroup aidlAttributesGroup;
144 static const int kStreamTypeEnumOffset =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000145 static_cast<int>(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000146 static_cast<int>(AudioStreamType::VOICE_CALL);
François Gaffie57ccab72024-04-17 11:47:51 +0200147 aidlAttributesGroup.streamType = xsdcAttributesGroup.hasStreamType()
148 ? VALUE_OR_FATAL(convertAudioStreamTypeToAidl(
149 xsdcAttributesGroup.getStreamType()))
150 : AudioStreamType::INVALID;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000151 aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
152 if (xsdcAttributesGroup.hasAttributes_optional()) {
153 aidlAttributesGroup.attributes =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000154 VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::AttributesType, AudioAttributes>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000155 xsdcAttributesGroup.getAttributes_optional(),
156 std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000157 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000158 } else if (xsdcAttributesGroup.hasContentType_optional() ||
159 xsdcAttributesGroup.hasUsage_optional() ||
160 xsdcAttributesGroup.hasSource_optional() ||
161 xsdcAttributesGroup.hasFlags_optional() ||
162 xsdcAttributesGroup.hasBundle_optional()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000163 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))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000169
170 } else {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000171 LOG(ERROR) << __func__ << " Review Audio Policy config: no audio attributes provided for "
172 << aidlAttributesGroup.toString();
173 return unexpected(BAD_VALUE);
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000174 }
175 return aidlAttributesGroup;
176}
177
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000178ConversionResult<AudioHalProductStrategy> EngineConfigXmlConverter::convertProductStrategyToAidl(
179 const eng_xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000180 AudioHalProductStrategy aidlProductStrategy;
181
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000182 aidlProductStrategy.id =
François Gaffie57ccab72024-04-17 11:47:51 +0200183 VALUE_OR_FATAL(convertProductStrategyIdToAidl(xsdcProductStrategy.getId()));
184 aidlProductStrategy.name = xsdcProductStrategy.getName();
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000185
186 if (xsdcProductStrategy.hasAttributesGroup()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000187 aidlProductStrategy.attributesGroups = VALUE_OR_FATAL(
188 (convertCollectionToAidl<eng_xsd::AttributesGroup, AudioHalAttributesGroup>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000189 xsdcProductStrategy.getAttributesGroup(),
190 std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000191 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000192 }
193 if ((mDefaultProductStrategyId != std::nullopt) && (mDefaultProductStrategyId.value() == -1)) {
194 mDefaultProductStrategyId = aidlProductStrategy.id;
195 }
196 return aidlProductStrategy;
197}
198
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000199ConversionResult<AudioHalVolumeCurve> EngineConfigXmlConverter::convertVolumeCurveToAidl(
200 const eng_xsd::Volume& xsdcVolumeCurve) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000201 AudioHalVolumeCurve aidlVolumeCurve;
202 aidlVolumeCurve.deviceCategory =
203 static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
204 if (xsdcVolumeCurve.hasRef()) {
205 if (mVolumesReferenceMap.empty()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000206 mVolumesReferenceMap = generateReferenceMap<eng_xsd::VolumesType, eng_xsd::VolumeRef>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000207 getXsdcConfig()->getVolumes());
208 }
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000209 aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
210 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000211 mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000212 &convertCurvePointToAidl)));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000213 } else {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000214 aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
215 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
216 xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl)));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000217 }
218 return aidlVolumeCurve;
219}
220
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000221ConversionResult<AudioHalVolumeGroup> EngineConfigXmlConverter::convertVolumeGroupToAidl(
222 const eng_xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000223 AudioHalVolumeGroup aidlVolumeGroup;
224 aidlVolumeGroup.name = xsdcVolumeGroup.getName();
225 aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin();
226 aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax();
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000227 aidlVolumeGroup.volumeCurves =
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000228 VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::Volume, AudioHalVolumeCurve>(
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000229 xsdcVolumeGroup.getVolume(),
230 std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000231 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000232 return aidlVolumeGroup;
233}
234
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000235AudioHalEngineConfig& EngineConfigXmlConverter::getAidlEngineConfig() {
236 return mAidlEngineConfig;
237}
238
239void EngineConfigXmlConverter::init() {
240 initProductStrategyMap();
241 if (getXsdcConfig()->hasProductStrategies()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000242 mAidlEngineConfig.productStrategies = VALUE_OR_FATAL(
243 (convertWrappedCollectionToAidl<eng_xsd::ProductStrategies,
244 eng_xsd::ProductStrategies::ProductStrategy,
245 AudioHalProductStrategy>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000246 getXsdcConfig()->getProductStrategies(),
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000247 &eng_xsd::ProductStrategies::getProductStrategy,
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000248 std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this,
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000249 std::placeholders::_1))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000250 if (mDefaultProductStrategyId) {
251 mAidlEngineConfig.defaultProductStrategyId = mDefaultProductStrategyId.value();
252 }
253 }
254 if (getXsdcConfig()->hasVolumeGroups()) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000255 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))));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000263 }
264 if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
265 AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
François Gaffie57ccab72024-04-17 11:47:51 +0200266 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;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000275 }
276}
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000277} // namespace aidl::android::hardware::audio::core::internal