blob: 7452c8ec7ac54abad3d947ba9043f988eeac334a [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
21#include <functional>
22#include <unordered_map>
23
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +000024#define LOG_TAG "AHAL_ApmXmlConverter"
25#include <android-base/logging.h>
26
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000027#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +000028#include <media/stagefright/foundation/MediaDefs.h>
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000029#include <system/audio-base-utils.h>
30
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +000031#include "core-impl/AidlConversionXsdc.h"
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000032#include "core-impl/AudioPolicyConfigXmlConverter.h"
33
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +000034using aidl::android::media::audio::common::AudioFormatDescription;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000035using aidl::android::media::audio::common::AudioHalEngineConfig;
36using aidl::android::media::audio::common::AudioHalVolumeCurve;
37using aidl::android::media::audio::common::AudioHalVolumeGroup;
38using aidl::android::media::audio::common::AudioStreamType;
39
Mikhail Naganovaf75a672023-10-13 23:38:25 +000040namespace xsd = android::audio::policy::configuration;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000041
42namespace aidl::android::hardware::audio::core::internal {
43
44static const int kDefaultVolumeIndexMin = 0;
45static const int kDefaultVolumeIndexMax = 100;
46static const int KVolumeIndexDeferredToAudioService = -1;
Mikhail Naganovaf75a672023-10-13 23:38:25 +000047/**
48 * Valid curve points take the form "<index>,<attenuationMb>", where the index
49 * must be in the range [0,100]. kInvalidCurvePointIndex is used to indicate
50 * that a point was formatted incorrectly (e.g. if a vendor accidentally typed a
51 * '.' instead of a ',' in their XML) -- using such a curve point will result in
52 * failed VTS tests.
53 */
54static const int8_t kInvalidCurvePointIndex = -1;
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000055
Mikhail Naganovaf75a672023-10-13 23:38:25 +000056AudioHalVolumeCurve::CurvePoint AudioPolicyConfigXmlConverter::convertCurvePointToAidl(
57 const std::string& xsdcCurvePoint) {
58 AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
59 if (sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
60 &aidlCurvePoint.attenuationMb) != 2) {
61 aidlCurvePoint.index = kInvalidCurvePointIndex;
62 }
63 return aidlCurvePoint;
64}
65
66AudioHalVolumeCurve AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl(
67 const xsd::Volume& xsdcVolumeCurve) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000068 AudioHalVolumeCurve aidlVolumeCurve;
69 aidlVolumeCurve.deviceCategory =
70 static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
71 if (xsdcVolumeCurve.hasRef()) {
72 if (mVolumesReferenceMap.empty()) {
Mikhail Naganovaf75a672023-10-13 23:38:25 +000073 mVolumesReferenceMap = generateReferenceMap<xsd::Volumes, xsd::Reference>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000074 getXsdcConfig()->getVolumes());
75 }
Mikhail Naganovaf75a672023-10-13 23:38:25 +000076 aidlVolumeCurve.curvePoints =
77 convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000078 mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
Mikhail Naganovaf75a672023-10-13 23:38:25 +000079 std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
80 std::placeholders::_1));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000081 } else {
Mikhail Naganovaf75a672023-10-13 23:38:25 +000082 aidlVolumeCurve.curvePoints =
83 convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
84 xsdcVolumeCurve.getPoint(),
85 std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
86 std::placeholders::_1));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000087 }
88 return aidlVolumeCurve;
89}
90
Mikhail Naganovaf75a672023-10-13 23:38:25 +000091void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const xsd::Volume& xsdcVolumeCurve) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000092 mStreamToVolumeCurvesMap[xsdcVolumeCurve.getStream()].push_back(
Mikhail Naganovaf75a672023-10-13 23:38:25 +000093 convertVolumeCurveToAidl(xsdcVolumeCurve));
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +000094}
95
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +000096const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() {
97 static const SurroundSoundConfig aidlSurroundSoundConfig = [this]() {
98 if (auto xsdcConfig = getXsdcConfig(); xsdcConfig && xsdcConfig->hasSurroundSound()) {
99 auto configConv = xsdc2aidl_SurroundSoundConfig(*xsdcConfig->getFirstSurroundSound());
100 if (configConv.ok()) {
101 return configConv.value();
102 }
103 LOG(ERROR) << "There was an error converting surround formats to AIDL: "
104 << configConv.error();
105 }
106 LOG(WARNING) << "Audio policy config does not have <surroundSound> section, using default";
107 return getDefaultSurroundSoundConfig();
108 }();
109 return aidlSurroundSoundConfig;
110}
111
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000112const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
113 if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
114 getXsdcConfig()->hasVolumes()) {
115 parseVolumes();
116 }
117 return mAidlEngineConfig;
118}
119
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000120// static
121const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig() {
122 // Provide a config similar to the one used by the framework by default
123 // (see AudioPolicyConfig::setDefaultSurroundFormats).
124#define ENCODED_FORMAT(format) \
125 AudioFormatDescription { \
126 .encoding = ::android::format \
127 }
128#define SIMPLE_FORMAT(format) \
129 SurroundSoundConfig::SurroundFormatFamily { \
130 .primaryFormat = ENCODED_FORMAT(format) \
131 }
132
133 static const SurroundSoundConfig defaultConfig = {
134 .formatFamilies = {
135 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC3),
136 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3),
137 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS),
138 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD),
139 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD_MA),
Mikhail Naganov724b24f2023-07-06 09:58:14 -0700140 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1),
Lorena Torres-Huertaaa8f76a2022-12-12 18:17:10 +0000141 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2),
142 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD),
143 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3_JOC),
144 SurroundSoundConfig::SurroundFormatFamily{
145 .primaryFormat = ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_LC),
146 .subFormats =
147 {
148 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1),
149 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2),
150 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_ELD),
151 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_XHE),
152 }},
153 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC4),
154 }};
155#undef SIMPLE_FORMAT
156#undef ENCODED_FORMAT
157
158 return defaultConfig;
159}
160
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000161void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
162 if (getXsdcConfig()->hasVolumes()) {
Mikhail Naganovaf75a672023-10-13 23:38:25 +0000163 for (const xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
164 for (const xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000165 mapStreamToVolumeCurve(xsdcVolume);
166 }
167 }
168 }
169}
170
171void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() {
172 for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) {
173 AudioHalVolumeGroup volumeGroup;
Mikhail Naganovaf75a672023-10-13 23:38:25 +0000174 volumeGroup.name = xsd::toString(xsdcStream);
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000175 if (static_cast<int>(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) {
176 volumeGroup.minIndex = kDefaultVolumeIndexMin;
177 volumeGroup.maxIndex = kDefaultVolumeIndexMax;
178 } else {
179 volumeGroup.minIndex = KVolumeIndexDeferredToAudioService;
180 volumeGroup.maxIndex = KVolumeIndexDeferredToAudioService;
181 }
182 volumeGroup.volumeCurves = volumeCurves;
183 mAidlEngineConfig.volumeGroups.push_back(std::move(volumeGroup));
184 }
185}
186
187void AudioPolicyConfigXmlConverter::parseVolumes() {
188 if (mStreamToVolumeCurvesMap.empty() && getXsdcConfig()->hasVolumes()) {
189 mapStreamsToVolumeCurves();
190 addVolumeGroupstoEngineConfig();
191 }
192}
Lorena Torres-Huertabc585bd2022-10-23 20:41:35 +0000193} // namespace aidl::android::hardware::audio::core::internal