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

Commit d4401987 authored by William Xiao's avatar William Xiao
Browse files

Stop overlay touch handling when the bouncer or glanceable hub are visible over the dream

The dream overlay listens to touches globally and intercepts some
gestures over the dream. Currently all of these handlers are paused
when the notification shade is open, but not the bouncer or the
glanceable hub.

This change also stops touch handling when the bouncer or glanceable
hub are open. The bouncer is already capable of handling the close
gesture, and the glanceable hub handles all its own touches, so we
don't need overlay touch handling above either.

Test: atest DreamOverlayServiceTest BouncerSwipeTouchHandlerTest
      also manually verified touches aren't intercepted when hub or
      bouncer are open
Bug: 328838259
Flag: ACONFIG com.android.systemui.communal_hub TEAMFOOD
Change-Id: I536a2e1ed2f9cc6e362b25648d02f63c6917637e
parent 72423fe1
Loading
Loading
Loading
Loading
+18 −180
Original line number Diff line number Diff line
@@ -149,7 +149,6 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
                mUiEventLogger);

        when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
        when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
        when(mVelocityTrackerFactory.obtain()).thenReturn(mVelocityTracker);
        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn(Float.MAX_VALUE);
@@ -193,11 +192,6 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
                        2)).isTrue();
    }

    private enum Direction {
        DOWN,
        UP,
    }

    @Test
    public void testSwipeUp_whenBouncerInitiallyShowing_reduceHeightWithExclusionRects() {
        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
@@ -278,69 +272,11 @@ 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);

        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)).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());
    }

    /**
     * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount.
     * Makes sure swiping down doesn't change the expansion amount.
     */
    @Test
    @DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
    public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion() {
    public void testSwipeDown_doesNotSetExpansion() {
        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
@@ -401,34 +337,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {

        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();

        verifyScroll(.3f, Direction.UP, false, gestureListener);

        // Ensure that subsequent gestures are treated as expanding even if the bouncer state
        // changes.
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
        verifyScroll(.7f, Direction.UP, false, gestureListener);
    }

    /**
     * Makes sure the expansion amount is proportional to scroll.
     */
    @Test
    public void testSwipeDown_setsCorrectExpansionAmount() {
        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();

        verifyScroll(.3f, Direction.DOWN, true, gestureListener);

        // Ensure that subsequent gestures are treated as collapsing even if the bouncer state
        // changes.
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
        verifyScroll(.7f, Direction.DOWN, true, gestureListener);
        verifyScroll(.3f, gestureListener);
        verifyScroll(.7f, gestureListener);
    }

    /**
@@ -493,25 +403,24 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        verify(mCentralSurfaces, never()).awakenDreams();
    }

    private void verifyScroll(float percent, Direction direction,
            boolean isBouncerInitiallyShowing, GestureDetector.OnGestureListener gestureListener) {
    private void verifyScroll(float percent,
            OnGestureListener gestureListener) {
        final float distanceY = SCREEN_HEIGHT_PX * percent;

        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, direction == Direction.UP ? SCREEN_HEIGHT_PX : 0, 0);
                0, SCREEN_HEIGHT_PX, 0);
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
                0, SCREEN_HEIGHT_PX - distanceY, 0);

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

        // Ensure only called once
        verify(mScrimController).expand(any());

        final float expansion = isBouncerInitiallyShowing ? percent : 1 - percent;
        final float dragDownAmount = event2.getY() - event1.getY();
        final float expansion = 1 - percent;

        // Ensure correct expansion passed in.
        ShadeExpansionChangeEvent event =
@@ -529,7 +438,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        final float expansion = 1 - swipeUpPercentage;
        // The upward velocity is ignored.
        final float velocityY = -1;
        swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
        swipeToPosition(swipeUpPercentage, velocityY);

        verify(mValueAnimatorCreator).create(eq(expansion),
                eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
@@ -552,7 +461,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        final float expansion = 1 - swipeUpPercentage;
        // The downward velocity is ignored.
        final float velocityY = 1;
        swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
        swipeToPosition(swipeUpPercentage, velocityY);

        verify(mValueAnimatorCreator).create(eq(expansion),
                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
@@ -572,57 +481,6 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
    }

    /**
     * Tests that ending a downward swipe above the set threshold will continue the expansion,
     * but will not trigger logging of the DREAM_SWIPED event.
     */
    @Test
    public void testSwipeDownPositionAboveThreshold_expandsBouncer_doesNotLog() {
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);

        final float swipeDownPercentage = .3f;
        // The downward velocity is ignored.
        final float velocityY = 1;
        swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);

        verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
        verify(mValueAnimator, never()).addListener(any());

        verify(mFlingAnimationUtils).apply(eq(mValueAnimator),
                eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
        verify(mValueAnimator).start();
        verify(mUiEventLogger, never()).log(any());
    }

    /**
     * Tests that swiping down with a speed above the set threshold leads to bouncer collapsing
     * down.
     */
    @Test
    public void testSwipeDownVelocityAboveMin_collapsesBouncer() {
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0);

        // The ending position above the set threshold is ignored.
        final float swipeDownPercentage = .3f;
        final float velocityY = 1;
        swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);

        verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
                eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
        verify(mValueAnimator, never()).addListener(any());

        verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator),
                eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_HIDDEN),
                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
        verify(mValueAnimator).start();
        verify(mUiEventLogger, never()).log(any());
    }

    /**
     * Tests that swiping up with a speed above the set threshold will continue the expansion.
     */
@@ -634,7 +492,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        final float swipeUpPercentage = .3f;
        final float expansion = 1 - swipeUpPercentage;
        final float velocityY = -1;
        swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
        swipeToPosition(swipeUpPercentage, velocityY);

        verify(mValueAnimatorCreator).create(eq(expansion),
                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
@@ -654,26 +512,6 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
    }

    /**
     * Ensures {@link CentralSurfaces}
     */
    @Test
    public void testInformBouncerShowingOnExpand() {
        swipeToPosition(1f, Direction.UP, 0);
    }

    /**
     * Ensures {@link CentralSurfaces}
     */
    @Test
    public void testInformBouncerHidingOnCollapse() {
        // Must swipe up to set initial state.
        swipeToPosition(1f, Direction.UP, 0);
        Mockito.clearInvocations(mCentralSurfaces);

        swipeToPosition(0f, Direction.DOWN, 0);
    }

    @Test
    public void testTouchSessionOnRemovedCalledTwice() {
        mTouchHandler.onSessionStart(mTouchSession);
@@ -684,7 +522,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        onRemovedCallbackCaptor.getValue().onRemoved();
    }

    private void swipeToPosition(float percent, Direction direction, float velocityY) {
    private void swipeToPosition(float percent, float velocityY) {
        Mockito.clearInvocations(mTouchSession);
        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
@@ -699,12 +537,12 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        final float distanceY = SCREEN_HEIGHT_PX * percent;

        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, direction == Direction.UP ? SCREEN_HEIGHT_PX : 0, 0);
                0, SCREEN_HEIGHT_PX, 0);
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
                0, SCREEN_HEIGHT_PX - distanceY, 0);

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

        final MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
+291 −77

File changed.

Preview size limit exceeded, changes collapsed.

+18 −38
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.internal.logging.UiEvent;
@@ -94,13 +95,11 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
    private Boolean mCapture;
    private Boolean mExpanded;

    private boolean mBouncerInitiallyShowing;

    private TouchSession mTouchSession;

    private ValueAnimatorCreator mValueAnimatorCreator;
    private final ValueAnimatorCreator mValueAnimatorCreator;

    private VelocityTrackerFactory mVelocityTrackerFactory;
    private final VelocityTrackerFactory mVelocityTrackerFactory;

    private final UiEventLogger mUiEventLogger;

@@ -118,17 +117,12 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
    private final GestureDetector.OnGestureListener mOnGestureListener =
            new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                public boolean onScroll(MotionEvent e1, @NonNull MotionEvent e2, float distanceX,
                        float distanceY) {
                    if (mCapture == null) {
                        mBouncerInitiallyShowing = mCentralSurfaces
                                .map(CentralSurfaces::isBouncerShowing)
                                .orElse(false);

                        if (Flags.dreamOverlayBouncerSwipeDirectionFiltering()) {
                            mCapture = Math.abs(distanceY) > Math.abs(distanceX)
                                    && ((distanceY < 0 && mBouncerInitiallyShowing)
                                    || (distanceY > 0 && !mBouncerInitiallyShowing));
                                    && distanceY > 0;
                        } else {
                            // If the user scrolling favors a vertical direction, begin capturing
                            // scrolls.
@@ -146,13 +140,8 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
                        return false;
                    }

                    // Don't set expansion for downward scroll when the bouncer is hidden.
                    if (!mBouncerInitiallyShowing && (e1.getY() < e2.getY())) {
                        return true;
                    }

                    // Don't set expansion for upward scroll when the bouncer is shown.
                    if (mBouncerInitiallyShowing && (e1.getY() > e2.getY())) {
                    // Don't set expansion for downward scroll.
                    if (e1.getY() < e2.getY()) {
                        return true;
                    }

@@ -176,8 +165,7 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
                    final float dragDownAmount = e2.getY() - e1.getY();
                    final float screenTravelPercentage = Math.abs(e1.getY() - e2.getY())
                            / mTouchSession.getBounds().height();
                    setPanelExpansion(mBouncerInitiallyShowing
                            ? screenTravelPercentage : 1 - screenTravelPercentage);
                    setPanelExpansion(1 - screenTravelPercentage);
                    return true;
                }
            };
@@ -247,17 +235,13 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
    public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
        final int width = bounds.width();
        final int height = bounds.height();
        final float minBouncerHeight = height * mMinBouncerZoneScreenPercentage;
        final int minAllowableBottom = Math.round(height * (1 - mMinBouncerZoneScreenPercentage));

        final boolean isBouncerShowing =
                mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false);
        final Rect normalRegion = isBouncerShowing
                ? new Rect(0, 0, width, Math.round(height * mBouncerZoneScreenPercentage))
                : new Rect(0, Math.round(height * (1 - mBouncerZoneScreenPercentage)),
        final Rect normalRegion = new Rect(0,
                Math.round(height * (1 - mBouncerZoneScreenPercentage)),
                width, height);

        if (!isBouncerShowing && exclusionRect != null) {
        if (exclusionRect != null) {
            int lowestBottom = Math.min(Math.max(0, exclusionRect.bottom), minAllowableBottom);
            normalRegion.top = Math.max(normalRegion.top, lowestBottom);
        }
@@ -322,8 +306,7 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
                        : KeyguardBouncerConstants.EXPANSION_HIDDEN;

                // Log the swiping up to show Bouncer event.
                if (!mBouncerInitiallyShowing
                        && expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
                if (expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
                    mUiEventLogger.log(DreamEvent.DREAM_SWIPED);
                }

@@ -335,17 +318,15 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
        }
    }

    private ValueAnimator createExpansionAnimator(float targetExpansion, float expansionHeight) {
    private ValueAnimator createExpansionAnimator(float targetExpansion) {
        final ValueAnimator animator =
                mValueAnimatorCreator.create(mCurrentExpansion, targetExpansion);
        animator.addUpdateListener(
                animation -> {
                    float expansionFraction = (float) animation.getAnimatedValue();
                    float dragDownAmount = expansionFraction * expansionHeight;
                    setPanelExpansion(expansionFraction);
                });
        if (!mBouncerInitiallyShowing
                && targetExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
        if (targetExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
            animator.addListener(
                    new AnimatorListenerAdapter() {
                        @Override
@@ -381,8 +362,7 @@ public class BouncerSwipeTouchHandler implements TouchHandler {
        final float viewHeight = mTouchSession.getBounds().height();
        final float currentHeight = viewHeight * mCurrentExpansion;
        final float targetHeight = viewHeight * expansion;
        final float expansionHeight = targetHeight - currentHeight;
        final ValueAnimator animator = createExpansionAnimator(expansion, expansionHeight);
        final ValueAnimator animator = createExpansionAnimator(expansion);
        if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
            // Hides the bouncer, i.e., fully expands the space above the bouncer.
            mFlingAnimationUtilsClosing.apply(animator, currentHeight, targetHeight, velocity,
+117 −16

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -226,7 +226,7 @@ constructor(
    val ambientIndicationVisible: Flow<Boolean> = repository.ambientIndicationVisible.asStateFlow()

    /** Whether the primary bouncer is showing or not. */
    val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
    @JvmField val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow

    /** Whether the alternate bouncer is showing or not. */
    val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
Loading