diff options
4 files changed, 126 insertions, 133 deletions
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java index 121577e438b0..78cd02fed9eb 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java @@ -345,6 +345,10 @@ public class QuickStepContract { || (sysuiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0) { return false; } + // Disable back gesture on the hub, but not when the shade is showing. + if ((sysuiStateFlags & SYSUI_STATE_COMMUNAL_HUB_SHOWING) != 0) { + return (sysuiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE) == 0; + } if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) { sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN; } diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt index 7fa9926ea920..2e67277d8327 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt @@ -108,7 +108,7 @@ constructor( fun dispatchTouchEvent( ev: MotionEvent?, - disallowInterceptConsumer: Consumer<Boolean>? + disallowInterceptConsumer: Consumer<Boolean>?, ): Boolean { disallowInterceptConsumer?.apply { consumers.add(this) } @@ -252,9 +252,7 @@ constructor( * * @throws RuntimeException if the view is already initialized */ - fun initView( - context: Context, - ): View { + fun initView(context: Context): View { return initView( ComposeView(context).apply { repeatWhenAttached { @@ -310,40 +308,26 @@ constructor( communalContainerView = containerView - val topEdgeSwipeRegionWidth = - containerView.resources.getDimensionPixelSize( - R.dimen.communal_top_edge_swipe_region_height - ) - val bottomEdgeSwipeRegionWidth = - containerView.resources.getDimensionPixelSize( - R.dimen.communal_bottom_edge_swipe_region_height - ) + if (!Flags.hubmodeFullscreenVerticalSwipeFix()) { + val topEdgeSwipeRegionWidth = + containerView.resources.getDimensionPixelSize( + R.dimen.communal_top_edge_swipe_region_height + ) + val bottomEdgeSwipeRegionWidth = + containerView.resources.getDimensionPixelSize( + R.dimen.communal_bottom_edge_swipe_region_height + ) - // BouncerSwipeTouchHandler has a larger gesture area than we want, set an exclusion area so - // the gesture area doesn't overlap with widgets. - // TODO(b/323035776): adjust gesture area for portrait mode - containerView.repeatWhenAttached { - // Run when the touch handling lifecycle is RESUMED, meaning the hub is visible and not - // occluded. - lifecycleRegistry.repeatOnLifecycle(Lifecycle.State.RESUMED) { - val ltr = containerView.layoutDirection == View.LAYOUT_DIRECTION_LTR - - val backGestureInset = - Rect( - 0, - 0, - if (ltr) 0 else containerView.right, - containerView.bottom, - ) - - containerView.systemGestureExclusionRects = - if (Flags.hubmodeFullscreenVerticalSwipeFix()) { - listOf( - // Disable back gestures on the left side of the screen, to avoid - // conflicting with scene transitions. - backGestureInset - ) - } else { + // BouncerSwipeTouchHandler has a larger gesture area than we want, set an exclusion + // area so + // the gesture area doesn't overlap with widgets. + // TODO(b/323035776): adjust gesture area for portrait mode + containerView.repeatWhenAttached { + // Run when the touch handling lifecycle is RESUMED, meaning the hub is visible and + // not + // occluded. + lifecycleRegistry.repeatOnLifecycle(Lifecycle.State.RESUMED) { + containerView.systemGestureExclusionRects = listOf( // Only allow swipe up to bouncer and swipe down to shade in the very // top/bottom to avoid conflicting with widgets in the hub grid. @@ -351,15 +335,13 @@ constructor( 0, topEdgeSwipeRegionWidth, containerView.right, - containerView.bottom - bottomEdgeSwipeRegionWidth - ), - // Disable back gestures on the left side of the screen, to avoid - // conflicting with scene transitions. - backGestureInset + containerView.bottom - bottomEdgeSwipeRegionWidth, + ) ) + + logger.d({ "Insets updated: $str1" }) { + str1 = containerView.systemGestureExclusionRects.toString() } - logger.d({ "Insets updated: $str1" }) { - str1 = containerView.systemGestureExclusionRects.toString() } } } @@ -372,7 +354,7 @@ constructor( containerView, anyOf( keyguardInteractor.primaryBouncerShowing, - keyguardInteractor.alternateBouncerShowing + keyguardInteractor.alternateBouncerShowing, ), { anyBouncerShowing = it @@ -380,12 +362,12 @@ constructor( logger.d({ "New value for anyBouncerShowing: $bool1" }) { bool1 = it } } updateTouchHandlingState() - } + }, ) collectFlow( containerView, keyguardTransitionInteractor.isFinishedIn(KeyguardState.LOCKSCREEN), - { onLockscreen = it } + { onLockscreen = it }, ) collectFlow( containerView, @@ -393,7 +375,7 @@ constructor( { hubShowing = it updateTouchHandlingState() - } + }, ) collectFlow( containerView, @@ -404,12 +386,12 @@ constructor( communalInteractor.editActivityShowing, keyguardTransitionInteractor.isInTransition( Edge.create(KeyguardState.GONE, KeyguardState.GLANCEABLE_HUB) - ) + ), ), { inEditModeTransition = it updateTouchHandlingState() - } + }, ) collectFlow( containerView, @@ -417,7 +399,7 @@ constructor( shadeInteractor.isAnyFullyExpanded, shadeInteractor.isUserInteracting, shadeInteractor.isShadeFullyCollapsed, - ::Triple + ::Triple, ), { (isFullyExpanded, isUserInteracting, isShadeFullyCollapsed) -> shadeConsumingTouches = isUserInteracting @@ -441,7 +423,7 @@ constructor( } } updateTouchHandlingState() - } + }, ) collectFlow(containerView, keyguardInteractor.isDreaming, { isDreaming = it }) @@ -628,7 +610,7 @@ constructor( powerManager.userActivity( SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_TOUCH, - 0 + 0, ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt index c0444fecb2bd..b4a0f23be9b1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt @@ -118,7 +118,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { override fun create( lifecycleOwner: LifecycleOwner, touchHandlers: Set<TouchHandler>, - loggingName: String + loggingName: String, ): AmbientTouchComponent = object : AmbientTouchComponent { override fun getTouchMonitor(): TouchMonitor = touchMonitor @@ -141,7 +141,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { kosmos.notificationStackScrollLayoutController, kosmos.keyguardMediaController, kosmos.lockscreenSmartspaceController, - logcatLogBuffer("GlanceableHubContainerControllerTest") + logcatLogBuffer("GlanceableHubContainerControllerTest"), ) } testableLooper = TestableLooper.get(this) @@ -150,7 +150,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { overrideResource(R.dimen.communal_top_edge_swipe_region_height, TOP_SWIPE_REGION_WIDTH) overrideResource( R.dimen.communal_bottom_edge_swipe_region_height, - BOTTOM_SWIPE_REGION_WIDTH + BOTTOM_SWIPE_REGION_WIDTH, ) // Make communal available so that communalInteractor.desiredScene accurately reflects @@ -188,7 +188,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { kosmos.notificationStackScrollLayoutController, kosmos.keyguardMediaController, kosmos.lockscreenSmartspaceController, - logcatLogBuffer("GlanceableHubContainerControllerTest") + logcatLogBuffer("GlanceableHubContainerControllerTest"), ) // First call succeeds. @@ -217,7 +217,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { kosmos.notificationStackScrollLayoutController, kosmos.keyguardMediaController, kosmos.lockscreenSmartspaceController, - logcatLogBuffer("GlanceableHubContainerControllerTest") + logcatLogBuffer("GlanceableHubContainerControllerTest"), ) assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.INITIALIZED) @@ -241,7 +241,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { kosmos.notificationStackScrollLayoutController, kosmos.keyguardMediaController, kosmos.lockscreenSmartspaceController, - logcatLogBuffer("GlanceableHubContainerControllerTest") + logcatLogBuffer("GlanceableHubContainerControllerTest"), ) // Only initView without attaching a view as we don't want the flows to start collecting @@ -342,7 +342,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.GLANCEABLE_HUB, value = 1.0f, - transitionState = TransitionState.RUNNING + transitionState = TransitionState.RUNNING, ) ) testableLooper.processAllMessages() @@ -449,7 +449,6 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { fun gestureExclusionZone_setAfterInit() = with(kosmos) { testScope.runTest { - whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_LTR) goToScene(CommunalScenes.Communal) assertThat(containerView.systemGestureExclusionRects) @@ -458,13 +457,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { /* left= */ 0, /* top= */ TOP_SWIPE_REGION_WIDTH, /* right= */ CONTAINER_WIDTH, - /* bottom= */ CONTAINER_HEIGHT - BOTTOM_SWIPE_REGION_WIDTH - ), - Rect( - /* left= */ 0, - /* top= */ 0, - /* right= */ 0, - /* bottom= */ CONTAINER_HEIGHT + /* bottom= */ CONTAINER_HEIGHT - BOTTOM_SWIPE_REGION_WIDTH, ) ) } @@ -475,67 +468,14 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { fun gestureExclusionZone_setAfterInit_fullSwipe() = with(kosmos) { testScope.runTest { - whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_LTR) goToScene(CommunalScenes.Communal) - assertThat(containerView.systemGestureExclusionRects) - .containsExactly( - Rect( - /* left= */ 0, - /* top= */ 0, - /* right= */ 0, - /* bottom= */ CONTAINER_HEIGHT - ) - ) + assertThat(containerView.systemGestureExclusionRects).isEmpty() } } @Test @DisableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) - fun gestureExclusionZone_setAfterInit_rtl() = - with(kosmos) { - testScope.runTest { - whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_RTL) - goToScene(CommunalScenes.Communal) - - assertThat(containerView.systemGestureExclusionRects) - .containsExactly( - Rect( - /* left= */ 0, - /* top= */ TOP_SWIPE_REGION_WIDTH, - /* right= */ CONTAINER_WIDTH, - /* bottom= */ CONTAINER_HEIGHT - BOTTOM_SWIPE_REGION_WIDTH - ), - Rect( - /* left= */ 0, - /* top= */ 0, - /* right= */ CONTAINER_WIDTH, - /* bottom= */ CONTAINER_HEIGHT - ) - ) - } - } - - @EnableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) - fun gestureExclusionZone_setAfterInit_rtl_fullSwipe() = - with(kosmos) { - testScope.runTest { - whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_RTL) - goToScene(CommunalScenes.Communal) - - assertThat(containerView.systemGestureExclusionRects) - .containsExactly( - Rect( - /* left= */ 0, - /* top= */ 0, - /* right= */ CONTAINER_WIDTH, - /* bottom= */ CONTAINER_HEIGHT - ) - ) - } - } - - @Test fun gestureExclusionZone_unsetWhenShadeOpen() = with(kosmos) { testScope.runTest { @@ -554,6 +494,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) fun gestureExclusionZone_unsetWhenBouncerOpen() = with(kosmos) { testScope.runTest { @@ -572,6 +513,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX) fun gestureExclusionZone_unsetWhenHubClosed() = with(kosmos) { testScope.runTest { @@ -597,7 +539,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { whenever( notificationStackScrollLayoutController.isBelowLastNotification( any(), - any() + any(), ) ) .thenReturn(false) @@ -675,7 +617,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.GLANCEABLE_HUB, value = 1.0f, - transitionState = TransitionState.RUNNING + transitionState = TransitionState.RUNNING, ) ) testableLooper.processAllMessages() @@ -696,7 +638,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { whenever( notificationStackScrollLayoutController.isBelowLastNotification( any(), - any() + any(), ) ) .thenReturn(true) @@ -728,7 +670,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { whenever( notificationStackScrollLayoutController.isBelowLastNotification( any(), - any() + any(), ) ) .thenReturn(true) @@ -752,7 +694,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { whenever( notificationStackScrollLayoutController.isBelowLastNotification( any(), - any() + any(), ) ) .thenReturn(true) @@ -805,13 +747,13 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB, - kosmos.testScope + kosmos.testScope, ) } else { kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN, - kosmos.testScope + kosmos.testScope, ) } testableLooper.processAllMessages() @@ -836,7 +778,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { MotionEvent.ACTION_DOWN, CONTAINER_WIDTH.toFloat() / 2, CONTAINER_HEIGHT.toFloat() / 2, - 0 + 0, ) private val CANCEL_EVENT = @@ -846,7 +788,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { MotionEvent.ACTION_CANCEL, CONTAINER_WIDTH.toFloat() / 2, CONTAINER_HEIGHT.toFloat() / 2, - 0 + 0, ) private val MOVE_EVENT = @@ -856,7 +798,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { MotionEvent.ACTION_MOVE, CONTAINER_WIDTH.toFloat() / 2, CONTAINER_HEIGHT.toFloat() / 2, - 0 + 0, ) private val UP_EVENT = @@ -866,7 +808,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { MotionEvent.ACTION_UP, CONTAINER_WIDTH.toFloat() / 2, CONTAINER_HEIGHT.toFloat() / 2, - 0 + 0, ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/QuickStepContractTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/system/QuickStepContractTest.kt new file mode 100644 index 000000000000..6254fb128859 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/QuickStepContractTest.kt @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.system + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_COMMUNAL_HUB_SHOWING +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE +import com.google.common.truth.Truth.assertThat +import kotlin.test.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class QuickStepContractTest : SysuiTestCase() { + @Test + fun isBackGestureDisabled_hubShowing() { + val sysuiStateFlags = SYSUI_STATE_COMMUNAL_HUB_SHOWING + + // Gestures are disabled while on the hub. + assertThat( + QuickStepContract.isBackGestureDisabled(sysuiStateFlags, /* forTrackpad= */ false) + ) + .isTrue() + } + + @Test + fun isBackGestureDisabled_hubAndShadeShowing() { + val sysuiStateFlags = + SYSUI_STATE_COMMUNAL_HUB_SHOWING and SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE + + // Gestures are enabled because the shade shows over the hub. + assertThat( + QuickStepContract.isBackGestureDisabled(sysuiStateFlags, /* forTrackpad= */ false) + ) + .isFalse() + } + + @Test + fun isBackGestureDisabled_hubAndBouncerShowing() { + val sysuiStateFlags = SYSUI_STATE_COMMUNAL_HUB_SHOWING and SYSUI_STATE_BOUNCER_SHOWING + + // Gestures are enabled because the bouncer shows over the hub. + assertThat( + QuickStepContract.isBackGestureDisabled(sysuiStateFlags, /* forTrackpad= */ false) + ) + .isFalse() + } +} |