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 "ConfigParsingUtils.h"
     24 #include "audio_policy_conf.h"
     25 #include <hardware/audio.h>
     26 #include <policy.h>
     27 
     28 namespace android {
     29 
     30 HwModule::HwModule(const char *name)
     31     : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)),
     32       mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0)
     33 {
     34 }
     35 
     36 HwModule::~HwModule()
     37 {
     38     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
     39         mOutputProfiles[i]->mSupportedDevices.clear();
     40     }
     41     for (size_t i = 0; i < mInputProfiles.size(); i++) {
     42         mInputProfiles[i]->mSupportedDevices.clear();
     43     }
     44     free((void *)mName);
     45 }
     46 
     47 status_t HwModule::loadInput(cnode *root)
     48 {
     49     cnode *node = root->first_child;
     50 
     51     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK);
     52 
     53     while (node) {
     54         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
     55             profile->loadSamplingRates((char *)node->value);
     56         } else if (strcmp(node->name, FORMATS_TAG) == 0) {
     57             profile->loadFormats((char *)node->value);
     58         } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
     59             profile->loadInChannels((char *)node->value);
     60         } else if (strcmp(node->name, DEVICES_TAG) == 0) {
     61             profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
     62                                                            mDeclaredDevices);
     63         } else if (strcmp(node->name, FLAGS_TAG) == 0) {
     64             profile->mFlags = ConfigParsingUtils::parseInputFlagNames((char *)node->value);
     65         } else if (strcmp(node->name, GAINS_TAG) == 0) {
     66             profile->loadGains(node);
     67         }
     68         node = node->next;
     69     }
     70     ALOGW_IF(profile->mSupportedDevices.isEmpty(),
     71             "loadInput() invalid supported devices");
     72     ALOGW_IF(profile->mChannelMasks.size() == 0,
     73             "loadInput() invalid supported channel masks");
     74     ALOGW_IF(profile->mSamplingRates.size() == 0,
     75             "loadInput() invalid supported sampling rates");
     76     ALOGW_IF(profile->mFormats.size() == 0,
     77             "loadInput() invalid supported formats");
     78     if (!profile->mSupportedDevices.isEmpty() &&
     79             (profile->mChannelMasks.size() != 0) &&
     80             (profile->mSamplingRates.size() != 0) &&
     81             (profile->mFormats.size() != 0)) {
     82 
     83         ALOGV("loadInput() adding input Supported Devices %04x",
     84               profile->mSupportedDevices.types());
     85 
     86         profile->attach(this);
     87         mInputProfiles.add(profile);
     88         return NO_ERROR;
     89     } else {
     90         return BAD_VALUE;
     91     }
     92 }
     93 
     94 status_t HwModule::loadOutput(cnode *root)
     95 {
     96     cnode *node = root->first_child;
     97 
     98     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE);
     99 
    100     while (node) {
    101         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
    102             profile->loadSamplingRates((char *)node->value);
    103         } else if (strcmp(node->name, FORMATS_TAG) == 0) {
    104             profile->loadFormats((char *)node->value);
    105         } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
    106             profile->loadOutChannels((char *)node->value);
    107         } else if (strcmp(node->name, DEVICES_TAG) == 0) {
    108             profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
    109                                                            mDeclaredDevices);
    110         } else if (strcmp(node->name, FLAGS_TAG) == 0) {
    111             profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value);
    112         } else if (strcmp(node->name, GAINS_TAG) == 0) {
    113             profile->loadGains(node);
    114         }
    115         node = node->next;
    116     }
    117     ALOGW_IF(profile->mSupportedDevices.isEmpty(),
    118             "loadOutput() invalid supported devices");
    119     ALOGW_IF(profile->mChannelMasks.size() == 0,
    120             "loadOutput() invalid supported channel masks");
    121     ALOGW_IF(profile->mSamplingRates.size() == 0,
    122             "loadOutput() invalid supported sampling rates");
    123     ALOGW_IF(profile->mFormats.size() == 0,
    124             "loadOutput() invalid supported formats");
    125     if (!profile->mSupportedDevices.isEmpty() &&
    126             (profile->mChannelMasks.size() != 0) &&
    127             (profile->mSamplingRates.size() != 0) &&
    128             (profile->mFormats.size() != 0)) {
    129 
    130         ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
    131               profile->mSupportedDevices.types(), profile->mFlags);
    132         profile->attach(this);
    133         mOutputProfiles.add(profile);
    134         return NO_ERROR;
    135     } else {
    136         return BAD_VALUE;
    137     }
    138 }
    139 
    140 status_t HwModule::loadDevice(cnode *root)
    141 {
    142     cnode *node = root->first_child;
    143 
    144     audio_devices_t type = AUDIO_DEVICE_NONE;
    145     while (node) {
    146         if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
    147             type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
    148             break;
    149         }
    150         node = node->next;
    151     }
    152     if (type == AUDIO_DEVICE_NONE ||
    153             (!audio_is_input_device(type) && !audio_is_output_device(type))) {
    154         ALOGW("loadDevice() bad type %08x", type);
    155         return BAD_VALUE;
    156     }
    157     sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type);
    158     deviceDesc->mTag = String8(root->name);
    159 
    160     node = root->first_child;
    161     while (node) {
    162         if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) {
    163             deviceDesc->mAddress = String8((char *)node->value);
    164         } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
    165             if (audio_is_input_device(type)) {
    166                 deviceDesc->loadInChannels((char *)node->value);
    167             } else {
    168                 deviceDesc->loadOutChannels((char *)node->value);
    169             }
    170         } else if (strcmp(node->name, GAINS_TAG) == 0) {
    171             deviceDesc->loadGains(node);
    172         }
    173         node = node->next;
    174     }
    175 
    176     ALOGV("loadDevice() adding device tag %s type %08x address %s",
    177           deviceDesc->mTag.string(), type, deviceDesc->mAddress.string());
    178 
    179     mDeclaredDevices.add(deviceDesc);
    180 
    181     return NO_ERROR;
    182 }
    183 
    184 status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
    185                                                   audio_devices_t device, String8 address)
    186 {
    187     sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE);
    188 
    189     profile->mSamplingRates.add(config->sample_rate);
    190     profile->mChannelMasks.add(config->channel_mask);
    191     profile->mFormats.add(config->format);
    192 
    193     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
    194     devDesc->mAddress = address;
    195     profile->mSupportedDevices.add(devDesc);
    196 
    197     profile->attach(this);
    198     mOutputProfiles.add(profile);
    199 
    200     return NO_ERROR;
    201 }
    202 
    203 status_t HwModule::removeOutputProfile(String8 name)
    204 {
    205     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
    206         if (mOutputProfiles[i]->mName == name) {
    207             mOutputProfiles.removeAt(i);
    208             break;
    209         }
    210     }
    211 
    212     return NO_ERROR;
    213 }
    214 
    215 status_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
    216                                                   audio_devices_t device, String8 address)
    217 {
    218     sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK);
    219 
    220     profile->mSamplingRates.add(config->sample_rate);
    221     profile->mChannelMasks.add(config->channel_mask);
    222     profile->mFormats.add(config->format);
    223 
    224     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
    225     devDesc->mAddress = address;
    226     profile->mSupportedDevices.add(devDesc);
    227 
    228     ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask);
    229 
    230     profile->attach(this);
    231     mInputProfiles.add(profile);
    232 
    233     return NO_ERROR;
    234 }
    235 
    236 status_t HwModule::removeInputProfile(String8 name)
    237 {
    238     for (size_t i = 0; i < mInputProfiles.size(); i++) {
    239         if (mInputProfiles[i]->mName == name) {
    240             mInputProfiles.removeAt(i);
    241             break;
    242         }
    243     }
    244 
    245     return NO_ERROR;
    246 }
    247 
    248 
    249 void HwModule::dump(int fd)
    250 {
    251     const size_t SIZE = 256;
    252     char buffer[SIZE];
    253     String8 result;
    254 
    255     snprintf(buffer, SIZE, "  - name: %s\n", mName);
    256     result.append(buffer);
    257     snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
    258     result.append(buffer);
    259     snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
    260     result.append(buffer);
    261     write(fd, result.string(), result.size());
    262     if (mOutputProfiles.size()) {
    263         write(fd, "  - outputs:\n", strlen("  - outputs:\n"));
    264         for (size_t i = 0; i < mOutputProfiles.size(); i++) {
    265             snprintf(buffer, SIZE, "    output %zu:\n", i);
    266             write(fd, buffer, strlen(buffer));
    267             mOutputProfiles[i]->dump(fd);
    268         }
    269     }
    270     if (mInputProfiles.size()) {
    271         write(fd, "  - inputs:\n", strlen("  - inputs:\n"));
    272         for (size_t i = 0; i < mInputProfiles.size(); i++) {
    273             snprintf(buffer, SIZE, "    input %zu:\n", i);
    274             write(fd, buffer, strlen(buffer));
    275             mInputProfiles[i]->dump(fd);
    276         }
    277     }
    278     if (mDeclaredDevices.size()) {
    279         write(fd, "  - devices:\n", strlen("  - devices:\n"));
    280         for (size_t i = 0; i < mDeclaredDevices.size(); i++) {
    281             mDeclaredDevices[i]->dump(fd, 4, i);
    282         }
    283     }
    284 }
    285 
    286 sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
    287 {
    288     sp <HwModule> module;
    289 
    290     for (size_t i = 0; i < size(); i++)
    291     {
    292         if (strcmp(itemAt(i)->mName, name) == 0) {
    293             return itemAt(i);
    294         }
    295     }
    296     return module;
    297 }
    298 
    299 
    300 sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
    301 {
    302     sp <HwModule> module;
    303 
    304     for (size_t i = 0; i < size(); i++) {
    305         if (itemAt(i)->mHandle == 0) {
    306             continue;
    307         }
    308         if (audio_is_output_device(device)) {
    309             for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
    310             {
    311                 if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) {
    312                     return itemAt(i);
    313                 }
    314             }
    315         } else {
    316             for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
    317                 if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() &
    318                         device & ~AUDIO_DEVICE_BIT_IN) {
    319                     return itemAt(i);
    320                 }
    321             }
    322         }
    323     }
    324     return module;
    325 }
    326 
    327 sp<DeviceDescriptor>  HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
    328                                                               const char *device_address,
    329                                                               const char *device_name) const
    330 {
    331     String8 address = (device_address == NULL) ? String8("") : String8(device_address);
    332     // handle legacy remote submix case where the address was not always specified
    333     if (device_distinguishes_on_address(device) && (address.length() == 0)) {
    334         address = String8("0");
    335     }
    336 
    337     for (size_t i = 0; i < size(); i++) {
    338         const sp<HwModule> hwModule = itemAt(i);
    339         if (hwModule->mHandle == 0) {
    340             continue;
    341         }
    342         DeviceVector deviceList =
    343                 hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
    344         if (!deviceList.isEmpty()) {
    345             return deviceList.itemAt(0);
    346         }
    347         deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device);
    348         if (!deviceList.isEmpty()) {
    349             return deviceList.itemAt(0);
    350         }
    351     }
    352 
    353     sp<DeviceDescriptor> devDesc =
    354             new DeviceDescriptor(device);
    355     devDesc->mName = device_name;
    356     devDesc->mAddress = address;
    357     return devDesc;
    358 }
    359 
    360 status_t HwModuleCollection::dump(int fd) const
    361 {
    362     const size_t SIZE = 256;
    363     char buffer[SIZE];
    364 
    365     snprintf(buffer, SIZE, "\nHW Modules dump:\n");
    366     write(fd, buffer, strlen(buffer));
    367     for (size_t i = 0; i < size(); i++) {
    368         snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
    369         write(fd, buffer, strlen(buffer));
    370         itemAt(i)->dump(fd);
    371     }
    372     return NO_ERROR;
    373 }
    374 
    375 } //namespace android
    376