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 <audio_utils/string.h>
     21 #include <media/TypeConverter.h>
     22 #include <set>
     23 #include "DeviceDescriptor.h"
     24 #include "TypeConverter.h"
     25 #include "AudioGain.h"
     26 #include "HwModule.h"
     27 
     28 namespace android {
     29 
     30 DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
     31         DeviceDescriptor(type, FormatVector{}, tagName)
     32 {
     33 }
     34 
     35 DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
     36         const String8 &tagName) :
     37     AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
     38               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
     39                                              AUDIO_PORT_ROLE_SOURCE),
     40     mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
     41 {
     42     mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
     43     if (audio_is_remote_submix_device(type)) {
     44         mAddress = String8("0");
     45     }
     46     /* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
     47      * FIXME: APM should know the version of the HAL and don't add the formats for V5.0.
     48      * For now, the workaround to remove AC3 and IEC61937 support on HDMI is to declare
     49      * something like 'encodedFormats="AUDIO_FORMAT_PCM_16_BIT"' on the HDMI devicePort.
     50      */
     51     if (type == AUDIO_DEVICE_OUT_HDMI && mEncodedFormats.isEmpty()) {
     52         mEncodedFormats.add(AUDIO_FORMAT_AC3);
     53         mEncodedFormats.add(AUDIO_FORMAT_IEC61937);
     54     }
     55 }
     56 
     57 audio_port_handle_t DeviceDescriptor::getId() const
     58 {
     59     return mId;
     60 }
     61 
     62 void DeviceDescriptor::attach(const sp<HwModule>& module)
     63 {
     64     AudioPort::attach(module);
     65     mId = getNextUniqueId();
     66 }
     67 
     68 void DeviceDescriptor::detach() {
     69     mId = AUDIO_PORT_HANDLE_NONE;
     70     AudioPort::detach();
     71 }
     72 
     73 template<typename T>
     74 bool checkEqual(const T& f1, const T& f2)
     75 {
     76     std::set<typename T::value_type> s1(f1.begin(), f1.end());
     77     std::set<typename T::value_type> s2(f2.begin(), f2.end());
     78     return s1 == s2;
     79 }
     80 
     81 bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
     82 {
     83     // Devices are considered equal if they:
     84     // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
     85     // - have the same address
     86     // - have the same encodingFormats (if device supports encoding)
     87     if (other == 0) {
     88         return false;
     89     }
     90 
     91     return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress) &&
     92            checkEqual(mEncodedFormats, other->mEncodedFormats);
     93 }
     94 
     95 bool DeviceDescriptor::hasCurrentEncodedFormat() const
     96 {
     97     if (!device_has_encoding_capability(type())) {
     98         return true;
     99     }
    100     if (mEncodedFormats.isEmpty()) {
    101         return true;
    102     }
    103 
    104     return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT);
    105 }
    106 
    107 bool DeviceDescriptor::supportsFormat(audio_format_t format)
    108 {
    109     if (mEncodedFormats.isEmpty()) {
    110         return true;
    111     }
    112 
    113     for (const auto& devFormat : mEncodedFormats) {
    114         if (devFormat == format) {
    115             return true;
    116         }
    117     }
    118     return false;
    119 }
    120 
    121 void DeviceVector::refreshTypes()
    122 {
    123     mDeviceTypes = AUDIO_DEVICE_NONE;
    124     for (size_t i = 0; i < size(); i++) {
    125         mDeviceTypes |= itemAt(i)->type();
    126     }
    127     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
    128 }
    129 
    130 ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
    131 {
    132     for (size_t i = 0; i < size(); i++) {
    133         if (itemAt(i)->equals(item)) { // item may be null sp<>, i.e. AUDIO_DEVICE_NONE
    134             return i;
    135         }
    136     }
    137     return -1;
    138 }
    139 
    140 void DeviceVector::add(const DeviceVector &devices)
    141 {
    142     bool added = false;
    143     for (const auto& device : devices) {
    144         if (indexOf(device) < 0 && SortedVector::add(device) >= 0) {
    145             added = true;
    146         }
    147     }
    148     if (added) {
    149         refreshTypes();
    150     }
    151 }
    152 
    153 ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
    154 {
    155     ssize_t ret = indexOf(item);
    156 
    157     if (ret < 0) {
    158         ret = SortedVector::add(item);
    159         if (ret >= 0) {
    160             refreshTypes();
    161         }
    162     } else {
    163         ALOGW("DeviceVector::add device %08x already in", item->type());
    164         ret = -1;
    165     }
    166     return ret;
    167 }
    168 
    169 ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
    170 {
    171     ssize_t ret = indexOf(item);
    172 
    173     if (ret < 0) {
    174         ALOGW("DeviceVector::remove device %08x not in", item->type());
    175     } else {
    176         ret = SortedVector::removeAt(ret);
    177         if (ret >= 0) {
    178             refreshTypes();
    179         }
    180     }
    181     return ret;
    182 }
    183 
    184 void DeviceVector::remove(const DeviceVector &devices)
    185 {
    186     for (const auto& device : devices) {
    187         remove(device);
    188     }
    189 }
    190 
    191 DeviceVector DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
    192 {
    193     DeviceVector devices;
    194     for (const auto& device : *this) {
    195         if (device->getModuleHandle() == moduleHandle) {
    196             devices.add(device);
    197         }
    198     }
    199     return devices;
    200 }
    201 
    202 audio_devices_t DeviceVector::getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const
    203 {
    204     audio_devices_t deviceTypes = AUDIO_DEVICE_NONE;
    205     for (const auto& device : *this) {
    206         if (device->getModuleHandle() == moduleHandle) {
    207             deviceTypes |= device->type();
    208         }
    209     }
    210     return deviceTypes;
    211 }
    212 
    213 sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
    214                                              audio_format_t format) const
    215 {
    216     sp<DeviceDescriptor> device;
    217     for (size_t i = 0; i < size(); i++) {
    218         if (itemAt(i)->type() == type) {
    219             // If format is specified, match it and ignore address
    220             // Otherwise if address is specified match it
    221             // Otherwise always match
    222             if (((address == "" || itemAt(i)->address() == address) &&
    223                  format == AUDIO_FORMAT_DEFAULT) ||
    224                 (itemAt(i)->supportsFormat(format) && format != AUDIO_FORMAT_DEFAULT)) {
    225                 device = itemAt(i);
    226                 if (itemAt(i)->address() == address) {
    227                     break;
    228                 }
    229             }
    230         }
    231     }
    232     ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p format %08x",
    233             __func__, type, address.string(), device.get(), format);
    234     return device;
    235 }
    236 
    237 sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
    238 {
    239     if (id != AUDIO_PORT_HANDLE_NONE) {
    240         for (const auto& device : *this) {
    241             if (device->getId() == id) {
    242                 return device;
    243             }
    244         }
    245     }
    246     return nullptr;
    247 }
    248 
    249 DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const
    250 {
    251     DeviceVector devices;
    252     bool isOutput = audio_is_output_devices(type);
    253     type &= ~AUDIO_DEVICE_BIT_IN;
    254     for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
    255         bool curIsOutput = audio_is_output_devices(itemAt(i)->type());
    256         audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
    257         if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
    258             devices.add(itemAt(i));
    259             type &= ~curType;
    260             ALOGV("DeviceVector::%s() for type %08x found %p",
    261                     __func__, itemAt(i)->type(), itemAt(i).get());
    262         }
    263     }
    264     return devices;
    265 }
    266 
    267 sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const
    268 {
    269     for (const auto& device : *this) {
    270         if (device->getTagName() == tagName) {
    271             return device;
    272         }
    273     }
    274     return nullptr;
    275 }
    276 
    277 void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const
    278 {
    279     if (isEmpty()) {
    280         return;
    281     }
    282     dst->appendFormat("%*s- %s devices:\n", spaces, "", tag.string());
    283     for (size_t i = 0; i < size(); i++) {
    284         itemAt(i)->dump(dst, spaces + 2, i, verbose);
    285     }
    286 }
    287 
    288 void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
    289                                          const struct audio_port_config *srcConfig) const
    290 {
    291     dstConfig->config_mask = AUDIO_PORT_CONFIG_GAIN;
    292     if (mSamplingRate != 0) {
    293         dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
    294     }
    295     if (mChannelMask != AUDIO_CHANNEL_NONE) {
    296         dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
    297     }
    298     if (mFormat != AUDIO_FORMAT_INVALID) {
    299         dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
    300     }
    301 
    302     if (srcConfig != NULL) {
    303         dstConfig->config_mask |= srcConfig->config_mask;
    304     }
    305 
    306     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
    307 
    308     dstConfig->id = mId;
    309     dstConfig->role = audio_is_output_device(mDeviceType) ?
    310                         AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
    311     dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
    312     dstConfig->ext.device.type = mDeviceType;
    313 
    314     //TODO Understand why this test is necessary. i.e. why at boot time does it crash
    315     // without the test?
    316     // This has been demonstrated to NOT be true (at start up)
    317     // ALOG_ASSERT(mModule != NULL);
    318     dstConfig->ext.device.hw_module = getModuleHandle();
    319     (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.string());
    320 }
    321 
    322 void DeviceDescriptor::toAudioPort(struct audio_port *port) const
    323 {
    324     ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceType);
    325     AudioPort::toAudioPort(port);
    326     port->id = mId;
    327     toAudioPortConfig(&port->active_config);
    328     port->ext.device.type = mDeviceType;
    329     port->ext.device.hw_module = getModuleHandle();
    330     (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
    331 }
    332 
    333 void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port, bool force) {
    334     if (!force && !port->hasDynamicAudioProfile()) {
    335         return;
    336     }
    337     AudioPort::importAudioPort(port);
    338     port->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
    339 }
    340 
    341 void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
    342 {
    343     dst->appendFormat("%*sDevice %d:\n", spaces, "", index + 1);
    344     if (mId != 0) {
    345         dst->appendFormat("%*s- id: %2d\n", spaces, "", mId);
    346     }
    347     if (!mTagName.isEmpty()) {
    348         dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string());
    349     }
    350 
    351     dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
    352 
    353     if (mAddress.size() != 0) {
    354         dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
    355     }
    356     AudioPort::dump(dst, spaces, verbose);
    357 }
    358 
    359 std::string DeviceDescriptor::toString() const
    360 {
    361     std::stringstream sstream;
    362     sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
    363     return sstream.str();
    364 }
    365 
    366 std::string DeviceVector::toString() const
    367 {
    368     if (isEmpty()) {
    369         return {"AUDIO_DEVICE_NONE"};
    370     }
    371     std::string result = {"{"};
    372     for (const auto &device : *this) {
    373         if (device != *begin()) {
    374            result += ";";
    375         }
    376         result += device->toString();
    377     }
    378     return result + "}";
    379 }
    380 
    381 DeviceVector DeviceVector::filter(const DeviceVector &devices) const
    382 {
    383     DeviceVector filteredDevices;
    384     for (const auto &device : *this) {
    385         if (devices.contains(device)) {
    386             filteredDevices.add(device);
    387         }
    388     }
    389     return filteredDevices;
    390 }
    391 
    392 bool DeviceVector::containsAtLeastOne(const DeviceVector &devices) const
    393 {
    394     return !filter(devices).isEmpty();
    395 }
    396 
    397 bool DeviceVector::containsAllDevices(const DeviceVector &devices) const
    398 {
    399     return filter(devices).size() == devices.size();
    400 }
    401 
    402 DeviceVector DeviceVector::filterForEngine() const
    403 {
    404     DeviceVector filteredDevices;
    405     for (const auto &device : *this) {
    406         if (audio_is_remote_submix_device(device->type()) && device->address() != "0") {
    407             continue;
    408         }
    409         filteredDevices.add(device);
    410     }
    411     return filteredDevices;
    412 }
    413 
    414 void DeviceDescriptor::log() const
    415 {
    416     ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId,  mDeviceType,
    417           ::android::toString(mDeviceType).c_str(),
    418           mAddress.string());
    419 
    420     AudioPort::log("  ");
    421 }
    422 
    423 } // namespace android
    424