Home | History | Annotate | Download | only in src
      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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    157 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 
    166 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 
    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 
    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 
    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 
    233 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 
    242 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 
    266 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 
    276 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 
    300 sp<HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device,
    301                                                      audio_format_t encodedFormat) const
    302 {
    303     return getModuleForDeviceTypes(device->type(), encodedFormat);
    304 }
    305 
    306 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 
    316 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 
    351 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 
    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 
    430 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