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