Merge "Limit recursive volume calculation" into main
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2dea379..3c3a43a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -7834,10 +7834,18 @@
float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
VolumeSource volumeSource,
int index,
- const DeviceTypeSet& deviceTypes)
+ const DeviceTypeSet& deviceTypes,
+ bool computeInternalInteraction)
{
float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(deviceTypes), index);
+ ALOGV("%s volume source %d, index %d, devices %s, compute internal %b ", __func__,
+ volumeSource, index, dumpDeviceTypes(deviceTypes).c_str(), computeInternalInteraction);
+
+ if (!computeInternalInteraction) {
+ return volumeDb;
+ }
+
// handle the case of accessibility active while a ringtone is playing: if the ringtone is much
// louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
// exploration of the dialer UI. In this situation, bring the accessibility volume closer to
@@ -7847,14 +7855,11 @@
const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC, false);
const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM, false);
const auto a11yVolumeSrc = toVolumeSource(AUDIO_STREAM_ACCESSIBILITY, false);
- // Verify that the current volume source is not the ringer volume to prevent recursively
- // calling to compute volume. This could happen in cases where a11y and ringer sounds belong
- // to the same volume group.
- if (volumeSource != ringVolumeSrc && volumeSource == a11yVolumeSrc
- && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
+ if (AUDIO_MODE_RINGTONE == mEngine->getPhoneState() &&
mOutputs.isActive(ringVolumeSrc, 0)) {
auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
- const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, deviceTypes);
+ const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, deviceTypes,
+ /* computeInternalInteraction= */ false);
return ringVolumeDb - 4 > volumeDb ? ringVolumeDb - 4 : volumeDb;
}
@@ -7871,7 +7876,8 @@
auto &voiceCurves = getVolumeCurves(callVolumeSrc);
int voiceVolumeIndex = voiceCurves.getVolumeIndex(deviceTypes);
const float maxVoiceVolDb =
- computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, deviceTypes)
+ computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, deviceTypes,
+ /* computeInternalInteraction= */ false)
+ IN_CALL_EARPIECE_HEADROOM_DB;
// FIXME: Workaround for call screening applications until a proper audio mode is defined
// to support this scenario : Exempt the RING stream from the audio cap if the audio was
@@ -7913,12 +7919,8 @@
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
// just stopped
- // Verify that the current volume source is not the music volume to prevent recursively
- // calling to compute volume. This could happen in cases where music and
- // (alarm, ring, notification, system, etc.) sounds belong to the same volume group.
- if (volumeSource != musicVolumeSrc &&
- (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)
- || mLimitRingtoneVolume)) {
+ if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)
+ || mLimitRingtoneVolume) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
DeviceTypeSet musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
@@ -7927,7 +7929,8 @@
float musicVolDb = computeVolume(musicCurves,
musicVolumeSrc,
musicCurves.getVolumeIndex(musicDevice),
- musicDevice);
+ musicDevice,
+ /* computeInternalInteraction= */ false);
float minVolDb = (musicVolDb > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
musicVolDb : SONIFICATION_HEADSET_VOLUME_MIN_DB;
if (volumeDb > minVolDb) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 0454e6e..50e8ed8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -565,12 +565,36 @@
status_t resetInputDevice(audio_io_handle_t input,
audio_patch_handle_t *patchHandle = NULL);
- // compute the actual volume for a given stream according to the requested index and a particular
- // device
- virtual float computeVolume(IVolumeCurves &curves,
- VolumeSource volumeSource,
- int index,
- const DeviceTypeSet& deviceTypes);
+ /**
+ * Compute volume in DB that should be applied for a volume source and device types for a
+ * particular volume index.
+ *
+ * <p><b>Note:</b>Internally the compute method recursively calls itself to accurately
+ * determine the volume given the currently active sources and devices. Some of the
+ * interaction that require recursive computation are:
+ * <ul>
+ * <li>Match accessibility volume if ringtone volume is much louder</li>
+ * <li>If voice call is active cap other volumes (except ringtone and accessibility)</li>
+ * <li>Attenuate notification if headset is connected to prevent burst in user's ear</li>
+ * <li>Attenuate ringtone if headset is connected and music is not playing and speaker is
+ * part of the devices to prevent burst in user's ear</li>
+ * <li>Limit music volume if headset is connected and notification is also active</li>
+ * </ul>
+ *
+ * @param curves volume curves to use for calculating volume value given the index
+ * @param volumeSource source (use case) of the volume
+ * @param index index to match in the volume curves for the calculation
+ * @param deviceTypes devices that should be considered in the volume curves for the
+ * calculation
+ * @param computeInternalInteraction boolean indicating whether recursive volume computation
+ * should continue within the volume computation. Defaults to {@code true} so the
+ * volume interactions can be computed. Calls within the method should always set the
+ * the value to {@code false} to prevent infinite recursion.
+ * @return computed volume in DB
+ */
+ virtual float computeVolume(IVolumeCurves &curves, VolumeSource volumeSource,
+ int index, const DeviceTypeSet& deviceTypes,
+ bool computeInternalInteraction = true);
// rescale volume index from srcStream within range of dstStream
int rescaleVolumeIndex(int srcIndex,