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

Commit 55443cc8 authored by Jonas Larsson's avatar Jonas Larsson Committed by Steve Kondik
Browse files

Sound tweaks: Always on speaker 2.0, headphone attenuation, headphone music...

Sound tweaks: Always on speaker 2.0, headphone attenuation, headphone music vol limit, audio focus requests.
parent 76ef08c2
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -1498,6 +1498,15 @@ public final class Settings {
        public static final String NOTIFICATIONS_USE_RING_VOLUME =
        public static final String NOTIFICATIONS_USE_RING_VOLUME =
            "notifications_use_ring_volume";
            "notifications_use_ring_volume";


        /**
         * Whether notifications should request audio focus. Could be disabled
         * if a users favorite app behaves badly when audio focus is requested.
         * Value is boolean.
         *
         * @hide
         */
        public static final String NOTIFICATIONS_AUDIO_FOCUS = "notifications_audio_focus";

        /**
        /**
         * Whether silent mode should allow vibration feedback. This is used
         * Whether silent mode should allow vibration feedback. This is used
         * internally in AudioService and the Sound settings activity to
         * internally in AudioService and the Sound settings activity to
+93 −13
Original line number Original line Diff line number Diff line
@@ -19,6 +19,8 @@
#include <utils/Log.h>
#include <utils/Log.h>
#include <hardware_legacy/AudioPolicyManagerBase.h>
#include <hardware_legacy/AudioPolicyManagerBase.h>
#include <media/mediarecorder.h>
#include <media/mediarecorder.h>
#include <cutils/properties.h>
#include <math.h>


namespace android {
namespace android {


@@ -1335,6 +1337,7 @@ void AudioPolicyManagerBase::checkOutputForAllStrategies(uint32_t &newDevice)
    // checkOutputForStrategy()
    // checkOutputForStrategy()
    checkOutputForStrategy(STRATEGY_PHONE, newDevice);
    checkOutputForStrategy(STRATEGY_PHONE, newDevice);
    checkOutputForStrategy(STRATEGY_SONIFICATION, newDevice);
    checkOutputForStrategy(STRATEGY_SONIFICATION, newDevice);
    checkOutputForStrategy(STRATEGY_MEDIA_SONIFICATION, newDevice);
    checkOutputForStrategy(STRATEGY_MEDIA, newDevice);
    checkOutputForStrategy(STRATEGY_MEDIA, newDevice);
    checkOutputForStrategy(STRATEGY_DTMF, newDevice);
    checkOutputForStrategy(STRATEGY_DTMF, newDevice);
}
}
@@ -1351,15 +1354,19 @@ uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fro
    //      use device for strategy phone
    //      use device for strategy phone
    // 2: the strategy sonification is active on the hardware output:
    // 2: the strategy sonification is active on the hardware output:
    //      use device for strategy sonification
    //      use device for strategy sonification
    // 3: the strategy media is active on the hardware output:
    // 3: the strategy media sonification is active on the hardware output:
    //      use device for strategy media sonification
    // 4: the strategy media is active on the hardware output:
    //      use device for strategy media
    //      use device for strategy media
    // 4: the strategy DTMF is active on the hardware output:
    // 5: the strategy DTMF is active on the hardware output:
    //      use device for strategy DTMF
    //      use device for strategy DTMF
    if (mPhoneState == AudioSystem::MODE_IN_CALL ||
    if (mPhoneState == AudioSystem::MODE_IN_CALL ||
        outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
        outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
        device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
        device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
    } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
    } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
        device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
        device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
    } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA_SONIFICATION)) {
        device = getDeviceForStrategy(STRATEGY_MEDIA_SONIFICATION, fromCache);
    } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
    } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
        device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
        device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
    } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
    } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
@@ -1372,14 +1379,36 @@ uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fro


AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(AudioSystem::stream_type stream)
AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(AudioSystem::stream_type stream)
{
{
    // http://code.google.com/p/android/issues/detail?id=5012
    // http://code.google.com/p/cyanogenmod/issues/detail?id=1229
    char buf[PROPERTY_VALUE_MAX];

    // stream to strategy mapping
    // stream to strategy mapping
    switch (stream) {
    switch (stream) {
    case AudioSystem::VOICE_CALL:
    case AudioSystem::VOICE_CALL:
    case AudioSystem::BLUETOOTH_SCO:
    case AudioSystem::BLUETOOTH_SCO:
        return STRATEGY_PHONE;
        return STRATEGY_PHONE;
    case AudioSystem::RING:
    case AudioSystem::RING:
        property_get("persist.sys.ring-speaker", buf, "0");
        if (atoi(buf)) {
            return STRATEGY_SONIFICATION;
        } else {
            return STRATEGY_MEDIA_SONIFICATION;
        }
    case AudioSystem::NOTIFICATION:
    case AudioSystem::NOTIFICATION:
        property_get("persist.sys.notif-speaker", buf, "0");
        if (atoi(buf)) {
            return STRATEGY_SONIFICATION;
        } else {
            return STRATEGY_MEDIA_SONIFICATION;
        }
    case AudioSystem::ALARM:
    case AudioSystem::ALARM:
        property_get("persist.sys.alarm-speaker", buf, "0");
        if (atoi(buf)) {
            return STRATEGY_SONIFICATION;
        } else {
            return STRATEGY_MEDIA_SONIFICATION;
        }
    case AudioSystem::ENFORCED_AUDIBLE:
    case AudioSystem::ENFORCED_AUDIBLE:
        return STRATEGY_SONIFICATION;
        return STRATEGY_SONIFICATION;
    case AudioSystem::DTMF:
    case AudioSystem::DTMF:
@@ -1472,6 +1501,7 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
    break;
    break;


    case STRATEGY_SONIFICATION:
    case STRATEGY_SONIFICATION:
    case STRATEGY_MEDIA_SONIFICATION:


        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
        // handleIncallSonification().
        // handleIncallSonification().
@@ -1479,10 +1509,12 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
            device = getDeviceForStrategy(STRATEGY_PHONE, false);
            device = getDeviceForStrategy(STRATEGY_PHONE, false);
            break;
            break;
        }
        }
        if (strategy == STRATEGY_SONIFICATION) {
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
            if (device == 0) {
            if (device == 0) {
                LOGE("getDeviceForStrategy() speaker device not found");
                LOGE("getDeviceForStrategy() speaker device not found");
            }
            }
        }
        // The second device used for sonification is the same as the device used by media strategy
        // The second device used for sonification is the same as the device used by media strategy
        // FALL THROUGH
        // FALL THROUGH


@@ -1675,13 +1707,58 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand
        AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
        AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
        AudioSystem::DEVICE_OUT_WIRED_HEADSET |
        AudioSystem::DEVICE_OUT_WIRED_HEADSET |
        AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
        AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
        (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) &&
        ((getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) ||
         (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_MEDIA_SONIFICATION)) &&
        streamDesc.mCanBeMuted) {
        streamDesc.mCanBeMuted) {
        volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
        float origVol = volume;
        char buf[PROPERTY_VALUE_MAX];
        float volumeFactor = SONIFICATION_HEADSET_VOLUME_FACTOR;
        switch ((AudioSystem::stream_type)stream) {
            case AudioSystem::RING:
                LOGV("computeVolume RING");
                property_get("persist.sys.ring-attn", buf, "6");
                volumeFactor = pow(10.0, -atof(buf)/20.0);
                break;
            case AudioSystem::NOTIFICATION:
                LOGV("computeVolume NOTIFICATION");
                property_get("persist.sys.notif-attn", buf, "6");
                volumeFactor = pow(10.0, -atof(buf)/20.0);
                break;
            case AudioSystem::ALARM:
                LOGV("computeVolume ALARM");
                property_get("persist.sys.alarm-attn", buf, "6");
                volumeFactor = pow(10.0, -atof(buf)/20.0);
                break;
            default:
                // Squash enumeration value not handled warnings
                break;
        }
        LOGV("computeVolume attenuation factor %f ", volumeFactor);
        volume *= volumeFactor;
        // when the phone is ringing we must consider that music could have been paused just before
        // 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
        // by the music application and behave as if music was active if the last music track was
        // just stopped
        // just stopped
        if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) {
        if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) {
            int limitVol = 1;
            switch ((AudioSystem::stream_type)stream) {
                case AudioSystem::RING:
                    property_get("persist.sys.ring-limitvol", buf, "1");
                    limitVol = atoi(buf);
                    break;
                case AudioSystem::NOTIFICATION:
                    property_get("persist.sys.notif-limitvol", buf, "1");
                    limitVol = atoi(buf);
                    break;
                case AudioSystem::ALARM:
                    property_get("persist.sys.alarm-limitvol", buf, "1");
                    limitVol = atoi(buf);
                    break;
                default:
                    // Squash enumeration value not handled warnings
                    break;
            }
            LOGV("computeVolume limitVol %i", limitVol);
            if (limitVol) {
                float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device);
                float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device);
                float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
                float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
                if (volume > minVol) {
                if (volume > minVol) {
@@ -1690,6 +1767,8 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand
                }
                }
            }
            }
        }
        }
        LOGV("computeVolume %f --> %f", origVol, volume);
    }


    return volume;
    return volume;
}
}
@@ -1792,7 +1871,8 @@ void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting,
    // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as
    // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as
    // many times as there are active tracks on the output
    // many times as there are active tracks on the output


    if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
    if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION ||
        getStrategy((AudioSystem::stream_type)stream) == STRATEGY_MEDIA_SONIFICATION) {
        AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
        AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
        LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
        LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
                stream, starting, outputDesc->mDevice, stateChange);
                stream, starting, outputDesc->mDevice, stateChange);
+4 −1
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.util.Log;


import java.io.IOException;
import java.io.IOException;
@@ -88,7 +89,9 @@ public class NotificationPlayer implements OnCompletionListener {
                    player.setDataSource(mCmd.context, mCmd.uri);
                    player.setDataSource(mCmd.context, mCmd.uri);
                    player.setLooping(mCmd.looping);
                    player.setLooping(mCmd.looping);
                    player.prepare();
                    player.prepare();
                    if ((mCmd.uri != null) && (mCmd.uri.getEncodedPath() != null)
                    boolean requestFocus = Settings.System.getInt(mCmd.context.getContentResolver(),
                            Settings.System.NOTIFICATIONS_AUDIO_FOCUS, 1) != 0;
                    if (requestFocus && (mCmd.uri != null) && (mCmd.uri.getEncodedPath() != null)
                            && (mCmd.uri.getEncodedPath().length() > 0)) {
                            && (mCmd.uri.getEncodedPath().length() > 0)) {
                        if (mCmd.looping) {
                        if (mCmd.looping) {
                            audioManager.requestAudioFocus(null, mCmd.stream,
                            audioManager.requestAudioFocus(null, mCmd.stream,