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

Commit 39ca23bc authored by Bryce Lee's avatar Bryce Lee
Browse files

Do not capture swipes in opposite direction.

This changelist updates the logic in BouncerSwipeTouchHandler to
validate the direction of the vertical swipe. Accepting swipes in the
opposite direction (such as down on a collapsed bouncer) can cause
lockscreen/shade ui locking up.

Test: atest BouncerSwipeTouchHandlerTest
Flag: ACONFIG com.android.systemui.dream_overlay_bouncer_swipe_direction_filtering DISABLED
Change-Id: I954fd8d61248319646539fa60c89fe728cf21f71
parent 869e636a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -731,3 +731,13 @@ flag {
    description: "Glow bar indicator reveals upon keyboard docking."
    bug: "324600132"
}

flag {
  name: "dream_overlay_bouncer_swipe_direction_filtering"
  namespace: "systemui"
  description: "do not initiate bouncer swipe when the direction is opposite of the expansion"
  bug: "333632464"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
 No newline at end of file
+67 −6
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import android.animation.ValueAnimator;
import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.graphics.Region;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
@@ -41,6 +43,7 @@ import androidx.test.filters.SmallTest;

import com.android.internal.logging.UiEventLogger;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.dreams.touch.scrim.ScrimController;
@@ -277,6 +280,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
    /**
     * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount.
     */
    @DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
    @Test
    public void testSwipeUp_whenBouncerInitiallyShowing_doesNotSetExpansion() {
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
@@ -297,8 +301,36 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, 0, 0);

        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
                .isTrue();
        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)).isTrue();

        verify(mScrimController, never()).expand(any());
    }

    /**
     * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount.
     */
    @Test
    @EnableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
    public void testSwipeUp_whenBouncerInitiallyShowing_doesNotSetExpansion_directionFiltering() {
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);

        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());

        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();

        final float percent = .3f;
        final float distanceY = SCREEN_HEIGHT_PX * percent;

        // Swiping up near the top of the screen where the touch initiation region is.
        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, distanceY, 0);
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, 0, 0);

        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)).isFalse();

        verify(mScrimController, never()).expand(any());
    }
@@ -307,6 +339,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
     * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount.
     */
    @Test
    @DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
    public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion() {
        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
@@ -324,8 +357,34 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, SCREEN_HEIGHT_PX, 0);

        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
                .isTrue();
        assertThat(gestureListener.onScroll(event1, event2, 0, -distanceY)).isTrue();

        verify(mScrimController, never()).expand(any());
    }

    /**
     * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount.
     */
    @Test
    @EnableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
    public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion_directionFiltering() {
        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());

        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();

        final float percent = .15f;
        final float distanceY = SCREEN_HEIGHT_PX * percent;

        // Swiping down near the bottom of the screen where the touch initiation region is.
        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, SCREEN_HEIGHT_PX - distanceY, 0);
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, SCREEN_HEIGHT_PX, 0);

        assertThat(gestureListener.onScroll(event1, event2, 0, -distanceY)).isFalse();

        verify(mScrimController, never()).expand(any());
    }
@@ -444,7 +503,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
                0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);

        reset(mScrimController);
        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
        assertThat(gestureListener.onScroll(event1, event2, 0,
                direction == Direction.UP ? distanceY : -distanceY))
                .isTrue();

        // Ensure only called once
@@ -643,7 +703,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);

        assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0, distanceY))
        assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0,
                direction == Direction.UP ? distanceY : -distanceY))
                .isTrue();

        final MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
+10 −3
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Flags;
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.dreams.touch.scrim.ScrimController;
import com.android.systemui.dreams.touch.scrim.ScrimManager;
@@ -124,13 +125,19 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                        float distanceY) {
                    if (mCapture == null) {
                        // If the user scrolling favors a vertical direction, begin capturing
                        // scrolls.
                        mCapture = Math.abs(distanceY) > Math.abs(distanceX);
                        mBouncerInitiallyShowing = mCentralSurfaces
                                .map(CentralSurfaces::isBouncerShowing)
                                .orElse(false);

                        if (Flags.dreamOverlayBouncerSwipeDirectionFiltering()) {
                            mCapture = Math.abs(distanceY) > Math.abs(distanceX)
                                    && ((distanceY < 0 && mBouncerInitiallyShowing)
                                    || (distanceY > 0 && !mBouncerInitiallyShowing));
                        } else {
                            // If the user scrolling favors a vertical direction, begin capturing
                            // scrolls.
                            mCapture = Math.abs(distanceY) > Math.abs(distanceX);
                        }
                        if (mCapture) {
                            // reset expanding
                            mExpanded = false;