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