Merge "Remove interception capabilities in STL drag handler" into main
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index cf0ba51..7a8d20a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:Suppress("NOTHING_TO_INLINE")
-
 package com.android.compose.animation.scene
 
 import androidx.compose.foundation.gestures.Orientation
@@ -97,68 +95,11 @@
     internal val positionalThreshold
         get() = with(layoutImpl.density) { 56.dp.toPx() }
 
-    /**
-     * Whether we should immediately intercept a gesture.
-     *
-     * Note: if this returns true, then [onDragStarted] will be called with overSlop equal to 0f,
-     * indicating that the transition should be intercepted.
-     */
-    internal fun shouldImmediatelyIntercept(pointersDown: PointersInfo.PointersDown?): Boolean {
-        // We don't intercept the touch if we are not currently driving the transition.
-        val dragController = dragController
-        if (dragController?.isDrivingTransition != true) {
-            return false
-        }
-
-        val swipeAnimation = dragController.swipeAnimation
-
-        // Only intercept the current transition if one of the 2 swipes results is also a transition
-        // between the same pair of contents.
-        val swipes = computeSwipes(pointersDown)
-        val fromContent = layoutImpl.content(swipeAnimation.currentContent)
-        val (upOrLeft, downOrRight) = swipes.computeSwipesResults(fromContent)
-        val currentScene = layoutImpl.state.currentScene
-        val contentTransition = swipeAnimation.contentTransition
-        return (upOrLeft != null &&
-            contentTransition.isTransitioningBetween(
-                fromContent.key,
-                upOrLeft.toContent(currentScene),
-            )) ||
-            (downOrRight != null &&
-                contentTransition.isTransitioningBetween(
-                    fromContent.key,
-                    downOrRight.toContent(currentScene),
-                ))
-    }
-
     override fun onDragStarted(
         pointersDown: PointersInfo.PointersDown?,
         overSlop: Float,
     ): DragController {
-        if (overSlop == 0f) {
-            val oldDragController = dragController
-            check(oldDragController != null && oldDragController.isDrivingTransition) {
-                val isActive = oldDragController?.isDrivingTransition
-                "onDragStarted(overSlop=0f) requires an active dragController, but was $isActive"
-            }
-
-            // This [transition] was already driving the animation: simply take over it.
-            // Stop animating and start from the current offset.
-            val oldSwipeAnimation = oldDragController.swipeAnimation
-
-            // We need to recompute the swipe results since this is a new gesture, and the
-            // fromScene.userActions may have changed.
-            val swipes = oldDragController.swipes
-            swipes.updateSwipesResults(
-                fromContent = layoutImpl.content(oldSwipeAnimation.fromContent)
-            )
-
-            // A new gesture should always create a new SwipeAnimation. This way there cannot be
-            // different gestures controlling the same transition.
-            val swipeAnimation = createSwipeAnimation(oldSwipeAnimation)
-            return updateDragController(swipes, swipeAnimation)
-        }
-
+        check(overSlop != 0f)
         val swipes = computeSwipes(pointersDown)
         val fromContent = layoutImpl.contentForUserActions()
 
@@ -196,7 +137,7 @@
         return createSwipeAnimation(layoutImpl, result, isUpOrLeft, orientation)
     }
 
-    internal fun resolveSwipeSource(startedPosition: Offset): SwipeSource.Resolved? {
+    private fun resolveSwipeSource(startedPosition: Offset): SwipeSource.Resolved? {
         return layoutImpl.swipeSourceDetector.source(
             layoutSize = layoutImpl.lastSize,
             position = startedPosition.round(),
@@ -291,71 +232,25 @@
             return 0f
         }
 
-        val toContent = swipeAnimation.toContent
         val distance = swipeAnimation.distance()
         val previousOffset = swipeAnimation.dragOffset
         val desiredOffset = previousOffset + delta
+        val desiredProgress = swipeAnimation.computeProgress(desiredOffset)
 
-        fun hasReachedToSceneUpOrLeft() =
-            distance < 0 &&
-                desiredOffset <= distance &&
-                swipes.upOrLeftResult?.toContent(layoutState.currentScene) == toContent
+        // Note: the distance could be negative if fromContent is above or to the left of
+        // toContent.
+        val newOffset =
+            when {
+                distance == DistanceUnspecified ||
+                    swipeAnimation.contentTransition.isWithinProgressRange(desiredProgress) ->
+                    desiredOffset
+                distance > 0f -> desiredOffset.fastCoerceIn(0f, distance)
+                else -> desiredOffset.fastCoerceIn(distance, 0f)
+            }
 
-        fun hasReachedToSceneDownOrRight() =
-            distance > 0 &&
-                desiredOffset >= distance &&
-                swipes.downOrRightResult?.toContent(layoutState.currentScene) == toContent
+        val consumedDelta = newOffset - previousOffset
 
-        // Considering accelerated swipe: Change fromContent in the case where the user quickly
-        // swiped multiple times in the same direction to accelerate the transition from A => B then
-        // B => C.
-        //
-        // TODO(b/290184746): the second drag needs to pass B to work. Add support for flinging
-        //  twice before B has been reached
-        val hasReachedToContent =
-            swipeAnimation.currentContent == toContent &&
-                (hasReachedToSceneUpOrLeft() || hasReachedToSceneDownOrRight())
-
-        val fromContent: ContentKey
-        val currentTransitionOffset: Float
-        val newOffset: Float
-        val consumedDelta: Float
-        if (hasReachedToContent) {
-            // The new transition will start from the current toContent.
-            fromContent = toContent
-
-            // The current transition is completed (we have reached the full swipe distance).
-            currentTransitionOffset = distance
-
-            // The next transition will start with the remaining offset.
-            newOffset = desiredOffset - distance
-            consumedDelta = delta
-        } else {
-            fromContent = swipeAnimation.fromContent
-            val desiredProgress = swipeAnimation.computeProgress(desiredOffset)
-
-            // Note: the distance could be negative if fromContent is above or to the left of
-            // toContent.
-            currentTransitionOffset =
-                when {
-                    distance == DistanceUnspecified ||
-                        swipeAnimation.contentTransition.isWithinProgressRange(desiredProgress) ->
-                        desiredOffset
-
-                    distance > 0f -> desiredOffset.fastCoerceIn(0f, distance)
-                    else -> desiredOffset.fastCoerceIn(distance, 0f)
-                }
-
-            // If there is a new transition, we will use the same offset
-            newOffset = currentTransitionOffset
-            consumedDelta = newOffset - previousOffset
-        }
-
-        swipeAnimation.dragOffset = currentTransitionOffset
-
-        if (hasReachedToContent) {
-            swipes.updateSwipesResults(draggableHandler.layoutImpl.content(fromContent))
-        }
+        swipeAnimation.dragOffset = newOffset
         val result = swipes.findUserActionResult(directionOffset = newOffset)
 
         if (result == null) {
@@ -372,13 +267,12 @@
 
         val needNewTransition =
             !currentTransitionIrreversible &&
-                (hasReachedToContent ||
-                    result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
+                (result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
                     result.transitionKey != swipeAnimation.contentTransition.key)
 
         if (needNewTransition) {
             // Make sure the current transition will finish to the right current scene.
-            swipeAnimation.currentContent = fromContent
+            swipeAnimation.currentContent = swipeAnimation.fromContent
 
             val newSwipeAnimation = draggableHandler.createSwipeAnimation(swipes, result)
             newSwipeAnimation.dragOffset = newOffset
@@ -499,7 +393,9 @@
     var upOrLeftResult: UserActionResult? = null
     var downOrRightResult: UserActionResult? = null
 
-    fun computeSwipesResults(fromContent: Content): Pair<UserActionResult?, UserActionResult?> {
+    private fun computeSwipesResults(
+        fromContent: Content
+    ): Pair<UserActionResult?, UserActionResult?> {
         val upOrLeftResult = fromContent.findActionResultBestMatch(swipe = upOrLeft)
         val downOrRightResult = fromContent.findActionResultBestMatch(swipe = downOrRight)
         return upOrLeftResult to downOrRightResult
@@ -564,48 +460,9 @@
                 .shouldEnableSwipes(draggableHandler.orientation)
         }
 
-        var isIntercepting = false
-
         return PriorityNestedScrollConnection(
             orientation = draggableHandler.orientation,
-            canStartPreScroll = { offsetAvailable, offsetBeforeStart, _ ->
-                val pointersDown: PointersInfo.PointersDown? =
-                    when (val info = pointersInfoOwner.pointersInfo()) {
-                        PointersInfo.MouseWheel -> {
-                            // Do not support mouse wheel interactions
-                            return@PriorityNestedScrollConnection false
-                        }
-
-                        is PointersInfo.PointersDown -> info
-                        null -> null
-                    }
-
-                canChangeScene =
-                    if (isExternalOverscrollGesture()) false else offsetBeforeStart == 0f
-
-                val canInterceptSwipeTransition =
-                    canChangeScene &&
-                        offsetAvailable != 0f &&
-                        draggableHandler.shouldImmediatelyIntercept(pointersDown)
-                if (!canInterceptSwipeTransition) return@PriorityNestedScrollConnection false
-
-                val layoutImpl = draggableHandler.layoutImpl
-                val threshold = layoutImpl.transitionInterceptionThreshold
-                val hasSnappedToIdle = layoutImpl.state.snapToIdleIfClose(threshold)
-                if (hasSnappedToIdle) {
-                    // If the current swipe transition is closed to 0f or 1f, then we want to
-                    // interrupt the transition (snapping it to Idle) and scroll the list.
-                    return@PriorityNestedScrollConnection false
-                }
-
-                lastPointersDown = pointersDown
-
-                // If the current swipe transition is *not* closed to 0f or 1f, then we want the
-                // scroll events to intercept the current transition to continue the scene
-                // transition.
-                isIntercepting = true
-                true
-            },
+            canStartPreScroll = { _, _, _ -> false },
             canStartPostScroll = { offsetAvailable, offsetBeforeStart, _ ->
                 val behavior: NestedScrollBehavior =
                     when {
@@ -629,29 +486,22 @@
                     }
                 lastPointersDown = pointersDown
 
-                val canStart =
-                    when (behavior) {
-                        NestedScrollBehavior.EdgeNoPreview -> {
-                            canChangeScene = isZeroOffset
-                            isZeroOffset && shouldEnableSwipes()
-                        }
-
-                        NestedScrollBehavior.EdgeWithPreview -> {
-                            canChangeScene = isZeroOffset
-                            shouldEnableSwipes()
-                        }
-
-                        NestedScrollBehavior.EdgeAlways -> {
-                            canChangeScene = true
-                            shouldEnableSwipes()
-                        }
+                when (behavior) {
+                    NestedScrollBehavior.EdgeNoPreview -> {
+                        canChangeScene = isZeroOffset
+                        isZeroOffset && shouldEnableSwipes()
                     }
 
-                if (canStart) {
-                    isIntercepting = false
-                }
+                    NestedScrollBehavior.EdgeWithPreview -> {
+                        canChangeScene = isZeroOffset
+                        shouldEnableSwipes()
+                    }
 
-                canStart
+                    NestedScrollBehavior.EdgeAlways -> {
+                        canChangeScene = true
+                        shouldEnableSwipes()
+                    }
+                }
             },
             canStartPostFling = { velocityAvailable ->
                 val behavior: NestedScrollBehavior =
@@ -676,19 +526,14 @@
                     }
                 lastPointersDown = pointersDown
 
-                val canStart = behavior.canStartOnPostFling && shouldEnableSwipes()
-                if (canStart) {
-                    isIntercepting = false
-                }
-
-                canStart
+                behavior.canStartOnPostFling && shouldEnableSwipes()
             },
             onStart = { firstScroll ->
                 scrollController(
                     dragController =
                         draggableHandler.onDragStarted(
                             pointersDown = lastPointersDown,
-                            overSlop = if (isIntercepting) 0f else firstScroll,
+                            overSlop = firstScroll,
                         ),
                     canChangeScene = canChangeScene,
                     pointersInfoOwner = pointersInfoOwner,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index 501fbb0..f5f01d4 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -80,7 +80,6 @@
 @Stable
 internal fun Modifier.multiPointerDraggable(
     orientation: Orientation,
-    startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
     onDragStarted: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
     onFirstPointerDown: () -> Unit = {},
     swipeDetector: SwipeDetector = DefaultSwipeDetector,
@@ -89,7 +88,6 @@
     this.then(
         MultiPointerDraggableElement(
             orientation,
-            startDragImmediately,
             onDragStarted,
             onFirstPointerDown,
             swipeDetector,
@@ -99,7 +97,6 @@
 
 private data class MultiPointerDraggableElement(
     private val orientation: Orientation,
-    private val startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
     private val onDragStarted:
         (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
     private val onFirstPointerDown: () -> Unit,
@@ -109,7 +106,6 @@
     override fun create(): MultiPointerDraggableNode =
         MultiPointerDraggableNode(
             orientation = orientation,
-            startDragImmediately = startDragImmediately,
             onDragStarted = onDragStarted,
             onFirstPointerDown = onFirstPointerDown,
             swipeDetector = swipeDetector,
@@ -118,7 +114,6 @@
 
     override fun update(node: MultiPointerDraggableNode) {
         node.orientation = orientation
-        node.startDragImmediately = startDragImmediately
         node.onDragStarted = onDragStarted
         node.onFirstPointerDown = onFirstPointerDown
         node.swipeDetector = swipeDetector
@@ -127,7 +122,6 @@
 
 internal class MultiPointerDraggableNode(
     orientation: Orientation,
-    var startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
     var onDragStarted: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
     var onFirstPointerDown: () -> Unit,
     swipeDetector: SwipeDetector = DefaultSwipeDetector,
@@ -293,7 +287,6 @@
                 try {
                     detectDragGestures(
                         orientation = orientation,
-                        startDragImmediately = startDragImmediately,
                         onDragStart = { pointersDown, overSlop ->
                             onDragStarted(pointersDown, overSlop)
                         },
@@ -434,13 +427,11 @@
      * Detect drag gestures in the given [orientation].
      *
      * This function is a mix of [androidx.compose.foundation.gestures.awaitDownAndSlop] and
-     * [androidx.compose.foundation.gestures.detectVerticalDragGestures] to add support for:
-     * 1) starting the gesture immediately without requiring a drag >= touch slope;
-     * 2) passing the number of pointers down to [onDragStart].
+     * [androidx.compose.foundation.gestures.detectVerticalDragGestures] to add support for passing
+     * the number of pointers down to [onDragStart].
      */
     private suspend fun AwaitPointerEventScope.detectDragGestures(
         orientation: Orientation,
-        startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
         onDragStart: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
         onDrag: (controller: DragController, dragAmount: Float) -> Unit,
         onDragEnd: (controller: DragController) -> Unit,
@@ -466,71 +457,49 @@
                 .first()
 
         var overSlop = 0f
-        var lastPointersDown: PointersInfo.PointersDown =
+        val onSlopReached = { change: PointerInputChange, over: Float ->
+            if (swipeDetector.detectSwipe(change)) {
+                change.consume()
+                overSlop = over
+            }
+        }
+
+        // TODO(b/291055080): Replace by await[Orientation]PointerSlopOrCancellation once it
+        // is public.
+        val drag =
+            when (orientation) {
+                Orientation.Horizontal ->
+                    awaitHorizontalTouchSlopOrCancellation(consumablePointer.id, onSlopReached)
+                Orientation.Vertical ->
+                    awaitVerticalTouchSlopOrCancellation(consumablePointer.id, onSlopReached)
+            } ?: return
+
+        val lastPointersDown =
             checkNotNull(pointersInfo()) {
                 "We should have pointers down, last event: $currentEvent"
             }
                 as PointersInfo.PointersDown
-
-        val drag =
-            if (startDragImmediately(lastPointersDown)) {
-                consumablePointer.consume()
-                consumablePointer
-            } else {
-                val onSlopReached = { change: PointerInputChange, over: Float ->
-                    if (swipeDetector.detectSwipe(change)) {
-                        change.consume()
-                        overSlop = over
-                    }
+        // Make sure that overSlop is not 0f. This can happen when the user drags by exactly
+        // the touch slop. However, the overSlop we pass to onDragStarted() is used to
+        // compute the direction we are dragging in, so overSlop should never be 0f.
+        if (overSlop == 0f) {
+            // If the user drags in the opposite direction, the delta becomes zero because
+            // we return to the original point. Therefore, we should use the previous event
+            // to calculate the direction.
+            val delta = (drag.position - drag.previousPosition).toFloat()
+            check(delta != 0f) {
+                buildString {
+                    append("delta is equal to 0 ")
+                    append("touchSlop ${currentValueOf(LocalViewConfiguration).touchSlop} ")
+                    append("consumablePointer.position ${consumablePointer.position} ")
+                    append("drag.position ${drag.position} ")
+                    append("drag.previousPosition ${drag.previousPosition}")
                 }
-
-                // TODO(b/291055080): Replace by await[Orientation]PointerSlopOrCancellation once it
-                // is public.
-                val drag =
-                    when (orientation) {
-                        Orientation.Horizontal ->
-                            awaitHorizontalTouchSlopOrCancellation(
-                                consumablePointer.id,
-                                onSlopReached,
-                            )
-                        Orientation.Vertical ->
-                            awaitVerticalTouchSlopOrCancellation(
-                                consumablePointer.id,
-                                onSlopReached,
-                            )
-                    } ?: return
-
-                lastPointersDown =
-                    checkNotNull(pointersInfo()) {
-                        "We should have pointers down, last event: $currentEvent"
-                    }
-                        as PointersInfo.PointersDown
-                // Make sure that overSlop is not 0f. This can happen when the user drags by exactly
-                // the touch slop. However, the overSlop we pass to onDragStarted() is used to
-                // compute the direction we are dragging in, so overSlop should never be 0f unless
-                // we intercept an ongoing swipe transition (i.e. startDragImmediately() returned
-                // true).
-                if (overSlop == 0f) {
-                    // If the user drags in the opposite direction, the delta becomes zero because
-                    // we return to the original point. Therefore, we should use the previous event
-                    // to calculate the direction.
-                    val delta = (drag.position - drag.previousPosition).toFloat()
-                    check(delta != 0f) {
-                        buildString {
-                            append("delta is equal to 0 ")
-                            append("touchSlop ${currentValueOf(LocalViewConfiguration).touchSlop} ")
-                            append("consumablePointer.position ${consumablePointer.position} ")
-                            append("drag.position ${drag.position} ")
-                            append("drag.previousPosition ${drag.previousPosition}")
-                        }
-                    }
-                    overSlop = delta.sign
-                }
-                drag
             }
+            overSlop = delta.sign
+        }
 
         val controller = onDragStart(lastPointersDown, overSlop)
-
         val successful: Boolean
         try {
             onDrag(controller, overSlop)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
index 5ab306a..6ef8b86 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -149,7 +149,6 @@
         delegate(
             MultiPointerDraggableNode(
                 orientation = draggableHandler.orientation,
-                startDragImmediately = ::startDragImmediately,
                 onDragStarted = draggableHandler::onDragStarted,
                 onFirstPointerDown = ::onFirstPointerDown,
                 swipeDetector = swipeDetector,
@@ -198,21 +197,6 @@
     ) = multiPointerDraggableNode.onPointerEvent(pointerEvent, pass, bounds)
 
     override fun onCancelPointerInput() = multiPointerDraggableNode.onCancelPointerInput()
-
-    private fun startDragImmediately(pointersDown: PointersInfo.PointersDown): Boolean {
-        // Immediately start the drag if the user can't swipe in the other direction and the gesture
-        // handler can intercept it.
-        return !canOppositeSwipe() && draggableHandler.shouldImmediatelyIntercept(pointersDown)
-    }
-
-    private fun canOppositeSwipe(): Boolean {
-        val oppositeOrientation =
-            when (draggableHandler.orientation) {
-                Orientation.Vertical -> Orientation.Horizontal
-                Orientation.Horizontal -> Orientation.Vertical
-            }
-        return draggableHandler.contentForSwipes().shouldEnableSwipes(oppositeOrientation)
-    }
 }
 
 /** Find the [ScrollBehaviorOwner] for the current orientation. */
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index a1077cf..394568d 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -234,12 +234,6 @@
             )
         }
 
-        fun onDragStartedImmediately(
-            pointersInfo: PointersInfo.PointersDown = pointersDown()
-        ): DragController {
-            return onDragStarted(draggableHandler, pointersInfo, overSlop = 0f)
-        }
-
         fun onDragStarted(
             draggableHandler: DraggableHandler,
             pointersInfo: PointersInfo.PointersDown = pointersDown(),
@@ -602,82 +596,6 @@
     }
 
     @Test
-    fun onAcceleratedScroll_scrollToThirdScene() = runGestureTest {
-        // Drag A -> B with progress 0.2
-        val dragController1 = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
-        assertTransition(
-            currentScene = SceneA,
-            fromScene = SceneA,
-            toScene = SceneB,
-            progress = 0.2f,
-        )
-
-        // Start animation A -> B with progress 0.2 -> 1.0
-        dragController1.onDragStoppedAnimateLater(velocity = -velocityThreshold)
-        assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
-
-        // While at A -> B do a 100% screen drag (progress 1.2). This should go past B and change
-        // the transition to B -> C with progress 0.2
-        val dragController2 = onDragStartedImmediately()
-        dragController2.onDragDelta(pixels = up(fractionOfScreen = 1f))
-        assertTransition(
-            currentScene = SceneB,
-            fromScene = SceneB,
-            toScene = SceneC,
-            progress = 0.2f,
-        )
-
-        // After the drag stopped scene C should be committed
-        dragController2.onDragStoppedAnimateNow(
-            velocity = -velocityThreshold,
-            onAnimationStart = {
-                assertTransition(currentScene = SceneC, fromScene = SceneB, toScene = SceneC)
-            },
-            expectedConsumedVelocity = -velocityThreshold,
-        )
-        assertIdle(currentScene = SceneC)
-    }
-
-    @Test
-    fun onAcceleratedScrollBothTargetsBecomeNull_settlesToIdle() = runGestureTest {
-        val dragController1 = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
-        dragController1.onDragDelta(pixels = up(fractionOfScreen = 0.2f))
-        dragController1.onDragStoppedAnimateLater(velocity = -velocityThreshold)
-        assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
-
-        mutableUserActionsA = emptyMap()
-        mutableUserActionsB = emptyMap()
-
-        // start acceleratedScroll and scroll over to B -> null
-        val dragController2 = onDragStartedImmediately()
-        dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
-        dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
-
-        // here onDragStopped is already triggered, but subsequent onDelta/onDragStopped calls may
-        // still be called. Make sure that they don't crash or change the scene
-        dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
-        dragController2.onDragStoppedAnimateNow(
-            velocity = 0f,
-            onAnimationStart = {
-                assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
-            },
-            expectedConsumedVelocity = 0f,
-        )
-
-        advanceUntilIdle()
-        assertIdle(SceneB)
-
-        // These events can still come in after the animation has settled
-        dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
-        dragController2.onDragStoppedAnimateNow(
-            velocity = 0f,
-            onAnimationStart = { assertIdle(SceneB) },
-            expectedConsumedVelocity = 0f,
-        )
-        assertIdle(SceneB)
-    }
-
-    @Test
     fun onDragTargetsChanged_targetStaysTheSame() = runGestureTest {
         val dragController1 = onDragStarted(overSlop = up(fractionOfScreen = 0.1f))
         assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.1f)
@@ -711,9 +629,8 @@
         dragController1.onDragStoppedAnimateLater(velocity = down(fractionOfScreen = 0.1f))
 
         // now target changed to C for new drag that started before previous drag settled to Idle
-        val dragController2 = onDragStartedImmediately()
-        dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.1f))
-        assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.3f)
+        onDragStarted(overSlop = up(fractionOfScreen = 0.1f))
+        assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.1f)
     }
 
     @Test
@@ -728,7 +645,7 @@
         assertThat(isUserInputOngoing).isFalse()
 
         // Start a new gesture while the offset is animating
-        onDragStartedImmediately()
+        onDragStarted(overSlop = up(fractionOfScreen = 0.1f))
         assertThat(isUserInputOngoing).isTrue()
     }
 
@@ -812,36 +729,6 @@
     }
 
     @Test
-    fun scrollAndFling_scrollLessThanInterceptable_goToIdleOnCurrentScene() = runGestureTest {
-        val firstScroll = (transitionInterceptionThreshold - 0.0001f) * SCREEN_SIZE
-        val secondScroll = 1f
-
-        preScrollAfterSceneTransition(firstScroll = firstScroll, secondScroll = secondScroll)
-
-        assertIdle(SceneA)
-    }
-
-    @Test
-    fun scrollAndFling_scrollMinInterceptable_interceptPreScrollEvents() = runGestureTest {
-        val firstScroll = (transitionInterceptionThreshold + 0.0001f) * SCREEN_SIZE
-        val secondScroll = 1f
-
-        preScrollAfterSceneTransition(firstScroll = firstScroll, secondScroll = secondScroll)
-
-        assertTransition(progress = (firstScroll + secondScroll) / SCREEN_SIZE)
-    }
-
-    @Test
-    fun scrollAndFling_scrollMaxInterceptable_interceptPreScrollEvents() = runGestureTest {
-        val firstScroll = -(1f - transitionInterceptionThreshold - 0.0001f) * SCREEN_SIZE
-        val secondScroll = -1f
-
-        preScrollAfterSceneTransition(firstScroll = firstScroll, secondScroll = secondScroll)
-
-        assertTransition(progress = -(firstScroll + secondScroll) / SCREEN_SIZE)
-    }
-
-    @Test
     fun scrollAndFling_scrollMoreThanInterceptable_goToIdleOnNextScene() = runGestureTest {
         val firstScroll = -(1f - transitionInterceptionThreshold + 0.0001f) * SCREEN_SIZE
         val secondScroll = -0.01f
@@ -1025,7 +912,7 @@
 
         // now we can intercept the scroll events
         nestedScroll.scroll(available = -offsetY10)
-        assertThat(progress).isEqualTo(0.2f)
+        assertThat(progress).isEqualTo(0.1f)
 
         // this should be ignored, we are scrolling now!
         dragController.onDragStoppedAnimateNow(
@@ -1036,10 +923,10 @@
         assertTransition(currentScene = SceneA)
 
         nestedScroll.scroll(available = -offsetY10)
-        assertThat(progress).isEqualTo(0.3f)
+        assertThat(progress).isEqualTo(0.2f)
 
         nestedScroll.scroll(available = -offsetY10)
-        assertThat(progress).isEqualTo(0.4f)
+        assertThat(progress).isEqualTo(0.3f)
 
         nestedScroll.preFling(available = Velocity(0f, -velocityThreshold))
         assertTransition(currentScene = SceneB)
@@ -1050,57 +937,6 @@
     }
 
     @Test
-    fun interceptTransition() = runGestureTest {
-        // Start at scene C.
-        navigateToSceneC()
-
-        // Swipe up from the middle to transition to scene B.
-        val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
-        onDragStarted(pointersInfo = middle, overSlop = up(0.1f))
-        assertTransition(
-            currentScene = SceneC,
-            fromScene = SceneC,
-            toScene = SceneB,
-            progress = 0.1f,
-            isUserInputOngoing = true,
-        )
-
-        val firstTransition = transitionState
-
-        // During the current gesture, start a new gesture, still in the middle of the screen. We
-        // should intercept it. Because it is intercepted, the overSlop passed to onDragStarted()
-        // should be 0f.
-        assertThat(draggableHandler.shouldImmediatelyIntercept(middle)).isTrue()
-        onDragStartedImmediately(pointersInfo = middle)
-
-        // We should have intercepted the transition, so the transition should be the same object.
-        assertTransition(
-            currentScene = SceneC,
-            fromScene = SceneC,
-            toScene = SceneB,
-            progress = 0.1f,
-            isUserInputOngoing = true,
-        )
-        // We should have a new transition
-        assertThat(transitionState).isNotSameInstanceAs(firstTransition)
-
-        // Start a new gesture from the bottom of the screen. Because swiping up from the bottom of
-        // C leads to scene A (and not B), the previous transitions is *not* intercepted and we
-        // instead animate from C to A.
-        val bottom = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2, SCREEN_SIZE))
-        assertThat(draggableHandler.shouldImmediatelyIntercept(bottom)).isFalse()
-        onDragStarted(pointersInfo = bottom, overSlop = up(0.1f))
-
-        assertTransition(
-            currentScene = SceneC,
-            fromScene = SceneC,
-            toScene = SceneA,
-            isUserInputOngoing = true,
-        )
-        assertThat(transitionState).isNotSameInstanceAs(firstTransition)
-    }
-
-    @Test
     fun freezeAndAnimateToCurrentState() = runGestureTest {
         // Start at scene C.
         navigateToSceneC()
@@ -1110,9 +946,6 @@
         onDragStarted(pointersInfo = middle, overSlop = up(0.1f))
         assertTransition(fromScene = SceneC, toScene = SceneB, isUserInputOngoing = true)
 
-        // The current transition can be intercepted.
-        assertThat(draggableHandler.shouldImmediatelyIntercept(middle)).isTrue()
-
         // Freeze the transition.
         val transition = transitionState as Transition
         transition.freezeAndAnimateToCurrentState()
@@ -1123,19 +956,6 @@
     }
 
     @Test
-    fun interruptedTransitionCanNotBeImmediatelyIntercepted() = runGestureTest {
-        assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isFalse()
-        onDragStarted(overSlop = up(0.1f))
-        assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isTrue()
-
-        layoutState.startTransitionImmediately(
-            animationScope = testScope.backgroundScope,
-            transition(SceneA, SceneB),
-        )
-        assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isFalse()
-    }
-
-    @Test
     fun blockTransition() = runGestureTest {
         assertIdle(SceneA)
 
@@ -1154,30 +974,6 @@
     }
 
     @Test
-    fun blockInterceptedTransition() = runGestureTest {
-        assertIdle(SceneA)
-
-        // Swipe up to B.
-        val dragController1 = onDragStarted(overSlop = up(0.1f))
-        assertTransition(currentScene = SceneA, fromScene = SceneA, toScene = SceneB)
-        dragController1.onDragStoppedAnimateLater(velocity = -velocityThreshold)
-        assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
-
-        // Intercept the transition and swipe down back to scene A.
-        assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isTrue()
-        val dragController2 = onDragStartedImmediately()
-
-        // Block the transition when the user release their finger.
-        canChangeScene = { false }
-        dragController2.onDragStoppedAnimateNow(
-            velocity = velocityThreshold,
-            onAnimationStart = { assertTransition(fromScene = SceneA, toScene = SceneB) },
-            expectedConsumedVelocity = velocityThreshold,
-        )
-        assertIdle(SceneB)
-    }
-
-    @Test
     fun scrollFromIdleWithNoTargetScene_shouldUseOverscrollSpecIfAvailable() = runGestureTest {
         layoutState.transitions = transitions {
             overscroll(SceneC, Orientation.Vertical) { fade(TestElements.Foo) }
@@ -1531,25 +1327,6 @@
     }
 
     @Test
-    fun interceptingTransitionKeepsDistance() = runGestureTest {
-        var swipeDistance = 75f
-        layoutState.transitions = transitions {
-            from(SceneA, to = SceneB) { distance = UserActionDistance { _, _, _ -> swipeDistance } }
-        }
-
-        // Start transition.
-        val controller = onDragStarted(overSlop = -50f)
-        assertTransition(fromScene = SceneA, toScene = SceneB, progress = 50f / 75f)
-
-        // Intercept the transition and change the swipe distance. The original distance and
-        // progress should be the same.
-        swipeDistance = 50f
-        controller.onDragStoppedAnimateLater(0f)
-        onDragStartedImmediately()
-        assertTransition(fromScene = SceneA, toScene = SceneB, progress = 50f / 75f)
-    }
-
-    @Test
     fun requireFullDistanceSwipe() = runGestureTest {
         mutableUserActionsA +=
             Swipe.Up to UserActionResult(SceneB, requiresFullDistanceSwipe = true)
@@ -1579,19 +1356,6 @@
     }
 
     @Test
-    fun interceptingTransitionReplacesCurrentTransition() = runGestureTest {
-        val controller = onDragStarted(overSlop = up(fractionOfScreen = 0.5f))
-        val transition = assertThat(layoutState.transitionState).isSceneTransition()
-        controller.onDragStoppedAnimateLater(velocity = 0f)
-
-        // Intercept the transition.
-        onDragStartedImmediately()
-        val newTransition = assertThat(layoutState.transitionState).isSceneTransition()
-        assertThat(newTransition).isNotSameInstanceAs(transition)
-        assertThat(newTransition.replacedTransition).isSameInstanceAs(transition)
-    }
-
-    @Test
     fun showOverlay() = runGestureTest {
         mutableUserActionsA = mapOf(Swipe.Down to UserActionResult.ShowOverlay(OverlayA))
 
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
index cb3e433..4153350 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
@@ -101,7 +101,6 @@
                     .thenIf(enabled) {
                         Modifier.multiPointerDraggable(
                             orientation = Orientation.Vertical,
-                            startDragImmediately = { false },
                             onDragStarted = { _, _ ->
                                 started = true
                                 SimpleDragController(
@@ -169,8 +168,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        // We want to start a drag gesture immediately
-                        startDragImmediately = { true },
                         onDragStarted = { _, _ ->
                             started = true
                             SimpleDragController(
@@ -242,7 +239,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        startDragImmediately = { false },
                         onDragStarted = { _, _ ->
                             started = true
                             SimpleDragController(
@@ -361,7 +357,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        startDragImmediately = { false },
                         onDragStarted = { _, _ ->
                             started = true
                             SimpleDragController(
@@ -466,7 +461,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        startDragImmediately = { false },
                         onDragStarted = { _, _ ->
                             verticalStarted = true
                             SimpleDragController(
@@ -478,7 +472,6 @@
                     )
                     .multiPointerDraggable(
                         orientation = Orientation.Horizontal,
-                        startDragImmediately = { false },
                         onDragStarted = { _, _ ->
                             horizontalStarted = true
                             SimpleDragController(
@@ -570,7 +563,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        startDragImmediately = { false },
                         swipeDetector =
                             object : SwipeDetector {
                                 override fun detectSwipe(change: PointerInputChange): Boolean {
@@ -636,7 +628,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        startDragImmediately = { false },
                         swipeDetector =
                             object : SwipeDetector {
                                 override fun detectSwipe(change: PointerInputChange): Boolean {
@@ -738,7 +729,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        startDragImmediately = { false },
                         onDragStarted = { _, _ ->
                             SimpleDragController(
                                 onDrag = { consumedOnDrag = it },
@@ -809,7 +799,6 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
-                        startDragImmediately = { false },
                         onDragStarted = { _, _ ->
                             SimpleDragController(
                                 onDrag = { /* do nothing */ },