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

Commit b2c88319 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Fix NPE in SwipeAnimation

This CL fixes a crash that could happen when a user action is invalid.
In some cases, we would still start the transition but the content used
to compute the swipe distance would not be composed, leading to a crash.

Bug: 416260000
Test: SwipeToSceneTest
Flag: EXEMPT bug fix
Change-Id: I00dfb04e414819106fc0841490f355598d7412b1
parent 0dda1101
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -481,7 +481,9 @@ internal class Swipes(val upOrLeft: Swipe.Resolved, val downOrRight: Swipe.Resol
                        actionSwipe.fromSource != swipe.fromSource) ||
                    // The action requires a specific pointerType.
                    (actionSwipe.pointerType != null &&
                        actionSwipe.pointerType != swipe.pointerType)
                        actionSwipe.pointerType != swipe.pointerType) ||
                    // The action is not valid in the current state.
                    !isActionValid(actionResult)
            ) {
                // This action is not eligible.
                return@forEach
@@ -507,6 +509,19 @@ internal class Swipes(val upOrLeft: Swipe.Resolved, val downOrRight: Swipe.Resol
        return bestMatch
    }

    /** Whether [result] is a valid user action in the current state. */
    private fun Content.isActionValid(result: UserActionResult): Boolean {
        val state = layoutImpl.state
        return when (result) {
            is UserActionResult.HideOverlay -> result.overlay in state.currentOverlays
            is UserActionResult.ReplaceByOverlay -> {
                val fromOverlay = key as? OverlayKey ?: return false
                fromOverlay in state.currentOverlays && result.overlay !in state.currentOverlays
            }
            else -> true
        }
    }

    /**
     * Update the swipes results.
     *
+27 −0
Original line number Diff line number Diff line
@@ -1144,4 +1144,31 @@ class SwipeToSceneTest {
        assertThat(state.transitionState).hasCurrentScene(SceneA)
        assertThat(state.transitionState).hasCurrentOverlays(OverlayB)
    }

    @Test
    fun invalidSwipeAction() {
        val state =
            rule.runOnUiThread { MutableSceneTransitionLayoutStateForTests(initialScene = SceneA) }

        rule.setContent {
            SceneTransitionLayout(state) {
                scene(
                    SceneA,
                    userActions = mapOf(Swipe.Up to UserActionResult.HideOverlay(OverlayA)),
                ) {
                    Box(Modifier.fillMaxSize())
                }
                overlay(OverlayA) { Box(Modifier.size(100.dp)) }
            }
        }

        // OverlayA is not shown.
        // Swipe up on SceneA. This should not trigger the HideOverlay action given that OverlayA is
        // already hidden.
        rule.onRoot().performTouchInput { swipeUp() }

        // The state should remain unchanged.
        assertThat(state.transitionState).isIdle()
        assertThat(state.transitionState).hasCurrentScene(SceneA)
    }
}