• 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::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