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