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

Commit 33f4e04e authored by John Spurlock's avatar John Spurlock
Browse files

Volume: Delay adjustments made when showing ringer UI.

Since the volume rocker is now the primary system UI for
entering ringer modes, we need to provide a way to display
the ui without making a sound.

Change the policy for the ringer stream to only display the
UI on the initial adjustment request, don't actually make
an adjustment.  However, don't break previous ability to
press and hold the vol keys down to vibrate, so allow this
after the standard framework long-press delay.

Audio service had no way of knowing whether or not the registered
volume controller was visible, so add a mechanism for the
controller (volume panel) to send that info back to the service.

Found and fixed a discrepancy between AudioManager.handleKeyDown
and MediaSessionLegacyHelper so that an adjustment over the
keyguard is allowed to vibrate as well as play sound during
adjustments.

Bug:16202639
Change-Id: Icd36c23e8d08c4ed57922c05724b281f32049be7
parent a4ab7808
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -2911,6 +2911,20 @@ public class AudioManager {
        }
    }

    /**
     * Notify audio manager about volume controller visibility changes.
     * Currently limited to SystemUI.
     *
     * @hide
     */
    public void notifyVolumeControllerVisible(IVolumeController controller, boolean visible) {
        try {
            getService().notifyVolumeControllerVisible(controller, visible);
        } catch (RemoteException e) {
            Log.w(TAG, "Error notifying about volume controller visibility", e);
        }
    }

    /**
     * Only useful for volume controllers.
     * @hide
+65 −2
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.Vibrator;
@@ -810,6 +811,9 @@ public class AudioService extends IAudioService.Stub {

        // Restore the default media button receiver from the system settings
        mMediaFocusControl.restoreMediaButtonReceiver();

        // Load settings for the volume controller
        mVolumeController.loadSettings(cr);
    }

    private int rescaleIndex(int index, int srcStream, int dstStream) {
@@ -851,12 +855,21 @@ public class AudioService extends IAudioService.Stub {
        } else {
            streamType = getActiveStreamType(suggestedStreamType);
        }
        final int resolvedStream = mStreamVolumeAlias[streamType];

        // Play sounds on STREAM_RING and STREAM_REMOTE_MUSIC only.
        if ((streamType != STREAM_REMOTE_MUSIC) &&
                (flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
                (mStreamVolumeAlias[streamType] != AudioSystem.STREAM_RING)) {
                resolvedStream != AudioSystem.STREAM_RING) {
            flags &= ~AudioManager.FLAG_PLAY_SOUND;
        }

        // For notifications/ring, show the ui before making any adjustments
        if (mVolumeController.suppressAdjustment(resolvedStream, flags)) {
            direction = 0;
            flags &= ~AudioManager.FLAG_PLAY_SOUND;
            flags &= ~AudioManager.FLAG_VIBRATE;
            if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
        }

        if (streamType == STREAM_REMOTE_MUSIC) {
@@ -4955,15 +4968,65 @@ public class AudioService extends IAudioService.Stub {
            }
        }
        mVolumeController.setController(controller);
        if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
    }

    @Override
    public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
        enforceSelfOrSystemUI("notify about volume controller visibility");

        // return early if the controller is not current
        if (!mVolumeController.isSameBinder(controller)) {
            return;
        }

        mVolumeController.setVisible(visible);
        if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
    }

    public static class VolumeController {
        private static final String TAG = "VolumeController";

        private IVolumeController mController;
        private boolean mVisible;
        private long mNextLongPress;
        private int mLongPressTimeout;

        public void setController(IVolumeController controller) {
            mController = controller;
            mVisible = false;
        }

        public void loadSettings(ContentResolver cr) {
            mLongPressTimeout = Settings.Secure.getIntForUser(cr,
                    Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
        }

        public boolean suppressAdjustment(int resolvedStream, int flags) {
            boolean suppress = false;
            if (resolvedStream == AudioSystem.STREAM_RING && mController != null) {
                final long now = SystemClock.uptimeMillis();
                if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
                    // ui will become visible
                    if (mNextLongPress < now) {
                        mNextLongPress = now + mLongPressTimeout;
                    }
                    suppress = true;
                } else if (mNextLongPress > 0) {  // in a long-press
                    if (now > mNextLongPress) {
                        // long press triggered, no more suppression
                        mNextLongPress = 0;
                    } else {
                        // keep suppressing until the long press triggers
                        suppress = true;
                    }
                }
            }
            return suppress;
        }

        public void setVisible(boolean visible) {
            mVisible = visible;
        }

        public boolean isSameBinder(IVolumeController controller) {
@@ -4980,7 +5043,7 @@ public class AudioService extends IAudioService.Stub {

        @Override
        public String toString() {
            return "VolumeController(" + asBinder() + ")";
            return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
        }

        public void postDisplaySafeVolumeWarning(int flags) {
+2 −0
Original line number Diff line number Diff line
@@ -195,6 +195,8 @@ interface IAudioService {

    void setVolumeController(in IVolumeController controller);

    void notifyVolumeControllerVisible(in IVolumeController controller, boolean visible);

    boolean isStreamAffectedByRingerMode(int streamType);

    void disableSafeMediaVolume();
+1 −1
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ public class MediaSessionLegacyHelper {
                if (up) {
                    flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE;
                } else {
                    flags = AudioManager.FLAG_SHOW_UI;
                    flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE;
                }
            }

+7 −0
Original line number Diff line number Diff line
@@ -908,6 +908,9 @@ public class VolumePanel extends Handler {

            if (mDialog != null) {
                mDialog.show();
                if (mCallback != null) {
                    mCallback.onVisible(true);
                }
            }
        }

@@ -1160,6 +1163,9 @@ public class VolumePanel extends Handler {
                        mDialog.dismiss();
                        clearRemoteStreamController();
                        mActiveStreamType = -1;
                        if (mCallback != null) {
                            mCallback.onVisible(false);
                        }
                    }
                }
                synchronized (sConfirmSafeVolumeLock) {
@@ -1262,5 +1268,6 @@ public class VolumePanel extends Handler {
    public interface Callback {
        void onZenSettings();
        void onInteraction();
        void onVisible(boolean visible);
    }
}
Loading