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

Commit 48556f26 authored by William Xiao's avatar William Xiao Committed by Android (Google) Code Review
Browse files

Merge changes I92b9c220,I31a55ca1,I536a2e1e into main

* changes:
  Fix ShadeTouchHandler over the lock screen
  Use TouchMonitor for touch handling over hub
  Stop overlay touch handling when the bouncer or glanceable hub are visible over the dream
parents 2e086e36 86fa77ab
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,
+63 −38
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@ package com.android.systemui.ambient.touch;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.view.GestureDetector;
import android.view.MotionEvent;
@@ -28,7 +30,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.phone.CentralSurfaces;

@@ -36,6 +37,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -48,67 +50,90 @@ public class ShadeTouchHandlerTest extends SysuiTestCase {
    @Mock
    CentralSurfaces mCentralSurfaces;

    @Mock
    ShadeViewController mShadeViewController;

    @Mock
    TouchHandler.TouchSession mTouchSession;

    ShadeTouchHandler mTouchHandler;

    @Captor
    ArgumentCaptor<GestureDetector.OnGestureListener> mGestureListenerCaptor;
    @Captor
    ArgumentCaptor<InputChannelCompat.InputEventListener> mInputListenerCaptor;

    private static final int TOUCH_HEIGHT = 20;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mTouchHandler = new ShadeTouchHandler(Optional.of(mCentralSurfaces), mShadeViewController,
                TOUCH_HEIGHT);

        mTouchHandler = new ShadeTouchHandler(Optional.of(mCentralSurfaces), TOUCH_HEIGHT);
    }

    /**
     * Verify that touches aren't handled when the bouncer is showing.
     */
    // Verifies that a swipe down in the gesture region is captured by the shade touch handler.
    @Test
    public void testInactiveOnBouncer() {
        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
        mTouchHandler.onSessionStart(mTouchSession);
        verify(mTouchSession).pop();
    public void testSwipeDown_captured() {
        final boolean captured = swipe(Direction.DOWN);

        assertThat(captured).isTrue();
    }

    /**
     * Make sure {@link ShadeTouchHandler}
     */
    // Verifies that a swipe in the upward direction is not catpured.
    @Test
    public void testTouchPilferingOnScroll() {
        final MotionEvent motionEvent1 = Mockito.mock(MotionEvent.class);
        final MotionEvent motionEvent2 = Mockito.mock(MotionEvent.class);
    public void testSwipeUp_notCaptured() {
        final boolean captured = swipe(Direction.UP);

        final ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerArgumentCaptor =
                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
        // Motion events not captured as the swipe is going in the wrong direction.
        assertThat(captured).isFalse();
    }

        mTouchHandler.onSessionStart(mTouchSession);
        verify(mTouchSession).registerGestureListener(gestureListenerArgumentCaptor.capture());
    // Verifies that a swipe down forwards captured touches to the shade window for handling.
    @Test
    public void testSwipeDown_sentToShadeWindow() {
        swipe(Direction.DOWN);

        assertThat(gestureListenerArgumentCaptor.getValue()
                .onScroll(motionEvent1, motionEvent2, 1, 1))
                .isTrue();
        // Both motion events are sent for the shade window to process.
        verify(mCentralSurfaces, times(2)).handleExternalShadeWindowTouch(any());
    }

    /**
     * Ensure touches are propagated to the {@link ShadeViewController}.
     */
    // Verifies that a swipe down is not forwarded to the shade window.
    @Test
    public void testEventPropagation() {
        final MotionEvent motionEvent = Mockito.mock(MotionEvent.class);
    public void testSwipeUp_touchesNotSent() {
        swipe(Direction.UP);

        final ArgumentCaptor<InputChannelCompat.InputEventListener>
                inputEventListenerArgumentCaptor =
                    ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
        // Motion events are not sent for the shade window to process as the swipe is going in the
        // wrong direction.
        verify(mCentralSurfaces, never()).handleExternalShadeWindowTouch(any());
    }

    /**
     * Simulates a swipe in the given direction and returns true if the touch was intercepted by the
     * touch handler's gesture listener.
     * <p>
     * Swipe down starts from a Y coordinate of 0 and goes downward. Swipe up starts from the edge
     * of the gesture region, {@link #TOUCH_HEIGHT}, and goes upward to 0.
     */
    private boolean swipe(Direction direction) {
        Mockito.clearInvocations(mTouchSession);
        mTouchHandler.onSessionStart(mTouchSession);
        verify(mTouchSession).registerInputListener(inputEventListenerArgumentCaptor.capture());
        inputEventListenerArgumentCaptor.getValue().onInputEvent(motionEvent);
        verify(mShadeViewController).handleExternalTouch(motionEvent);

        verify(mTouchSession).registerGestureListener(mGestureListenerCaptor.capture());
        verify(mTouchSession).registerInputListener(mInputListenerCaptor.capture());

        final float startY = direction == Direction.UP ? TOUCH_HEIGHT : 0;
        final float endY = direction == Direction.UP ? 0 : TOUCH_HEIGHT;

        // Send touches to the input and gesture listener.
        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, startY, 0);
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, endY, 0);
        mInputListenerCaptor.getValue().onInputEvent(event1);
        mInputListenerCaptor.getValue().onInputEvent(event2);
        final boolean captured = mGestureListenerCaptor.getValue().onScroll(event1, event2, 0,
                startY - endY);

        return captured;
    }

    private enum Direction {
        DOWN, UP,
    }
}
Loading