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

Commit 6768e5f0 authored by Gustav Sennton's avatar Gustav Sennton Committed by Android (Google) Code Review
Browse files

Merge "Drag-to-desktop transition: attach visual indicator to transition root" into main

parents 300f9f59 38a5db4f
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -103,6 +103,10 @@ public class DesktopModeVisualIndicator {
                return null;
            }
        }

        private static boolean isDragToDesktopStartState(DragStartState startState) {
            return startState == FROM_FULLSCREEN || startState == FROM_SPLIT;
        }
    }

    private final VisualIndicatorViewContainer mVisualIndicatorViewContainer;
@@ -125,7 +129,12 @@ public class DesktopModeVisualIndicator {
            @Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider,
            SnapEventHandler snapEventHandler) {
        SurfaceControl.Builder builder = new SurfaceControl.Builder();
        if (!DragStartState.isDragToDesktopStartState(dragStartState)
                || !DesktopModeFlags.ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX.isTrue()) {
            // In the DragToDesktop transition we attach the indicator to the transition root once
            // that is available - for all other cases attach the indicator here.
            taskDisplayAreaOrganizer.attachToDisplayArea(taskInfo.displayId, builder);
        }
        mVisualIndicatorViewContainer = new VisualIndicatorViewContainer(
                DesktopModeFlags.ENABLE_DESKTOP_INDICATOR_IN_SEPARATE_THREAD_BUGFIX.isTrue()
                        ? desktopExecutor : mainExecutor,
@@ -159,6 +168,18 @@ public class DesktopModeVisualIndicator {
        mVisualIndicatorViewContainer.releaseVisualIndicator();
    }

    /** Reparent the visual indicator to {@code newParent}. */
    void reparentLeash(SurfaceControl.Transaction t, SurfaceControl newParent) {
        mVisualIndicatorViewContainer.reparentLeash(t, newParent);
    }

    /** Start the fade-in animation. */
    void fadeInIndicator() {
        mVisualIndicatorViewContainer.fadeInIndicator(
                mDisplayController.getDisplayLayout(mTaskInfo.displayId), mCurrentType,
                mTaskInfo.displayId);
    }

    /**
     * Based on the coordinates of the current drag event, determine which indicator type we should
     * display, including no visible indicator.
+1 −0
Original line number Diff line number Diff line
@@ -639,6 +639,7 @@ class DesktopTasksController(
        dragToDesktopTransitionHandler.startDragToDesktopTransition(
            taskInfo,
            dragToDesktopValueAnimator,
            visualIndicator,
        )
    }

+29 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.SystemProperties
import android.os.UserHandle
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_CLOSE
import android.window.DesktopModeFlags
import android.window.TransitionInfo
import android.window.TransitionInfo.Change
import android.window.TransitionRequestInfo
@@ -118,6 +119,7 @@ sealed class DragToDesktopTransitionHandler(
    fun startDragToDesktopTransition(
        taskInfo: RunningTaskInfo,
        dragToDesktopAnimator: MoveToDesktopAnimator,
        visualIndicator: DesktopModeVisualIndicator?,
    ) {
        if (inProgress) {
            logV("Drag to desktop transition already in progress.")
@@ -163,12 +165,14 @@ sealed class DragToDesktopTransitionHandler(
                    dragAnimator = dragToDesktopAnimator,
                    startTransitionToken = startTransitionToken,
                    otherSplitTask = otherTask,
                    visualIndicator = visualIndicator,
                )
            } else {
                TransitionState.FromFullscreen(
                    draggedTaskId = taskInfo.taskId,
                    dragAnimator = dragToDesktopAnimator,
                    startTransitionToken = startTransitionToken,
                    visualIndicator = visualIndicator,
                )
            }
    }
@@ -457,6 +461,13 @@ sealed class DragToDesktopTransitionHandler(
        state.surfaceLayers = layers
        state.startTransitionFinishCb = finishCallback
        state.startTransitionFinishTransaction = finishTransaction

        val taskChange = state.draggedTaskChange ?: error("Expected non-null task change.")
        val taskInfo = taskChange.taskInfo ?: error("Expected non-null task info.")

        if (DesktopModeFlags.ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX.isTrue) {
            attachIndicatorToTransitionRoot(state, info, taskInfo, startTransaction)
        }
        startTransaction.apply()

        if (state.cancelState == CancelState.NO_CANCEL) {
@@ -485,8 +496,6 @@ sealed class DragToDesktopTransitionHandler(
                } else {
                    SPLIT_POSITION_BOTTOM_OR_RIGHT
                }
            val taskInfo =
                state.draggedTaskChange?.taskInfo ?: error("Expected non-null task info.")
            val wct = WindowContainerTransaction()
            restoreWindowOrder(wct)
            state.startTransitionFinishTransaction?.apply()
@@ -511,6 +520,21 @@ sealed class DragToDesktopTransitionHandler(
        return true
    }

    private fun attachIndicatorToTransitionRoot(
        state: TransitionState,
        info: TransitionInfo,
        taskInfo: RunningTaskInfo,
        t: SurfaceControl.Transaction,
    ) {
        val transitionRoot = info.getRoot(info.findRootIndex(taskInfo.displayId))
        state.visualIndicator?.let {
            // Attach the indicator to the transition root so that it's removed at the end of the
            // transition regardless of whether we managed to release the indicator.
            it.reparentLeash(t, transitionRoot.leash)
            it.fadeInIndicator()
        }
    }

    /**
     * Calculates start drag to desktop layers for transition [info]. The leash layer is calculated
     * based on its change position in the transition, e.g. `appLayer = appLayers - i`, where i is
@@ -901,6 +925,7 @@ sealed class DragToDesktopTransitionHandler(
        abstract var surfaceLayers: DragToDesktopLayers?
        abstract var cancelState: CancelState
        abstract var startAborted: Boolean
        abstract val visualIndicator: DesktopModeVisualIndicator?

        data class FromFullscreen(
            override val draggedTaskId: Int,
@@ -915,6 +940,7 @@ sealed class DragToDesktopTransitionHandler(
            override var surfaceLayers: DragToDesktopLayers? = null,
            override var cancelState: CancelState = CancelState.NO_CANCEL,
            override var startAborted: Boolean = false,
            override val visualIndicator: DesktopModeVisualIndicator?,
            var otherRootChanges: MutableList<Change> = mutableListOf(),
        ) : TransitionState()

@@ -931,6 +957,7 @@ sealed class DragToDesktopTransitionHandler(
            override var surfaceLayers: DragToDesktopLayers? = null,
            override var cancelState: CancelState = CancelState.NO_CANCEL,
            override var startAborted: Boolean = false,
            override val visualIndicator: DesktopModeVisualIndicator?,
            var splitRootChange: Change? = null,
            var otherSplitTask: Int,
        ) : TransitionState()
+20 −2
Original line number Diff line number Diff line
@@ -130,6 +130,12 @@ constructor(
        }
    }

    /** Reparent the indicator to {@code newParent}. */
    fun reparentLeash(t: SurfaceControl.Transaction, newParent: SurfaceControl) {
        val leash = indicatorLeash ?: return
        t.reparent(leash, newParent)
    }

    private fun showIndicator(taskSurface: SurfaceControl, leash: SurfaceControl) {
        mainExecutor.execute {
            indicatorLeash = leash
@@ -166,7 +172,7 @@ constructor(
                displayController.getDisplayLayout(taskInfo.displayId)
                    ?: error("Expected to find DisplayLayout for taskId${taskInfo.taskId}.")
            if (currentType == IndicatorType.NO_INDICATOR) {
                fadeInIndicator(layout, newType, taskInfo.displayId, snapEventHandler)
                fadeInIndicatorInternal(layout, newType, taskInfo.displayId, snapEventHandler)
            } else if (newType == IndicatorType.NO_INDICATOR) {
                fadeOutIndicator(
                    layout,
@@ -194,11 +200,23 @@ constructor(
        }
    }

    /**
     * Fade indicator in as provided type.
     *
     * Animator fades the indicator in while expanding the bounds outwards.
     */
    fun fadeInIndicator(layout: DisplayLayout, type: IndicatorType, displayId: Int) {
        if (isReleased) return
        desktopExecutor.execute {
            fadeInIndicatorInternal(layout, type, displayId, snapEventHandler)
        }
    }

    /**
     * Fade indicator in as provided type. Animator fades it in while expanding the bounds outwards.
     */
    @VisibleForTesting
    fun fadeInIndicator(
    fun fadeInIndicatorInternal(
        layout: DisplayLayout,
        type: IndicatorType,
        displayId: Int,
+36 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.animation.AnimatorTestRule
import android.app.ActivityManager.RunningTaskInfo
import android.graphics.PointF
import android.graphics.Rect
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -28,6 +29,7 @@ import android.view.SurfaceControl
import androidx.test.filters.SmallTest
import com.android.internal.policy.SystemBarUtils
import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE
import com.android.window.flags.Flags.FLAG_ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTestCase
@@ -45,6 +47,8 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.kotlin.any
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

/**
@@ -345,6 +349,38 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
        assertThat(visualIndicator.indicatorBounds).isEqualTo(dropTargetBounds)
    }

    @Test
    @DisableFlags(FLAG_ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX)
    fun createIndicator_inTransitionFlagDisabled_isAttachedToDisplayArea() {
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN)

        verify(taskDisplayAreaOrganizer).attachToDisplayArea(anyInt(), any())
    }

    @Test
    @EnableFlags(FLAG_ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX)
    fun createIndicator_fromFreeform_inTransitionFlagEnabled_isAttachedToDisplayArea() {
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM)

        verify(taskDisplayAreaOrganizer).attachToDisplayArea(anyInt(), any())
    }

    @Test
    @EnableFlags(FLAG_ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX)
    fun createIndicator_fromFullscreen_inTransitionFlagEnabled_notAttachedToDisplayArea() {
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN)

        verify(taskDisplayAreaOrganizer, never()).attachToDisplayArea(anyInt(), any())
    }

    @Test
    @EnableFlags(FLAG_ENABLE_VISUAL_INDICATOR_IN_TRANSITION_BUGFIX)
    fun createIndicator_fromSplit_inTransitionFlagEnabled_notAttachedToDisplayArea() {
        createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT)

        verify(taskDisplayAreaOrganizer, never()).attachToDisplayArea(anyInt(), any())
    }

    private fun createVisualIndicator(dragStartState: DesktopModeVisualIndicator.DragStartState) {
        visualIndicator =
            DesktopModeVisualIndicator(
Loading