Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11c9fb1f authored by Jon Eklund's avatar Jon Eklund Committed by Eric Laurent
Browse files

AudioPolicyManager: Use "safe" speaker for notifications if available

On particularly loud devices, unexpected audio bursts can be harmful.
For longer audio events, the conventional mitigation strategy is to
somehow soft-start (ramp) the loudspeaker volume, but this strategy
can severely impact the audibility of short audio events.

Use of the "safe" speaker path hints to AudioHAL to immediately output
at best allowable level for transient audio events.

SPEAKER_SAFE is aliased to SPEAKER for purposes of volume control.

Bug: 17319721
Change-Id: I75187c23f3d1f18e9f638c5d14e7b0bf805a67bc
parent 4bcbb07b
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ struct StringToEnum {
const StringToEnum sDeviceNameToEnumTable[] = {
    STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
@@ -3824,6 +3825,14 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre
            break;
        }
    }

    /*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
      and doesn't really need to.*/
    if (devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
        devices |= AUDIO_DEVICE_OUT_SPEAKER;
        devices &= ~AUDIO_DEVICE_OUT_SPEAKER_SAFE;
    }

    return devices;
}

@@ -3926,12 +3935,20 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
            //   the isStreamActive() method only informs about the activity of a stream, not
            //   if it's for local playback. Note also that we use the same delay between both tests
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
            //user "safe" speaker if available instead of normal speaker to avoid triggering
            //other acoustic safety mechanisms for notification
            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
        } else if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
            // while media is playing (or has recently played), use the same device
            device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
        } else {
            // when media is not playing anymore, fall back on the sonification behavior
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
            //user "safe" speaker if available instead of normal speaker to avoid triggering
            //other acoustic safety mechanisms for notification
            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
        }

        break;
@@ -4668,6 +4685,10 @@ audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device)
        }
    }

    /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
    if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
        device = AUDIO_DEVICE_OUT_SPEAKER;

    ALOGW_IF(popcount(device) != 1,
            "getDeviceForVolume() invalid device combination: %08x",
            device);