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 if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) { 119 pp_out = &mMainOutput; 120 out = new AudioStreamOut(*this, false); 121 } else { 122 pp_out = &mMCOutput; 123 out = new AudioStreamOut(*this, true); 124 } 125 126 if (out == NULL) { 127 *status = NO_MEMORY; 128 return NULL; 129 } 130 131 *status = out->set(format, channels, sampleRate); 132 133 if (*status == NO_ERROR) { 134 *pp_out = out; 135 updateTgtDevices_l(); 136 } else { 137 delete out; 138 } 139 140 return *pp_out; 141 } 142 143 void AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) { 144 if (out == NULL) 145 return; 146 147 // Putting the stream into "standby" should cause it to release all of its 148 // physical outputs. 149 out->standby(); 150 151 { 152 Mutex::Autolock _l(mStreamLock); 153 if (mMainOutput && out == mMainOutput) { 154 delete mMainOutput; 155 mMainOutput = NULL; 156 } else if (mMCOutput && out == mMCOutput) { 157 delete mMCOutput; 158 mMCOutput = NULL; 159 } 160 161 updateTgtDevices_l(); 162 } 163 } 164 165 status_t AudioHardwareOutput::setMasterVolume(float volume) 166 { 167 Mutex::Autolock _l1(mOutputLock); 168 Mutex::Autolock _l2(mSettingsLock); 169 170 mSettings.masterVolume = volume; 171 172 AudioOutputList::iterator I; 173 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 174 (*I)->setVolume(mSettings.masterVolume); 175 176 return NO_ERROR; 177 } 178 179 status_t AudioHardwareOutput::getMasterVolume(float* volume) { 180 181 if (NULL == volume) 182 return BAD_VALUE; 183 184 // Explicit scope for auto-lock pattern. 185 { 186 Mutex::Autolock _l(mSettingsLock); 187 *volume = mSettings.masterVolume; 188 } 189 190 return NO_ERROR; 191 } 192 193 status_t AudioHardwareOutput::setMasterMute(bool muted) 194 { 195 Mutex::Autolock _l1(mOutputLock); 196 Mutex::Autolock _l2(mSettingsLock); 197 198 mSettings.masterMute = muted; 199 200 AudioOutputList::iterator I; 201 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 202 (*I)->setMute(mSettings.masterMute); 203 204 return NO_ERROR; 205 } 206 207 status_t AudioHardwareOutput::getMasterMute(bool* muted) { 208 if (NULL == muted) 209 return BAD_VALUE; 210 211 // Explicit scope for auto-lock pattern. 212 { 213 Mutex::Autolock _l(mSettingsLock); 214 *muted = mSettings.masterMute; 215 } 216 217 return NO_ERROR; 218 } 219 220 status_t AudioHardwareOutput::setParameters(const char* kvpairs) { 221 AudioParameter param = AudioParameter(String8(kvpairs)); 222 status_t status = NO_ERROR; 223 float floatVal; 224 int intVal; 225 Settings initial, s; 226 227 { 228 // Record the initial state of the settings from inside the lock. Then 229 // leave the lock in order to parse the changes to be made. 230 Mutex::Autolock _l(mSettingsLock); 231 initial = s = mSettings; 232 } 233 234 /*************************************************************** 235 * HDMI Audio Options * 236 ***************************************************************/ 237 if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) { 238 s.hdmi.allowed = (intVal != 0); 239 param.remove(kHDMIAllowedParamKey); 240 } 241 242 if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) && 243 (floatVal >= 0.0) && 244 (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) { 245 uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0); 246 s.hdmi.delayCompUsec = delay_comp; 247 param.remove(kHDMIDelayCompParamKey); 248 } 249 250 if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) { 251 s.hdmi.isFixed = (intVal != 0); 252 param.remove(kFixedHDMIOutputParamKey); 253 } 254 255 if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR) 256 && (floatVal <= 0.0)) { 257 s.hdmi.fixedLvl = floatVal; 258 param.remove(kFixedHDMIOutputLevelParamKey); 259 } 260 261 /*************************************************************** 262 * Other Options * 263 ***************************************************************/ 264 if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) && 265 (floatVal >= 0.0) && 266 (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) { 267 s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0); 268 param.remove(kVideoDelayCompParamKey); 269 } 270 271 if (param.size()) 272 status = BAD_VALUE; 273 274 // If there was a change made to settings, go ahead and apply it now. 275 bool allowedOutputsChanged = false; 276 if (memcmp(&initial, &s, sizeof(initial))) { 277 Mutex::Autolock _l1(mOutputLock); 278 Mutex::Autolock _l2(mSettingsLock); 279 280 if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi))) 281 allowedOutputsChanged = allowedOutputsChanged || 282 applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi, 283 HDMIAudioOutput::classDevMask()); 284 285 if (initial.videoDelayCompUsec != s.videoDelayCompUsec) 286 mSettings.videoDelayCompUsec = s.videoDelayCompUsec; 287 288 uint32_t tmp = 0; 289 if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec)) 290 tmp = mSettings.hdmi.delayCompUsec; 291 if (mMaxDelayCompUsec != tmp) 292 mMaxDelayCompUsec = tmp; 293 } 294 295 if (allowedOutputsChanged) { 296 Mutex::Autolock _l(mStreamLock); 297 updateTgtDevices_l(); 298 } 299 300 return status; 301 } 302 303 bool AudioHardwareOutput::applyOutputSettings_l( 304 const AudioHardwareOutput::OutputSettings& initial, 305 const AudioHardwareOutput::OutputSettings& current, 306 AudioHardwareOutput::OutputSettings& updateMe, 307 uint32_t outDevMask) { 308 // ASSERT(holding mOutputLock and mSettingsLock) 309 sp<AudioOutput> out; 310 311 // Check for a change in the allowed/not-allowed state. Update if needed 312 // and return true if there was a change made. 313 bool ret = false; 314 if (initial.allowed != current.allowed) { 315 updateMe.allowed = current.allowed; 316 ret = true; 317 } 318 319 // Look for an instance of the output to be updated in case other changes 320 // were made. 321 AudioOutputList::iterator I; 322 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 323 if (outDevMask == (*I)->devMask()) { 324 out = (*I); 325 break; 326 } 327 } 328 329 // Update the other settings, if needed. 330 if (initial.delayCompUsec != current.delayCompUsec) { 331 updateMe.delayCompUsec = current.delayCompUsec; 332 if (out != NULL) 333 out->setExternalDelay_uSec(current.delayCompUsec); 334 } 335 336 if (initial.isFixed != current.isFixed) { 337 updateMe.isFixed = current.isFixed; 338 if (out != NULL) 339 out->setOutputIsFixed(current.isFixed); 340 } 341 342 if (initial.fixedLvl != current.fixedLvl) { 343 updateMe.fixedLvl = current.fixedLvl; 344 if (out != NULL) 345 out->setFixedOutputLevel(current.fixedLvl); 346 } 347 348 return ret; 349 } 350 351 352 char* AudioHardwareOutput::getParameters(const char* keys) { 353 Settings s; 354 355 // Explicit scope for auto-lock pattern. 356 { 357 // Snapshot the current settings so we don't have to hold the settings 358 // lock while formatting the results. 359 Mutex::Autolock _l(mSettingsLock); 360 s = mSettings; 361 } 362 363 AudioParameter param = AudioParameter(String8(keys)); 364 String8 tmp; 365 366 /*************************************************************** 367 * HDMI Audio Options * 368 ***************************************************************/ 369 if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR) 370 param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0); 371 372 if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR) 373 param.addFloat(kHDMIDelayCompParamKey, 374 static_cast<float>(s.hdmi.delayCompUsec) / 1000.0); 375 376 if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR) 377 param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0); 378 379 if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR) 380 param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl); 381 382 /*************************************************************** 383 * Other Options * 384 ***************************************************************/ 385 if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR) 386 param.addFloat(kVideoDelayCompParamKey, 387 static_cast<float>(s.videoDelayCompUsec) / 1000.0); 388 389 return strdup(param.toString().string()); 390 } 391 392 void AudioHardwareOutput::updateRouting(uint32_t devMask) { 393 Mutex::Autolock _l(mStreamLock); 394 395 bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask()); 396 ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected); 397 if (mHDMIConnected != hasHDMI) { 398 mHDMIConnected = hasHDMI; 399 400 if (mHDMIConnected) 401 mHDMIAudioCaps.loadCaps(mHDMICardID); 402 else 403 mHDMIAudioCaps.reset(); 404 405 updateTgtDevices_l(); 406 } 407 } 408 409 status_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream, 410 uint32_t devMask, 411 sp<AudioOutput>* newOutput) { 412 Mutex::Autolock _l1(mOutputLock); 413 414 // Sanity check the device mask passed to us. There should exactly one bit 415 // set, no less, no more. 416 if (popcount(devMask) != 1) { 417 ALOGW("bad device mask in obtainOutput, %08x", devMask); 418 return INVALID_OPERATION; 419 } 420 421 // Start by checking to see if the requested output is currently busy. 422 AudioOutputList::iterator I; 423 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 424 if (devMask & (*I)->devMask()) 425 return OK; // Yup; its busy. 426 427 // Looks like we don't currently have an output of the requested type. 428 // Figure out which type is being requested and try to construct one. 429 OutputSettings* S = NULL; 430 if (devMask & HDMIAudioOutput::classDevMask()) { 431 *newOutput = new HDMIAudioOutput(); 432 S = &mSettings.hdmi; 433 } 434 else { 435 ALOGW("%s stream out requested output of unknown type %08x", 436 tgtStream.getName(), devMask); 437 return BAD_VALUE; 438 } 439 440 if (*newOutput == NULL) 441 return NO_MEMORY; 442 443 status_t res = (*newOutput)->setupForStream(tgtStream); 444 if (res != OK) { 445 ALOGE("%s setupForStream() returned %d", 446 tgtStream.getName(), res); 447 *newOutput = NULL; 448 } else { 449 ALOGI("%s stream out adding %s output.", 450 tgtStream.getName(), (*newOutput)->getOutputName()); 451 mPhysOutputs.push_back(*newOutput); 452 453 { // Apply current settings 454 Mutex::Autolock _l2(mSettingsLock); 455 (*newOutput)->setVolume(mSettings.masterVolume); 456 (*newOutput)->setMute(mSettings.masterMute); 457 (*newOutput)->setExternalDelay_uSec(S->delayCompUsec); 458 (*newOutput)->setOutputIsFixed(S->isFixed); 459 (*newOutput)->setFixedOutputLevel(S->fixedLvl); 460 } 461 } 462 463 return res; 464 } 465 466 void AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream, 467 const sp<AudioOutput>& releaseMe) { 468 Mutex::Autolock _l(mOutputLock); 469 470 ALOGI("%s stream out removing %s output.", 471 tgtStream.getName(), releaseMe->getOutputName()); 472 473 // Immediately release any resources associated with this output (In 474 // particular, make sure to close any ALSA device driver handles ASAP) 475 releaseMe->cleanupResources(); 476 477 // Now, clear our internal bookkeeping. 478 AudioOutputList::iterator I; 479 for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 480 if (releaseMe.get() == (*I).get()) { 481 mPhysOutputs.erase(I); 482 break; 483 } 484 } 485 } 486 487 void AudioHardwareOutput::updateTgtDevices_l() { 488 // ASSERT(holding mStreamLock) 489 uint32_t mcMask = 0; 490 uint32_t mainMask = 0; 491 492 { 493 Mutex::Autolock _l(mSettingsLock); 494 if (mSettings.hdmi.allowed && mHDMIConnected) { 495 if (NULL != mMCOutput) 496 mcMask |= HDMIAudioOutput::classDevMask(); 497 else 498 mainMask |= HDMIAudioOutput::classDevMask(); 499 } 500 } 501 502 if (NULL != mMainOutput) 503 mMainOutput->setTgtDevices(mainMask); 504 505 if (NULL != mMCOutput) 506 mMCOutput->setTgtDevices(mcMask); 507 } 508 509 void AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) { 510 511 Mutex::Autolock _l1(mStreamLock); 512 Mutex::Autolock _l2(mSettingsLock); 513 514 // If there is no HDMI, do nothing 515 if (mSettings.hdmi.allowed && mHDMIConnected) { 516 // If a multi-channel stream goes to standy state, we must switch 517 // to stereo stream. If MC comes out of standby, we must switch 518 // back to MC. No special processing needed for main stream. 519 // AudioStreamOut class handles that correctly 520 if (isMCStream) { 521 uint32_t mcMask; 522 uint32_t mainMask; 523 if (isInStandby) { 524 mainMask = HDMIAudioOutput::classDevMask(); 525 mcMask = 0; 526 } else { 527 mainMask = 0; 528 mcMask = HDMIAudioOutput::classDevMask(); 529 } 530 531 if (NULL != mMainOutput) 532 mMainOutput->setTgtDevices(mainMask); 533 534 if (NULL != mMCOutput) 535 mMCOutput->setTgtDevices(mcMask); 536 } 537 } 538 } 539 540 #define DUMP(a...) \ 541 snprintf(buffer, SIZE, a); \ 542 buffer[SIZE - 1] = 0; \ 543 result.append(buffer); 544 #define B2STR(b) b ? "true" : "false" 545 546 status_t AudioHardwareOutput::dump(int fd) 547 { 548 const size_t SIZE = 256; 549 char buffer[SIZE]; 550 String8 result; 551 Settings s; 552 553 // Explicit scope for auto-lock pattern. 554 { 555 // Snapshot the current settings so we don't have to hold the settings 556 // lock while formatting the results. 557 Mutex::Autolock _l(mSettingsLock); 558 s = mSettings; 559 } 560 561 DUMP("AudioHardwareOutput::dump\n"); 562 DUMP("\tMaster Volume : %0.3f\n", s.masterVolume); 563 DUMP("\tMaster Mute : %s\n", B2STR(s.masterMute)); 564 DUMP("\tHDMI Output Allowed : %s\n", B2STR(s.hdmi.allowed)); 565 DUMP("\tHDMI Delay Comp : %u uSec\n", s.hdmi.delayCompUsec); 566 DUMP("\tHDMI Output Fixed : %s\n", B2STR(s.hdmi.isFixed)); 567 DUMP("\tHDMI Fixed Level : %.1f dB\n", s.hdmi.fixedLvl); 568 DUMP("\tVideo Delay Comp : %u uSec\n", s.videoDelayCompUsec); 569 570 ::write(fd, result.string(), result.size()); 571 572 // Explicit scope for auto-lock pattern. 573 { 574 Mutex::Autolock _l(mOutputLock); 575 if (mMainOutput) 576 mMainOutput->dump(fd); 577 578 if (mMCOutput) 579 mMCOutput->dump(fd); 580 } 581 582 return NO_ERROR; 583 } 584 585 #undef B2STR 586 #undef DUMP 587 588 }; // namespace android 589