xref: /aosp_15_r20/frameworks/av/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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