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

Commit d4bd7f60 authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez
Browse files

Adding null check to slider haptic plugin when delivering haptics from

holding the volume keys.

Test: Turn off "Haptic Volume Slider" flag in Flag Flipper -> change the
  volume by holding the volume keys
Test: atest SystemUITests:VolumeDialogImplTest
Flag: ACONFIG com.android.systemui.haptic_volume_slider TEAMFOOD
Bug: 328545341
Change-Id: Iddb8e251f338a694bd1079baa25799c0766e7d4d
parent 3034ebdc
Loading
Loading
Loading
Loading
+27 −9
Original line number Diff line number Diff line
@@ -173,6 +173,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
    private static final String TYPE_DISMISS = "dismiss";
    /** Volume dialog slider animation. */
    private static final String TYPE_UPDATE = "update";
    static final short PROGRESS_HAPTICS_DISABLED = 0;
    static final short PROGRESS_HAPTICS_EAGER = 1;
    static final short PROGRESS_HAPTICS_ANIMATED = 2;

    /**
     *  TODO(b/290612381): remove lingering animations or tolerate them
@@ -2077,14 +2080,17 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
                if (row.anim == null) {
                    row.anim = ObjectAnimator.ofInt(row.slider, "progress", progress, newProgress);
                    row.anim.setInterpolator(new DecelerateInterpolator());
                    row.anim.addListener(
                        getJankListener(row.view, TYPE_UPDATE, UPDATE_ANIMATION_DURATION));
                    Animator.AnimatorListener listener =
                            getJankListener(row.view, TYPE_UPDATE, UPDATE_ANIMATION_DURATION);
                    if (listener != null) {
                        row.anim.addListener(listener);
                    }
                } else {
                    row.anim.cancel();
                    row.anim.setIntValues(progress, newProgress);
                    // The animator can't keep up with the volume changes so haptics need to be
                    // triggered here. This happens when the volume keys are continuously pressed.
                    row.deliverOnProgressChangedHaptics(false, newProgress);
                    row.deliverOnProgressChangedHaptics(false, newProgress, PROGRESS_HAPTICS_EAGER);
                }
                row.animTargetProgress = newProgress;
                row.anim.setDuration(UPDATE_ANIMATION_DURATION);
@@ -2099,6 +2105,15 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
        }
    }

    @VisibleForTesting short progressHapticsForStream(int stream) {
        for (VolumeRow row: mRows) {
            if (row.stream == stream) {
                return row.mProgressHapticsType;
            }
        }
        return PROGRESS_HAPTICS_DISABLED;
    }

    private void recheckH(VolumeRow row) {
        if (row == null) {
            if (D.BUG) Log.d(TAG, "recheckH ALL");
@@ -2486,13 +2501,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (mRow.ss == null) return;
            if (getActiveRow().equals(mRow)
                    && mRow.slider.getVisibility() == VISIBLE
                    && mRow.mHapticPlugin != null) {
            if (getActiveRow().equals(mRow) && mRow.slider.getVisibility() == VISIBLE) {
                if (fromUser || mRow.animTargetProgress == progress) {
                    // Deliver user-generated slider changes immediately, or when the animation
                    // Deliver user-generated slider haptics immediately, or when the animation
                    // completes
                    mRow.deliverOnProgressChangedHaptics(fromUser, progress);
                    mRow.deliverOnProgressChangedHaptics(
                            fromUser, progress, PROGRESS_HAPTICS_ANIMATED);
                }
            }
            if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream)
@@ -2605,6 +2619,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
        private int animTargetProgress;
        private int lastAudibleLevel = 1;
        private SeekableSliderHapticPlugin mHapticPlugin;
        private short mProgressHapticsType = PROGRESS_HAPTICS_DISABLED;

        void setIcon(int iconRes, Resources.Theme theme) {
            if (icon != null) {
@@ -2646,12 +2661,15 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
            slider.setOnTouchListener(null);
        }

        void deliverOnProgressChangedHaptics(boolean fromUser, int progress) {
        void deliverOnProgressChangedHaptics(boolean fromUser, int progress, short hapticsType) {
            if (mHapticPlugin == null) return;

            mHapticPlugin.onProgressChanged(slider, progress, fromUser);
            if (!fromUser) {
                // Consider a change from program as the volume key being continuously pressed
                mHapticPlugin.onKeyDown();
            }
            mProgressHapticsType = hapticsType;
        }
    }

+52 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;

import static com.android.systemui.Flags.FLAG_HAPTIC_VOLUME_SLIDER;
import static com.android.systemui.volume.Events.DISMISS_REASON_UNKNOWN;
import static com.android.systemui.volume.Events.SHOW_REASON_UNKNOWN;
import static com.android.systemui.volume.VolumeDialogControllerImpl.STREAMS;
@@ -46,7 +47,10 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.SystemClock;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -264,6 +268,54 @@ public class VolumeDialogImplTest extends SysuiTestCase {
        }
    }

    @Test
    @DisableFlags(FLAG_HAPTIC_VOLUME_SLIDER)
    public void testVolumeChange_noSliderHaptics_doesNotDeliverOnProgressChangedHaptics() {
        // Initialize the dialog again with haptic sliders disabled
        mDialog.init(0, null);
        final State shellState = createShellState();
        VolumeDialogController.StreamState musicStreamState =
                shellState.states.get(AudioSystem.STREAM_MUSIC);

        mDialog.show(SHOW_REASON_UNKNOWN);
        mTestableLooper.processMessages(1); //Only the SHOW message

        // Change the volume two times
        musicStreamState.level += 10;
        mDialog.onStateChangedH(shellState);
        mAnimatorTestRule.advanceTimeBy(10);
        musicStreamState.level += 10;
        mDialog.onStateChangedH(shellState);

        // expected: the type of the progress haptics for the stream should be DISABLED
        short type = mDialog.progressHapticsForStream(AudioSystem.STREAM_MUSIC);
        assertEquals(VolumeDialogImpl.PROGRESS_HAPTICS_DISABLED, type);
    }

    @Test
    @EnableFlags(FLAG_HAPTIC_VOLUME_SLIDER)
    public void testVolumeChange_withSliderHaptics_deliversOnProgressChangedHapticsEagerly() {
       // Initialize the dialog again to create haptic plugins on the rows with the flag enabled
        mDialog.init(0, null);
        final State shellState = createShellState();
        VolumeDialogController.StreamState musicStreamState =
                shellState.states.get(AudioSystem.STREAM_MUSIC);

        mDialog.show(SHOW_REASON_UNKNOWN);
        mTestableLooper.processMessages(1); //Only the SHOW message

        // Change the volume two times
        musicStreamState.level += 10;
        mDialog.onStateChangedH(shellState);
        mAnimatorTestRule.advanceTimeBy(10);
        musicStreamState.level += 10;
        mDialog.onStateChangedH(shellState);

        // expected: the type of the progress haptics for the stream should be EAGER
        short type = mDialog.progressHapticsForStream(AudioSystem.STREAM_MUSIC);
        assertEquals(VolumeDialogImpl.PROGRESS_HAPTICS_EAGER, type);
    }

    @Test
    public void testComputeTimeout() {
        Mockito.reset(mAccessibilityMgr);