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::Devices"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include "DeviceDescriptor.h"
     21 #include "TypeConverter.h"
     22 #include "AudioGain.h"
     23 #include "HwModule.h"
     24 
     25 namespace android {
     26 
     27 DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
     28     AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
     29               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
     30                                              AUDIO_PORT_ROLE_SOURCE),
     31     mAddress(""), mTagName(tagName), mDeviceType(type), mId(0)
     32 {
     33     if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
     34         mAddress = String8("0");
     35     }
     36 }
     37 
     38 audio_port_handle_t DeviceDescriptor::getId() const
     39 {
     40     return mId;
     41 }
     42 
     43 void DeviceDescriptor::attach(const sp<HwModule>& module)
     44 {
     45     AudioPort::attach(module);
     46     mId = getNextUniqueId();
     47 }
     48 
     49 bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
     50 {
     51     // Devices are considered equal if they:
     52     // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
     53     // - have the same address
     54     if (other == 0) {
     55         return false;
     56     }
     57     return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress);
     58 }
     59 
     60 void DeviceVector::refreshTypes()
     61 {
     62     mDeviceTypes = AUDIO_DEVICE_NONE;
     63     for(size_t i = 0; i < size(); i++) {
     64         mDeviceTypes |= itemAt(i)->type();
     65     }
     66     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
     67 }
     68 
     69 ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
     70 {
     71     for(size_t i = 0; i < size(); i++) {
     72         if (item->equals(itemAt(i))) {
     73             return i;
     74         }
     75     }
     76     return -1;
     77 }
     78 
     79 void DeviceVector::add(const DeviceVector &devices)
     80 {
     81     for (size_t i = 0; i < devices.size(); i++) {
     82         sp<DeviceDescriptor> device = devices.itemAt(i);
     83         if (indexOf(device) < 0 && SortedVector::add(device) >= 0) {
     84             refreshTypes();
     85         }
     86     }
     87 }
     88 
     89 ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
     90 {
     91     ssize_t ret = indexOf(item);
     92 
     93     if (ret < 0) {
     94         ret = SortedVector::add(item);
     95         if (ret >= 0) {
     96             refreshTypes();
     97         }
     98     } else {
     99         ALOGW("DeviceVector::add device %08x already in", item->type());
    100         ret = -1;
    101     }
    102     return ret;
    103 }
    104 
    105 ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
    106 {
    107     ssize_t ret = indexOf(item);
    108 
    109     if (ret < 0) {
    110         ALOGW("DeviceVector::remove device %08x not in", item->type());
    111     } else {
    112         ret = SortedVector::removeAt(ret);
    113         if (ret >= 0) {
    114             refreshTypes();
    115         }
    116     }
    117     return ret;
    118 }
    119 
    120 audio_devices_t DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
    121 {
    122     audio_devices_t devices = AUDIO_DEVICE_NONE;
    123     for (size_t i = 0; i < size(); i++) {
    124         if (itemAt(i)->getModuleHandle() == moduleHandle) {
    125             devices |= itemAt(i)->type();
    126         }
    127     }
    128     return devices;
    129 }
    130 
    131 sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, String8 address) const
    132 {
    133     sp<DeviceDescriptor> device;
    134     for (size_t i = 0; i < size(); i++) {
    135         if (itemAt(i)->type() == type) {
    136             if (address == "" || itemAt(i)->mAddress == address) {
    137                 device = itemAt(i);
    138                 if (itemAt(i)->mAddress == address) {
    139                     break;
    140                 }
    141             }
    142         }
    143     }
    144     ALOGV("DeviceVector::getDevice() for type %08x address %s found %p",
    145           type, address.string(), device.get());
    146     return device;
    147 }
    148 
    149 sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
    150 {
    151     sp<DeviceDescriptor> device;
    152     for (size_t i = 0; i < size(); i++) {
    153         if (itemAt(i)->getId() == id) {
    154             device = itemAt(i);
    155             break;
    156         }
    157     }
    158     return device;
    159 }
    160 
    161 DeviceVector DeviceVector::getDevicesFromType(audio_devices_t type) const
    162 {
    163     DeviceVector devices;
    164     bool isOutput = audio_is_output_devices(type);
    165     type &= ~AUDIO_DEVICE_BIT_IN;
    166     for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
    167         bool curIsOutput = audio_is_output_devices(itemAt(i)->mDeviceType);
    168         audio_devices_t curType = itemAt(i)->mDeviceType & ~AUDIO_DEVICE_BIT_IN;
    169         if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
    170             devices.add(itemAt(i));
    171             type &= ~curType;
    172             ALOGV("DeviceVector::getDevicesFromType() for type %x found %p",
    173                   itemAt(i)->type(), itemAt(i).get());
    174         }
    175     }
    176     return devices;
    177 }
    178 
    179 DeviceVector DeviceVector::getDevicesFromTypeAddr(
    180         audio_devices_t type, String8 address) const
    181 {
    182     DeviceVector devices;
    183     for (size_t i = 0; i < size(); i++) {
    184         if (itemAt(i)->type() == type) {
    185             if (itemAt(i)->mAddress == address) {
    186                 devices.add(itemAt(i));
    187             }
    188         }
    189     }
    190     return devices;
    191 }
    192 
    193 sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const
    194 {
    195     sp<DeviceDescriptor> device;
    196     for (size_t i = 0; i < size(); i++) {
    197         if (itemAt(i)->getTagName() == tagName) {
    198             device = itemAt(i);
    199             break;
    200         }
    201     }
    202     return device;
    203 }
    204 
    205 status_t DeviceVector::dump(int fd, const String8 &tag, int spaces, bool verbose) const
    206 {
    207     if (isEmpty()) {
    208         return NO_ERROR;
    209     }
    210     const size_t SIZE = 256;
    211     char buffer[SIZE];
    212 
    213     snprintf(buffer, SIZE, "%*s- %s devices:\n", spaces, "", tag.string());
    214     write(fd, buffer, strlen(buffer));
    215     for (size_t i = 0; i < size(); i++) {
    216         itemAt(i)->dump(fd, spaces + 2, i, verbose);
    217     }
    218     return NO_ERROR;
    219 }
    220 
    221 void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
    222                                          const struct audio_port_config *srcConfig) const
    223 {
    224     dstConfig->config_mask = AUDIO_PORT_CONFIG_GAIN;
    225     if (mSamplingRate != 0) {
    226         dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
    227     }
    228     if (mChannelMask != AUDIO_CHANNEL_NONE) {
    229         dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
    230     }
    231     if (mFormat != AUDIO_FORMAT_INVALID) {
    232         dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
    233     }
    234 
    235     if (srcConfig != NULL) {
    236         dstConfig->config_mask |= srcConfig->config_mask;
    237     }
    238 
    239     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
    240 
    241     dstConfig->id = mId;
    242     dstConfig->role = audio_is_output_device(mDeviceType) ?
    243                         AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
    244     dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
    245     dstConfig->ext.device.type = mDeviceType;
    246 
    247     //TODO Understand why this test is necessary. i.e. why at boot time does it crash
    248     // without the test?
    249     // This has been demonstrated to NOT be true (at start up)
    250     // ALOG_ASSERT(mModule != NULL);
    251     dstConfig->ext.device.hw_module = mModule != 0 ? mModule->mHandle : AUDIO_MODULE_HANDLE_NONE;
    252     strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
    253 }
    254 
    255 void DeviceDescriptor::toAudioPort(struct audio_port *port) const
    256 {
    257     ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType);
    258     AudioPort::toAudioPort(port);
    259     port->id = mId;
    260     toAudioPortConfig(&port->active_config);
    261     port->ext.device.type = mDeviceType;
    262     port->ext.device.hw_module = mModule->mHandle;
    263     strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
    264 }
    265 
    266 void DeviceDescriptor::importAudioPort(const sp<AudioPort> port) {
    267     AudioPort::importAudioPort(port);
    268     port->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
    269 }
    270 
    271 status_t DeviceDescriptor::dump(int fd, int spaces, int index, bool verbose) const
    272 {
    273     const size_t SIZE = 256;
    274     char buffer[SIZE];
    275     String8 result;
    276 
    277     snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1);
    278     result.append(buffer);
    279     if (mId != 0) {
    280         snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId);
    281         result.append(buffer);
    282     }
    283     if (!mTagName.isEmpty()) {
    284         snprintf(buffer, SIZE, "%*s- tag name: %s\n", spaces, "", mTagName.string());
    285         result.append(buffer);
    286     }
    287     std::string deviceLiteral;
    288     if (DeviceConverter::toString(mDeviceType, deviceLiteral)) {
    289         snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "", deviceLiteral.c_str());
    290         result.append(buffer);
    291     }
    292     if (mAddress.size() != 0) {
    293         snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string());
    294         result.append(buffer);
    295     }
    296     write(fd, result.string(), result.size());
    297     AudioPort::dump(fd, spaces, verbose);
    298 
    299     return NO_ERROR;
    300 }
    301 
    302 void DeviceDescriptor::log() const
    303 {
    304     std::string device;
    305     DeviceConverter::toString(mDeviceType, device);
    306     ALOGI("Device id:%d type:0x%X:%s, addr:%s", mId,  mDeviceType, device.c_str(),
    307           mAddress.string());
    308 
    309     AudioPort::log("  ");
    310 }
    311 
    312 }; // namespace android
    313