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

Commit bcc1087a authored by John Spurlock's avatar John Spurlock
Browse files

Volume: Improve inline volume controls used in settings.

 - Make the system internal ringer mode change signal available to
   other system components via a standard intent, instead of a
   volume-controller-only binder call.
 - Update sysui to use new intent for icon policy.
 - Add proper muting state to the volumizer, to look more like
   the associated volume panel slider.
 - Add basic ringer mode state tracking for the notification-ring
   slider setting.

Bug: 17899613
Change-Id: Ie2df52edb070055ef59c74039162a0e785d2fdbb
parent c1de25d8
Loading
Loading
Loading
Loading
+78 −22
Original line number Original line Diff line number Diff line
@@ -44,6 +44,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba


    public interface Callback {
    public interface Callback {
        void onSampleStarting(SeekBarVolumizer sbv);
        void onSampleStarting(SeekBarVolumizer sbv);
        void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch);
        void onMuted(boolean muted);
    }
    }


    private final Context mContext;
    private final Context mContext;
@@ -53,6 +55,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
    private final AudioManager mAudioManager;
    private final AudioManager mAudioManager;
    private final int mStreamType;
    private final int mStreamType;
    private final int mMaxStreamVolume;
    private final int mMaxStreamVolume;
    private boolean mAffectedByRingerMode;
    private boolean mNotificationOrRing;
    private final Receiver mReceiver = new Receiver();
    private final Receiver mReceiver = new Receiver();


    private Handler mHandler;
    private Handler mHandler;
@@ -60,8 +64,10 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
    private int mOriginalStreamVolume;
    private int mOriginalStreamVolume;
    private Ringtone mRingtone;
    private Ringtone mRingtone;
    private int mLastProgress = -1;
    private int mLastProgress = -1;
    private boolean mMuted;
    private SeekBar mSeekBar;
    private SeekBar mSeekBar;
    private int mVolumeBeforeMute = -1;
    private int mVolumeBeforeMute = -1;
    private int mRingerMode;


    private static final int MSG_SET_STREAM_VOLUME = 0;
    private static final int MSG_SET_STREAM_VOLUME = 0;
    private static final int MSG_START_SAMPLE = 1;
    private static final int MSG_START_SAMPLE = 1;
@@ -69,14 +75,22 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
    private static final int MSG_INIT_SAMPLE = 3;
    private static final int MSG_INIT_SAMPLE = 3;
    private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000;
    private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000;


    public SeekBarVolumizer(Context context, int streamType, Uri defaultUri,
    public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
            Callback callback) {
        mContext = context;
        mContext = context;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mStreamType = streamType;
        mStreamType = streamType;
        mAffectedByRingerMode = mAudioManager.isStreamAffectedByRingerMode(mStreamType);
        mNotificationOrRing = isNotificationOrRing(mStreamType);
        if (mNotificationOrRing) {
            mRingerMode = mAudioManager.getRingerModeInternal();
        }
        mMaxStreamVolume = mAudioManager.getStreamMaxVolume(mStreamType);
        mMaxStreamVolume = mAudioManager.getStreamMaxVolume(mStreamType);
        mCallback = callback;
        mCallback = callback;
        mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
        mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
        mMuted = mAudioManager.isStreamMute(mStreamType);
        if (mCallback != null) {
            mCallback.onMuted(mMuted);
        }
        if (defaultUri == null) {
        if (defaultUri == null) {
            if (mStreamType == AudioManager.STREAM_RING) {
            if (mStreamType == AudioManager.STREAM_RING) {
                defaultUri = Settings.System.DEFAULT_RINGTONE_URI;
                defaultUri = Settings.System.DEFAULT_RINGTONE_URI;
@@ -89,6 +103,10 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
        mDefaultUri = defaultUri;
        mDefaultUri = defaultUri;
    }
    }


    private static boolean isNotificationOrRing(int stream) {
        return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
    }

    public void setSeekBar(SeekBar seekBar) {
    public void setSeekBar(SeekBar seekBar) {
        if (mSeekBar != null) {
        if (mSeekBar != null) {
            mSeekBar.setOnSeekBarChangeListener(null);
            mSeekBar.setOnSeekBarChangeListener(null);
@@ -96,10 +114,23 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
        mSeekBar = seekBar;
        mSeekBar = seekBar;
        mSeekBar.setOnSeekBarChangeListener(null);
        mSeekBar.setOnSeekBarChangeListener(null);
        mSeekBar.setMax(mMaxStreamVolume);
        mSeekBar.setMax(mMaxStreamVolume);
        mSeekBar.setProgress(mLastProgress > -1 ? mLastProgress : mOriginalStreamVolume);
        updateSeekBar();
        mSeekBar.setOnSeekBarChangeListener(this);
        mSeekBar.setOnSeekBarChangeListener(this);
    }
    }


    protected void updateSeekBar() {
        if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
            mSeekBar.setEnabled(true);
            mSeekBar.setProgress(0);
        } else if (mMuted) {
            mSeekBar.setEnabled(false);
            mSeekBar.setProgress(0);
        } else {
            mSeekBar.setEnabled(true);
            mSeekBar.setProgress(mLastProgress > -1 ? mLastProgress : mOriginalStreamVolume);
        }
    }

    @Override
    @Override
    public boolean handleMessage(Message msg) {
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
        switch (msg.what) {
@@ -193,14 +224,14 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
        mAudioManager.setStreamVolume(mStreamType, mOriginalStreamVolume, 0);
        mAudioManager.setStreamVolume(mStreamType, mOriginalStreamVolume, 0);
    }
    }


    public void onProgressChanged(SeekBar seekBar, int progress,
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
            boolean fromTouch) {
        if (fromTouch) {
        if (!fromTouch) {
            return;
        }

            postSetVolume(progress);
            postSetVolume(progress);
        }
        }
        if (mCallback != null) {
            mCallback.onProgressChanged(seekBar, progress, fromTouch);
        }
    }


    private void postSetVolume(int progress) {
    private void postSetVolume(int progress) {
        if (mHandler == null) return;
        if (mHandler == null) return;
@@ -276,14 +307,29 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            if (msg.what == UPDATE_SLIDER) {
            if (msg.what == UPDATE_SLIDER) {
                if (mSeekBar != null) {
                if (mSeekBar != null) {
                    mSeekBar.setProgress(msg.arg1);
                    mLastProgress = msg.arg1;
                    mLastProgress = mSeekBar.getProgress();
                    final boolean muted = msg.arg2 != 0;
                    if (muted != mMuted) {
                        mMuted = muted;
                        if (mCallback != null) {
                            mCallback.onMuted(mMuted);
                        }
                    }
                    updateSeekBar();
                }
                }
            }
            }
        }
        }


        public void postUpdateSlider(int volume) {
        public void postUpdateSlider(int volume, boolean mute) {
            obtainMessage(UPDATE_SLIDER, volume, 0).sendToTarget();
            obtainMessage(UPDATE_SLIDER, volume, mute ? 1 : 0).sendToTarget();
        }
    }

    private void updateSlider() {
        if (mSeekBar != null && mAudioManager != null) {
            final int volume = mAudioManager.getStreamVolume(mStreamType);
            final boolean mute = mAudioManager.isStreamMute(mStreamType);
            mUiHandler.postUpdateSlider(volume, mute);
        }
        }
    }
    }


@@ -295,10 +341,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
        @Override
        @Override
        public void onChange(boolean selfChange) {
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            super.onChange(selfChange);
            if (mSeekBar != null && mAudioManager != null) {
            updateSlider();
                final int volume = mAudioManager.getStreamVolume(mStreamType);
                mUiHandler.postUpdateSlider(volume);
            }
        }
        }
    }
    }


@@ -310,6 +353,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
            mListening = listening;
            mListening = listening;
            if (listening) {
            if (listening) {
                final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
                final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
                filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
                mContext.registerReceiver(this, filter);
                mContext.registerReceiver(this, filter);
            } else {
            } else {
                mContext.unregisterReceiver(this);
                mContext.unregisterReceiver(this);
@@ -318,11 +362,23 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba


        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            if (!AudioManager.VOLUME_CHANGED_ACTION.equals(intent.getAction())) return;
            final String action = intent.getAction();
            final int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
            if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) {
            final int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
            if (mSeekBar != null && streamType == mStreamType && streamValue != -1) {
                int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
                mUiHandler.postUpdateSlider(streamValue);
                final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType)
                        : (streamType == mStreamType);
                if (mSeekBar != null && streamMatch && streamValue != -1) {
                    final boolean muted = mAudioManager.isStreamMute(mStreamType);
                    mUiHandler.postUpdateSlider(streamValue, muted);
                }
            } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
                if (mNotificationOrRing) {
                    mRingerMode = mAudioManager.getRingerModeInternal();
                }
                if (mAffectedByRingerMode) {
                    updateSlider();
                }
            }
            }
        }
        }
    }
    }
+10 −0
Original line number Original line Diff line number Diff line
@@ -149,6 +149,16 @@ public class VolumePreference extends SeekBarDialogPreference implements
        }
        }
    }
    }


    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
        // noop
    }

    @Override
    public void onMuted(boolean muted) {
        // noop
    }

    @Override
    @Override
    protected Parcelable onSaveInstanceState() {
    protected Parcelable onSaveInstanceState() {
        final Parcelable superState = super.onSaveInstanceState();
        final Parcelable superState = super.onSaveInstanceState();
+11 −0
Original line number Original line Diff line number Diff line
@@ -89,6 +89,17 @@ public class AudioManager {
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";
    public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";


    /**
     * @hide
     * Sticky broadcast intent action indicating that the internal ringer mode has
     * changed. Includes the new ringer mode.
     *
     * @see #EXTRA_RINGER_MODE
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String INTERNAL_RINGER_MODE_CHANGED_ACTION =
            "android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION";

    /**
    /**
     * The new ringer mode.
     * The new ringer mode.
     *
     *
+12 −16
Original line number Original line Diff line number Diff line
@@ -927,8 +927,9 @@ public class AudioService extends IAudioService.Stub {


        // Each stream will read its own persisted settings
        // Each stream will read its own persisted settings


        // Broadcast the sticky intent
        // Broadcast the sticky intents
        broadcastRingerMode(ringerMode);
        broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
        broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);


        // Broadcast vibrate settings
        // Broadcast vibrate settings
        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
@@ -1837,7 +1838,6 @@ public class AudioService extends IAudioService.Stub {
        } else /*internal*/ {
        } else /*internal*/ {
            if (ringerMode != ringerModeInternal) {
            if (ringerMode != ringerModeInternal) {
                setRingerModeInt(ringerMode, true /*persist*/);
                setRingerModeInt(ringerMode, true /*persist*/);
                mVolumeController.postInternalRingerModeChanged(ringerMode);
            }
            }
            if (mRingerModeDelegate != null) {
            if (mRingerModeDelegate != null) {
                ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
                ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
@@ -1853,11 +1853,13 @@ public class AudioService extends IAudioService.Stub {
            mRingerModeExternal = ringerMode;
            mRingerModeExternal = ringerMode;
        }
        }
        // Send sticky broadcast
        // Send sticky broadcast
        broadcastRingerMode(ringerMode);
        broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
    }
    }


    private void setRingerModeInt(int ringerMode, boolean persist) {
    private void setRingerModeInt(int ringerMode, boolean persist) {
        final boolean change;
        synchronized(mSettingsLock) {
        synchronized(mSettingsLock) {
            change = mRingerMode != ringerMode;
            mRingerMode = ringerMode;
            mRingerMode = ringerMode;
        }
        }


@@ -1903,6 +1905,10 @@ public class AudioService extends IAudioService.Stub {
            sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
            sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
                    SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
                    SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
        }
        }
        if (change) {
            // Send sticky broadcast
            broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
        }
    }
    }


    private void restoreMasterVolume() {
    private void restoreMasterVolume() {
@@ -3276,9 +3282,9 @@ public class AudioService extends IAudioService.Stub {
        return suggestedStreamType;
        return suggestedStreamType;
    }
    }


    private void broadcastRingerMode(int ringerMode) {
    private void broadcastRingerMode(String action, int ringerMode) {
        // Send sticky broadcast
        // Send sticky broadcast
        Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION);
        Intent broadcast = new Intent(action);
        broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
        broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
        broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
        broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
@@ -5711,16 +5717,6 @@ public class AudioService extends IAudioService.Stub {
                Log.w(TAG, "Error calling dismiss", e);
                Log.w(TAG, "Error calling dismiss", e);
            }
            }
        }
        }

        public void postInternalRingerModeChanged(int mode) {
            if (mController == null)
                return;
            try {
                mController.internalRingerModeChanged(mode);
            } catch (RemoteException e) {
                Log.w(TAG, "Error calling internalRingerModeChanged", e);
            }
        }
    }
    }


    /**
    /**
+0 −2
Original line number Original line Diff line number Diff line
@@ -34,6 +34,4 @@ oneway interface IVolumeController {
    void setLayoutDirection(int layoutDirection);
    void setLayoutDirection(int layoutDirection);


    void dismiss();
    void dismiss();

    void internalRingerModeChanged(int mode);
}
}
Loading