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

Commit fde16d58 authored by Eric Laurent's avatar Eric Laurent
Browse files

more fixes on safe volume warning message

Fixes the following problems with safe headphone volume warning message:
- Do not display the warning dialog when screen is off.
- Use the same 3 second timeout as for the volume slider to dismiss the dialog.
- Do not dismiss the warning dialog when touching outside of the slider window
but inside the warning window.
- Disable the volume slider when the warning message is displayed.
- When setting volume directly (touching the volume slider), and the warning
is displayed, save the requested volume and apply it if acknowledged by the user.
- Do not display the warning message when restoring safe volume after 20h of
cumulative listenening

Bug 7658641.

Change-Id: Ib3d1315193a433dad918aa5df78fa071062b2394
parent e81f55ba
Loading
Loading
Loading
Loading
+53 −37
Original line number Diff line number Diff line
@@ -218,12 +218,14 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie

    private static class WarningDialogReceiver extends BroadcastReceiver
            implements DialogInterface.OnDismissListener {
        private Context mContext;
        private Dialog mDialog;
        private final Context mContext;
        private final Dialog mDialog;
        private final VolumePanel mVolumePanel;

        WarningDialogReceiver(Context context, Dialog dialog) {
        WarningDialogReceiver(Context context, Dialog dialog, VolumePanel volumePanel) {
            mContext = context;
            mDialog = dialog;
            mVolumePanel = volumePanel;
            IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            context.registerReceiver(this, filter);
        }
@@ -231,16 +233,20 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
        @Override
        public void onReceive(Context context, Intent intent) {
            mDialog.cancel();
            synchronized (sConfirmSafeVolumeLock) {
                sConfirmSafeVolumeDialog = null;
            }
            cleanUp();
        }

        public void onDismiss(DialogInterface unused) {
            mContext.unregisterReceiver(this);
            cleanUp();
        }

        private void cleanUp() {
            synchronized (sConfirmSafeVolumeLock) {
                sConfirmSafeVolumeDialog = null;
            }
            mVolumePanel.forceTimeout();
            mVolumePanel.updateStates();
        }
    }

@@ -276,7 +282,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie

        mDialog = new Dialog(context, R.style.Theme_Panel_Volume) {
            public boolean onTouchEvent(MotionEvent event) {
                if (isShowing() && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                if (isShowing() && event.getAction() == MotionEvent.ACTION_OUTSIDE &&
                        sConfirmSafeVolumeDialog == null) {
                    forceTimeout();
                    return true;
                }
@@ -461,7 +468,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
            // never disable touch interactions for remote playback, the muting is not tied to
            // the state of the phone.
            sc.seekbarView.setEnabled(true);
        } else if (sc.streamType != mAudioManager.getMasterStreamType() && muted) {
        } else if ((sc.streamType != mAudioManager.getMasterStreamType() && muted) ||
                        (sConfirmSafeVolumeDialog != null)) {
            sc.seekbarView.setEnabled(false);
        } else {
            sc.seekbarView.setEnabled(true);
@@ -490,7 +498,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
        }
    }

    private void updateStates() {
    public void updateStates() {
        final int count = mSliderGroup.getChildCount();
        for (int i = 0; i < count; i++) {
            StreamControl sc = (StreamControl) mSliderGroup.getChildAt(i).getTag();
@@ -562,9 +570,9 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
        postMuteChanged(STREAM_MASTER, flags);
    }

    public void postDisplaySafeVolumeWarning() {
    public void postDisplaySafeVolumeWarning(int flags) {
        if (hasMessages(MSG_DISPLAY_SAFE_VOLUME_WARNING)) return;
        obtainMessage(MSG_DISPLAY_SAFE_VOLUME_WARNING, 0, 0).sendToTarget();
        obtainMessage(MSG_DISPLAY_SAFE_VOLUME_WARNING, flags, 0).sendToTarget();
    }

    /**
@@ -598,7 +606,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie

        removeMessages(MSG_FREE_RESOURCES);
        sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);

        resetTimeout();
    }

@@ -704,7 +711,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
            if (((flags & AudioManager.FLAG_FIXED_VOLUME) != 0) ||
                    (streamType != mAudioManager.getMasterStreamType() &&
                     streamType != AudioService.STREAM_REMOTE_MUSIC &&
                     isMuted(streamType))) {
                     isMuted(streamType)) ||
                     sConfirmSafeVolumeDialog != null) {
                sc.seekbarView.setEnabled(false);
            } else {
                sc.seekbarView.setEnabled(true);
@@ -802,7 +810,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie

        removeMessages(MSG_FREE_RESOURCES);
        sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);

        resetTimeout();
    }

@@ -838,7 +845,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
        }
    }

    protected void onDisplaySafeVolumeWarning() {
    protected void onDisplaySafeVolumeWarning(int flags) {
        if ((flags & AudioManager.FLAG_SHOW_UI) != 0 || mDialog.isShowing()) {
            synchronized (sConfirmSafeVolumeLock) {
                if (sConfirmSafeVolumeDialog != null) {
                    return;
@@ -855,13 +863,16 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
                        .setIconAttribute(android.R.attr.alertDialogIcon)
                        .create();
                final WarningDialogReceiver warning = new WarningDialogReceiver(mContext,
                    sConfirmSafeVolumeDialog);
                        sConfirmSafeVolumeDialog, this);

                sConfirmSafeVolumeDialog.setOnDismissListener(warning);
                sConfirmSafeVolumeDialog.getWindow().setType(
                                                WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
                sConfirmSafeVolumeDialog.show();
            }
            updateStates();
        }
        resetTimeout();
    }

    /**
@@ -957,6 +968,11 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
                    mDialog.dismiss();
                    mActiveStreamType = -1;
                }
                synchronized (sConfirmSafeVolumeLock) {
                    if (sConfirmSafeVolumeDialog != null) {
                        sConfirmSafeVolumeDialog.dismiss();
                    }
                }
                break;
            }
            case MSG_RINGER_MODE_CHANGED: {
@@ -980,7 +996,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
                break;

            case MSG_DISPLAY_SAFE_VOLUME_WARNING:
                onDisplaySafeVolumeWarning();
                onDisplaySafeVolumeWarning(msg.arg1);
                break;
        }
    }
+79 −35
Original line number Diff line number Diff line
@@ -439,6 +439,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {

    private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;

    // Used when safe volume warning message display is requested by setStreamVolume(). In this
    // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
    // and used later when/if disableSafeMediaVolume() is called.
    private StreamVolumeCommand mPendingVolumeCommand;

    ///////////////////////////////////////////////////////////////////////////
    // Construction
    ///////////////////////////////////////////////////////////////////////////
@@ -831,6 +836,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        int index;
        int oldIndex;

        // reset any pending volume command
        synchronized (mSafeMediaVolumeState) {
            mPendingVolumeCommand = null;
        }

        flags &= ~AudioManager.FLAG_FIXED_VOLUME;
        if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
               ((device & mFixedVolumeDevices) != 0)) {
@@ -858,6 +868,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            index = mStreamStates[streamType].getIndex(device,
                                                 (streamState.muteCount() != 0)  /* lastAudible */);
            oldIndex = index;
            mVolumePanel.postDisplaySafeVolumeWarning(flags);
        } else {
            // If either the client forces allowing ringer modes for this adjustment,
            // or the stream type is one that is affected by ringer modes
@@ -929,6 +940,44 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        setMasterVolume(volume, flags);
    }

    // StreamVolumeCommand contains the information needed to defer the process of
    // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
    class StreamVolumeCommand {
        public final int mStreamType;
        public final int mIndex;
        public final int mFlags;
        public final int mDevice;

        StreamVolumeCommand(int streamType, int index, int flags, int device) {
            mStreamType = streamType;
            mIndex = index;
            mFlags = flags;
            mDevice = device;
        }
    };

    private void onSetStreamVolume(int streamType, int index, int flags, int device) {
        // setting volume on master stream type also controls silent mode
        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
            int newRingerMode;
            if (index == 0) {
                newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
                                              : AudioManager.RINGER_MODE_SILENT;
                setStreamVolumeInt(mStreamVolumeAlias[streamType],
                                   index,
                                   device,
                                   false,
                                   true);
            } else {
                newRingerMode = AudioManager.RINGER_MODE_NORMAL;
            }
            setRingerMode(newRingerMode);
        }

        setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
    }

    /** @see AudioManager#setStreamVolume(int, int, int) */
    public void setStreamVolume(int streamType, int index, int flags) {
        ensureValidStreamType(streamType);
@@ -937,6 +986,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        final int device = getDeviceForStream(streamType);
        int oldIndex;

        synchronized (mSafeMediaVolumeState) {
            // reset any pending volume command
            mPendingVolumeCommand = null;

            // get last audible index if stream is muted, current index otherwise
            oldIndex = streamState.getIndex(device,
                                            (streamState.muteCount() != 0) /* lastAudible */);
@@ -947,6 +1000,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            if ((mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
                    ((device & mFixedVolumeDevices) != 0)) {
                flags |= AudioManager.FLAG_FIXED_VOLUME;

                // volume is either 0 or max allowed for fixed volume devices
                if (index != 0) {
                    if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
@@ -959,31 +1013,16 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            }

            if (!checkSafeMediaVolume(mStreamVolumeAlias[streamType], index, device)) {
            return;
        }

        // setting volume on master stream type also controls silent mode
        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
            int newRingerMode;
            if (index == 0) {
                newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
                                              : AudioManager.RINGER_MODE_SILENT;
                setStreamVolumeInt(mStreamVolumeAlias[streamType],
                                   index,
                                   device,
                                   false,
                                   true);
                mVolumePanel.postDisplaySafeVolumeWarning(flags);
                mPendingVolumeCommand = new StreamVolumeCommand(
                                                    streamType, index, flags, device);
            } else {
                newRingerMode = AudioManager.RINGER_MODE_NORMAL;
            }
            setRingerMode(newRingerMode);
        }

        setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
                onSetStreamVolume(streamType, index, flags, device);
                // get last audible index if stream is muted, current index otherwise
                index = mStreamStates[streamType].getIndex(device,
                                    (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
            }
        }
        sendVolumeUpdate(streamType, oldIndex, index, flags);
    }

@@ -2317,7 +2356,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                        if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
                            setSafeMediaVolumeEnabled(true);
                            mMusicActiveMs = 0;
                            mVolumePanel.postDisplaySafeVolumeWarning();
                        }
                    }
                }
@@ -5993,7 +6031,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                    (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
                    ((device & mSafeMediaVolumeDevices) != 0) &&
                    (index > mSafeMediaVolumeIndex)) {
                mVolumePanel.postDisplaySafeVolumeWarning();
                return false;
            }
            return true;
@@ -6003,6 +6040,13 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
    public void disableSafeMediaVolume() {
        synchronized (mSafeMediaVolumeState) {
            setSafeMediaVolumeEnabled(false);
            if (mPendingVolumeCommand != null) {
                onSetStreamVolume(mPendingVolumeCommand.mStreamType,
                                  mPendingVolumeCommand.mIndex,
                                  mPendingVolumeCommand.mFlags,
                                  mPendingVolumeCommand.mDevice);
                mPendingVolumeCommand = null;
            }
        }
    }