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

Commit d37a3610 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix issues with transitionValue after cancellations." into main

parents 778cbd12 d76a16bc
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -269,6 +269,54 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
            assertThat(startedSteps).isEqualTo(listOf(0f, 0.5f, 1f, 1f, 0.5f, 0f))
        }

    @Test
    fun transitionValue_canceled_toAnotherState() =
        testScope.runTest {
            val transitionValuesGone by collectValues(underTest.transitionValue(state = GONE))
            val transitionValuesAod by collectValues(underTest.transitionValue(state = AOD))
            val transitionValuesLs by collectValues(underTest.transitionValue(state = LOCKSCREEN))

            listOf(
                    TransitionStep(GONE, AOD, 0f, STARTED),
                    TransitionStep(GONE, AOD, 0.5f, RUNNING),
                    TransitionStep(GONE, AOD, 0.5f, CANCELED),
                    TransitionStep(AOD, LOCKSCREEN, 0.5f, STARTED),
                    TransitionStep(AOD, LOCKSCREEN, 0.7f, RUNNING),
                    TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED),
                )
                .forEach {
                    repository.sendTransitionStep(it)
                    runCurrent()
                }

            assertThat(transitionValuesGone).isEqualTo(listOf(1f, 0.5f, 0f))
            assertThat(transitionValuesAod).isEqualTo(listOf(0f, 0.5f, 0.5f, 0.3f, 0f))
            assertThat(transitionValuesLs).isEqualTo(listOf(0.5f, 0.7f, 1f))
        }

    @Test
    fun transitionValue_canceled_backToOriginalState() =
        testScope.runTest {
            val transitionValuesGone by collectValues(underTest.transitionValue(state = GONE))
            val transitionValuesAod by collectValues(underTest.transitionValue(state = AOD))

            listOf(
                    TransitionStep(GONE, AOD, 0f, STARTED),
                    TransitionStep(GONE, AOD, 0.5f, RUNNING),
                    TransitionStep(GONE, AOD, 1f, CANCELED),
                    TransitionStep(AOD, GONE, 0.5f, STARTED),
                    TransitionStep(AOD, GONE, 0.7f, RUNNING),
                    TransitionStep(AOD, GONE, 1f, FINISHED),
                )
                .forEach {
                    repository.sendTransitionStep(it)
                    runCurrent()
                }

            assertThat(transitionValuesGone).isEqualTo(listOf(1f, 0.5f, 0.5f, 0.7f, 1f))
            assertThat(transitionValuesAod).isEqualTo(listOf(0f, 0.5f, 0.5f, 0.3f, 0f))
        }

    @Test
    fun isInTransitionToAnyState() =
        testScope.runTest {
@@ -276,6 +324,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true, // The repo is seeded with a transition from OFF to LOCKSCREEN.
                    false,
                ),
@@ -288,6 +337,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                    true,
@@ -301,6 +351,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                    true,
@@ -314,6 +365,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                    true,
@@ -330,6 +382,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                ),
@@ -345,6 +398,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                    true,
@@ -359,6 +413,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                    true,
@@ -379,6 +434,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                    true,
@@ -398,6 +454,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {

            assertEquals(
                listOf(
                    false,
                    true,
                    false,
                    true,
+27 −18
Original line number Diff line number Diff line
@@ -119,24 +119,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
    init {
        // Seed with transitions signaling a boot into lockscreen state. If updating this, please
        // also update FakeKeyguardTransitionRepository.
        emitTransition(
            TransitionStep(
                KeyguardState.OFF,
                KeyguardState.LOCKSCREEN,
                0f,
                TransitionState.STARTED,
                KeyguardTransitionRepositoryImpl::class.simpleName!!,
            )
        )
        emitTransition(
            TransitionStep(
                KeyguardState.OFF,
                KeyguardState.LOCKSCREEN,
                1f,
                TransitionState.FINISHED,
                KeyguardTransitionRepositoryImpl::class.simpleName!!,
            )
        )
        initialTransitionSteps.forEach(::emitTransition)
    }

    override fun startTransition(info: TransitionInfo): UUID? {
@@ -256,5 +239,31 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio

    companion object {
        private const val TAG = "KeyguardTransitionRepository"

        /**
         * Transition steps to seed the repository with, so that all of the transition interactor
         * flows emit reasonable initial values.
         */
        val initialTransitionSteps: List<TransitionStep> =
            listOf(
                TransitionStep(
                    KeyguardState.OFF,
                    KeyguardState.OFF,
                    1f,
                    TransitionState.FINISHED,
                ),
                TransitionStep(
                    KeyguardState.OFF,
                    KeyguardState.LOCKSCREEN,
                    0f,
                    TransitionState.STARTED,
                ),
                TransitionStep(
                    KeyguardState.OFF,
                    KeyguardState.LOCKSCREEN,
                    1f,
                    TransitionState.FINISHED,
                ),
            )
    }
}
+38 −20
Original line number Diff line number Diff line
@@ -91,13 +91,48 @@ constructor(
        }
    }

    val transitions = repository.transitions

    /**
     * A pair of the most recent STARTED step, and the transition step immediately preceding it. The
     * transition framework enforces that the previous step is either a CANCELED or FINISHED step,
     * and that the previous step was *to* the state the STARTED step is *from*.
     *
     * This flow can be used to access the previous step to determine whether it was CANCELED or
     * FINISHED. In the case of a CANCELED step, we can also figure out which state we were coming
     * from when we were canceled.
     */
    val startedStepWithPrecedingStep =
        transitions
            .pairwise()
            .filter { it.newValue.transitionState == TransitionState.STARTED }
            .shareIn(scope, SharingStarted.Eagerly)

    init {
        // Collect non-canceled steps and emit transition values.
        scope.launch(mainDispatcher) {
            repository.transitions.collect { step ->
            repository.transitions
                .filter { it.transitionState != TransitionState.CANCELED }
                .collect { step ->
                    getTransitionValueFlow(step.from).emit(1f - step.value)
                    getTransitionValueFlow(step.to).emit(step.value)
                }
        }

        // If a transition from state A -> B is canceled in favor of a transition from B -> C, we
        // need to ensure we emit transitionValue(A) = 0f, since no further steps will be emitted
        // where the from or to states are A. This would leave transitionValue(A) stuck at an
        // arbitrary non-zero value.
        scope.launch(mainDispatcher) {
            startedStepWithPrecedingStep.collect { (prevStep, startedStep) ->
                if (
                    prevStep.transitionState == TransitionState.CANCELED &&
                        startedStep.to != prevStep.from
                ) {
                    getTransitionValueFlow(prevStep.from).emit(0f)
                }
            }
        }
    }

    /** (any)->GONE transition information */
@@ -202,8 +237,6 @@ constructor(
    val dozingToLockscreenTransition: Flow<TransitionStep> =
        repository.transition(DOZING, LOCKSCREEN)

    val transitions = repository.transitions

    /** Receive all [TransitionStep] matching a filter of [from]->[to] */
    fun transition(from: KeyguardState, to: KeyguardState): Flow<TransitionStep> {
        return repository.transition(from, to)
@@ -249,21 +282,6 @@ constructor(
            .map { aodAvailable -> if (aodAvailable) AOD else DOZING }
            .stateIn(scope, SharingStarted.Eagerly, DOZING)

    /**
     * A pair of the most recent STARTED step, and the transition step immediately preceding it. The
     * transition framework enforces that the previous step is either a CANCELED or FINISHED step,
     * and that the previous step was *to* the state the STARTED step is *from*.
     *
     * This flow can be used to access the previous step to determine whether it was CANCELED or
     * FINISHED. In the case of a CANCELED step, we can also figure out which state we were coming
     * from when we were canceled.
     */
    val startedStepWithPrecedingStep =
        transitions
            .pairwise()
            .filter { it.newValue.transitionState == TransitionState.STARTED }
            .stateIn(scope, SharingStarted.Eagerly, null)

    /**
     * The last [KeyguardState] to which we [TransitionState.FINISHED] a transition.
     *
+4 −19
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.data.repository

import android.annotation.FloatRange
import android.util.Log
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
@@ -48,21 +47,8 @@ class FakeKeyguardTransitionRepository @Inject constructor() : KeyguardTransitio
    override val transitions: SharedFlow<TransitionStep> = _transitions

    init {
        _transitions.tryEmit(
            TransitionStep(
                transitionState = TransitionState.STARTED,
                from = KeyguardState.OFF,
                to = KeyguardState.LOCKSCREEN,
            )
        )

        _transitions.tryEmit(
            TransitionStep(
                transitionState = TransitionState.FINISHED,
                from = KeyguardState.OFF,
                to = KeyguardState.LOCKSCREEN,
            )
        )
        // Seed the fake repository with the same initial steps the actual repository uses.
        KeyguardTransitionRepositoryImpl.initialTransitionSteps.forEach { _transitions.tryEmit(it) }
    }

    /**
@@ -207,16 +193,15 @@ class FakeKeyguardTransitionRepository @Inject constructor() : KeyguardTransitio
    suspend fun sendTransitionSteps(
        steps: List<TransitionStep>,
        testScope: TestScope,
        validateStep: Boolean = true
        validateSteps: Boolean = true
    ) {
        steps.forEach {
            sendTransitionStep(step = it, validateStep = validateStep)
            sendTransitionStep(step = it, validateStep = validateSteps)
            testScope.testScheduler.runCurrent()
        }
    }

    override fun startTransition(info: TransitionInfo): UUID? {
        Log.i("TEST", "Start transition: ", Exception())
        return if (info.animator == null) UUID.randomUUID() else null
    }