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
21 #include <functional>
22 #include <unordered_map>
23
24 #define LOG_TAG "AHAL_ApmXmlConverter"
25 #include <android-base/logging.h>
26
27 #include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
28 #include <media/stagefright/foundation/MediaDefs.h>
29 #include <system/audio-base-utils.h>
30
31 #include "core-impl/AidlConversionXsdc.h"
32 #include "core-impl/AudioPolicyConfigXmlConverter.h"
33 #include "core-impl/XsdcConversion.h"
34
35 using aidl::android::media::audio::common::AudioFormatDescription;
36 using aidl::android::media::audio::common::AudioHalEngineConfig;
37 using aidl::android::media::audio::common::AudioHalVolumeCurve;
38 using aidl::android::media::audio::common::AudioHalVolumeGroup;
39 using aidl::android::media::audio::common::AudioStreamType;
40
41 namespace ap_xsd = android::audio::policy::configuration;
42
43 namespace aidl::android::hardware::audio::core::internal {
44
45 static const int kDefaultVolumeIndexMin = 0;
46 static const int kDefaultVolumeIndexMax = 100;
47 static const int KVolumeIndexDeferredToAudioService = -1;
48
convertVolumeCurveToAidl(const ap_xsd::Volume & xsdcVolumeCurve)49 ConversionResult<AudioHalVolumeCurve> AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl(
50 const ap_xsd::Volume& xsdcVolumeCurve) {
51 AudioHalVolumeCurve aidlVolumeCurve;
52 aidlVolumeCurve.deviceCategory =
53 static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
54 if (xsdcVolumeCurve.hasRef()) {
55 if (mVolumesReferenceMap.empty()) {
56 mVolumesReferenceMap = generateReferenceMap<ap_xsd::Volumes, ap_xsd::Reference>(
57 getXsdcConfig()->getVolumes());
58 }
59 aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
60 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
61 mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
62 &convertCurvePointToAidl)));
63 } else {
64 aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
65 (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
66 xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl)));
67 }
68 return aidlVolumeCurve;
69 }
70
mapStreamToVolumeCurve(const ap_xsd::Volume & xsdcVolumeCurve)71 void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const ap_xsd::Volume& xsdcVolumeCurve) {
72 mStreamToVolumeCurvesMap[xsdcVolumeCurve.getStream()].push_back(
73 VALUE_OR_FATAL(convertVolumeCurveToAidl(xsdcVolumeCurve)));
74 }
75
getSurroundSoundConfig()76 const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() {
77 static const SurroundSoundConfig aidlSurroundSoundConfig = [this]() {
78 if (auto xsdcConfig = getXsdcConfig(); xsdcConfig && xsdcConfig->hasSurroundSound()) {
79 auto configConv = xsdc2aidl_SurroundSoundConfig(*xsdcConfig->getFirstSurroundSound());
80 if (configConv.ok()) {
81 return configConv.value();
82 }
83 LOG(ERROR) << "There was an error converting surround formats to AIDL: "
84 << configConv.error();
85 }
86 LOG(WARNING) << "Audio policy config does not have <surroundSound> section, using default";
87 return getDefaultSurroundSoundConfig();
88 }();
89 return aidlSurroundSoundConfig;
90 }
91
92 std::unique_ptr<AudioPolicyConfigXmlConverter::ModuleConfigs>
releaseModuleConfigs()93 AudioPolicyConfigXmlConverter::releaseModuleConfigs() {
94 return std::move(mModuleConfigurations);
95 }
96
getAidlEngineConfig()97 const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
98 if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
99 getXsdcConfig()->hasVolumes()) {
100 parseVolumes();
101 }
102 return mAidlEngineConfig;
103 }
104
105 // static
getDefaultSurroundSoundConfig()106 const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig() {
107 // Provide a config similar to the one used by the framework by default
108 // (see AudioPolicyConfig::setDefaultSurroundFormats).
109 #define ENCODED_FORMAT(format) \
110 AudioFormatDescription { \
111 .encoding = ::android::format \
112 }
113 #define SIMPLE_FORMAT(format) \
114 SurroundSoundConfig::SurroundFormatFamily { \
115 .primaryFormat = ENCODED_FORMAT(format) \
116 }
117
118 static const SurroundSoundConfig defaultConfig = {
119 .formatFamilies = {
120 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC3),
121 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3),
122 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS),
123 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD),
124 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD_MA),
125 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1),
126 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2),
127 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD),
128 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3_JOC),
129 SurroundSoundConfig::SurroundFormatFamily{
130 .primaryFormat = ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_LC),
131 .subFormats =
132 {
133 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1),
134 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2),
135 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_ELD),
136 ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_XHE),
137 }},
138 SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC4),
139 }};
140 #undef SIMPLE_FORMAT
141 #undef ENCODED_FORMAT
142
143 return defaultConfig;
144 }
145
mapStreamsToVolumeCurves()146 void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
147 if (getXsdcConfig()->hasVolumes()) {
148 for (const ap_xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
149 for (const ap_xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
150 mapStreamToVolumeCurve(xsdcVolume);
151 }
152 }
153 }
154 }
155
addVolumeGroupstoEngineConfig()156 void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() {
157 for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) {
158 AudioHalVolumeGroup volumeGroup;
159 volumeGroup.name = ap_xsd::toString(xsdcStream);
160 if (static_cast<int>(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) {
161 volumeGroup.minIndex = kDefaultVolumeIndexMin;
162 volumeGroup.maxIndex = kDefaultVolumeIndexMax;
163 } else {
164 volumeGroup.minIndex = KVolumeIndexDeferredToAudioService;
165 volumeGroup.maxIndex = KVolumeIndexDeferredToAudioService;
166 }
167 volumeGroup.volumeCurves = volumeCurves;
168 mAidlEngineConfig.volumeGroups.push_back(std::move(volumeGroup));
169 }
170 }
171
parseVolumes()172 void AudioPolicyConfigXmlConverter::parseVolumes() {
173 if (mStreamToVolumeCurvesMap.empty() && getXsdcConfig()->hasVolumes()) {
174 mapStreamsToVolumeCurves();
175 addVolumeGroupstoEngineConfig();
176 }
177 }
178
init()179 void AudioPolicyConfigXmlConverter::init() {
180 if (!getXsdcConfig()->hasModules()) return;
181 for (const ap_xsd::Modules& xsdcModulesType : getXsdcConfig()->getModules()) {
182 if (!xsdcModulesType.has_module()) continue;
183 for (const ap_xsd::Modules::Module& xsdcModule : xsdcModulesType.get_module()) {
184 // 'primary' in the XML schema used by HIDL is equivalent to 'default' module.
185 const std::string name =
186 xsdcModule.getName() != "primary" ? xsdcModule.getName() : "default";
187 if (name != "r_submix") {
188 mModuleConfigurations->emplace_back(
189 name, VALUE_OR_FATAL(convertModuleConfigToAidl(xsdcModule)));
190 } else {
191 // See the note on the 'getRSubmixConfiguration' function.
192 mModuleConfigurations->emplace_back(name, nullptr);
193 }
194 }
195 }
196 }
197
198 } // namespace aidl::android::hardware::audio::core::internal
199