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