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

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

Merge "Add transitions between glanceable hub and occluded state" into main

parents a3df2e68 993a0b42
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -40,13 +40,13 @@ class FromGlanceableHubTransitionInteractor
@Inject
constructor(
    @Background private val scope: CoroutineScope,
    @Main mainDispatcher: CoroutineDispatcher,
    @Background bgDispatcher: CoroutineDispatcher,
    private val glanceableHubTransitions: GlanceableHubTransitions,
    private val keyguardInteractor: KeyguardInteractor,
    override val transitionRepository: KeyguardTransitionRepository,
    transitionInteractor: KeyguardTransitionInteractor,
    private val powerInteractor: PowerInteractor,
    @Main mainDispatcher: CoroutineDispatcher,
    @Background bgDispatcher: CoroutineDispatcher,
) :
    TransitionInteractor(
        fromState = KeyguardState.GLANCEABLE_HUB,
@@ -62,6 +62,7 @@ constructor(
        listenForHubToDozing()
        listenForHubToPrimaryBouncer()
        listenForHubToAlternateBouncer()
        listenForHubToOccluded()
        listenForHubToGone()
    }

@@ -130,6 +131,17 @@ constructor(
        }
    }

    private fun listenForHubToOccluded() {
        scope.launch {
            keyguardInteractor.isKeyguardOccluded.sample(startedKeyguardState, ::Pair).collect {
                (isOccluded, keyguardState) ->
                if (isOccluded && keyguardState == fromState) {
                    startTransitionTo(KeyguardState.OCCLUDED)
                }
            }
        }
    }

    private fun listenForHubToGone() {
        scope.launch {
            keyguardInteractor.isKeyguardGoingAway
+16 −10
Original line number Diff line number Diff line
@@ -18,12 +18,14 @@ package com.android.systemui.keyguard.domain.interactor

import android.animation.ValueAnimator
import com.android.app.animation.Interpolators
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.util.kotlin.Utils.Companion.sample
import com.android.systemui.util.kotlin.Utils.Companion.toTriple
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
@@ -44,6 +46,7 @@ constructor(
    @Main mainDispatcher: CoroutineDispatcher,
    private val keyguardInteractor: KeyguardInteractor,
    private val powerInteractor: PowerInteractor,
    private val communalInteractor: CommunalInteractor,
) :
    TransitionInteractor(
        fromState = KeyguardState.OCCLUDED,
@@ -53,7 +56,7 @@ constructor(
    ) {

    override fun start() {
        listenForOccludedToLockscreen()
        listenForOccludedToLockscreenOrHub()
        listenForOccludedToDreaming()
        listenForOccludedToAodOrDozing()
        listenForOccludedToGone()
@@ -86,18 +89,15 @@ constructor(
        }
    }

    private fun listenForOccludedToLockscreen() {
    private fun listenForOccludedToLockscreenOrHub() {
        scope.launch {
            keyguardInteractor.isKeyguardOccluded
                .sample(
                    combine(
                    keyguardInteractor.isKeyguardShowing,
                    startedKeyguardTransitionStep,
                        ::Pair
                    ),
                    ::toTriple
                    communalInteractor.isIdleOnCommunal,
                )
                .collect { (isOccluded, isShowing, lastStartedKeyguardState) ->
                .collect { (isOccluded, isShowing, lastStartedKeyguardState, isIdleOnCommunal) ->
                    // Occlusion signals come from the framework, and should interrupt any
                    // existing transition
                    if (
@@ -105,7 +105,13 @@ constructor(
                            isShowing &&
                            lastStartedKeyguardState.to == KeyguardState.OCCLUDED
                    ) {
                        startTransitionTo(KeyguardState.LOCKSCREEN)
                        val to =
                            if (isIdleOnCommunal) {
                                KeyguardState.GLANCEABLE_HUB
                            } else {
                                KeyguardState.LOCKSCREEN
                            }
                        startTransitionTo(to)
                    }
                }
        }
+71 −0
Original line number Diff line number Diff line
@@ -270,6 +270,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
                    transitionRepository = transitionRepository,
                    transitionInteractor = transitionInteractor,
                    powerInteractor = powerInteractor,
                    communalInteractor = communalInteractor,
                )
                .apply { start() }

@@ -1300,6 +1301,43 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
            coroutineContext.cancelChildren()
        }

    @Test
    fun occludedToGlanceableHub() =
        testScope.runTest {
            // GIVEN a device on lockscreen
            keyguardRepository.setKeyguardShowing(true)
            runCurrent()

            // GIVEN the device is idle on the glanceable hub
            val idleTransitionState =
                MutableStateFlow<ObservableCommunalTransitionState>(
                    ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal)
                )
            communalInteractor.setTransitionState(idleTransitionState)
            runCurrent()

            // GIVEN a prior transition has run to OCCLUDED
            runTransitionAndSetWakefulness(KeyguardState.GLANCEABLE_HUB, KeyguardState.OCCLUDED)
            keyguardRepository.setKeyguardOccluded(true)
            runCurrent()

            // WHEN occlusion ends
            keyguardRepository.setKeyguardOccluded(false)
            runCurrent()

            val info =
                withArgCaptor<TransitionInfo> {
                    verify(transitionRepository).startTransition(capture())
                }
            // THEN a transition to GLANCEABLE_HUB should occur
            assertThat(info.ownerName).isEqualTo(FromOccludedTransitionInteractor::class.simpleName)
            assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED)
            assertThat(info.to).isEqualTo(KeyguardState.GLANCEABLE_HUB)
            assertThat(info.animator).isNotNull()

            coroutineContext.cancelChildren()
        }

    @Test
    fun occludedToAlternateBouncer() =
        testScope.runTest {
@@ -1796,6 +1834,39 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
            coroutineContext.cancelChildren()
        }

    @Test
    fun glanceableHubToOccluded() =
        testScope.runTest {
            // GIVEN a prior transition has run to GLANCEABLE_HUB
            runTransitionAndSetWakefulness(KeyguardState.GONE, KeyguardState.GLANCEABLE_HUB)
            runCurrent()

            // GIVEN the device is idle on the glanceable hub
            val idleTransitionState =
                MutableStateFlow<ObservableCommunalTransitionState>(
                    ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal)
                )
            communalInteractor.setTransitionState(idleTransitionState)
            runCurrent()

            // WHEN the keyguard is occluded
            keyguardRepository.setKeyguardOccluded(true)
            runCurrent()

            val info =
                withArgCaptor<TransitionInfo> {
                    verify(transitionRepository).startTransition(capture())
                }
            // THEN a transition to OCCLUDED should occur
            assertThat(info.ownerName)
                .isEqualTo(FromGlanceableHubTransitionInteractor::class.simpleName)
            assertThat(info.from).isEqualTo(KeyguardState.GLANCEABLE_HUB)
            assertThat(info.to).isEqualTo(KeyguardState.OCCLUDED)
            assertThat(info.animator).isNotNull()

            coroutineContext.cancelChildren()
        }

    @Test
    fun glanceableHubToGone() =
        testScope.runTest {