diff options
9 files changed, 298 insertions, 39 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java index 58c3fec5b45e..bd33e52689c2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java @@ -20,7 +20,9 @@ import static com.google.common.truth.Truth.assertThat; import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyFloat; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,11 +31,12 @@ import android.content.pm.UserInfo; import android.graphics.Rect; import android.platform.test.annotations.DisableFlags; 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.MotionEvent; import android.view.VelocityTracker; -import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; 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.ScrimManager; 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.kosmos.KosmosJavaAdapter; 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.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.CentralSurfaces; @@ -58,10 +64,14 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.util.List; import java.util.Optional; +import platform.test.runner.parameterized.ParameterizedAndroidJunit4; +import platform.test.runner.parameterized.Parameters; + @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(ParameterizedAndroidJunit4.class) @EnableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) @DisableFlags(Flags.FLAG_COMMUNAL_BOUNCER_DO_NOT_MODIFY_PLUGIN_OPEN) public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase { @@ -114,6 +124,11 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase { @Mock KeyguardInteractor mKeyguardInteractor; + @Mock + WindowRootView mWindowRootView; + + private SceneInteractor mSceneInteractor; + private static final float TOUCH_REGION = .3f; private static final float MIN_BOUNCER_HEIGHT = .05f; @@ -124,9 +139,21 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase { /* flags= */ 0 ); + @Parameters(name = "{0}") + public static List<FlagsParameterization> getParams() { + return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag(); + } + + public BouncerFullscreenSwipeTouchHandlerTest(FlagsParameterization flags) { + super(); + mSetFlagsRule.setFlagsParameterization(flags); + } + @Before public void setup() { mKosmos = new KosmosJavaAdapter(this); + mSceneInteractor = spy(mKosmos.getSceneInteractor()); + MockitoAnnotations.initMocks(this); mTouchHandler = new BouncerSwipeTouchHandler( mKosmos.getTestScope(), @@ -142,7 +169,9 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase { MIN_BOUNCER_HEIGHT, mUiEventLogger, mActivityStarter, - mKeyguardInteractor); + mKeyguardInteractor, + mSceneInteractor, + Optional.of(() -> mWindowRootView)); when(mScrimManager.getCurrentController()).thenReturn(mScrimController); when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator); @@ -153,6 +182,38 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase { } /** + * 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. */ @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java index 95681671b545..494e0b4deef4 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -37,12 +38,12 @@ import android.graphics.Rect; import android.graphics.Region; import android.platform.test.annotations.DisableFlags; 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.MotionEvent; import android.view.VelocityTracker; -import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; 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.bouncer.shared.constants.KeyguardBouncerConstants; 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.kosmos.KosmosJavaAdapter; 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.shared.system.InputChannelCompat; import com.android.systemui.statusbar.NotificationShadeWindowController; @@ -70,10 +74,14 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.util.List; import java.util.Optional; +import platform.test.runner.parameterized.ParameterizedAndroidJunit4; +import platform.test.runner.parameterized.Parameters; + @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(ParameterizedAndroidJunit4.class) @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { private KosmosJavaAdapter mKosmos; @@ -122,6 +130,9 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { Region mRegion; @Mock + WindowRootView mWindowRootView; + + @Mock CommunalViewModel mCommunalViewModel; @Mock @@ -130,6 +141,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { @Captor ArgumentCaptor<Rect> mRectCaptor; + private SceneInteractor mSceneInteractor; + private static final float TOUCH_REGION = .3f; private static final int SCREEN_WIDTH_PX = 1024; private static final int SCREEN_HEIGHT_PX = 100; @@ -142,9 +155,21 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { /* flags= */ 0 ); + @Parameters(name = "{0}") + public static List<FlagsParameterization> getParams() { + return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag(); + } + + public BouncerSwipeTouchHandlerTest(FlagsParameterization flags) { + super(); + mSetFlagsRule.setFlagsParameterization(flags); + } + @Before public void setup() { mKosmos = new KosmosJavaAdapter(this); + mSceneInteractor = spy(mKosmos.getSceneInteractor()); + MockitoAnnotations.initMocks(this); mTouchHandler = new BouncerSwipeTouchHandler( mKosmos.getTestScope(), @@ -160,7 +185,10 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { MIN_BOUNCER_HEIGHT, mUiEventLogger, mActivityStarter, - mKeyguardInteractor); + mKeyguardInteractor, + mSceneInteractor, + Optional.of(() -> mWindowRootView) + ); when(mScrimManager.getCurrentController()).thenReturn(mScrimController); 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). */ @Test + @DisableFlags(Flags.FLAG_SCENE_CONTAINER) public void testSwipeUp_setsCorrectExpansionAmount() { mTouchHandler.onSessionStart(mTouchSession); ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor = @@ -380,6 +409,36 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { } /** + * 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 * 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. */ @Test + @DisableFlags(Flags.FLAG_SCENE_CONTAINER) public void testSwipeUpPositionBelowThreshold_collapsesBouncer() { final float swipeUpPercentage = .3f; 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. */ @Test + @DisableFlags(Flags.FLAG_SCENE_CONTAINER) public void testSwipeUpPositionAboveThreshold_expandsBouncer() { final float swipeUpPercentage = .7f; 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. */ @Test + @DisableFlags(Flags.FLAG_SCENE_CONTAINER) public void testSwipeUpVelocityAboveMin_expandsBouncer() { when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt index 38ea44976175..ad636cf613ad 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt @@ -18,9 +18,9 @@ package com.android.systemui.ambient.touch import android.app.DreamManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.FlagsParameterization import android.view.GestureDetector import android.view.MotionEvent -import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags 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.ui.viewmodel.CommunalViewModel 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.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.shared.system.InputChannelCompat import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.testKosmos import com.google.common.truth.Truth +import com.google.common.truth.Truth.assertThat import java.util.Optional +import javax.inject.Provider import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -47,22 +53,29 @@ import org.mockito.kotlin.never import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever +import platform.test.runner.parameterized.ParameterizedAndroidJunit4 +import platform.test.runner.parameterized.Parameters @SmallTest -@RunWith(AndroidJUnit4::class) -class ShadeTouchHandlerTest : SysuiTestCase() { +@RunWith(ParameterizedAndroidJunit4::class) +class ShadeTouchHandlerTest(flags: FlagsParameterization) : SysuiTestCase() { private var kosmos = testKosmos() private var mCentralSurfaces = mock<CentralSurfaces>() private var mShadeViewController = mock<ShadeViewController>() private var mDreamManager = mock<DreamManager>() private var mTouchSession = mock<TouchSession>() private var communalViewModel = mock<CommunalViewModel>() + private var windowRootView = mock<WindowRootView>() private lateinit var mTouchHandler: ShadeTouchHandler private var mGestureListenerCaptor = argumentCaptor<GestureDetector.OnGestureListener>() private var mInputListenerCaptor = argumentCaptor<InputChannelCompat.InputEventListener>() + init { + mSetFlagsRule.setFlagsParameterization(flags) + } + @Before fun setup() { mTouchHandler = @@ -73,7 +86,9 @@ class ShadeTouchHandlerTest : SysuiTestCase() { mDreamManager, communalViewModel, 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. @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) fun testSwipeDown_communalEnabled_sentToCentralSurfaces() { 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. @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() { 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 // handling. @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() { whenever(mDreamManager.isDreaming).thenReturn(true) swipe(Direction.DOWN) @@ -130,9 +149,34 @@ class ShadeTouchHandlerTest : SysuiTestCase() { 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) + fun testSwipeDown_sceneContainerEnabled_sentToWindowRootView() { + 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 + @EnableFlags(Flags.FLAG_SCENE_CONTAINER) @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) + fun testSwipeDown_dreaming_sentToWindowRootView() { + whenever(mDreamManager.isDreaming).thenReturn(true) + 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) fun testSwipeUp_communalEnabled_touchesNotSent() { kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true) @@ -146,7 +190,11 @@ class ShadeTouchHandlerTest : SysuiTestCase() { // Verifies that a swipe up is not forwarded to the shade view. @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() { swipe(Direction.UP) @@ -155,6 +203,17 @@ class ShadeTouchHandlerTest : SysuiTestCase() { 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 @DisableFlags(Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) fun testCancelMotionEvent_popsTouchSession() { @@ -243,10 +302,16 @@ class ShadeTouchHandlerTest : SysuiTestCase() { private enum class Direction { DOWN, - UP + UP, } companion object { private const val TOUCH_HEIGHT = 20 + + @JvmStatic + @Parameters(name = "{0}") + fun getParams(): List<FlagsParameterization> { + return FlagsParameterization.allCombinationsOf().andSceneContainer() + } } } diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt index fd06bb174ea3..a55f9ffd1c5a 100644 --- a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt @@ -38,6 +38,9 @@ import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor 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.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.phone.CentralSurfaces @@ -45,6 +48,7 @@ import com.android.wm.shell.animation.FlingAnimationUtils import java.util.Optional import javax.inject.Inject import javax.inject.Named +import javax.inject.Provider import kotlin.math.abs import kotlin.math.hypot import kotlin.math.max @@ -74,6 +78,8 @@ constructor( private val uiEventLogger: UiEventLogger, private val activityStarter: ActivityStarter, private val keyguardInteractor: KeyguardInteractor, + private val sceneInteractor: SceneInteractor, + private val windowRootViewProvider: Optional<Provider<WindowRootView>>, ) : TouchHandler { /** An interface for creating ValueAnimators. */ interface ValueAnimatorCreator { @@ -100,6 +106,8 @@ constructor( currentScrimController = controller } + private val windowRootView by lazy { windowRootViewProvider.get().get() } + /** Determines whether the touch handler should process touches in fullscreen swiping mode */ private var touchAvailable = false @@ -109,7 +117,7 @@ constructor( e1: MotionEvent?, e2: MotionEvent, distanceX: Float, - distanceY: Float + distanceY: Float, ): Boolean { if (capture == null) { capture = @@ -128,6 +136,11 @@ constructor( expanded = false // Since the user is dragging the bouncer up, set scrimmed to false. currentScrimController?.show() + + if (SceneContainerFlag.isEnabled) { + sceneInteractor.onRemoteUserInputStarted("bouncer touch handler") + e1?.apply { windowRootView.dispatchTouchEvent(e1) } + } } } if (capture != true) { @@ -152,20 +165,27 @@ constructor( /* cancelAction= */ null, /* dismissShade= */ true, /* afterKeyguardGone= */ true, - /* deferred= */ false + /* deferred= */ false, ) return true } - // For consistency, we adopt the expansion definition found in the - // PanelViewController. In this case, expansion refers to the view above the - // bouncer. As that view's expansion shrinks, the bouncer appears. The bouncer - // is fully hidden at full expansion (1) and fully visible when fully collapsed - // (0). - touchSession?.apply { - val screenTravelPercentage = - (abs((this@outer.y - e2.y).toDouble()) / getBounds().height()).toFloat() - setPanelExpansion(1 - screenTravelPercentage) + if (SceneContainerFlag.isEnabled) { + windowRootView.dispatchTouchEvent(e2) + } else { + // For consistency, we adopt the expansion definition found in the + // PanelViewController. In this case, expansion refers to the view above the + // bouncer. As that view's expansion shrinks, the bouncer appears. The + // bouncer + // is fully hidden at full expansion (1) and fully visible when fully + // collapsed + // (0). + touchSession?.apply { + val screenTravelPercentage = + (abs((this@outer.y - e2.y).toDouble()) / getBounds().height()) + .toFloat() + setPanelExpansion(1 - screenTravelPercentage) + } } } @@ -194,7 +214,7 @@ constructor( ShadeExpansionChangeEvent( /* fraction= */ currentExpansion, /* expanded= */ expanded, - /* tracking= */ true + /* tracking= */ true, ) currentScrimController?.expand(event) } @@ -347,7 +367,7 @@ constructor( currentHeight, targetHeight, velocity, - viewHeight + viewHeight, ) } else { // Shows the bouncer, i.e., fully collapses the space above the bouncer. @@ -356,7 +376,7 @@ constructor( currentHeight, targetHeight, velocity, - viewHeight + viewHeight, ) } animator.start() diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.kt index 9da9a3a98ef5..3cf94ba558fe 100644 --- a/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.kt @@ -27,11 +27,15 @@ import com.android.systemui.ambient.touch.TouchHandler.TouchSession import com.android.systemui.ambient.touch.dagger.ShadeModule import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor import com.android.systemui.communal.ui.viewmodel.CommunalViewModel +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.ShadeViewController import com.android.systemui.statusbar.phone.CentralSurfaces import java.util.Optional import javax.inject.Inject import javax.inject.Named +import javax.inject.Provider import kotlin.math.abs import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -49,8 +53,10 @@ constructor( private val dreamManager: DreamManager, private val communalViewModel: CommunalViewModel, private val communalSettingsInteractor: CommunalSettingsInteractor, + private val sceneInteractor: SceneInteractor, + private val windowRootViewProvider: Optional<Provider<WindowRootView>>, @param:Named(ShadeModule.NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT) - private val initiationHeight: Int + private val initiationHeight: Int, ) : TouchHandler { /** * Tracks whether or not we are capturing a given touch. Will be null before and after a touch. @@ -60,6 +66,8 @@ constructor( /** Determines whether the touch handler should process touches in fullscreen swiping mode */ private var touchAvailable = false + private val windowRootView by lazy { windowRootViewProvider.get().get() } + init { if (Flags.hubmodeFullscreenVerticalSwipeFix()) { scope.launch { @@ -100,7 +108,7 @@ constructor( e1: MotionEvent?, e2: MotionEvent, distanceX: Float, - distanceY: Float + distanceY: Float, ): Boolean { if (capture == null) { // Only capture swipes that are going downwards. @@ -110,6 +118,10 @@ constructor( if (Flags.hubmodeFullscreenVerticalSwipeFix()) touchAvailable else true if (capture == true) { + if (SceneContainerFlag.isEnabled) { + sceneInteractor.onRemoteUserInputStarted("shade touch handler") + } + // Send the initial touches over, as the input listener has already // processed these touches. e1?.apply { sendTouchEvent(this) } @@ -123,7 +135,7 @@ constructor( e1: MotionEvent?, e2: MotionEvent, velocityX: Float, - velocityY: Float + velocityY: Float, ): Boolean { return capture == true } @@ -132,6 +144,11 @@ constructor( } private fun sendTouchEvent(event: MotionEvent) { + if (SceneContainerFlag.isEnabled) { + windowRootView.dispatchTouchEvent(event) + return + } + if (communalSettingsInteractor.isCommunalFlagEnabled() && !dreamManager.isDreaming) { // Send touches to central surfaces only when on the glanceable hub while not dreaming. // While sending touches where while dreaming will open the shade, the shade diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java index bc2f35467312..1c781d608b04 100644 --- a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java +++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java @@ -22,8 +22,10 @@ import com.android.systemui.ambient.touch.ShadeTouchHandler; import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.res.R; +import com.android.systemui.scene.ui.view.WindowRootView; import dagger.Binds; +import dagger.BindsOptionalOf; import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; @@ -51,6 +53,13 @@ public abstract class ShadeModule { ShadeTouchHandler touchHandler); /** + * Window root view is used to send touches to the scene container. Declaring as optional as it + * may not be present on all SysUI variants. + */ + @BindsOptionalOf + abstract WindowRootView bindWindowRootView(); + + /** * Provides the height of the gesture area for notification swipe down. */ @Provides diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index 7a6ca0859a09..1ffbbd2a9f32 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -65,7 +65,6 @@ import com.android.systemui.dreams.dagger.DreamOverlayComponent; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.navigationbar.gestural.domain.GestureInteractor; import com.android.systemui.navigationbar.gestural.domain.TaskMatcher; -import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.util.concurrency.DelayableExecutor; @@ -503,10 +502,10 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamOverlayContainerViewController = dreamOverlayComponent.getDreamOverlayContainerViewController(); - if (!SceneContainerFlag.isEnabled()) { - mTouchMonitor = ambientTouchComponent.getTouchMonitor(); - mTouchMonitor.init(); - } + // Touch monitor are also used with SceneContainer. See individual touch handlers for + // handling of SceneContainer. + mTouchMonitor = ambientTouchComponent.getTouchMonitor(); + mTouchMonitor.init(); mStateController.setShouldShowComplications(shouldShowComplications()); diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java index 12984efb52c2..85fb90d32d98 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java @@ -30,8 +30,10 @@ import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarViewController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.DreamOverlayContainerView; import com.android.systemui.res.R; +import com.android.systemui.scene.ui.view.WindowRootView; import com.android.systemui.touch.TouchInsetManager; +import dagger.BindsOptionalOf; import dagger.Module; import dagger.Provides; @@ -54,6 +56,13 @@ public abstract class DreamOverlayModule { public static final String DREAM_IN_TRANSLATION_Y_DURATION = "dream_in_complications_translation_y_duration"; + /** + * Window root view is used to send touches to the scene container. Declaring as optional as it + * may not be present on all SysUI variants. + */ + @BindsOptionalOf + abstract WindowRootView bindWindowRootView(); + /** */ @Provides @DreamOverlayComponent.DreamOverlayScope diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java index 5ba780f9c99d..42a68771cdcf 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java @@ -31,6 +31,9 @@ import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor; import com.android.systemui.communal.domain.interactor.CommunalInteractor; import com.android.systemui.dreams.touch.dagger.CommunalTouchModule; +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.statusbar.phone.CentralSurfaces; import kotlinx.coroutines.Job; @@ -42,6 +45,7 @@ import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; +import javax.inject.Provider; /** {@link TouchHandler} responsible for handling touches to open communal hub. **/ public class CommunalTouchHandler implements TouchHandler { @@ -51,6 +55,8 @@ public class CommunalTouchHandler implements TouchHandler { private final CommunalInteractor mCommunalInteractor; private final ConfigurationInteractor mConfigurationInteractor; + private final SceneInteractor mSceneInteractor; + private final WindowRootView mWindowRootView; private Boolean mIsEnabled = false; private ArrayList<Job> mFlows = new ArrayList<>(); @@ -69,12 +75,16 @@ public class CommunalTouchHandler implements TouchHandler { @Named(CommunalTouchModule.COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth, CommunalInteractor communalInteractor, ConfigurationInteractor configurationInteractor, + SceneInteractor sceneInteractor, + Optional<Provider<WindowRootView>> windowRootViewProvider, Lifecycle lifecycle) { mInitiationWidth = initiationWidth; mCentralSurfaces = centralSurfaces; mLifecycle = lifecycle; mCommunalInteractor = communalInteractor; mConfigurationInteractor = configurationInteractor; + mSceneInteractor = sceneInteractor; + mWindowRootView = windowRootViewProvider.get().get(); mFlows.add(collectFlow( mLifecycle, @@ -125,8 +135,15 @@ public class CommunalTouchHandler implements TouchHandler { private void handleSessionStart(CentralSurfaces surfaces, TouchSession session) { // Notification shade window has its own logic to be visible if the hub is open, no need to // do anything here other than send touch events over. + if (SceneContainerFlag.isEnabled()) { + mSceneInteractor.onRemoteUserInputStarted("communal touch handler"); + } session.registerInputListener(ev -> { - surfaces.handleCommunalHubTouch((MotionEvent) ev); + if (SceneContainerFlag.isEnabled()) { + mWindowRootView.dispatchTouchEvent((MotionEvent) ev); + } else { + surfaces.handleCommunalHubTouch((MotionEvent) ev); + } if (ev != null && ((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) { var unused = session.pop(); } |