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

Commit 766f507d authored by Ivan Tkachenko's avatar Ivan Tkachenko
Browse files

Fix enter desktop transition flicker in BD2A build

There's an extra home change in enter desktop transition info in BD2A
builds (b/368334295).
- It helped to uncover that the dragged layer z-order is being reset for the 2nd (merged) transition and puts it behind wallpaper task, effectively hiding it. It's fixed by restoring the dragged layer z-order to the one assigned in the first transition.
- It also produced an unwanted consequence. Currently we expect only 1 home change in transition info, but we receive more. This CL filters only for the visible home task and uses it for the animation.

Bug: 361641893
Test: manual, atest WMShellUnitTests:DragToDesktopTransitionHandlerTest
Flag: EXEMPT bugfix
Change-Id: Ic08d55e123ad89ff3f5478b73560f56c8f46339b
parent 4addccb4
Loading
Loading
Loading
Loading
+38 −17
Original line number Original line Diff line number Diff line
@@ -304,14 +304,14 @@ sealed class DragToDesktopTransitionHandler(
        val leafTaskFilter = TransitionUtil.LeafTaskFilter()
        val leafTaskFilter = TransitionUtil.LeafTaskFilter()
        info.changes.withIndex().forEach { (i, change) ->
        info.changes.withIndex().forEach { (i, change) ->
            if (TransitionUtil.isWallpaper(change)) {
            if (TransitionUtil.isWallpaper(change)) {
                val layer = layers.wallpaperLayers - i
                val layer = layers.topWallpaperLayer - i
                startTransaction.apply {
                startTransaction.apply {
                    setLayer(change.leash, layer)
                    setLayer(change.leash, layer)
                    show(change.leash)
                    show(change.leash)
                }
                }
            } else if (isHomeChange(change)) {
            } else if (isHomeChange(change)) {
                state.homeChange = change
                state.homeChange = change
                val layer = layers.homeLayers - i
                val layer = layers.topHomeLayer - i
                startTransaction.apply {
                startTransaction.apply {
                    setLayer(change.leash, layer)
                    setLayer(change.leash, layer)
                    show(change.leash)
                    show(change.leash)
@@ -325,7 +325,7 @@ sealed class DragToDesktopTransitionHandler(
                            if (state.cancelState == CancelState.NO_CANCEL) {
                            if (state.cancelState == CancelState.NO_CANCEL) {
                                // Normal case, split root goes to the bottom behind everything
                                // Normal case, split root goes to the bottom behind everything
                                // else.
                                // else.
                                layers.appLayers - i
                                layers.topAppLayer - i
                            } else {
                            } else {
                                // Cancel-early case, pretend nothing happened so split root stays
                                // Cancel-early case, pretend nothing happened so split root stays
                                // top.
                                // top.
@@ -357,7 +357,7 @@ sealed class DragToDesktopTransitionHandler(
                            state.otherRootChanges.add(change)
                            state.otherRootChanges.add(change)
                            val bounds = change.endAbsBounds
                            val bounds = change.endAbsBounds
                            startTransaction.apply {
                            startTransaction.apply {
                                setLayer(change.leash, layers.appLayers - i)
                                setLayer(change.leash, layers.topAppLayer - i)
                                setWindowCrop(change.leash, bounds.width(), bounds.height())
                                setWindowCrop(change.leash, bounds.width(), bounds.height())
                                show(change.leash)
                                show(change.leash)
                            }
                            }
@@ -398,6 +398,7 @@ sealed class DragToDesktopTransitionHandler(
                }
                }
            }
            }
        }
        }
        state.surfaceLayers = layers
        state.startTransitionFinishCb = finishCallback
        state.startTransitionFinishCb = finishCallback
        state.startTransitionFinishTransaction = finishTransaction
        state.startTransitionFinishTransaction = finishTransaction
        startTransaction.apply()
        startTransaction.apply()
@@ -522,6 +523,10 @@ sealed class DragToDesktopTransitionHandler(
                    startTransaction.show(change.leash)
                    startTransaction.show(change.leash)
                    finishTransaction.show(change.leash)
                    finishTransaction.show(change.leash)
                    state.draggedTaskChange = change
                    state.draggedTaskChange = change
                    // Restoring the dragged leash layer as it gets reset in the merge transition
                    state.surfaceLayers?.let {
                        startTransaction.setLayer(change.leash, it.dragLayer)
                    }
                }
                }
                change.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM -> {
                change.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM -> {
                    // Other freeform tasks that are being restored go behind the dragged task.
                    // Other freeform tasks that are being restored go behind the dragged task.
@@ -642,8 +647,15 @@ sealed class DragToDesktopTransitionHandler(
        }
        }
    }
    }


    private fun isHomeChange(change: Change): Boolean {
    /** Checks if the change is a home task change */
        return change.taskInfo?.activityType == ACTIVITY_TYPE_HOME
    @VisibleForTesting
    fun isHomeChange(change: Change): Boolean {
        return change.taskInfo?.let {
            it.activityType == ACTIVITY_TYPE_HOME &&
                // Skip translucent wizard task with type home
                // TODO(b/368334295): Remove when the multiple home changes issue is resolved
                !(it.isTopActivityTransparent && it.numActivities == 1)
        } ?: false
    }
    }


    private fun startCancelAnimation() {
    private fun startCancelAnimation() {
@@ -760,12 +772,18 @@ sealed class DragToDesktopTransitionHandler(


    /**
    /**
     * Represents the layering (Z order) that will be given to any window based on its type during
     * Represents the layering (Z order) that will be given to any window based on its type during
     * the "start" transition of the drag-to-desktop transition
     * the "start" transition of the drag-to-desktop transition.
     *
     * @param topAppLayer Used to calculate the app layer z-order = `topAppLayer - changeIndex`.
     * @param topHomeLayer Used to calculate the home layer z-order = `topHomeLayer - changeIndex`.
     * @param topWallpaperLayer Used to calculate the wallpaper layer z-order = `topWallpaperLayer -
     *   changeIndex`
     * @param dragLayer Defines the drag layer z-order
     */
     */
    protected data class DragToDesktopLayers(
    data class DragToDesktopLayers(
        val appLayers: Int,
        val topAppLayer: Int,
        val homeLayers: Int,
        val topHomeLayer: Int,
        val wallpaperLayers: Int,
        val topWallpaperLayer: Int,
        val dragLayer: Int,
        val dragLayer: Int,
    )
    )


@@ -785,6 +803,7 @@ sealed class DragToDesktopTransitionHandler(
        abstract var homeChange: Change?
        abstract var homeChange: Change?
        abstract var draggedTaskChange: Change?
        abstract var draggedTaskChange: Change?
        abstract var freeformTaskChanges: List<Change>
        abstract var freeformTaskChanges: List<Change>
        abstract var surfaceLayers: DragToDesktopLayers?
        abstract var cancelState: CancelState
        abstract var cancelState: CancelState
        abstract var startAborted: Boolean
        abstract var startAborted: Boolean


@@ -798,6 +817,7 @@ sealed class DragToDesktopTransitionHandler(
            override var homeChange: Change? = null,
            override var homeChange: Change? = null,
            override var draggedTaskChange: Change? = null,
            override var draggedTaskChange: Change? = null,
            override var freeformTaskChanges: List<Change> = emptyList(),
            override var freeformTaskChanges: List<Change> = emptyList(),
            override var surfaceLayers: DragToDesktopLayers? = null,
            override var cancelState: CancelState = CancelState.NO_CANCEL,
            override var cancelState: CancelState = CancelState.NO_CANCEL,
            override var startAborted: Boolean = false,
            override var startAborted: Boolean = false,
            var otherRootChanges: MutableList<Change> = mutableListOf()
            var otherRootChanges: MutableList<Change> = mutableListOf()
@@ -813,6 +833,7 @@ sealed class DragToDesktopTransitionHandler(
            override var homeChange: Change? = null,
            override var homeChange: Change? = null,
            override var draggedTaskChange: Change? = null,
            override var draggedTaskChange: Change? = null,
            override var freeformTaskChanges: List<Change> = emptyList(),
            override var freeformTaskChanges: List<Change> = emptyList(),
            override var surfaceLayers: DragToDesktopLayers? = null,
            override var cancelState: CancelState = CancelState.NO_CANCEL,
            override var cancelState: CancelState = CancelState.NO_CANCEL,
            override var startAborted: Boolean = false,
            override var startAborted: Boolean = false,
            var splitRootChange: Change? = null,
            var splitRootChange: Change? = null,
@@ -867,9 +888,9 @@ constructor(
     */
     */
    override fun calculateStartDragToDesktopLayers(info: TransitionInfo): DragToDesktopLayers =
    override fun calculateStartDragToDesktopLayers(info: TransitionInfo): DragToDesktopLayers =
        DragToDesktopLayers(
        DragToDesktopLayers(
            appLayers = info.changes.size,
            topAppLayer = info.changes.size,
            homeLayers = info.changes.size * 2,
            topHomeLayer = info.changes.size * 2,
            wallpaperLayers = info.changes.size * 3,
            topWallpaperLayer = info.changes.size * 3,
            dragLayer = info.changes.size * 3
            dragLayer = info.changes.size * 3
        )
        )
}
}
@@ -909,9 +930,9 @@ constructor(
     */
     */
    override fun calculateStartDragToDesktopLayers(info: TransitionInfo): DragToDesktopLayers =
    override fun calculateStartDragToDesktopLayers(info: TransitionInfo): DragToDesktopLayers =
        DragToDesktopLayers(
        DragToDesktopLayers(
            appLayers = -1,
            topAppLayer = -1,
            homeLayers = info.changes.size - 1,
            topHomeLayer = info.changes.size - 1,
            wallpaperLayers = info.changes.size * 2 - 1,
            topWallpaperLayer = info.changes.size * 2 - 1,
            dragLayer = info.changes.size * 2
            dragLayer = info.changes.size * 2
        )
        )


+14 −0
Original line number Original line Diff line number Diff line
@@ -47,6 +47,8 @@ public final class TestRunningTaskInfoBuilder {
    private ActivityManager.TaskDescription.Builder mTaskDescriptionBuilder = null;
    private ActivityManager.TaskDescription.Builder mTaskDescriptionBuilder = null;
    private final Point mPositionInParent = new Point();
    private final Point mPositionInParent = new Point();
    private boolean mIsVisible = false;
    private boolean mIsVisible = false;
    private boolean mIsTopActivityTransparent = false;
    private int mNumActivities = 1;
    private long mLastActiveTime;
    private long mLastActiveTime;


    public static WindowContainerToken createMockWCToken() {
    public static WindowContainerToken createMockWCToken() {
@@ -113,6 +115,16 @@ public final class TestRunningTaskInfoBuilder {
        return this;
        return this;
    }
    }


    public TestRunningTaskInfoBuilder setTopActivityTransparent(boolean isTopActivityTransparent) {
        mIsTopActivityTransparent = isTopActivityTransparent;
        return this;
    }

    public TestRunningTaskInfoBuilder setNumActivities(int numActivities) {
        mNumActivities = numActivities;
        return this;
    }

    public TestRunningTaskInfoBuilder setLastActiveTime(long lastActiveTime) {
    public TestRunningTaskInfoBuilder setLastActiveTime(long lastActiveTime) {
        mLastActiveTime = lastActiveTime;
        mLastActiveTime = lastActiveTime;
        return this;
        return this;
@@ -134,6 +146,8 @@ public final class TestRunningTaskInfoBuilder {
                mTaskDescriptionBuilder != null ? mTaskDescriptionBuilder.build() : null;
                mTaskDescriptionBuilder != null ? mTaskDescriptionBuilder.build() : null;
        info.positionInParent = mPositionInParent;
        info.positionInParent = mPositionInParent;
        info.isVisible = mIsVisible;
        info.isVisible = mIsVisible;
        info.isTopActivityTransparent = mIsTopActivityTransparent;
        info.numActivities = mNumActivities;
        info.lastActiveTime = mLastActiveTime;
        info.lastActiveTime = mLastActiveTime;
        return info;
        return info;
    }
    }
+59 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
import java.util.function.Supplier
import java.util.function.Supplier
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.After
import org.junit.After
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
@@ -209,6 +210,60 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
            )
            )
    }
    }


    @Test
    fun isHomeChange_withoutTaskInfo_returnsFalse() {
        val change =
            TransitionInfo.Change(mock(), homeTaskLeash).apply {
                parent = null
                taskInfo = null
            }

        assertFalse(defaultHandler.isHomeChange(change))
        assertFalse(springHandler.isHomeChange(change))
    }

    @Test
    fun isHomeChange_withStandardActivityTaskInfo_returnsFalse() {
        val change =
            TransitionInfo.Change(mock(), homeTaskLeash).apply {
                parent = null
                taskInfo =
                    TestRunningTaskInfoBuilder().setActivityType(ACTIVITY_TYPE_STANDARD).build()
            }

        assertFalse(defaultHandler.isHomeChange(change))
        assertFalse(springHandler.isHomeChange(change))
    }

    @Test
    fun isHomeChange_withHomeActivityTaskInfo_returnsTrue() {
        val change =
            TransitionInfo.Change(mock(), homeTaskLeash).apply {
                parent = null
                taskInfo = TestRunningTaskInfoBuilder().setActivityType(ACTIVITY_TYPE_HOME).build()
            }

        assertTrue(defaultHandler.isHomeChange(change))
        assertTrue(springHandler.isHomeChange(change))
    }

    @Test
    fun isHomeChange_withSingleTranslucentHomeActivityTaskInfo_returnsFalse() {
        val change =
            TransitionInfo.Change(mock(), homeTaskLeash).apply {
                parent = null
                taskInfo =
                    TestRunningTaskInfoBuilder()
                        .setActivityType(ACTIVITY_TYPE_HOME)
                        .setTopActivityTransparent(true)
                        .setNumActivities(1)
                        .build()
            }

        assertFalse(defaultHandler.isHomeChange(change))
        assertFalse(springHandler.isHomeChange(change))
    }

    @Test
    @Test
    fun cancelDragToDesktop_startWasReady_cancel() {
    fun cancelDragToDesktop_startWasReady_cancel() {
        startDrag(defaultHandler)
        startDrag(defaultHandler)
@@ -341,6 +396,8 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
        // Should show dragged task layer in start and finish transaction
        // Should show dragged task layer in start and finish transaction
        verify(mergedStartTransaction).show(draggedTaskLeash)
        verify(mergedStartTransaction).show(draggedTaskLeash)
        verify(playingFinishTransaction).show(draggedTaskLeash)
        verify(playingFinishTransaction).show(draggedTaskLeash)
        // Should update the dragged task layer
        verify(mergedStartTransaction).setLayer(eq(draggedTaskLeash), anyInt())
        // Should merge animation
        // Should merge animation
        verify(finishCallback).onTransitionFinished(null)
        verify(finishCallback).onTransitionFinished(null)
    }
    }
@@ -371,6 +428,8 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
        // Should show dragged task layer in start and finish transaction
        // Should show dragged task layer in start and finish transaction
        verify(mergedStartTransaction).show(draggedTaskLeash)
        verify(mergedStartTransaction).show(draggedTaskLeash)
        verify(playingFinishTransaction).show(draggedTaskLeash)
        verify(playingFinishTransaction).show(draggedTaskLeash)
        // Should update the dragged task layer
        verify(mergedStartTransaction).setLayer(eq(draggedTaskLeash), anyInt())
        // Should hide home task leash in finish transaction
        // Should hide home task leash in finish transaction
        verify(playingFinishTransaction).hide(homeTaskLeash)
        verify(playingFinishTransaction).hide(homeTaskLeash)
        // Should merge animation
        // Should merge animation