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