diff options
author | Eric Laurent <elaurent@google.com> | 2012-04-13 18:48:06 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2012-04-20 13:51:53 -0700 |
commit | b2971bf2ae4e9da3155559aa134e3aa6c2b216a4 (patch) | |
tree | 89424b57fc117fad7d2a4f927822e1b8438b8a13 /audio | |
parent | 0977cf534ffb71c2abac622716510ae8ea25f3e9 (diff) | |
download | hardware_libhardware_legacy-b2971bf2ae4e9da3155559aa134e3aa6c2b216a4.zip hardware_libhardware_legacy-b2971bf2ae4e9da3155559aa134e3aa6c2b216a4.tar.gz hardware_libhardware_legacy-b2971bf2ae4e9da3155559aa134e3aa6c2b216a4.tar.bz2 |
audio policy: add support for deep audio buffers
Added definitions for parsing deep buffer flags in output profiles.
Make sure that sound start is delayed enough to allow
duck/mute effect to apply before starting a notification on an output
with lower latency.
Change-Id: I1578e245da19d1a0f9ec62a2ea6dddaf82ea282b
Diffstat (limited to 'audio')
-rw-r--r-- | audio/AudioPolicyManagerBase.cpp | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp index 89ce456..7efa4ba 100644 --- a/audio/AudioPolicyManagerBase.cpp +++ b/audio/AudioPolicyManagerBase.cpp @@ -621,23 +621,30 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, if (outputDesc->mRefCount[stream] == 1) { audio_devices_t prevDevice = outputDesc->device(); audio_devices_t newDevice = getNewDevice(output, false /*fromCache*/); - - // force a device change if any other output is active, is managed by the same and hw - // module and has a current device selection that differs from newly selected device. - // In this case, the audio HAL must receive the new device selection so that it can - // change the device currently selected by the other active output. + routing_strategy strategy = getStrategy(stream); + bool shouldWait = (strategy == STRATEGY_SONIFICATION) || + (strategy == STRATEGY_SONIFICATION_RESPECTFUL); + uint32_t waitMs = 0; bool force = false; for (size_t i = 0; i < mOutputs.size(); i++) { AudioOutputDescriptor *desc = mOutputs.valueAt(i); - if (output != mOutputs.keyAt(i) && - desc->refCount() != 0 && - outputDesc->sharesHwModuleWith(desc) && + if (desc != outputDesc) { + // force a device change if any other output is managed by the same hw + // module and has a current device selection that differs from selected device. + // In this case, the audio HAL must receive the new device selection so that it can + // change the device currently selected by the other active output. + if (outputDesc->sharesHwModuleWith(desc) && desc->device() != newDevice) { - force = true; - break; + force = true; + } + // wait for audio on other active outputs to be presented when starting + // a notification so that audio focus effect can propagate. + if (shouldWait && (desc->refCount() != 0) && (waitMs < desc->latency())) { + waitMs = desc->latency(); + } } } - setOutputDevice(output, newDevice, force); + uint32_t muteWaitMs = setOutputDevice(output, newDevice, force); // handle special case for sonification while in call if (isInCall()) { @@ -653,6 +660,9 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, // update the outputs if starting an output with a stream that can affect notification // routing handleNotificationRoutingForStream(stream); + if (waitMs > muteWaitMs) { + usleep((waitMs - muteWaitMs) * 2 * 1000); + } } return NO_ERROR; } @@ -2055,15 +2065,11 @@ void AudioPolicyManagerBase::updateDeviceForStrategy() } } -void AudioPolicyManagerBase::checkDeviceMuteStrategies(AudioOutputDescriptor *outputDesc, +uint32_t AudioPolicyManagerBase::checkDeviceMuteStrategies(AudioOutputDescriptor *outputDesc, uint32_t delayMs) { - // mute/unmute strategies using an incompatible device combination - // if muting, wait for the audio in pcm buffer to be drained before proceeding - // if unmuting, unmute only after the specified delay - if (outputDesc->isDuplicated()) { - return; + return 0; } uint32_t muteWaitMs = 0; @@ -2109,11 +2115,14 @@ void AudioPolicyManagerBase::checkDeviceMuteStrategies(AudioOutputDescriptor *ou muteWaitMs *= 2; // wait for the PCM output buffers to empty before proceeding with the rest of the command if (muteWaitMs > delayMs) { - usleep((muteWaitMs - delayMs)*1000); + muteWaitMs -= delayMs; + usleep(muteWaitMs * 1000); + return muteWaitMs; } + return 0; } -void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, +uint32_t AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, audio_devices_t device, bool force, int delayMs) @@ -2121,11 +2130,12 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs); AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); AudioParameter param; + uint32_t muteWaitMs = 0; if (outputDesc->isDuplicated()) { - setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs); - setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs); - return; + muteWaitMs = setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs); + muteWaitMs += setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs); + return muteWaitMs; } // filter devices according to output selected device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices); @@ -2137,7 +2147,7 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, if (device != 0) { outputDesc->mDevice = device; } - checkDeviceMuteStrategies(outputDesc, delayMs); + muteWaitMs = checkDeviceMuteStrategies(outputDesc, delayMs); // Do not change the routing if: // - the requested device is 0 @@ -2145,7 +2155,7 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, // Doing this check here allows the caller to call setOutputDevice() without conditions if ((device == 0 || device == prevDevice) && !force) { ALOGV("setOutputDevice() setting same device %04x or null device for output %d", device, output); - return; + return muteWaitMs; } ALOGV("setOutputDevice() changing device"); @@ -2155,6 +2165,8 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, // update stream volumes according to new device applyStreamVolumes(output, device, delayMs); + + return muteWaitMs; } AudioPolicyManagerBase::IOProfile *AudioPolicyManagerBase::getInputProfile(audio_devices_t device, @@ -3047,6 +3059,8 @@ const struct StringToEnum sDeviceNameToEnumTable[] = { const struct StringToEnum sFlagNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY), + STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST), + STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER), }; const struct StringToEnum sFormatNameToEnumTable[] = { |