• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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