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

Commit 2f641ffc authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Fix crash in MutableSTLState.finishTransition()

This CL fixes a rare crash that could happen when finishing a
transition, because a replaced transition was not correctly removed from
MutableSTLState.finishedTransitions.

Bug: 373589988
Test: atest SceneTransitionLayoutTest
Flag: EXEMPT crash fix
Change-Id: Ib692aee3c1a70203917628da7dbae4b181a9db91
parent 249f87d7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -430,6 +430,10 @@ internal class MutableSceneTransitionLayoutStateImpl(
                    // Replace the transition.
                    transitionStates =
                        transitionStates.subList(0, transitionStates.lastIndex) + transition

                    // Make sure it is removed from the finishedTransitions set if it was already
                    // finished.
                    finishedTransitions.remove(currentState)
                } else {
                    // Append the new transition.
                    transitionStates = transitionStates + transition
+41 −0
Original line number Diff line number Diff line
@@ -727,4 +727,45 @@ class SceneTransitionLayoutStateTest {
        // The previous job is cancelled and does not infinitely collect the progress.
        job.join()
    }

    @Test
    fun replacedTransitionIsRemovedFromFinishedTransitions() = runTest {
        val state = MutableSceneTransitionLayoutState(SceneA)

        val aToB =
            transition(
                SceneA,
                SceneB,
                onFreezeAndAnimate = {
                    // Do nothing, so that this transition stays in the transitionStates list and we
                    // can finish() it manually later.
                },
            )
        val replacingAToB = transition(SceneB, SceneC)
        val replacingBToC = transition(SceneB, SceneC, replacedTransition = replacingAToB)

        // Start A => B.
        val aToBJob = state.startTransitionImmediately(animationScope = this, aToB)

        // Start B => C and immediately finish it. It will be flagged as finished in
        // STLState.finishedTransitions given that A => B is not finished yet.
        val bToCJob = state.startTransitionImmediately(animationScope = this, replacingAToB)
        replacingAToB.finish()
        bToCJob.join()

        // Start a new B => C that replaces the previously finished B => C.
        val replacingBToCJob =
            state.startTransitionImmediately(animationScope = this, replacingBToC)

        // Finish A => B.
        aToB.finish()
        aToBJob.join()

        // Finish the new B => C.
        replacingBToC.finish()
        replacingBToCJob.join()

        assertThat(state.transitionState).isIdle()
        assertThat(state.transitionState).hasCurrentScene(SceneC)
    }
}