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