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

Commit 10c5af21 authored by Andreas Miko's avatar Andreas Miko
Browse files

Fix race condition in LockscreenSceneTransitionInteractor

LockscreenSceneTransitionInteractor did rely on sharedFlows which might
be not up-to-date and therefore caused a race condition. With the recent
addition of currentTransitionInfoInternal we are able to get the most
recent transition info.

Test: Ignored unit test now working
Test: Manual test of the scenario in the bug
Bug: b/340616271
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT
Change-Id: I435036354ec76f68600c72acee280e5f14d695bb
parent e3e8a89b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -218,6 +218,8 @@ constructor(
            .map { step -> step.to }
            .shareIn(scope, SharingStarted.Eagerly, replay = 1)

    val currentTransitionInfo: StateFlow<TransitionInfo> = repository.currentTransitionInfoInternal

    /** The from state of the last [TransitionState.STARTED] transition. */
    // TODO: is it performant to have several SharedFlows side by side instead of one?
    @SuppressLint("SharedFlowCreation")
+5 −3
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ constructor(
        val newTransition =
            TransitionInfo(
                ownerName = this::class.java.simpleName,
                from = transitionInteractor.getStartedState(),
                from = transitionInteractor.currentTransitionInfo.value.to,
                to = state,
                animator = null,
                modeOnCanceled = TransitionModeOnCanceled.REVERSE
@@ -150,7 +150,7 @@ constructor(
    private suspend fun handleTransition(transition: ObservableTransitionState.Transition) {
        if (transition.fromScene == Scenes.Lockscreen) {
            if (currentTransitionId != null) {
                val currentToState = transitionInteractor.getStartedState()
                val currentToState = transitionInteractor.currentTransitionInfo.value.to
                if (currentToState == UNDEFINED) {
                    transitionKtfTo(transitionInteractor.getStartedFromState())
                }
@@ -169,6 +169,8 @@ constructor(
    }

    private suspend fun transitionKtfTo(state: KeyguardState) {
        // TODO(b/330311871): This is based on a sharedFlow and thus might not be up-to-date and
        //  cause a race condition. (There is no known scenario that is currently affected.)
        val currentTransition = transitionInteractor.transitionState.value
        if (currentTransition.isFinishedIn(state)) {
            // This is already the state we want to be in
@@ -199,7 +201,7 @@ constructor(
    }

    private suspend fun startTransitionFromLockscreen() {
        val currentState = transitionInteractor.getStartedState()
        val currentState = transitionInteractor.currentTransitionInfo.value.to
        val newTransition =
            TransitionInfo(
                ownerName = this::class.java.simpleName,
+0 −2
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Ignore
import org.junit.runner.RunWith

@SmallTest
@@ -1149,7 +1148,6 @@ class LockscreenSceneTransitionInteractorTest : SysuiTestCase() {
     *
     * In STL there is no guarantee that transitions settle in Idle before continuing.
     */
    @Ignore("Suffers from a race condition that will be fixed in followup CL")
    @Test
    fun transition_from_ls_scene_interrupted_by_other_from_ls_transition() =
        testScope.runTest {