1 /*
2 * Copyright (C) 2009 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 #define LOG_TAG "APM_Config"
18
19 #include <AudioPolicyConfig.h>
20 #include <IOProfile.h>
21 #include <Serializer.h>
22 #include <hardware/audio.h>
23 #include <media/AidlConversion.h>
24 #include <media/AidlConversionUtil.h>
25 #include <media/AudioProfile.h>
26 #include <system/audio.h>
27 #include <system/audio_config.h>
28 #include <utils/Log.h>
29
30 namespace android {
31
32 using media::audio::common::AudioIoFlags;
33 using media::audio::common::AudioPortDeviceExt;
34 using media::audio::common::AudioPortExt;
35
36 namespace {
37
38 ConversionResult<sp<PolicyAudioPort>>
aidl2legacy_portId_PolicyAudioPort(int32_t portId,const std::unordered_map<int32_t,sp<PolicyAudioPort>> & ports)39 aidl2legacy_portId_PolicyAudioPort(int32_t portId,
40 const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
41 if (auto it = ports.find(portId); it != ports.end()) {
42 return it->second;
43 }
44 return base::unexpected(BAD_VALUE);
45 }
46
47 ConversionResult<sp<AudioRoute>>
aidl2legacy_AudioRoute(const media::AudioRoute & aidl,const std::unordered_map<int32_t,sp<PolicyAudioPort>> & ports)48 aidl2legacy_AudioRoute(const media::AudioRoute& aidl,
49 const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
50 auto legacy = sp<AudioRoute>::make(aidl.isExclusive ? AUDIO_ROUTE_MUX : AUDIO_ROUTE_MIX);
51 auto legacySink = VALUE_OR_RETURN(aidl2legacy_portId_PolicyAudioPort(aidl.sinkPortId, ports));
52 legacy->setSink(legacySink);
53 PolicyAudioPortVector legacySources;
54 for (int32_t portId : aidl.sourcePortIds) {
55 sp<PolicyAudioPort> legacyPort = VALUE_OR_RETURN(
56 aidl2legacy_portId_PolicyAudioPort(portId, ports));
57 legacySources.add(legacyPort);
58 }
59 legacy->setSources(legacySources);
60 legacySink->addRoute(legacy);
61 for (const auto& legacySource : legacySources) {
62 legacySource->addRoute(legacy);
63 }
64 return legacy;
65 }
66
aidl2legacy_AudioHwModule_HwModule(const media::AudioHwModule & aidl,sp<HwModule> * legacy,DeviceVector * attachedInputDevices,DeviceVector * attachedOutputDevices,sp<DeviceDescriptor> * defaultOutputDevice)67 status_t aidl2legacy_AudioHwModule_HwModule(const media::AudioHwModule& aidl,
68 sp<HwModule>* legacy,
69 DeviceVector* attachedInputDevices, DeviceVector* attachedOutputDevices,
70 sp<DeviceDescriptor>* defaultOutputDevice) {
71 *legacy = sp<HwModule>::make(aidl.name.c_str(), AUDIO_DEVICE_API_VERSION_CURRENT);
72 audio_module_handle_t legacyHandle = VALUE_OR_RETURN_STATUS(
73 aidl2legacy_int32_t_audio_module_handle_t(aidl.handle));
74 (*legacy)->setHandle(legacyHandle);
75 IOProfileCollection mixPorts;
76 DeviceVector devicePorts;
77 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
78 std::unordered_map<int32_t, sp<PolicyAudioPort>> ports;
79 for (const auto& aidlPort : aidl.ports) {
80 const bool isInput = aidlPort.flags.getTag() == AudioIoFlags::input;
81 audio_port_v7 legacyPort = VALUE_OR_RETURN_STATUS(
82 aidl2legacy_AudioPort_audio_port_v7(aidlPort, isInput));
83 // This conversion fills out both 'hal' and 'sys' parts.
84 media::AudioPortFw fwPort = VALUE_OR_RETURN_STATUS(
85 legacy2aidl_audio_port_v7_AudioPortFw(legacyPort));
86 // Since audio_port_v7 lacks some fields, for example, 'maxOpen/ActiveCount',
87 // replace the converted data with the actual data from the HAL.
88 fwPort.hal = aidlPort;
89 if (aidlPort.ext.getTag() == AudioPortExt::mix) {
90 auto mixPort = sp<IOProfile>::make("", AUDIO_PORT_ROLE_NONE);
91 RETURN_STATUS_IF_ERROR(mixPort->readFromParcelable(fwPort));
92 auto& profiles = mixPort->getAudioProfiles();
93 if (profiles.empty()) {
94 profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
95 } else {
96 sortAudioProfiles(mixPort->getAudioProfiles());
97 }
98 mixPorts.add(mixPort);
99 ports.emplace(aidlPort.id, mixPort);
100 } else if (aidlPort.ext.getTag() == AudioPortExt::device) {
101 // In the legacy XML, device ports use 'tagName' instead of 'AudioPort.name'.
102 auto devicePort =
103 sp<DeviceDescriptor>::make(AUDIO_DEVICE_NONE, aidlPort.name);
104 RETURN_STATUS_IF_ERROR(devicePort->readFromParcelable(fwPort));
105 devicePort->setName("");
106 auto& profiles = devicePort->getAudioProfiles();
107 if (profiles.empty()) {
108 profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
109 } else {
110 sortAudioProfiles(profiles);
111 }
112 devicePorts.add(devicePort);
113 ports.emplace(aidlPort.id, devicePort);
114
115 if (const auto& deviceExt = aidlPort.ext.get<AudioPortExt::device>();
116 deviceExt.device.type.connection.empty()) { // Attached device
117 if (isInput) {
118 attachedInputDevices->add(devicePort);
119 } else {
120 attachedOutputDevices->add(devicePort);
121 if ((deviceExt.flags & defaultDeviceFlag) != 0) {
122 *defaultOutputDevice = devicePort;
123 }
124 }
125 }
126 } else {
127 return BAD_VALUE;
128 }
129 }
130 (*legacy)->setProfiles(mixPorts);
131 (*legacy)->setDeclaredDevices(devicePorts);
132 AudioRouteVector routes;
133 for (const auto& aidlRoute : aidl.routes) {
134 sp<AudioRoute> legacy = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioRoute(aidlRoute, ports));
135 routes.add(legacy);
136 }
137 (*legacy)->setRoutes(routes);
138 return OK;
139 }
140
aidl2legacy_AudioHwModules_HwModuleCollection(const std::vector<media::AudioHwModule> & aidl,HwModuleCollection * legacyModules,DeviceVector * attachedInputDevices,DeviceVector * attachedOutputDevices,sp<DeviceDescriptor> * defaultOutputDevice)141 status_t aidl2legacy_AudioHwModules_HwModuleCollection(
142 const std::vector<media::AudioHwModule>& aidl,
143 HwModuleCollection* legacyModules, DeviceVector* attachedInputDevices,
144 DeviceVector* attachedOutputDevices, sp<DeviceDescriptor>* defaultOutputDevice) {
145 for (const auto& aidlModule : aidl) {
146 sp<HwModule> legacy;
147 RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModule_HwModule(aidlModule, &legacy,
148 attachedInputDevices, attachedOutputDevices, defaultOutputDevice));
149 legacyModules->add(legacy);
150 }
151 return OK;
152 }
153
154 using SurroundFormatFamily = AudioPolicyConfig::SurroundFormats::value_type;
155 ConversionResult<SurroundFormatFamily>
aidl2legacy_SurroundFormatFamily(const media::SurroundSoundConfig::SurroundFormatFamily & aidl)156 aidl2legacy_SurroundFormatFamily(const media::SurroundSoundConfig::SurroundFormatFamily& aidl) {
157 audio_format_t legacyPrimary = VALUE_OR_RETURN(
158 aidl2legacy_AudioFormatDescription_audio_format_t(aidl.primaryFormat));
159 std::unordered_set<audio_format_t> legacySubs = VALUE_OR_RETURN(
160 convertContainer<std::unordered_set<audio_format_t>>(
161 aidl.subFormats, aidl2legacy_AudioFormatDescription_audio_format_t));
162 return std::make_pair(legacyPrimary, legacySubs);
163 }
164
165 ConversionResult<AudioPolicyConfig::SurroundFormats>
aidl2legacy_SurroundSoundConfig_SurroundFormats(const media::SurroundSoundConfig & aidl)166 aidl2legacy_SurroundSoundConfig_SurroundFormats(const media::SurroundSoundConfig& aidl) {
167 return convertContainer<AudioPolicyConfig::SurroundFormats>(aidl.formatFamilies,
168 aidl2legacy_SurroundFormatFamily);
169 };
170
171 } // namespace
172
173 // static
createDefault()174 sp<const AudioPolicyConfig> AudioPolicyConfig::createDefault() {
175 auto config = sp<AudioPolicyConfig>::make();
176 config->setDefault();
177 return config;
178 }
179
180 // static
loadFromApmAidlConfigWithFallback(const media::AudioPolicyConfig & aidl)181 sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmAidlConfigWithFallback(
182 const media::AudioPolicyConfig& aidl) {
183 auto config = sp<AudioPolicyConfig>::make();
184 if (status_t status = config->loadFromAidl(aidl); status == NO_ERROR) {
185 return config;
186 }
187 return createDefault();
188 }
189
190 // static
loadFromApmXmlConfigWithFallback(const std::string & xmlFilePath)191 sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
192 const std::string& xmlFilePath) {
193 const std::string filePath =
194 xmlFilePath.empty() ? audio_get_audio_policy_config_file() : xmlFilePath;
195 auto config = sp<AudioPolicyConfig>::make();
196 if (status_t status = config->loadFromXml(filePath, false /*forVts*/); status == NO_ERROR) {
197 return config;
198 }
199 return createDefault();
200 }
201
202 // static
createWritableForTests()203 sp<AudioPolicyConfig> AudioPolicyConfig::createWritableForTests() {
204 return sp<AudioPolicyConfig>::make();
205 }
206
207 // static
loadFromCustomXmlConfigForTests(const std::string & xmlFilePath)208 error::Result<sp<AudioPolicyConfig>> AudioPolicyConfig::loadFromCustomXmlConfigForTests(
209 const std::string& xmlFilePath) {
210 auto config = sp<AudioPolicyConfig>::make();
211 if (status_t status = config->loadFromXml(xmlFilePath, false /*forVts*/); status == NO_ERROR) {
212 return config;
213 } else {
214 return base::unexpected(status);
215 }
216 }
217
218 // static
loadFromCustomXmlConfigForVtsTests(const std::string & configPath,const std::string & xmlFileName)219 error::Result<sp<AudioPolicyConfig>> AudioPolicyConfig::loadFromCustomXmlConfigForVtsTests(
220 const std::string& configPath, const std::string& xmlFileName) {
221 auto filePath = configPath;
222 if (filePath.empty()) {
223 for (const auto& location : audio_get_configuration_paths()) {
224 std::string path = location + '/' + xmlFileName;
225 if (access(path.c_str(), F_OK) == 0) {
226 filePath = location;
227 break;
228 }
229 }
230 }
231 if (filePath.empty()) {
232 ALOGE("Did not find a config file \"%s\" among known config paths", xmlFileName.c_str());
233 return base::unexpected(BAD_VALUE);
234 }
235 auto config = sp<AudioPolicyConfig>::make();
236 if (status_t status = config->loadFromXml(filePath + "/" + xmlFileName, true /*forVts*/);
237 status == NO_ERROR) {
238 return config;
239 } else {
240 return base::unexpected(status);
241 }
242 }
243
augmentData()244 void AudioPolicyConfig::augmentData() {
245 // If microphones address is empty, set it according to device type
246 for (size_t i = 0; i < mInputDevices.size(); i++) {
247 if (mInputDevices[i]->address().empty()) {
248 if (mInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
249 mInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
250 } else if (mInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
251 mInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
252 }
253 }
254 }
255 }
256
loadFromAidl(const media::AudioPolicyConfig & aidl)257 status_t AudioPolicyConfig::loadFromAidl(const media::AudioPolicyConfig& aidl) {
258 RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModules_HwModuleCollection(aidl.modules,
259 &mHwModules, &mInputDevices, &mOutputDevices, &mDefaultOutputDevice));
260 mIsCallScreenModeSupported = std::find(aidl.supportedModes.begin(), aidl.supportedModes.end(),
261 media::audio::common::AudioMode::CALL_SCREEN) != aidl.supportedModes.end();
262 mSurroundFormats = VALUE_OR_RETURN_STATUS(
263 aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
264 mSource = kAidlConfigSource;
265 // No need to augmentData() as AIDL HAL must provide correct mic addresses.
266 return NO_ERROR;
267 }
268
loadFromXml(const std::string & xmlFilePath,bool forVts)269 status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
270 if (xmlFilePath.empty()) {
271 ALOGE("Audio policy configuration file name is empty");
272 return BAD_VALUE;
273 }
274 status_t status = forVts ? deserializeAudioPolicyFileForVts(xmlFilePath.c_str(), this)
275 : deserializeAudioPolicyFile(xmlFilePath.c_str(), this);
276 if (status == NO_ERROR) {
277 mSource = xmlFilePath;
278 augmentData();
279 } else {
280 ALOGE("Could not load audio policy from the configuration file \"%s\": %d",
281 xmlFilePath.c_str(), status);
282 }
283 return status;
284 }
285
setDefault()286 void AudioPolicyConfig::setDefault() {
287 mSource = kDefaultConfigSource;
288 mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
289
290 mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
291 mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
292 sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
293 defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
294 sp<AudioProfile> micProfile = new AudioProfile(
295 AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
296 defaultInputDevice->addAudioProfile(micProfile);
297 mOutputDevices.add(mDefaultOutputDevice);
298 mInputDevices.add(defaultInputDevice);
299
300 sp<HwModule> module = new HwModule(
301 AUDIO_HARDWARE_MODULE_ID_PRIMARY, AUDIO_DEVICE_API_VERSION_2_0);
302 mHwModules.add(module);
303
304 sp<OutputProfile> outProfile = new OutputProfile("primary");
305 outProfile->addAudioProfile(
306 new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
307 outProfile->addSupportedDevice(mDefaultOutputDevice);
308 outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
309 module->addOutputProfile(outProfile);
310
311 sp<InputProfile> inProfile = new InputProfile("primary");
312 inProfile->addAudioProfile(micProfile);
313 inProfile->addSupportedDevice(defaultInputDevice);
314 module->addInputProfile(inProfile);
315
316 setDefaultSurroundFormats();
317 augmentData();
318 }
319
setDefaultSurroundFormats()320 void AudioPolicyConfig::setDefaultSurroundFormats() {
321 mSurroundFormats = {
322 {AUDIO_FORMAT_AC3, {}},
323 {AUDIO_FORMAT_E_AC3, {}},
324 {AUDIO_FORMAT_DTS, {}},
325 {AUDIO_FORMAT_DTS_HD, {}},
326 {AUDIO_FORMAT_DTS_HD_MA, {}},
327 {AUDIO_FORMAT_DTS_UHD, {}},
328 {AUDIO_FORMAT_DTS_UHD_P2, {}},
329 {AUDIO_FORMAT_AAC_LC, {
330 AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
331 AUDIO_FORMAT_AAC_XHE}},
332 {AUDIO_FORMAT_DOLBY_TRUEHD, {}},
333 {AUDIO_FORMAT_E_AC3_JOC, {}},
334 {AUDIO_FORMAT_AC4, {}}};
335 }
336
337 } // namespace android
338