1 /* 2 ** 3 ** Copyright 2014, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "AudioHAL_AudioHardwareOutput" 19 20 #include <utils/Log.h> 21 22 #include <stdint.h> 23 #include <limits.h> 24 #include <math.h> 25 26 #include <common_time/local_clock.h> 27 #include <cutils/properties.h> 28 29 #include "AudioHardwareOutput.h" 30 #include "AudioStreamOut.h" 31 #include "HDMIAudioOutput.h" 32 33 namespace android { 34 35 // Global singleton. 36 AudioHardwareOutput gAudioHardwareOutput; 37 38 // HDMI options. 39 const String8 AudioHardwareOutput::kHDMIAllowedParamKey( 40 "atv.hdmi_audio.allowed"); 41 const String8 AudioHardwareOutput::kHDMIDelayCompParamKey( 42 "atv.hdmi.audio_delay"); 43 const String8 AudioHardwareOutput::kFixedHDMIOutputParamKey( 44 "atv.hdmi.fixed_volume"); 45 const String8 AudioHardwareOutput::kFixedHDMIOutputLevelParamKey( 46 "atv.hdmi.fixed_level"); 47 48 // Video delay comp hack options (not exposed to user level) 49 const String8 AudioHardwareOutput::kVideoDelayCompParamKey( 50 "atv.video.delay_comp"); 51 52 // Defaults for settings. 53 void AudioHardwareOutput::OutputSettings::setDefaults() 54 { 55 allowed = true; 56 delayCompUsec = 0; 57 isFixed = false; 58 fixedLvl = 0.0f; 59 } 60 61 void AudioHardwareOutput::Settings::setDefaults() { 62 hdmi.setDefaults(); 63 64 masterVolume = 0.60; 65 masterMute = false; 66 67 // Default this to 16mSec or so. Since audio start times are not sync'ed to 68 // to the VBI, there should be a +/-0.5 output frame rate error in the AV 69 // sync, even under the best of circumstances. 70 // 71 // In practice, the android core seems to have a hard time hitting its frame 72 // cadence consistently. Sometimes the frames are on time, and sometimes 73 // they are even a little early, but more often than not, the frames are 74 // late by about a full output frame time. 75 // 76 // ATV pretty much always uses a 60fps output rate, and the only thing 77 // consuming the latency estimate provided by the HAL is the path handling 78 // AV sync. For now, we can fudge this number to move things back in the 79 // direction of correct by providing a setting for video delay compensation 80 // which will be subtracted from the latency estimate and defaulting it to 81 // a reasonable middle gound (12mSec in this case). 82 videoDelayCompUsec = 12000; 83 } 84 85 AudioHardwareOutput::AudioHardwareOutput() 86 : mMainOutput(NULL) 87 , mMCOutput(NULL) 88 , mHDMIConnected(false) 89 , mMaxDelayCompUsec(0) 90 { 91 mSettings.setDefaults(); 92 mHDMICardID = find_alsa_card_by_name(kHDMI_ALSADeviceName); 93 } 94 95 AudioHardwareOutput::~AudioHardwareOutput() 96 { 97 closeOutputStream(mMainOutput); 98 closeOutputStream(mMCOutput); 99 } 100 101 status_t AudioHardwareOutput::initCheck() { 102 return NO_ERROR; 103 } 104 105 AudioStreamOut* AudioHardwareOutput::openOutputStream( 106 uint32_t devices, 107 audio_format_t *format, 108 uint32_t *channels, 109 uint32_t *sampleRate, 110 audio_output_flags_t flags, 111 status_t *status) { 112 (void) devices; 113 AutoMutex lock(mStreamLock); 114 115 AudioStreamOut** pp_out; 116 AudioStreamOut* out; 117 118 bool isIec958NonAudio = (flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) != 0; 119 if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) { 120 pp_out = &mMainOutput; 121 out = new AudioStreamOut(*this, false, isIec958NonAudio); 122 } else { 123 pp_out = &mMCOutput; 124 out = new AudioStreamOut(*this, true, isIec958NonAudio); 125 } 126 127 if (out == NULL) { 128 *status = NO_MEMORY; 129 return NULL; 130 } 131 132 *status = out->set(format, channels, sampleRate); 133 134 if (*status == NO_ERROR) { 135 *pp_out = out; 136 updateTgtDevices_l(); 137 } else { 138 delete out; 139 } 140 141 return *pp_out; 142 } 143 144 void AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) { 145 if (out == NULL) 146 return; 147 148 // Putting the stream into "standby" should cause it to release all of its 149 // physical outputs. 150 out->standby(); 151 152 { 153 Mutex::Autolock _l(mStreamLock); 154 if (mMainOutput && out == mMainOutput) { 155 delete mMainOutput; 156 mMainOutput = NULL; 157 } else if (mMCOutput && out == mMCOutput) { 158 delete mMCOutput; 159 mMCOutput = NULL; 160 } 161 162 updateTgtDevices_l(); 163 } 164 } 165 166 status_t AudioHardwareOutput::setMasterVolume(float volume) 167 { 168 Mutex::Autolock _l1(mOutputLock); 169 Mutex::Autolock _l2(mSettingsLock); 170 171 mSettings.masterVolume = volume; 172 173 AudioOutputList::iterator I; 174 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 175 (*I)->setVolume(mSettings.masterVolume); 176 177 return NO_ERROR; 178 } 179 180 status_t AudioHardwareOutput::getMasterVolume(float* volume) { 181 182 if (NULL == volume) 183 return BAD_VALUE; 184 185 // Explicit scope for auto-lock pattern. 186 { 187 Mutex::Autolock _l(mSettingsLock); 188 *volume = mSettings.masterVolume; 189 } 190 191 return NO_ERROR; 192 } 193 194 status_t AudioHardwareOutput::setMasterMute(bool muted) 195 { 196 Mutex::Autolock _l1(mOutputLock); 197 Mutex::Autolock _l2(mSettingsLock); 198 199 mSettings.masterMute = muted; 200 201 AudioOutputList::iterator I; 202 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 203 (*I)->setMute(mSettings.masterMute); 204 205 return NO_ERROR; 206 } 207 208 status_t AudioHardwareOutput::getMasterMute(bool* muted) { 209 if (NULL == muted) 210 return BAD_VALUE; 211 212 // Explicit scope for auto-lock pattern. 213 { 214 Mutex::Autolock _l(mSettingsLock); 215 *muted = mSettings.masterMute; 216 } 217 218 return NO_ERROR; 219 } 220 221 status_t AudioHardwareOutput::setParameters(const char* kvpairs) { 222 AudioParameter param = AudioParameter(String8(kvpairs)); 223 status_t status = NO_ERROR; 224 float floatVal; 225 int intVal; 226 Settings initial, s; 227 228 { 229 // Record the initial state of the settings from inside the lock. Then 230 // leave the lock in order to parse the changes to be made. 231 Mutex::Autolock _l(mSettingsLock); 232 initial = s = mSettings; 233 } 234 235 /*************************************************************** 236 * HDMI Audio Options * 237 ***************************************************************/ 238 if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) { 239 s.hdmi.allowed = (intVal != 0); 240 param.remove(kHDMIAllowedParamKey); 241 } 242 243 if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) && 244 (floatVal >= 0.0) && 245 (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) { 246 uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0); 247 s.hdmi.delayCompUsec = delay_comp; 248 param.remove(kHDMIDelayCompParamKey); 249 } 250 251 if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) { 252 s.hdmi.isFixed = (intVal != 0); 253 param.remove(kFixedHDMIOutputParamKey); 254 } 255 256 if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR) 257 && (floatVal <= 0.0)) { 258 s.hdmi.fixedLvl = floatVal; 259 param.remove(kFixedHDMIOutputLevelParamKey); 260 } 261 262 /*************************************************************** 263 * Other Options * 264 ***************************************************************/ 265 if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) && 266 (floatVal >= 0.0) && 267 (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) { 268 s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0); 269 param.remove(kVideoDelayCompParamKey); 270 } 271 272 if (param.size()) 273 status = BAD_VALUE; 274 275 // If there was a change made to settings, go ahead and apply it now. 276 bool allowedOutputsChanged = false; 277 if (memcmp(&initial, &s, sizeof(initial))) { 278 Mutex::Autolock _l1(mOutputLock); 279 Mutex::Autolock _l2(mSettingsLock); 280 281 if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi))) 282 allowedOutputsChanged = allowedOutputsChanged || 283 applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi, 284 HDMIAudioOutput::classDevMask()); 285 286 if (initial.videoDelayCompUsec != s.videoDelayCompUsec) 287 mSettings.videoDelayCompUsec = s.videoDelayCompUsec; 288 289 uint32_t tmp = 0; 290 if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec)) 291 tmp = mSettings.hdmi.delayCompUsec; 292 if (mMaxDelayCompUsec != tmp) 293 mMaxDelayCompUsec = tmp; 294 } 295 296 if (allowedOutputsChanged) { 297 Mutex::Autolock _l(mStreamLock); 298 updateTgtDevices_l(); 299 } 300 301 return status; 302 } 303 304 bool AudioHardwareOutput::applyOutputSettings_l( 305 const AudioHardwareOutput::OutputSettings& initial, 306 const AudioHardwareOutput::OutputSettings& current, 307 AudioHardwareOutput::OutputSettings& updateMe, 308 uint32_t outDevMask) { 309 // ASSERT(holding mOutputLock and mSettingsLock) 310 sp<AudioOutput> out; 311 312 // Check for a change in the allowed/not-allowed state. Update if needed 313 // and return true if there was a change made. 314 bool ret = false; 315 if (initial.allowed != current.allowed) { 316 updateMe.allowed = current.allowed; 317 ret = true; 318 } 319 320 // Look for an instance of the output to be updated in case other changes 321 // were made. 322 AudioOutputList::iterator I; 323 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 324 if (outDevMask == (*I)->devMask()) { 325 out = (*I); 326 break; 327 } 328 } 329 330 // Update the other settings, if needed. 331 if (initial.delayCompUsec != current.delayCompUsec) { 332 updateMe.delayCompUsec = current.delayCompUsec; 333 if (out != NULL) 334 out->setExternalDelay_uSec(current.delayCompUsec); 335 } 336 337 if (initial.isFixed != current.isFixed) { 338 updateMe.isFixed = current.isFixed; 339 if (out != NULL) 340 out->setOutputIsFixed(current.isFixed); 341 } 342 343 if (initial.fixedLvl != current.fixedLvl) { 344 updateMe.fixedLvl = current.fixedLvl; 345 if (out != NULL) 346 out->setFixedOutputLevel(current.fixedLvl); 347 } 348 349 return ret; 350 } 351 352 353 char* AudioHardwareOutput::getParameters(const char* keys) { 354 Settings s; 355 356 // Explicit scope for auto-lock pattern. 357 { 358 // Snapshot the current settings so we don't have to hold the settings 359 // lock while formatting the results. 360 Mutex::Autolock _l(mSettingsLock); 361 s = mSettings; 362 } 363 364 AudioParameter param = AudioParameter(String8(keys)); 365 String8 tmp; 366 367 /*************************************************************** 368 * HDMI Audio Options * 369 ***************************************************************/ 370 if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR) 371 param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0); 372 373 if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR) 374 param.addFloat(kHDMIDelayCompParamKey, 375 static_cast<float>(s.hdmi.delayCompUsec) / 1000.0); 376 377 if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR) 378 param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0); 379 380 if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR) 381 param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl); 382 383 /*************************************************************** 384 * Other Options * 385 ***************************************************************/ 386 if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR) 387 param.addFloat(kVideoDelayCompParamKey, 388 static_cast<float>(s.videoDelayCompUsec) / 1000.0); 389 390 return strdup(param.toString().string()); 391 } 392 393 void AudioHardwareOutput::updateRouting(uint32_t devMask) { 394 Mutex::Autolock _l(mStreamLock); 395 396 bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask()); 397 ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected); 398 if (mHDMIConnected != hasHDMI) { 399 mHDMIConnected = hasHDMI; 400 401 if (mHDMIConnected) 402 mHDMIAudioCaps.loadCaps(mHDMICardID); 403 else 404 mHDMIAudioCaps.reset(); 405 406 updateTgtDevices_l(); 407 } 408 } 409 410 status_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream, 411 uint32_t devMask, 412 sp<AudioOutput>* newOutput) { 413 Mutex::Autolock _l1(mOutputLock); 414 415 // Sanity check the device mask passed to us. There should exactly one bit 416 // set, no less, no more. 417 if (popcount(devMask) != 1) { 418 ALOGW("bad device mask in obtainOutput, %08x", devMask); 419 return INVALID_OPERATION; 420 } 421 422 // Start by checking to see if the requested output is currently busy. 423 AudioOutputList::iterator I; 424 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 425 if (devMask & (*I)->devMask()) 426 return OK; // Yup; its busy. 427 428 // Looks like we don't currently have an output of the requested type. 429 // Figure out which type is being requested and try to construct one. 430 OutputSettings* S = NULL; 431 if (devMask & HDMIAudioOutput::classDevMask()) { 432 *newOutput = new HDMIAudioOutput(); 433 S = &mSettings.hdmi; 434 } 435 else { 436 ALOGW("%s stream out requested output of unknown type %08x", 437 tgtStream.getName(), devMask); 438 return BAD_VALUE; 439 } 440 441 if (*newOutput == NULL) 442 return NO_MEMORY; 443 444 status_t res = (*newOutput)->setupForStream(tgtStream); 445 if (res != OK) { 446 ALOGE("%s setupForStream() returned %d", 447 tgtStream.getName(), res); 448 *newOutput = NULL; 449 } else { 450 ALOGI("%s stream out adding %s output.", 451 tgtStream.getName(), (*newOutput)->getOutputName()); 452 mPhysOutputs.push_back(*newOutput); 453 454 { // Apply current settings 455 Mutex::Autolock _l2(mSettingsLock); 456 (*newOutput)->setVolume(mSettings.masterVolume); 457 (*newOutput)->setMute(mSettings.masterMute); 458 (*newOutput)->setExternalDelay_uSec(S->delayCompUsec); 459 (*newOutput)->setOutputIsFixed(S->isFixed); 460 (*newOutput)->setFixedOutputLevel(S->fixedLvl); 461 } 462 } 463 464 return res; 465 } 466 467 void AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream, 468 const sp<AudioOutput>& releaseMe) { 469 Mutex::Autolock _l(mOutputLock); 470 471 ALOGI("%s stream out removing %s output.", 472 tgtStream.getName(), releaseMe->getOutputName()); 473 474 // Immediately release any resources associated with this output (In 475 // particular, make sure to close any ALSA device driver handles ASAP) 476 releaseMe->cleanupResources(); 477 478 // Now, clear our internal bookkeeping. 479 AudioOutputList::iterator I; 480 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 481 if (releaseMe.get() == (*I).get()) { 482 mPhysOutputs.erase(I); 483 break; 484 } 485 } 486 } 487 488 void AudioHardwareOutput::updateTgtDevices_l() { 489 // ASSERT(holding mStreamLock) 490 uint32_t mcMask = 0; 491 uint32_t mainMask = 0; 492 493 { 494 Mutex::Autolock _l(mSettingsLock); 495 if (mSettings.hdmi.allowed && mHDMIConnected) { 496 if (NULL != mMCOutput) 497 mcMask |= HDMIAudioOutput::classDevMask(); 498 else 499 mainMask |= HDMIAudioOutput::classDevMask(); 500 } 501 } 502 503 if (NULL != mMainOutput) 504 mMainOutput->setTgtDevices(mainMask); 505 506 if (NULL != mMCOutput) 507 mMCOutput->setTgtDevices(mcMask); 508 } 509 510 void AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) { 511 512 Mutex::Autolock _l1(mStreamLock); 513 bool hdmiAllowed; 514 { 515 Mutex::Autolock _l2(mSettingsLock); 516 hdmiAllowed = mSettings.hdmi.allowed; 517 } 518 // If there is no HDMI, do nothing 519 if (hdmiAllowed && mHDMIConnected) { 520 // If a multi-channel stream goes to standy state, we must switch 521 // to stereo stream. If MC comes out of standby, we must switch 522 // back to MC. No special processing needed for main stream. 523 // AudioStreamOut class handles that correctly 524 if (isMCStream) { 525 uint32_t mcMask; 526 uint32_t mainMask; 527 if (isInStandby) { 528 mainMask = HDMIAudioOutput::classDevMask(); 529 mcMask = 0; 530 } else { 531 mainMask = 0; 532 mcMask = HDMIAudioOutput::classDevMask(); 533 } 534 535 if (NULL != mMainOutput) 536 mMainOutput->setTgtDevices(mainMask); 537 538 if (NULL != mMCOutput) 539 mMCOutput->setTgtDevices(mcMask); 540 } 541 } 542 } 543 544 #define DUMP(a...) \ 545 snprintf(buffer, SIZE, a); \ 546 buffer[SIZE - 1] = 0; \ 547 result.append(buffer); 548 #define B2STR(b) b ? "true" : "false" 549 550 status_t AudioHardwareOutput::dump(int fd) 551 { 552 const size_t SIZE = 256; 553 char buffer[SIZE]; 554 String8 result; 555 Settings s; 556 557 // Explicit scope for auto-lock pattern. 558 { 559 // Snapshot the current settings so we don't have to hold the settings 560 // lock while formatting the results. 561 Mutex::Autolock _l(mSettingsLock); 562 s = mSettings; 563 } 564 565 DUMP("AudioHardwareOutput::dump\n"); 566 DUMP("\tMaster Volume : %0.3f\n", s.masterVolume); 567 DUMP("\tMaster Mute : %s\n", B2STR(s.masterMute)); 568 DUMP("\tHDMI Output Allowed : %s\n", B2STR(s.hdmi.allowed)); 569 DUMP("\tHDMI Delay Comp : %u uSec\n", s.hdmi.delayCompUsec); 570 DUMP("\tHDMI Output Fixed : %s\n", B2STR(s.hdmi.isFixed)); 571 DUMP("\tHDMI Fixed Level : %.1f dB\n", s.hdmi.fixedLvl); 572 DUMP("\tVideo Delay Comp : %u uSec\n", s.videoDelayCompUsec); 573 574 ::write(fd, result.string(), result.size()); 575 576 // Explicit scope for auto-lock pattern. 577 { 578 Mutex::Autolock _l(mOutputLock); 579 if (mMainOutput) 580 mMainOutput->dump(fd); 581 582 if (mMCOutput) 583 mMCOutput->dump(fd); 584 } 585 586 return NO_ERROR; 587 } 588 589 #undef B2STR 590 #undef DUMP 591 592 }; // namespace android 593