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::AudioOutputDescriptor" 18 //#define LOG_NDEBUG 0 19 20 #include <AudioPolicyInterface.h> 21 #include "AudioOutputDescriptor.h" 22 #include "IOProfile.h" 23 #include "AudioGain.h" 24 #include "Volume.h" 25 #include "HwModule.h" 26 #include <media/AudioParameter.h> 27 #include <media/AudioPolicy.h> 28 29 // A device mask for all audio output devices that are considered "remote" when evaluating 30 // active output devices in isStreamActiveRemotely() 31 #define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX 32 33 namespace android { 34 35 AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port, 36 AudioPolicyClientInterface *clientInterface) 37 : mPort(port), mDevice(AUDIO_DEVICE_NONE), 38 mClientInterface(clientInterface), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0) 39 { 40 // clear usage count for all stream types 41 for (int i = 0; i < AUDIO_STREAM_CNT; i++) { 42 mRefCount[i] = 0; 43 mCurVolume[i] = -1.0; 44 mMuteCount[i] = 0; 45 mStopTime[i] = 0; 46 } 47 for (int i = 0; i < NUM_STRATEGIES; i++) { 48 mStrategyMutedByDevice[i] = false; 49 } 50 if (mPort.get() != nullptr) { 51 mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat); 52 if (mPort->mGains.size() > 0) { 53 mPort->mGains[0]->getDefaultConfig(&mGain); 54 } 55 } 56 } 57 58 audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const 59 { 60 return mPort.get() != nullptr ? mPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE; 61 } 62 63 audio_port_handle_t AudioOutputDescriptor::getId() const 64 { 65 return mId; 66 } 67 68 audio_devices_t AudioOutputDescriptor::device() const 69 { 70 return mDevice; 71 } 72 73 audio_devices_t AudioOutputDescriptor::supportedDevices() 74 { 75 return mDevice; 76 } 77 78 bool AudioOutputDescriptor::sharesHwModuleWith( 79 const sp<AudioOutputDescriptor>& outputDesc) 80 { 81 if (outputDesc->isDuplicated()) { 82 return sharesHwModuleWith(outputDesc->subOutput1()) || 83 sharesHwModuleWith(outputDesc->subOutput2()); 84 } else { 85 return hasSameHwModuleAs(outputDesc); 86 } 87 } 88 89 void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, 90 int delta) 91 { 92 if ((delta + (int)mRefCount[stream]) < 0) { 93 ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", 94 delta, stream, mRefCount[stream]); 95 mRefCount[stream] = 0; 96 return; 97 } 98 mRefCount[stream] += delta; 99 ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); 100 } 101 102 bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const 103 { 104 nsecs_t sysTime = 0; 105 if (inPastMs != 0) { 106 sysTime = systemTime(); 107 } 108 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 109 if (i == AUDIO_STREAM_PATCH) { 110 continue; 111 } 112 if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { 113 return true; 114 } 115 } 116 return false; 117 } 118 119 bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, 120 uint32_t inPastMs, 121 nsecs_t sysTime) const 122 { 123 if (mRefCount[stream] != 0) { 124 return true; 125 } 126 if (inPastMs == 0) { 127 return false; 128 } 129 if (sysTime == 0) { 130 sysTime = systemTime(); 131 } 132 if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { 133 return true; 134 } 135 return false; 136 } 137 138 139 bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused) 140 { 141 return false; 142 } 143 144 bool AudioOutputDescriptor::setVolume(float volume, 145 audio_stream_type_t stream, 146 audio_devices_t device __unused, 147 uint32_t delayMs, 148 bool force) 149 { 150 // We actually change the volume if: 151 // - the float value returned by computeVolume() changed 152 // - the force flag is set 153 if (volume != mCurVolume[stream] || force) { 154 ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs); 155 mCurVolume[stream] = volume; 156 return true; 157 } 158 return false; 159 } 160 161 void AudioOutputDescriptor::toAudioPortConfig( 162 struct audio_port_config *dstConfig, 163 const struct audio_port_config *srcConfig) const 164 { 165 dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| 166 AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; 167 if (srcConfig != NULL) { 168 dstConfig->config_mask |= srcConfig->config_mask; 169 } 170 AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); 171 172 dstConfig->id = mId; 173 dstConfig->role = AUDIO_PORT_ROLE_SOURCE; 174 dstConfig->type = AUDIO_PORT_TYPE_MIX; 175 dstConfig->ext.mix.hw_module = getModuleHandle(); 176 dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; 177 } 178 179 void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const 180 { 181 // Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig. 182 mPort->toAudioPort(port); 183 port->id = mId; 184 port->ext.mix.hw_module = getModuleHandle(); 185 } 186 187 status_t AudioOutputDescriptor::dump(int fd) 188 { 189 const size_t SIZE = 256; 190 char buffer[SIZE]; 191 String8 result; 192 193 snprintf(buffer, SIZE, " ID: %d\n", mId); 194 result.append(buffer); 195 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); 196 result.append(buffer); 197 snprintf(buffer, SIZE, " Format: %08x\n", mFormat); 198 result.append(buffer); 199 snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); 200 result.append(buffer); 201 snprintf(buffer, SIZE, " Devices %08x\n", device()); 202 result.append(buffer); 203 snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); 204 result.append(buffer); 205 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 206 snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", 207 i, mCurVolume[i], mRefCount[i], mMuteCount[i]); 208 result.append(buffer); 209 } 210 write(fd, result.string(), result.size()); 211 212 return NO_ERROR; 213 } 214 215 void AudioOutputDescriptor::log(const char* indent) 216 { 217 ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X]", 218 indent, mId, mId, mSamplingRate, mFormat, mChannelMask); 219 } 220 221 // SwAudioOutputDescriptor implementation 222 SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile, 223 AudioPolicyClientInterface *clientInterface) 224 : AudioOutputDescriptor(profile, clientInterface), 225 mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0), 226 mFlags((audio_output_flags_t)0), mPolicyMix(NULL), 227 mOutput1(0), mOutput2(0), mDirectOpenCount(0), 228 mDirectClientSession(AUDIO_SESSION_NONE), mGlobalRefCount(0) 229 { 230 if (profile != NULL) { 231 mFlags = (audio_output_flags_t)profile->getFlags(); 232 } 233 } 234 235 status_t SwAudioOutputDescriptor::dump(int fd) 236 { 237 const size_t SIZE = 256; 238 char buffer[SIZE]; 239 String8 result; 240 241 snprintf(buffer, SIZE, " Latency: %d\n", mLatency); 242 result.append(buffer); 243 snprintf(buffer, SIZE, " Flags %08x\n", mFlags); 244 result.append(buffer); 245 write(fd, result.string(), result.size()); 246 247 AudioOutputDescriptor::dump(fd); 248 249 return NO_ERROR; 250 } 251 252 audio_devices_t SwAudioOutputDescriptor::device() const 253 { 254 if (isDuplicated()) { 255 return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); 256 } else { 257 return mDevice; 258 } 259 } 260 261 bool SwAudioOutputDescriptor::sharesHwModuleWith( 262 const sp<AudioOutputDescriptor>& outputDesc) 263 { 264 if (isDuplicated()) { 265 return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); 266 } else if (outputDesc->isDuplicated()){ 267 return sharesHwModuleWith(outputDesc->subOutput1()) || 268 sharesHwModuleWith(outputDesc->subOutput2()); 269 } else { 270 return AudioOutputDescriptor::sharesHwModuleWith(outputDesc); 271 } 272 } 273 274 audio_devices_t SwAudioOutputDescriptor::supportedDevices() 275 { 276 if (isDuplicated()) { 277 return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); 278 } else { 279 return mProfile->getSupportedDevicesType(); 280 } 281 } 282 283 uint32_t SwAudioOutputDescriptor::latency() 284 { 285 if (isDuplicated()) { 286 return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; 287 } else { 288 return mLatency; 289 } 290 } 291 292 void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, 293 int delta) 294 { 295 // forward usage count change to attached outputs 296 if (isDuplicated()) { 297 mOutput1->changeRefCount(stream, delta); 298 mOutput2->changeRefCount(stream, delta); 299 } 300 AudioOutputDescriptor::changeRefCount(stream, delta); 301 302 // handle stream-independent ref count 303 uint32_t oldGlobalRefCount = mGlobalRefCount; 304 if ((delta + (int)mGlobalRefCount) < 0) { 305 ALOGW("changeRefCount() invalid delta %d globalRefCount %d", delta, mGlobalRefCount); 306 mGlobalRefCount = 0; 307 } else { 308 mGlobalRefCount += delta; 309 } 310 if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) { 311 if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) 312 { 313 mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress, 314 MIX_STATE_MIXING); 315 } 316 317 } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) { 318 if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) 319 { 320 mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress, 321 MIX_STATE_IDLE); 322 } 323 } 324 } 325 326 327 bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device) 328 { 329 // unit gain if rerouting to external policy 330 if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) { 331 if (mPolicyMix != NULL) { 332 ALOGV("max gain when rerouting for output=%d", mIoHandle); 333 return true; 334 } 335 } 336 if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) { 337 ALOGV("max gain when output device is telephony tx"); 338 return true; 339 } 340 return false; 341 } 342 343 void SwAudioOutputDescriptor::toAudioPortConfig( 344 struct audio_port_config *dstConfig, 345 const struct audio_port_config *srcConfig) const 346 { 347 348 ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); 349 AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig); 350 351 dstConfig->ext.mix.handle = mIoHandle; 352 } 353 354 void SwAudioOutputDescriptor::toAudioPort( 355 struct audio_port *port) const 356 { 357 ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); 358 359 AudioOutputDescriptor::toAudioPort(port); 360 361 toAudioPortConfig(&port->active_config); 362 port->ext.mix.handle = mIoHandle; 363 port->ext.mix.latency_class = 364 mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; 365 } 366 367 bool SwAudioOutputDescriptor::setVolume(float volume, 368 audio_stream_type_t stream, 369 audio_devices_t device, 370 uint32_t delayMs, 371 bool force) 372 { 373 bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force); 374 375 if (changed) { 376 // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is 377 // enabled 378 float volume = Volume::DbToAmpl(mCurVolume[stream]); 379 if (stream == AUDIO_STREAM_BLUETOOTH_SCO) { 380 mClientInterface->setStreamVolume( 381 AUDIO_STREAM_VOICE_CALL, volume, mIoHandle, delayMs); 382 } 383 mClientInterface->setStreamVolume(stream, volume, mIoHandle, delayMs); 384 } 385 return changed; 386 } 387 388 status_t SwAudioOutputDescriptor::open(const audio_config_t *config, 389 audio_devices_t device, 390 const String8& address, 391 audio_stream_type_t stream, 392 audio_output_flags_t flags, 393 audio_io_handle_t *output) 394 { 395 audio_config_t lConfig; 396 if (config == nullptr) { 397 lConfig = AUDIO_CONFIG_INITIALIZER; 398 lConfig.sample_rate = mSamplingRate; 399 lConfig.channel_mask = mChannelMask; 400 lConfig.format = mFormat; 401 } else { 402 lConfig = *config; 403 } 404 405 mDevice = device; 406 // if the selected profile is offloaded and no offload info was specified, 407 // create a default one 408 if ((mProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && 409 lConfig.offload_info.format == AUDIO_FORMAT_DEFAULT) { 410 flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); 411 lConfig.offload_info = AUDIO_INFO_INITIALIZER; 412 lConfig.offload_info.sample_rate = lConfig.sample_rate; 413 lConfig.offload_info.channel_mask = lConfig.channel_mask; 414 lConfig.offload_info.format = lConfig.format; 415 lConfig.offload_info.stream_type = stream; 416 lConfig.offload_info.duration_us = -1; 417 lConfig.offload_info.has_video = true; // conservative 418 lConfig.offload_info.is_streaming = true; // likely 419 } 420 421 mFlags = (audio_output_flags_t)(mFlags | flags); 422 423 ALOGV("opening output for device %08x address %s profile %p name %s", 424 mDevice, address.string(), mProfile.get(), mProfile->getName().string()); 425 426 status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(), 427 output, 428 &lConfig, 429 &mDevice, 430 address, 431 &mLatency, 432 mFlags); 433 LOG_ALWAYS_FATAL_IF(mDevice != device, 434 "%s openOutput returned device %08x when given device %08x", 435 __FUNCTION__, mDevice, device); 436 437 if (status == NO_ERROR) { 438 LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE, 439 "%s openOutput returned output handle %d for device %08x", 440 __FUNCTION__, *output, device); 441 mSamplingRate = lConfig.sample_rate; 442 mChannelMask = lConfig.channel_mask; 443 mFormat = lConfig.format; 444 mId = AudioPort::getNextUniqueId(); 445 mIoHandle = *output; 446 mProfile->curOpenCount++; 447 } 448 449 return status; 450 } 451 452 status_t SwAudioOutputDescriptor::start() 453 { 454 if (isDuplicated()) { 455 status_t status = mOutput1->start(); 456 if (status != NO_ERROR) { 457 return status; 458 } 459 status = mOutput2->start(); 460 if (status != NO_ERROR) { 461 mOutput1->stop(); 462 return status; 463 } 464 return NO_ERROR; 465 } 466 if (!isActive()) { 467 if (!mProfile->canStartNewIo()) { 468 return INVALID_OPERATION; 469 } 470 mProfile->curActiveCount++; 471 } 472 return NO_ERROR; 473 } 474 475 void SwAudioOutputDescriptor::stop() 476 { 477 if (isDuplicated()) { 478 mOutput1->stop(); 479 mOutput2->stop(); 480 return; 481 } 482 483 if (!isActive()) { 484 LOG_ALWAYS_FATAL_IF(mProfile->curActiveCount < 1, 485 "%s invalid profile active count %u", 486 __func__, mProfile->curActiveCount); 487 mProfile->curActiveCount--; 488 } 489 } 490 491 void SwAudioOutputDescriptor::close() 492 { 493 if (mIoHandle != AUDIO_IO_HANDLE_NONE) { 494 AudioParameter param; 495 param.add(String8("closing"), String8("true")); 496 mClientInterface->setParameters(mIoHandle, param.toString()); 497 498 mClientInterface->closeOutput(mIoHandle); 499 500 LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u", 501 __FUNCTION__, mProfile->curOpenCount); 502 // do not call stop() here as stop() is supposed to be called after changeRefCount(-1) 503 // and we don't know how many streams are still active at this time 504 if (isActive()) { 505 mProfile->curActiveCount--; 506 } 507 mProfile->curOpenCount--; 508 mIoHandle = AUDIO_IO_HANDLE_NONE; 509 } 510 } 511 512 status_t SwAudioOutputDescriptor::openDuplicating(const sp<SwAudioOutputDescriptor>& output1, 513 const sp<SwAudioOutputDescriptor>& output2, 514 audio_io_handle_t *ioHandle) 515 { 516 // open a duplicating output thread for the new output and the primary output 517 // Note: openDuplicateOutput() API expects the output handles in the reverse order from the 518 // numbering in SwAudioOutputDescriptor mOutput1 and mOutput2 519 *ioHandle = mClientInterface->openDuplicateOutput(output2->mIoHandle, output1->mIoHandle); 520 if (*ioHandle == AUDIO_IO_HANDLE_NONE) { 521 return INVALID_OPERATION; 522 } 523 524 mId = AudioPort::getNextUniqueId(); 525 mIoHandle = *ioHandle; 526 mOutput1 = output1; 527 mOutput2 = output2; 528 mSamplingRate = output2->mSamplingRate; 529 mFormat = output2->mFormat; 530 mChannelMask = output2->mChannelMask; 531 mLatency = output2->mLatency; 532 533 return NO_ERROR; 534 } 535 536 // HwAudioOutputDescriptor implementation 537 HwAudioOutputDescriptor::HwAudioOutputDescriptor(const sp<AudioSourceDescriptor>& source, 538 AudioPolicyClientInterface *clientInterface) 539 : AudioOutputDescriptor(source->mDevice, clientInterface), 540 mSource(source) 541 { 542 } 543 544 status_t HwAudioOutputDescriptor::dump(int fd) 545 { 546 const size_t SIZE = 256; 547 char buffer[SIZE]; 548 String8 result; 549 550 AudioOutputDescriptor::dump(fd); 551 552 snprintf(buffer, SIZE, "Source:\n"); 553 result.append(buffer); 554 write(fd, result.string(), result.size()); 555 mSource->dump(fd); 556 557 return NO_ERROR; 558 } 559 560 audio_devices_t HwAudioOutputDescriptor::supportedDevices() 561 { 562 return mDevice; 563 } 564 565 void HwAudioOutputDescriptor::toAudioPortConfig( 566 struct audio_port_config *dstConfig, 567 const struct audio_port_config *srcConfig) const 568 { 569 mSource->mDevice->toAudioPortConfig(dstConfig, srcConfig); 570 } 571 572 void HwAudioOutputDescriptor::toAudioPort( 573 struct audio_port *port) const 574 { 575 mSource->mDevice->toAudioPort(port); 576 } 577 578 579 bool HwAudioOutputDescriptor::setVolume(float volume, 580 audio_stream_type_t stream, 581 audio_devices_t device, 582 uint32_t delayMs, 583 bool force) 584 { 585 bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force); 586 587 if (changed) { 588 // TODO: use gain controller on source device if any to adjust volume 589 } 590 return changed; 591 } 592 593 // SwAudioOutputCollection implementation 594 bool SwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const 595 { 596 nsecs_t sysTime = systemTime(); 597 for (size_t i = 0; i < this->size(); i++) { 598 const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i); 599 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 600 return true; 601 } 602 } 603 return false; 604 } 605 606 bool SwAudioOutputCollection::isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs) const 607 { 608 nsecs_t sysTime = systemTime(); 609 for (size_t i = 0; i < this->size(); i++) { 610 const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i); 611 if (outputDesc->isStreamActive(stream, inPastMs, sysTime) 612 && ((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) { 613 return true; 614 } 615 } 616 return false; 617 } 618 619 bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, 620 uint32_t inPastMs) const 621 { 622 nsecs_t sysTime = systemTime(); 623 for (size_t i = 0; i < size(); i++) { 624 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 625 if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && 626 outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 627 // do not consider re routing (when the output is going to a dynamic policy) 628 // as "remote playback" 629 if (outputDesc->mPolicyMix == NULL) { 630 return true; 631 } 632 } 633 } 634 return false; 635 } 636 637 audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const 638 { 639 for (size_t i = 0; i < size(); i++) { 640 sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 641 if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { 642 return this->keyAt(i); 643 } 644 } 645 return 0; 646 } 647 648 bool SwAudioOutputCollection::isA2dpOffloadedOnPrimary() const 649 { 650 sp<SwAudioOutputDescriptor> primaryOutput = getPrimaryOutput(); 651 652 if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL) 653 && (primaryOutput->mProfile->mModule != NULL)) { 654 sp<HwModule> primaryHwModule = primaryOutput->mProfile->mModule; 655 Vector <sp<IOProfile>> primaryHwModuleOutputProfiles = 656 primaryHwModule->getOutputProfiles(); 657 for (size_t i = 0; i < primaryHwModuleOutputProfiles.size(); i++) { 658 if (primaryHwModuleOutputProfiles[i]->supportDevice(AUDIO_DEVICE_OUT_ALL_A2DP)) { 659 return true; 660 } 661 } 662 } 663 return false; 664 } 665 666 bool SwAudioOutputCollection::isA2dpSupported() const 667 { 668 return (isA2dpOffloadedOnPrimary() || (getA2dpOutput() != 0)); 669 } 670 671 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const 672 { 673 for (size_t i = 0; i < size(); i++) { 674 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 675 if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { 676 return outputDesc; 677 } 678 } 679 return NULL; 680 } 681 682 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const 683 { 684 sp<SwAudioOutputDescriptor> outputDesc = NULL; 685 for (size_t i = 0; i < size(); i++) { 686 outputDesc = valueAt(i); 687 if (outputDesc->getId() == id) { 688 break; 689 } 690 } 691 return outputDesc; 692 } 693 694 bool SwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const 695 { 696 for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { 697 if (s == (size_t) streamToIgnore) { 698 continue; 699 } 700 for (size_t i = 0; i < size(); i++) { 701 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 702 if (outputDesc->mRefCount[s] != 0) { 703 return true; 704 } 705 } 706 } 707 return false; 708 } 709 710 audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const 711 { 712 sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle); 713 audio_devices_t devices = outputDesc->mProfile->getSupportedDevicesType(); 714 return devices; 715 } 716 717 718 status_t SwAudioOutputCollection::dump(int fd) const 719 { 720 const size_t SIZE = 256; 721 char buffer[SIZE]; 722 723 snprintf(buffer, SIZE, "\nOutputs dump:\n"); 724 write(fd, buffer, strlen(buffer)); 725 for (size_t i = 0; i < size(); i++) { 726 snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i)); 727 write(fd, buffer, strlen(buffer)); 728 valueAt(i)->dump(fd); 729 } 730 731 return NO_ERROR; 732 } 733 734 // HwAudioOutputCollection implementation 735 bool HwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const 736 { 737 nsecs_t sysTime = systemTime(); 738 for (size_t i = 0; i < this->size(); i++) { 739 const sp<HwAudioOutputDescriptor> outputDesc = this->valueAt(i); 740 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 741 return true; 742 } 743 } 744 return false; 745 } 746 747 bool HwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const 748 { 749 for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { 750 if (s == (size_t) streamToIgnore) { 751 continue; 752 } 753 for (size_t i = 0; i < size(); i++) { 754 const sp<HwAudioOutputDescriptor> outputDesc = valueAt(i); 755 if (outputDesc->mRefCount[s] != 0) { 756 return true; 757 } 758 } 759 } 760 return false; 761 } 762 763 status_t HwAudioOutputCollection::dump(int fd) const 764 { 765 const size_t SIZE = 256; 766 char buffer[SIZE]; 767 768 snprintf(buffer, SIZE, "\nOutputs dump:\n"); 769 write(fd, buffer, strlen(buffer)); 770 for (size_t i = 0; i < size(); i++) { 771 snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i)); 772 write(fd, buffer, strlen(buffer)); 773 valueAt(i)->dump(fd); 774 } 775 776 return NO_ERROR; 777 } 778 779 }; //namespace android 780