Loading packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt +24 −6 Original line number Diff line number Diff line Loading @@ -229,7 +229,9 @@ constructor( // the gesture area doesn't overlap with widgets. // TODO(b/323035776): adjust gesture areaa for portrait mode containerView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { // Run when the touch handling lifecycle is RESUMED, meaning the hub is visible and not // occluded. lifecycleRegistry.repeatOnLifecycle(Lifecycle.State.RESUMED) { val exclusionRect = Rect( 0, Loading @@ -242,12 +244,19 @@ constructor( } } // Listen to bouncer visibility directly as these flows become true as soon as any portion // of the bouncers are visible when the transition starts. The keyguard transition state // only changes once transitions are fully finished, which would mean touches during a // transition to the bouncer would be incorrectly intercepted by the hub. collectFlow( containerView, keyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState), or( keyguardInteractor.primaryBouncerShowing, keyguardInteractor.alternateBouncerShowing ), { anyBouncerShowing = it updateLifecycleState() updateTouchHandlingState() } ) collectFlow( Loading @@ -255,7 +264,7 @@ constructor( communalInteractor.isCommunalShowing, { hubShowing = it updateLifecycleState() updateTouchHandlingState() } ) collectFlow( Loading @@ -263,7 +272,7 @@ constructor( and(shadeInteractor.isAnyFullyExpanded, not(shadeInteractor.isUserInteracting)), { shadeShowing = it updateLifecycleState() updateTouchHandlingState() } ) collectFlow(containerView, keyguardInteractor.isDreaming, { isDreaming = it }) Loading @@ -276,13 +285,22 @@ constructor( /** * Updates the lifecycle stored by the [lifecycleRegistry] to control when the [touchMonitor] * should listen for and intercept top and bottom swipes. * * Also clears gesture exclusion zones when the hub is occluded or gone. */ private fun updateLifecycleState() { private fun updateTouchHandlingState() { val shouldInterceptGestures = hubShowing && !(shadeShowing || anyBouncerShowing) if (shouldInterceptGestures) { lifecycleRegistry.currentState = Lifecycle.State.RESUMED } else { // Hub is either occluded or no longer showing, turn off touch handling. lifecycleRegistry.currentState = Lifecycle.State.STARTED // Clear exclusion rects if the hub is not showing or is covered, so we don't interfere // with back gestures when the bouncer or shade. We do this here instead of with // repeatOnLifecycle as repeatOnLifecycle does not run when going from RESUMED back to // STARTED, only when going from CREATED to STARTED. communalContainerView!!.systemGestureExclusionRects = emptyList() } } Loading packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt +51 −17 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.ambient.touch.TouchHandler import com.android.systemui.ambient.touch.TouchMonitor import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.fakeCommunalRepository import com.android.systemui.communal.domain.interactor.communalInteractor Loading @@ -42,10 +43,8 @@ import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.communal.util.CommunalColors import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope Loading Loading @@ -238,11 +237,7 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardTransitionRepository.sendTransitionSteps( KeyguardState.GLANCEABLE_HUB, KeyguardState.PRIMARY_BOUNCER, testScope ) fakeKeyguardBouncerRepository.setPrimaryShow(true) testableLooper.processAllMessages() // Touch events are not intercepted. Loading Loading @@ -368,11 +363,7 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardTransitionRepository.sendTransitionSteps( KeyguardState.GLANCEABLE_HUB, KeyguardState.PRIMARY_BOUNCER, testScope ) fakeKeyguardBouncerRepository.setPrimaryShow(true) testableLooper.processAllMessages() assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED) Loading @@ -387,11 +378,7 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardTransitionRepository.sendTransitionSteps( KeyguardState.GLANCEABLE_HUB, KeyguardState.ALTERNATE_BOUNCER, testScope ) fakeKeyguardBouncerRepository.setAlternateVisible(true) testableLooper.processAllMessages() assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED) Loading Loading @@ -452,6 +439,53 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu } } @Test fun gestureExclusionZone_unsetWhenShadeOpen() = with(kosmos) { testScope.runTest { goToScene(CommunalScenes.Communal) // Shade shows up. shadeTestUtil.setQsExpansion(1.0f) testableLooper.processAllMessages() // Exclusion rects are unset. assertThat(containerView.systemGestureExclusionRects).isEmpty() } } @Test fun gestureExclusionZone_unsetWhenBouncerOpen() = with(kosmos) { testScope.runTest { goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardBouncerRepository.setPrimaryShow(true) testableLooper.processAllMessages() // Exclusion rects are unset. assertThat(containerView.systemGestureExclusionRects).isEmpty() } } @Test fun gestureExclusionZone_unsetWhenHubClosed() = with(kosmos) { testScope.runTest { goToScene(CommunalScenes.Communal) // Exclusion rect is set. assertThat(containerView.systemGestureExclusionRects).hasSize(1) // Leave the hub. goToScene(CommunalScenes.Blank) // Exclusion rect is unset. assertThat(containerView.systemGestureExclusionRects).isEmpty() } } private fun initAndAttachContainerView() { containerView = View(context) Loading Loading
packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt +24 −6 Original line number Diff line number Diff line Loading @@ -229,7 +229,9 @@ constructor( // the gesture area doesn't overlap with widgets. // TODO(b/323035776): adjust gesture areaa for portrait mode containerView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { // Run when the touch handling lifecycle is RESUMED, meaning the hub is visible and not // occluded. lifecycleRegistry.repeatOnLifecycle(Lifecycle.State.RESUMED) { val exclusionRect = Rect( 0, Loading @@ -242,12 +244,19 @@ constructor( } } // Listen to bouncer visibility directly as these flows become true as soon as any portion // of the bouncers are visible when the transition starts. The keyguard transition state // only changes once transitions are fully finished, which would mean touches during a // transition to the bouncer would be incorrectly intercepted by the hub. collectFlow( containerView, keyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState), or( keyguardInteractor.primaryBouncerShowing, keyguardInteractor.alternateBouncerShowing ), { anyBouncerShowing = it updateLifecycleState() updateTouchHandlingState() } ) collectFlow( Loading @@ -255,7 +264,7 @@ constructor( communalInteractor.isCommunalShowing, { hubShowing = it updateLifecycleState() updateTouchHandlingState() } ) collectFlow( Loading @@ -263,7 +272,7 @@ constructor( and(shadeInteractor.isAnyFullyExpanded, not(shadeInteractor.isUserInteracting)), { shadeShowing = it updateLifecycleState() updateTouchHandlingState() } ) collectFlow(containerView, keyguardInteractor.isDreaming, { isDreaming = it }) Loading @@ -276,13 +285,22 @@ constructor( /** * Updates the lifecycle stored by the [lifecycleRegistry] to control when the [touchMonitor] * should listen for and intercept top and bottom swipes. * * Also clears gesture exclusion zones when the hub is occluded or gone. */ private fun updateLifecycleState() { private fun updateTouchHandlingState() { val shouldInterceptGestures = hubShowing && !(shadeShowing || anyBouncerShowing) if (shouldInterceptGestures) { lifecycleRegistry.currentState = Lifecycle.State.RESUMED } else { // Hub is either occluded or no longer showing, turn off touch handling. lifecycleRegistry.currentState = Lifecycle.State.STARTED // Clear exclusion rects if the hub is not showing or is covered, so we don't interfere // with back gestures when the bouncer or shade. We do this here instead of with // repeatOnLifecycle as repeatOnLifecycle does not run when going from RESUMED back to // STARTED, only when going from CREATED to STARTED. communalContainerView!!.systemGestureExclusionRects = emptyList() } } Loading
packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt +51 −17 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.ambient.touch.TouchHandler import com.android.systemui.ambient.touch.TouchMonitor import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.fakeCommunalRepository import com.android.systemui.communal.domain.interactor.communalInteractor Loading @@ -42,10 +43,8 @@ import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.communal.util.CommunalColors import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope Loading Loading @@ -238,11 +237,7 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardTransitionRepository.sendTransitionSteps( KeyguardState.GLANCEABLE_HUB, KeyguardState.PRIMARY_BOUNCER, testScope ) fakeKeyguardBouncerRepository.setPrimaryShow(true) testableLooper.processAllMessages() // Touch events are not intercepted. Loading Loading @@ -368,11 +363,7 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardTransitionRepository.sendTransitionSteps( KeyguardState.GLANCEABLE_HUB, KeyguardState.PRIMARY_BOUNCER, testScope ) fakeKeyguardBouncerRepository.setPrimaryShow(true) testableLooper.processAllMessages() assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED) Loading @@ -387,11 +378,7 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardTransitionRepository.sendTransitionSteps( KeyguardState.GLANCEABLE_HUB, KeyguardState.ALTERNATE_BOUNCER, testScope ) fakeKeyguardBouncerRepository.setAlternateVisible(true) testableLooper.processAllMessages() assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED) Loading Loading @@ -452,6 +439,53 @@ class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : Sysu } } @Test fun gestureExclusionZone_unsetWhenShadeOpen() = with(kosmos) { testScope.runTest { goToScene(CommunalScenes.Communal) // Shade shows up. shadeTestUtil.setQsExpansion(1.0f) testableLooper.processAllMessages() // Exclusion rects are unset. assertThat(containerView.systemGestureExclusionRects).isEmpty() } } @Test fun gestureExclusionZone_unsetWhenBouncerOpen() = with(kosmos) { testScope.runTest { goToScene(CommunalScenes.Communal) // Bouncer is visible. fakeKeyguardBouncerRepository.setPrimaryShow(true) testableLooper.processAllMessages() // Exclusion rects are unset. assertThat(containerView.systemGestureExclusionRects).isEmpty() } } @Test fun gestureExclusionZone_unsetWhenHubClosed() = with(kosmos) { testScope.runTest { goToScene(CommunalScenes.Communal) // Exclusion rect is set. assertThat(containerView.systemGestureExclusionRects).hasSize(1) // Leave the hub. goToScene(CommunalScenes.Blank) // Exclusion rect is unset. assertThat(containerView.systemGestureExclusionRects).isEmpty() } } private fun initAndAttachContainerView() { containerView = View(context) Loading