xref: /aosp_15_r20/frameworks/av/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2015 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::HwModule"
18 //#define LOG_NDEBUG 0
19 
20 #include <android-base/stringprintf.h>
21 #include <policy.h>
22 #include <system/audio.h>
23 
24 #include "HwModule.h"
25 #include "IOProfile.h"
26 
27 namespace android {
28 
HwModule(const char * name,uint32_t halVersionMajor,uint32_t halVersionMinor)29 HwModule::HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersionMinor)
30     : mName(String8(name)),
31       mHandle(AUDIO_MODULE_HANDLE_NONE)
32 {
33     setHalVersion(halVersionMajor, halVersionMinor);
34 }
35 
HwModule(const char * name,uint32_t halVersion)36 HwModule::HwModule(const char *name, uint32_t halVersion)
37     : mName(String8(name)),
38       mHandle(AUDIO_MODULE_HANDLE_NONE),
39       mHalVersion(halVersion)
40 {
41 }
42 
~HwModule()43 HwModule::~HwModule()
44 {
45     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
46         mOutputProfiles[i]->clearSupportedDevices();
47     }
48     for (size_t i = 0; i < mInputProfiles.size(); i++) {
49         mInputProfiles[i]->clearSupportedDevices();
50     }
51 }
52 
getTagForDevice(audio_devices_t device,const String8 & address,audio_format_t codec)53 std::string HwModule::getTagForDevice(audio_devices_t device, const String8 &address,
54                                           audio_format_t codec)
55 {
56     DeviceVector declaredDevices = getDeclaredDevices();
57     sp<DeviceDescriptor> deviceDesc = declaredDevices.getDevice(device, address, codec);
58     return deviceDesc ? deviceDesc->getTagName() : std::string{};
59 }
60 
addOutputProfile(const std::string & name,const audio_config_t * config,audio_devices_t device,const String8 & address,audio_output_flags_t flags)61 status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config,
62                                     audio_devices_t device, const String8& address,
63                                     audio_output_flags_t flags)
64 {
65     sp<IOProfile> profile = new OutputProfile(name);
66     profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
67                                               config->sample_rate));
68     profile->setFlags(flags);
69 
70     sp<DeviceDescriptor> devDesc =
71             new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
72     addDynamicDevice(devDesc);
73     // Reciprocally attach the device to the module
74     devDesc->attach(this);
75     profile->addSupportedDevice(devDesc);
76 
77     return addOutputProfile(profile);
78 }
79 
addOutputProfile(const sp<IOProfile> & profile)80 status_t HwModule::addOutputProfile(const sp<IOProfile> &profile)
81 {
82     profile->attach(this);
83     mOutputProfiles.add(profile);
84     mPorts.add(profile);
85     return NO_ERROR;
86 }
87 
addInputProfile(const sp<IOProfile> & profile)88 status_t HwModule::addInputProfile(const sp<IOProfile> &profile)
89 {
90     profile->attach(this);
91     mInputProfiles.add(profile);
92     mPorts.add(profile);
93     return NO_ERROR;
94 }
95 
addProfile(const sp<IOProfile> & profile)96 status_t HwModule::addProfile(const sp<IOProfile> &profile)
97 {
98     switch (profile->getRole()) {
99     case AUDIO_PORT_ROLE_SOURCE:
100         return addOutputProfile(profile);
101     case AUDIO_PORT_ROLE_SINK:
102         return addInputProfile(profile);
103     case AUDIO_PORT_ROLE_NONE:
104         return BAD_VALUE;
105     }
106     return BAD_VALUE;
107 }
108 
setProfiles(const IOProfileCollection & profiles)109 void HwModule::setProfiles(const IOProfileCollection &profiles)
110 {
111     for (size_t i = 0; i < profiles.size(); i++) {
112         addProfile(profiles[i]);
113     }
114 }
115 
removeOutputProfile(const std::string & name)116 status_t HwModule::removeOutputProfile(const std::string& name)
117 {
118     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
119         if (mOutputProfiles[i]->getName() == name) {
120             for (const auto &device : mOutputProfiles[i]->getSupportedDevices()) {
121                 removeDynamicDevice(device);
122             }
123             mOutputProfiles.removeAt(i);
124             break;
125         }
126     }
127 
128     return NO_ERROR;
129 }
130 
addInputProfile(const std::string & name,const audio_config_t * config,audio_devices_t device,const String8 & address,audio_input_flags_t flags)131 status_t HwModule::addInputProfile(const std::string& name, const audio_config_t *config,
132                                    audio_devices_t device, const String8& address,
133                                    audio_input_flags_t flags)
134 {
135     sp<IOProfile> profile = new InputProfile(name);
136     profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
137                                               config->sample_rate));
138     profile->setFlags(flags);
139 
140     sp<DeviceDescriptor> devDesc =
141             new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
142     addDynamicDevice(devDesc);
143     // Reciprocally attach the device to the module
144     devDesc->attach(this);
145     profile->addSupportedDevice(devDesc);
146 
147     ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
148           name.c_str(), config->sample_rate, config->channel_mask);
149 
150     return addInputProfile(profile);
151 }
152 
removeInputProfile(const std::string & name)153 status_t HwModule::removeInputProfile(const std::string& name)
154 {
155     for (size_t i = 0; i < mInputProfiles.size(); i++) {
156         if (mInputProfiles[i]->getName() == name) {
157             for (const auto &device : mInputProfiles[i]->getSupportedDevices()) {
158                 removeDynamicDevice(device);
159             }
160             mInputProfiles.removeAt(i);
161             break;
162         }
163     }
164 
165     return NO_ERROR;
166 }
167 
setDeclaredDevices(const DeviceVector & devices)168 void HwModule::setDeclaredDevices(const DeviceVector &devices)
169 {
170     mDeclaredDevices = devices;
171     for (size_t i = 0; i < devices.size(); i++) {
172         mPorts.add(devices[i]);
173     }
174 }
175 
getRouteSinkDevice(const sp<AudioRoute> & route) const176 sp<DeviceDescriptor> HwModule::getRouteSinkDevice(const sp<AudioRoute> &route) const
177 {
178     sp<DeviceDescriptor> sinkDevice = 0;
179     if (route->getSink()->asAudioPort()->getType() == AUDIO_PORT_TYPE_DEVICE) {
180         sinkDevice = mDeclaredDevices.getDeviceFromTagName(route->getSink()->getTagName());
181     }
182     return sinkDevice;
183 }
184 
getRouteSourceDevices(const sp<AudioRoute> & route) const185 DeviceVector HwModule::getRouteSourceDevices(const sp<AudioRoute> &route) const
186 {
187     DeviceVector sourceDevices;
188     for (const auto& source : route->getSources()) {
189         if (source->asAudioPort()->getType() == AUDIO_PORT_TYPE_DEVICE) {
190             sourceDevices.add(mDeclaredDevices.getDeviceFromTagName(source->getTagName()));
191         }
192     }
193     return sourceDevices;
194 }
195 
setRoutes(const AudioRouteVector & routes)196 void HwModule::setRoutes(const AudioRouteVector &routes)
197 {
198     mRoutes = routes;
199     // Now updating the streams (aka IOProfile until now) supported devices
200     refreshSupportedDevices();
201 }
202 
refreshSupportedDevices()203 void HwModule::refreshSupportedDevices()
204 {
205     // Now updating the streams (aka IOProfile until now) supported devices
206     for (const auto& stream : mInputProfiles) {
207         DeviceVector sourceDevices;
208         for (const auto& route : stream->getRoutes()) {
209             sp<PolicyAudioPort> sink = route->getSink();
210             if (sink == 0 || stream != sink) {
211                 ALOGE("%s: Invalid route attached to input stream", __FUNCTION__);
212                 continue;
213             }
214             DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route);
215             if (sourceDevicesForRoute.isEmpty()) {
216                 ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
217                 continue;
218             }
219             sourceDevices.add(sourceDevicesForRoute);
220         }
221         if (sourceDevices.isEmpty()) {
222             ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
223             continue;
224         }
225         stream->setSupportedDevices(sourceDevices);
226     }
227     for (const auto& stream : mOutputProfiles) {
228         DeviceVector sinkDevices;
229         for (const auto& route : stream->getRoutes()) {
230             sp<PolicyAudioPort> source = findByTagName(route->getSources(), stream->getTagName());
231             if (source == 0 || stream != source) {
232                 ALOGE("%s: Invalid route attached to output stream", __FUNCTION__);
233                 continue;
234             }
235             sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route);
236             if (sinkDevice == 0) {
237                 ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().c_str());
238                 continue;
239             }
240             sinkDevices.add(sinkDevice);
241         }
242         stream->setSupportedDevices(sinkDevices);
243     }
244 }
245 
setHandle(audio_module_handle_t handle)246 void HwModule::setHandle(audio_module_handle_t handle) {
247     ALOGW_IF(mHandle != AUDIO_MODULE_HANDLE_NONE,
248             "HwModule handle is changing from %d to %d", mHandle, handle);
249     mHandle = handle;
250 }
251 
supportsPatch(const sp<PolicyAudioPort> & srcPort,const sp<PolicyAudioPort> & dstPort) const252 bool HwModule::supportsPatch(const sp<PolicyAudioPort> &srcPort,
253                              const sp<PolicyAudioPort> &dstPort) const {
254     for (const auto &route : mRoutes) {
255         if (route->supportsPatch(srcPort, dstPort)) {
256             return true;
257         }
258     }
259     return false;
260 }
261 
dump(String8 * dst,int spaces) const262 void HwModule::dump(String8 *dst, int spaces) const
263 {
264     dst->appendFormat("Handle: %d; \"%s\"\n", mHandle, getName());
265     if (mOutputProfiles.size()) {
266         dst->appendFormat("%*s- Output MixPorts (%zu):\n", spaces - 2, "", mOutputProfiles.size());
267         for (size_t i = 0; i < mOutputProfiles.size(); i++) {
268             const std::string prefix = base::StringPrintf("%*s %zu. ", spaces, "", i + 1);
269             dst->append(prefix.c_str());
270             mOutputProfiles[i]->dump(dst, prefix.size());
271         }
272     }
273     if (mInputProfiles.size()) {
274         dst->appendFormat("%*s- Input MixPorts (%zu):\n", spaces - 2, "", mInputProfiles.size());
275         for (size_t i = 0; i < mInputProfiles.size(); i++) {
276             const std::string prefix = base::StringPrintf("%*s %zu. ", spaces, "", i + 1);
277             dst->append(prefix.c_str());
278             mInputProfiles[i]->dump(dst, prefix.size());
279         }
280     }
281     mDeclaredDevices.dump(dst, String8("- Declared"), spaces - 2, true);
282     mDynamicDevices.dump(dst, String8("- Dynamic"),  spaces - 2, true);
283     dumpAudioRouteVector(mRoutes, dst, spaces);
284 }
285 
getModuleFromHandle(audio_module_handle_t handle) const286 sp<HwModule> HwModuleCollection::getModuleFromHandle(audio_module_handle_t handle) const
287 {
288     for (const auto& module : *this) {
289         if (module->getHandle() == handle) {
290             return module;
291         }
292     }
293     return nullptr;
294 }
295 
getModuleFromName(const char * name) const296 sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
297 {
298     for (const auto& module : *this) {
299         if (strcmp(module->getName(), name) == 0) {
300             return module;
301         }
302     }
303     return nullptr;
304 }
305 
getModuleForDeviceType(audio_devices_t type,audio_format_t encodedFormat,std::string * tagName) const306 sp<HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
307                                                         audio_format_t encodedFormat,
308                                                         std::string *tagName) const
309 {
310     for (const auto& module : *this) {
311         const auto& profiles = audio_is_output_device(type) ?
312                 module->getOutputProfiles() : module->getInputProfiles();
313         for (const auto& profile : profiles) {
314             if (profile->supportsDeviceTypes({type})) {
315                 if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
316                     DeviceVector declaredDevices = module->getDeclaredDevices();
317                     sp <DeviceDescriptor> deviceDesc =
318                             declaredDevices.getDevice(type, String8(), encodedFormat);
319                     if (deviceDesc) {
320                         if (tagName != nullptr) {
321                             *tagName = deviceDesc->getTagName();
322                         }
323                         return module;
324                     }
325                 } else {
326                     if (tagName != nullptr) {
327                         *tagName = profile->getTag({type});
328                     }
329                     return module;
330                 }
331             }
332         }
333     }
334     return nullptr;
335 }
336 
getModuleForDevice(const sp<DeviceDescriptor> & device,audio_format_t encodedFormat) const337 sp<HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device,
338                                                      audio_format_t encodedFormat) const
339 {
340     return getModuleForDeviceType(device->type(), encodedFormat);
341 }
342 
getAvailableDevicesFromModuleName(const char * name,const DeviceVector & availableDevices) const343 DeviceVector HwModuleCollection::getAvailableDevicesFromModuleName(
344         const char *name, const DeviceVector &availableDevices) const
345 {
346     sp<HwModule> module = getModuleFromName(name);
347     if (module == nullptr) {
348         return DeviceVector();
349     }
350     return availableDevices.getDevicesFromHwModule(module->getHandle());
351 }
352 
getDeviceDescriptor(const audio_devices_t deviceType,const char * address,const char * name,const audio_format_t encodedFormat,bool allowToCreate,bool matchAddress) const353 sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t deviceType,
354                                                              const char *address,
355                                                              const char *name,
356                                                              const audio_format_t encodedFormat,
357                                                              bool allowToCreate,
358                                                              bool matchAddress) const
359 {
360     String8 devAddress = (address == nullptr || !matchAddress) ? String8("") : String8(address);
361     // handle legacy remote submix case where the address was not always specified
362     if (audio_is_remote_submix_device(deviceType) && (devAddress.length() == 0)) {
363         devAddress = String8("0");
364     }
365 
366     for (const auto& hwModule : *this) {
367         if (!allowToCreate) {
368             auto dynamicDevices = hwModule->getDynamicDevices();
369             auto dynamicDevice = dynamicDevices.getDevice(deviceType, devAddress, encodedFormat);
370             if (dynamicDevice) {
371                 return dynamicDevice;
372             }
373         }
374         DeviceVector moduleDevices = hwModule->getAllDevices();
375         auto moduleDevice = moduleDevices.getDevice(deviceType, devAddress, encodedFormat);
376 
377         // Prevent overwriting moduleDevice address if connected device does not have the same
378         // address (since getDevice with empty address ignores match on address), use dynamic device
379         if (moduleDevice && allowToCreate &&
380                 (!moduleDevice->address().empty() &&
381                  (moduleDevice->address().compare(devAddress.c_str()) != 0))) {
382             break;
383         }
384         if (moduleDevice) {
385             if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
386                 moduleDevice->setEncodedFormat(encodedFormat);
387             }
388             if (allowToCreate) {
389                 moduleDevice->attach(hwModule);
390                 // Name may be overwritten, restored on detach.
391                 moduleDevice->setAddress(devAddress.c_str());
392                 // Name may be overwritten, restored on detach.
393                 moduleDevice->setName(name);
394             }
395             return moduleDevice;
396         }
397     }
398     if (!allowToCreate) {
399         ALOGW("%s: could not find HW module for device %s (%s, %08x) address %s", __FUNCTION__,
400                 name, audio_device_to_string(deviceType), deviceType, address);
401         return nullptr;
402     }
403     return createDevice(deviceType, address, name, encodedFormat);
404 }
405 
createDevice(const audio_devices_t type,const char * address,const char * name,const audio_format_t encodedFormat) const406 sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type,
407                                                       const char *address,
408                                                       const char *name,
409                                                       const audio_format_t encodedFormat) const
410 {
411     std::string tagName = {};
412     sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat, &tagName);
413     if (hwModule == 0) {
414         if (encodedFormat == AUDIO_FORMAT_DEFAULT) {
415             ALOGE("%s: could not find HW module for device type '%s' (%08x)",
416                     __FUNCTION__, audio_device_to_string(type), type);
417         } else {
418             ALOGE("%s: could not find HW module for device type '%s' (%08x), "
419                     "encoded format '%s'", __FUNCTION__, audio_device_to_string(type), type,
420                     audio_format_to_string(encodedFormat));
421         }
422         return nullptr;
423     }
424 
425     sp<DeviceDescriptor> device = new DeviceDescriptor(type, tagName, address);
426     device->setName(name);
427     device->setEncodedFormat(encodedFormat);
428     device->setDynamic();
429     // Add the device to the list of dynamic devices
430     hwModule->addDynamicDevice(device);
431     // Reciprocally attach the device to the module
432     device->attach(hwModule);
433     ALOGD("%s: adding dynamic device %s to module %s", __FUNCTION__,
434           device->toString().c_str(), hwModule->getName());
435 
436     const auto &profiles = (audio_is_output_device(type) ? hwModule->getOutputProfiles() :
437                                                              hwModule->getInputProfiles());
438     for (const auto &profile : profiles) {
439         // Add the device as supported to all profile supporting "weakly" or not the device
440         // according to its type
441         if (profile->supportsDevice(device, false /*matchAddress*/)) {
442 
443             // @todo quid of audio profile? import the profile from device of the same type?
444             const auto &isoTypeDeviceForProfile =
445                 profile->getSupportedDevices().getDevice(type, String8(), AUDIO_FORMAT_DEFAULT);
446             device->importAudioPortAndPickAudioProfile(isoTypeDeviceForProfile, true /* force */);
447 
448             ALOGV("%s: adding device %s to profile %s", __FUNCTION__,
449                   device->toString().c_str(), profile->getTagName().c_str());
450             profile->addSupportedDevice(device);
451         }
452     }
453     return device;
454 }
455 
cleanUpForDevice(const sp<DeviceDescriptor> & device)456 void HwModuleCollection::cleanUpForDevice(const sp<DeviceDescriptor> &device)
457 {
458     for (const auto& hwModule : *this) {
459         DeviceVector moduleDevices = hwModule->getAllDevices();
460         if (!moduleDevices.contains(device)) {
461             continue;
462         }
463 
464         // removal of remote submix devices associated with a dynamic policy is
465         // handled by removeOutputProfile() and removeInputProfile()
466         if (audio_is_remote_submix_device(device->type()) && device->address() != "0") {
467             continue;
468         }
469 
470         device->detach();
471         // Only remove from dynamic list, not from declared list!!!
472         if (!hwModule->removeDynamicDevice(device)) {
473             return;
474         }
475         ALOGV("%s: removed dynamic device %s from module %s", __FUNCTION__,
476               device->toString().c_str(), hwModule->getName());
477 
478         const IOProfileCollection &profiles = audio_is_output_device(device->type()) ?
479                     hwModule->getOutputProfiles() : hwModule->getInputProfiles();
480         for (const auto &profile : profiles) {
481             // For cleanup, strong match is required
482             if (profile->supportsDevice(device, true /*matchAdress*/)) {
483                 ALOGV("%s: removing device %s from profile %s", __FUNCTION__,
484                       device->toString().c_str(), profile->getTagName().c_str());
485                 profile->removeSupportedDevice(device);
486             }
487         }
488     }
489 }
490 
dump(String8 * dst) const491 void HwModuleCollection::dump(String8 *dst) const
492 {
493     dst->appendFormat("\n Hardware modules (%zu):\n", size());
494     for (size_t i = 0; i < size(); i++) {
495         const std::string prefix = base::StringPrintf("  %zu. ", i + 1);
496         dst->append(prefix.c_str());
497         itemAt(i)->dump(dst, prefix.size());
498     }
499 }
500 
501 
502 } //namespace android
503