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

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

Merge "Fix hub touch interactions with bouncer and shade" into main

parents 23f82b28 dfde304a
Loading
Loading
Loading
Loading
+24 −6
Original line number Diff line number Diff line
@@ -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,
@@ -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(
@@ -255,7 +264,7 @@ constructor(
            communalInteractor.isCommunalShowing,
            {
                hubShowing = it
                updateLifecycleState()
                updateTouchHandlingState()
            }
        )
        collectFlow(
@@ -263,7 +272,7 @@ constructor(
            and(shadeInteractor.isAnyFullyExpanded, not(shadeInteractor.isUserInteracting)),
            {
                shadeShowing = it
                updateLifecycleState()
                updateTouchHandlingState()
            }
        )
        collectFlow(containerView, keyguardInteractor.isDreaming, { isDreaming = it })
@@ -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()
        }
    }

+51 −17
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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.
@@ -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)
@@ -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)
@@ -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)