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