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

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

Merge "Reland "Route dream touch handling to scene container"" into main

parents a01198b7 877f8e0e
Loading
Loading
Loading
Loading
+64 −3
Original line number Original line Diff line number Diff line
@@ -20,7 +20,9 @@ import static com.google.common.truth.Truth.assertThat;


import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;


import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;


@@ -29,11 +31,12 @@ import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.VelocityTracker;


import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;


import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLogger;
@@ -42,9 +45,12 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.ambient.touch.scrim.ScrimController;
import com.android.systemui.ambient.touch.scrim.ScrimController;
import com.android.systemui.ambient.touch.scrim.ScrimManager;
import com.android.systemui.ambient.touch.scrim.ScrimManager;
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel;
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel;
import com.android.systemui.flags.SceneContainerFlagParameterizationKt;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.ui.view.WindowRootView;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -58,10 +64,14 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;


import java.util.List;
import java.util.Optional;
import java.util.Optional;


import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;

@SmallTest
@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWith(ParameterizedAndroidJunit4.class)
@EnableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
@EnableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
@DisableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN)
@DisableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN)
public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
@@ -114,6 +124,11 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
    @Mock
    @Mock
    KeyguardInteractor mKeyguardInteractor;
    KeyguardInteractor mKeyguardInteractor;


    @Mock
    WindowRootView mWindowRootView;

    private SceneInteractor mSceneInteractor;

    private static final float TOUCH_REGION = .3f;
    private static final float TOUCH_REGION = .3f;
    private static final float MIN_BOUNCER_HEIGHT = .05f;
    private static final float MIN_BOUNCER_HEIGHT = .05f;


@@ -124,9 +139,21 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
            /* flags= */ 0
            /* flags= */ 0
    );
    );


    @Parameters(name = "{0}")
    public static List<FlagsParameterization> getParams() {
        return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag();
    }

    public BouncerFullscreenSwipeTouchHandlerTest(FlagsParameterization flags) {
        super();
        mSetFlagsRule.setFlagsParameterization(flags);
    }

    @Before
    @Before
    public void setup() {
    public void setup() {
        mKosmos = new KosmosJavaAdapter(this);
        mKosmos = new KosmosJavaAdapter(this);
        mSceneInteractor = spy(mKosmos.getSceneInteractor());

        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
        mTouchHandler = new BouncerSwipeTouchHandler(
        mTouchHandler = new BouncerSwipeTouchHandler(
                mKosmos.getTestScope(),
                mKosmos.getTestScope(),
@@ -142,7 +169,9 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
                MIN_BOUNCER_HEIGHT,
                MIN_BOUNCER_HEIGHT,
                mUiEventLogger,
                mUiEventLogger,
                mActivityStarter,
                mActivityStarter,
                mKeyguardInteractor);
                mKeyguardInteractor,
                mSceneInteractor,
                Optional.of(() -> mWindowRootView));


        when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
        when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
        when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
        when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
@@ -152,6 +181,38 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
        when(mKeyguardInteractor.isKeyguardDismissible()).thenReturn(MutableStateFlow(false));
        when(mKeyguardInteractor.isKeyguardDismissible()).thenReturn(MutableStateFlow(false));
    }
    }


    /**
     * Makes sure that touches go to the scene container when the flag is on.
     */
    @Test
    @EnableFlags(Flags.FLAG_SCENE_CONTAINER)
    public void testSwipeUp_sendsTouchesToWindowRootView() {
        mTouchHandler.onGlanceableTouchAvailable(true);
        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());

        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();

        final int screenHeight = 100;
        final float distanceY = screenHeight * 0.42f;

        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, screenHeight, 0);
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, screenHeight - distanceY, 0);

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

        // Ensure only called once
        verify(mSceneInteractor).onRemoteUserInputStarted(any());
        verify(mWindowRootView).dispatchTouchEvent(event1);
        verify(mWindowRootView).dispatchTouchEvent(event2);
    }

    /**
    /**
     * Ensures expansion does not happen for full vertical swipes when touch is not available.
     * Ensures expansion does not happen for full vertical swipes when touch is not available.
     */
     */
+65 −3
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;
@@ -37,12 +38,12 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.view.GestureDetector;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.VelocityTracker;


import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;


import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLogger;
@@ -52,9 +53,12 @@ import com.android.systemui.ambient.touch.scrim.ScrimController;
import com.android.systemui.ambient.touch.scrim.ScrimManager;
import com.android.systemui.ambient.touch.scrim.ScrimManager;
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel;
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel;
import com.android.systemui.flags.SceneContainerFlagParameterizationKt;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.ui.view.WindowRootView;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -70,10 +74,14 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;


import java.util.List;
import java.util.Optional;
import java.util.Optional;


import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;

@SmallTest
@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWith(ParameterizedAndroidJunit4.class)
@DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
@DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
    private KosmosJavaAdapter mKosmos;
    private KosmosJavaAdapter mKosmos;
@@ -121,6 +129,9 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
    @Mock
    @Mock
    Region mRegion;
    Region mRegion;


    @Mock
    WindowRootView mWindowRootView;

    @Mock
    @Mock
    CommunalViewModel mCommunalViewModel;
    CommunalViewModel mCommunalViewModel;


@@ -130,6 +141,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
    @Captor
    @Captor
    ArgumentCaptor<Rect> mRectCaptor;
    ArgumentCaptor<Rect> mRectCaptor;


    private SceneInteractor mSceneInteractor;

    private static final float TOUCH_REGION = .3f;
    private static final float TOUCH_REGION = .3f;
    private static final int SCREEN_WIDTH_PX = 1024;
    private static final int SCREEN_WIDTH_PX = 1024;
    private static final int SCREEN_HEIGHT_PX = 100;
    private static final int SCREEN_HEIGHT_PX = 100;
@@ -142,9 +155,21 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
            /* flags= */ 0
            /* flags= */ 0
    );
    );


    @Parameters(name = "{0}")
    public static List<FlagsParameterization> getParams() {
        return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag();
    }

    public BouncerSwipeTouchHandlerTest(FlagsParameterization flags) {
        super();
        mSetFlagsRule.setFlagsParameterization(flags);
    }

    @Before
    @Before
    public void setup() {
    public void setup() {
        mKosmos = new KosmosJavaAdapter(this);
        mKosmos = new KosmosJavaAdapter(this);
        mSceneInteractor = spy(mKosmos.getSceneInteractor());

        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
        mTouchHandler = new BouncerSwipeTouchHandler(
        mTouchHandler = new BouncerSwipeTouchHandler(
                mKosmos.getTestScope(),
                mKosmos.getTestScope(),
@@ -160,7 +185,10 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
                MIN_BOUNCER_HEIGHT,
                MIN_BOUNCER_HEIGHT,
                mUiEventLogger,
                mUiEventLogger,
                mActivityStarter,
                mActivityStarter,
                mKeyguardInteractor);
                mKeyguardInteractor,
                mSceneInteractor,
                Optional.of(() -> mWindowRootView)
        );


        when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
        when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
        when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
        when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
@@ -367,6 +395,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
     * Makes sure the expansion amount is proportional to (1 - scroll).
     * Makes sure the expansion amount is proportional to (1 - scroll).
     */
     */
    @Test
    @Test
    @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
    public void testSwipeUp_setsCorrectExpansionAmount() {
    public void testSwipeUp_setsCorrectExpansionAmount() {
        mTouchHandler.onSessionStart(mTouchSession);
        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
@@ -379,6 +408,36 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
        verifyScroll(.7f, gestureListener);
        verifyScroll(.7f, gestureListener);
    }
    }


    /**
     * Makes sure that touches go to the scene container when the flag is on.
     */
    @Test
    @EnableFlags(Flags.FLAG_SCENE_CONTAINER)
    public void testSwipeUp_sendsTouchesToWindowRootView() {
        mTouchHandler.onSessionStart(mTouchSession);
        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());

        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();

        final float distanceY = SCREEN_HEIGHT_PX * 0.42f;

        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, SCREEN_HEIGHT_PX, 0);
        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
                0, SCREEN_HEIGHT_PX - distanceY, 0);

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

        // Ensure only called once
        verify(mSceneInteractor).onRemoteUserInputStarted(any());
        verify(mWindowRootView).dispatchTouchEvent(event1);
        verify(mWindowRootView).dispatchTouchEvent(event2);
    }

    /**
    /**
     * Verifies that swiping up when the lock pattern is not secure dismissed dream and consumes
     * Verifies that swiping up when the lock pattern is not secure dismissed dream and consumes
     * the gesture.
     * the gesture.
@@ -476,6 +535,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
     * Tests that ending an upward swipe before the set threshold leads to bouncer collapsing down.
     * Tests that ending an upward swipe before the set threshold leads to bouncer collapsing down.
     */
     */
    @Test
    @Test
    @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
    public void testSwipeUpPositionBelowThreshold_collapsesBouncer() {
    public void testSwipeUpPositionBelowThreshold_collapsesBouncer() {
        final float swipeUpPercentage = .3f;
        final float swipeUpPercentage = .3f;
        final float expansion = 1 - swipeUpPercentage;
        final float expansion = 1 - swipeUpPercentage;
@@ -499,6 +559,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
     * Tests that ending an upward swipe above the set threshold will continue the expansion.
     * Tests that ending an upward swipe above the set threshold will continue the expansion.
     */
     */
    @Test
    @Test
    @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
    public void testSwipeUpPositionAboveThreshold_expandsBouncer() {
    public void testSwipeUpPositionAboveThreshold_expandsBouncer() {
        final float swipeUpPercentage = .7f;
        final float swipeUpPercentage = .7f;
        final float expansion = 1 - swipeUpPercentage;
        final float expansion = 1 - swipeUpPercentage;
@@ -528,6 +589,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
     * Tests that swiping up with a speed above the set threshold will continue the expansion.
     * Tests that swiping up with a speed above the set threshold will continue the expansion.
     */
     */
    @Test
    @Test
    @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
    public void testSwipeUpVelocityAboveMin_expandsBouncer() {
    public void testSwipeUpVelocityAboveMin_expandsBouncer() {
        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0);
        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0);


+80 −10
Original line number Original line Diff line number Diff line
@@ -18,9 +18,9 @@ package com.android.systemui.ambient.touch
import android.app.DreamManager
import android.app.DreamManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.view.GestureDetector
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.MotionEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
@@ -28,14 +28,20 @@ import com.android.systemui.ambient.touch.TouchHandler.TouchSession
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.data.repository.sceneContainerRepository
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeViewController
import com.android.systemui.shade.ShadeViewController
import com.android.systemui.shared.system.InputChannelCompat
import com.android.systemui.shared.system.InputChannelCompat
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
import com.google.common.truth.Truth
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import java.util.Optional
import java.util.Optional
import javax.inject.Provider
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
@@ -47,22 +53,29 @@ import org.mockito.kotlin.never
import org.mockito.kotlin.times
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.mockito.kotlin.whenever
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters


@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(ParameterizedAndroidJunit4::class)
class ShadeTouchHandlerTest : SysuiTestCase() {
class ShadeTouchHandlerTest(flags: FlagsParameterization) : SysuiTestCase() {
    private var kosmos = testKosmos()
    private var kosmos = testKosmos()
    private var mCentralSurfaces = mock<CentralSurfaces>()
    private var mCentralSurfaces = mock<CentralSurfaces>()
    private var mShadeViewController = mock<ShadeViewController>()
    private var mShadeViewController = mock<ShadeViewController>()
    private var mDreamManager = mock<DreamManager>()
    private var mDreamManager = mock<DreamManager>()
    private var mTouchSession = mock<TouchSession>()
    private var mTouchSession = mock<TouchSession>()
    private var communalViewModel = mock<CommunalViewModel>()
    private var communalViewModel = mock<CommunalViewModel>()
    private var windowRootView = mock<WindowRootView>()


    private lateinit var mTouchHandler: ShadeTouchHandler
    private lateinit var mTouchHandler: ShadeTouchHandler


    private var mGestureListenerCaptor = argumentCaptor<GestureDetector.OnGestureListener>()
    private var mGestureListenerCaptor = argumentCaptor<GestureDetector.OnGestureListener>()
    private var mInputListenerCaptor = argumentCaptor<InputChannelCompat.InputEventListener>()
    private var mInputListenerCaptor = argumentCaptor<InputChannelCompat.InputEventListener>()


    init {
        mSetFlagsRule.setFlagsParameterization(flags)
    }

    @Before
    @Before
    fun setup() {
    fun setup() {
        mTouchHandler =
        mTouchHandler =
@@ -73,7 +86,9 @@ class ShadeTouchHandlerTest : SysuiTestCase() {
                mDreamManager,
                mDreamManager,
                communalViewModel,
                communalViewModel,
                kosmos.communalSettingsInteractor,
                kosmos.communalSettingsInteractor,
                TOUCH_HEIGHT
                kosmos.sceneInteractor,
                Optional.of(Provider<WindowRootView> { windowRootView }),
                TOUCH_HEIGHT,
            )
            )
    }
    }


@@ -97,7 +112,7 @@ class ShadeTouchHandlerTest : SysuiTestCase() {


    // Verifies that a swipe down forwards captured touches to central surfaces for handling.
    // Verifies that a swipe down forwards captured touches to central surfaces for handling.
    @Test
    @Test
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX, Flags.FLAG_SCENE_CONTAINER)
    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
    fun testSwipeDown_communalEnabled_sentToCentralSurfaces() {
    fun testSwipeDown_communalEnabled_sentToCentralSurfaces() {
        kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
        kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
@@ -110,7 +125,11 @@ class ShadeTouchHandlerTest : SysuiTestCase() {


    // Verifies that a swipe down forwards captured touches to the shade view for handling.
    // Verifies that a swipe down forwards captured touches to the shade view for handling.
    @Test
    @Test
    @DisableFlags(Flags.FLAG_COMMUNAL_HUB, Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    @DisableFlags(
        Flags.FLAG_COMMUNAL_HUB,
        Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX,
        Flags.FLAG_SCENE_CONTAINER,
    )
    fun testSwipeDown_communalDisabled_sentToShadeView() {
    fun testSwipeDown_communalDisabled_sentToShadeView() {
        swipe(Direction.DOWN)
        swipe(Direction.DOWN)


@@ -121,7 +140,7 @@ class ShadeTouchHandlerTest : SysuiTestCase() {
    // Verifies that a swipe down while dreaming forwards captured touches to the shade view for
    // Verifies that a swipe down while dreaming forwards captured touches to the shade view for
    // handling.
    // handling.
    @Test
    @Test
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX, Flags.FLAG_SCENE_CONTAINER)
    fun testSwipeDown_dreaming_sentToShadeView() {
    fun testSwipeDown_dreaming_sentToShadeView() {
        whenever(mDreamManager.isDreaming).thenReturn(true)
        whenever(mDreamManager.isDreaming).thenReturn(true)
        swipe(Direction.DOWN)
        swipe(Direction.DOWN)
@@ -130,9 +149,39 @@ class ShadeTouchHandlerTest : SysuiTestCase() {
        verify(mShadeViewController, times(2)).handleExternalTouch(any())
        verify(mShadeViewController, times(2)).handleExternalTouch(any())
    }
    }


    // Verifies that a swipe up is not forwarded to central surfaces.
    // Verifies that a swipe down forwards captured touches to the window root view for handling.
    @Test
    @EnableFlags(
        Flags.FLAG_COMMUNAL_HUB,
        Flags.FLAG_SCENE_CONTAINER,
        Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX,
    )
    fun testSwipeDown_sceneContainerEnabled_sentToWindowRootView() {
        mTouchHandler.onGlanceableTouchAvailable(true)

        swipe(Direction.DOWN)

        // Both motion events are sent for central surfaces to process.
        assertThat(kosmos.sceneContainerRepository.isRemoteUserInputOngoing.value).isTrue()
        verify(windowRootView, times(2)).dispatchTouchEvent(any())
    }

    // Verifies that a swipe down while dreaming forwards captured touches to the window root view
    // for handling.
    @Test
    @Test
    @EnableFlags(Flags.FLAG_SCENE_CONTAINER)
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    fun testSwipeDown_sceneContainerEnabledFullscreenSwipeDisabled_sentToWindowRootView() {
        swipe(Direction.DOWN)

        // Both motion events are sent for the shade view to process.
        assertThat(kosmos.sceneContainerRepository.isRemoteUserInputOngoing.value).isTrue()
        verify(windowRootView, times(2)).dispatchTouchEvent(any())
    }

    // Verifies that a swipe up is not forwarded to central surfaces.
    @Test
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX, Flags.FLAG_SCENE_CONTAINER)
    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
    fun testSwipeUp_communalEnabled_touchesNotSent() {
    fun testSwipeUp_communalEnabled_touchesNotSent() {
        kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
        kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
@@ -146,7 +195,11 @@ class ShadeTouchHandlerTest : SysuiTestCase() {


    // Verifies that a swipe up is not forwarded to the shade view.
    // Verifies that a swipe up is not forwarded to the shade view.
    @Test
    @Test
    @DisableFlags(Flags.FLAG_COMMUNAL_HUB, Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    @DisableFlags(
        Flags.FLAG_COMMUNAL_HUB,
        Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX,
        Flags.FLAG_SCENE_CONTAINER,
    )
    fun testSwipeUp_communalDisabled_touchesNotSent() {
    fun testSwipeUp_communalDisabled_touchesNotSent() {
        swipe(Direction.UP)
        swipe(Direction.UP)


@@ -155,6 +208,17 @@ class ShadeTouchHandlerTest : SysuiTestCase() {
        verify(mShadeViewController, never()).handleExternalTouch(any())
        verify(mShadeViewController, never()).handleExternalTouch(any())
    }
    }


    // Verifies that a swipe up is not forwarded to the window root view.
    @Test
    @EnableFlags(Flags.FLAG_COMMUNAL_HUB, Flags.FLAG_SCENE_CONTAINER)
    fun testSwipeUp_sceneContainerEnabled_touchesNotSent() {
        swipe(Direction.UP)

        // Motion events are not sent for window root view to process as the swipe is going in the
        // wrong direction.
        verify(windowRootView, never()).dispatchTouchEvent(any())
    }

    @Test
    @Test
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
    fun testCancelMotionEvent_popsTouchSession() {
    fun testCancelMotionEvent_popsTouchSession() {
@@ -243,10 +307,16 @@ class ShadeTouchHandlerTest : SysuiTestCase() {


    private enum class Direction {
    private enum class Direction {
        DOWN,
        DOWN,
        UP
        UP,
    }
    }


    companion object {
    companion object {
        private const val TOUCH_HEIGHT = 20
        private const val TOUCH_HEIGHT = 20

        @JvmStatic
        @Parameters(name = "{0}")
        fun getParams(): List<FlagsParameterization> {
            return FlagsParameterization.allCombinationsOf().andSceneContainer()
        }
    }
    }
}
}
+35 −15
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.view.InputEvent
import android.view.MotionEvent
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.VelocityTracker
import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEventLogger
import com.android.internal.logging.UiEventLogger
import com.android.systemui.Flags
import com.android.systemui.Flags
@@ -38,6 +39,9 @@ import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -45,12 +49,12 @@ import com.android.wm.shell.animation.FlingAnimationUtils
import java.util.Optional
import java.util.Optional
import javax.inject.Inject
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Named
import javax.inject.Provider
import kotlin.math.abs
import kotlin.math.abs
import kotlin.math.hypot
import kotlin.math.hypot
import kotlin.math.max
import kotlin.math.max
import kotlin.math.min
import kotlin.math.min
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import com.android.app.tracing.coroutines.launchTraced as launch


/** Monitor for tracking touches on the DreamOverlay to bring up the bouncer. */
/** Monitor for tracking touches on the DreamOverlay to bring up the bouncer. */
class BouncerSwipeTouchHandler
class BouncerSwipeTouchHandler
@@ -74,6 +78,8 @@ constructor(
    private val uiEventLogger: UiEventLogger,
    private val uiEventLogger: UiEventLogger,
    private val activityStarter: ActivityStarter,
    private val activityStarter: ActivityStarter,
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardInteractor: KeyguardInteractor,
    private val sceneInteractor: SceneInteractor,
    private val windowRootViewProvider: Optional<Provider<WindowRootView>>,
) : TouchHandler {
) : TouchHandler {
    /** An interface for creating ValueAnimators. */
    /** An interface for creating ValueAnimators. */
    interface ValueAnimatorCreator {
    interface ValueAnimatorCreator {
@@ -100,6 +106,8 @@ constructor(
            currentScrimController = controller
            currentScrimController = controller
        }
        }


    private val windowRootView by lazy { windowRootViewProvider.get().get() }

    /** Determines whether the touch handler should process touches in fullscreen swiping mode */
    /** Determines whether the touch handler should process touches in fullscreen swiping mode */
    private var touchAvailable = false
    private var touchAvailable = false


@@ -109,7 +117,7 @@ constructor(
                e1: MotionEvent?,
                e1: MotionEvent?,
                e2: MotionEvent,
                e2: MotionEvent,
                distanceX: Float,
                distanceX: Float,
                distanceY: Float
                distanceY: Float,
            ): Boolean {
            ): Boolean {
                if (capture == null) {
                if (capture == null) {
                    capture =
                    capture =
@@ -128,6 +136,11 @@ constructor(
                        expanded = false
                        expanded = false
                        // Since the user is dragging the bouncer up, set scrimmed to false.
                        // Since the user is dragging the bouncer up, set scrimmed to false.
                        currentScrimController?.show()
                        currentScrimController?.show()

                        if (SceneContainerFlag.isEnabled) {
                            sceneInteractor.onRemoteUserInputStarted("bouncer touch handler")
                            e1?.apply { windowRootView.dispatchTouchEvent(e1) }
                        }
                    }
                    }
                }
                }
                if (capture != true) {
                if (capture != true) {
@@ -152,22 +165,29 @@ constructor(
                            /* cancelAction= */ null,
                            /* cancelAction= */ null,
                            /* dismissShade= */ true,
                            /* dismissShade= */ true,
                            /* afterKeyguardGone= */ true,
                            /* afterKeyguardGone= */ true,
                            /* deferred= */ false
                            /* deferred= */ false,
                        )
                        )
                        return true
                        return true
                    }
                    }


                    if (SceneContainerFlag.isEnabled) {
                        windowRootView.dispatchTouchEvent(e2)
                    } else {
                        // For consistency, we adopt the expansion definition found in the
                        // For consistency, we adopt the expansion definition found in the
                        // PanelViewController. In this case, expansion refers to the view above the
                        // PanelViewController. In this case, expansion refers to the view above the
                    // bouncer. As that view's expansion shrinks, the bouncer appears. The bouncer
                        // bouncer. As that view's expansion shrinks, the bouncer appears. The
                    // is fully hidden at full expansion (1) and fully visible when fully collapsed
                        // bouncer
                        // is fully hidden at full expansion (1) and fully visible when fully
                        // collapsed
                        // (0).
                        // (0).
                        touchSession?.apply {
                        touchSession?.apply {
                            val screenTravelPercentage =
                            val screenTravelPercentage =
                            (abs((this@outer.y - e2.y).toDouble()) / getBounds().height()).toFloat()
                                (abs((this@outer.y - e2.y).toDouble()) / getBounds().height())
                                    .toFloat()
                            setPanelExpansion(1 - screenTravelPercentage)
                            setPanelExpansion(1 - screenTravelPercentage)
                        }
                        }
                    }
                    }
                }


                return true
                return true
            }
            }
@@ -194,7 +214,7 @@ constructor(
            ShadeExpansionChangeEvent(
            ShadeExpansionChangeEvent(
                /* fraction= */ currentExpansion,
                /* fraction= */ currentExpansion,
                /* expanded= */ expanded,
                /* expanded= */ expanded,
                /* tracking= */ true
                /* tracking= */ true,
            )
            )
        currentScrimController?.expand(event)
        currentScrimController?.expand(event)
    }
    }
@@ -347,7 +367,7 @@ constructor(
                    currentHeight,
                    currentHeight,
                    targetHeight,
                    targetHeight,
                    velocity,
                    velocity,
                    viewHeight
                    viewHeight,
                )
                )
            } else {
            } else {
                // Shows the bouncer, i.e., fully collapses the space above the bouncer.
                // Shows the bouncer, i.e., fully collapses the space above the bouncer.
@@ -356,7 +376,7 @@ constructor(
                    currentHeight,
                    currentHeight,
                    targetHeight,
                    targetHeight,
                    velocity,
                    velocity,
                    viewHeight
                    viewHeight,
                )
                )
            }
            }
            animator.start()
            animator.start()
+21 −4

File changed.

Preview size limit exceeded, changes collapsed.

Loading