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

Commit ebab3341 authored by Ats Jenk's avatar Ats Jenk
Browse files

Reparent task before setting always on top

Always on top does not work for nested tasks.
Make sure task is reparented before setting it to always on top.

Bug: 396313972
Test: atest WMShellUnitTests:BubbleUtilsTest
Flag: com.android.wm.shell.enable_create_any_bubble
Change-Id: Ia0b421a70403e2dd853b4695032c2c742ecbcc68
parent f3df552c
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -1077,16 +1077,15 @@ public class BubbleTransitions {
            }
            final Rect launchBounds = new Rect();
            mLayerView.getExpandedViewRestBounds(launchBounds);
            final boolean reparentToTda =
                    mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
                            && mTaskInfo.getParentTaskId() != INVALID_TASK_ID;

            final WindowContainerTransaction wct = getEnterBubbleTransaction(
                    mTaskInfo.token, true /* isAppBubble */);
                    mTaskInfo.token, true /* isAppBubble */, reparentToTda);
            mHomeIntentProvider.addLaunchHomePendingIntent(wct, mTaskInfo.displayId,
                    mTaskInfo.userId);

            if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
                if (mTaskInfo.getParentTaskId() != INVALID_TASK_ID) {
                    wct.reparent(mTaskInfo.token, null, true);
                }
            }
            wct.setBounds(mTaskInfo.token, launchBounds);

            final TaskView tv = b.getTaskView();
+12 −0
Original line number Diff line number Diff line
@@ -30,8 +30,14 @@ private fun getBubbleTransaction(
    token: WindowContainerToken,
    toBubble: Boolean,
    isAppBubble: Boolean,
    reparentToTda: Boolean,
): WindowContainerTransaction {
    val wct = WindowContainerTransaction()
    if (reparentToTda) {
        // Reparenting must happen before setAlwaysOnTop() below since WCT operations are applied in
        // order and always-on-top for nested tasks is not supported
        wct.reparent(token, null, true)
    }
    wct.setWindowingMode(
        token,
        if (toBubble)
@@ -64,15 +70,20 @@ private fun getBubbleTransaction(
 * Returns a [WindowContainerTransaction] that includes the necessary operations of entering Bubble.
 *
 * @param isAppBubble App Bubble has some different UX from Chat Bubble.
 * @param reparentToTda Whether to reparent the task to the ancestor TaskDisplayArea (for if this
 *                      task is a child of another root task)
 */
@JvmOverloads
fun getEnterBubbleTransaction(
    token: WindowContainerToken,
    isAppBubble: Boolean,
    reparentToTda: Boolean = false,
): WindowContainerTransaction {
    return getBubbleTransaction(
        token,
        toBubble = true,
        isAppBubble,
        reparentToTda,
    )
}

@@ -87,6 +98,7 @@ fun getExitBubbleTransaction(
        toBubble = false,
        // Everything will be reset, so doesn't matter for exit.
        isAppBubble = true,
        reparentToTda = false,
    )
}
+19 −1
Original line number Diff line number Diff line
@@ -58,6 +58,24 @@ class BubbleUtilsTest : ShellTestCase() {
        verifyEnterBubbleTransaction(wctWithLaunchNextToBubble, token.asBinder(), isAppBubble)
    }

    @EnableFlags(
        FLAG_ENABLE_CREATE_ANY_BUBBLE,
        FLAG_EXCLUDE_TASK_FROM_RECENTS,
        FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP,
    )
    @Test
    fun testGetEnterBubbleTransaction_reparentToTda(@TestParameter isAppBubble: Boolean) {
        val wctWithLaunchNextToBubble =
            getEnterBubbleTransaction(token, isAppBubble, reparentToTda = true)

        verifyEnterBubbleTransaction(
            wctWithLaunchNextToBubble,
            token.asBinder(),
            isAppBubble,
            reparentToTda = true,
        )
    }

    @EnableFlags(
        FLAG_ENABLE_CREATE_ANY_BUBBLE,
        FLAG_EXCLUDE_TASK_FROM_RECENTS,
+21 −5
Original line number Diff line number Diff line
@@ -20,20 +20,36 @@ import android.app.WindowConfiguration
import android.os.IBinder
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.Change.CHANGE_LAUNCH_NEXT_TO_BUBBLE
import android.window.WindowContainerTransaction.HierarchyOp
import com.google.common.truth.Truth.assertThat

/** Verifies the [WindowContainerTransaction] to enter Bubble. */
@JvmOverloads
fun verifyEnterBubbleTransaction(
    wct: WindowContainerTransaction,
    taskToken: IBinder,
    isAppBubble: Boolean,
    reparentToTda: Boolean = false,
) {
    // Verify hierarchy ops

    val alwaysOnTopOp: HierarchyOp

    if (reparentToTda) {
        assertThat(wct.hierarchyOps.size).isEqualTo(2)
        val reparentOp = wct.hierarchyOps[0]
        assertThat(reparentOp.container).isEqualTo(taskToken)
        assertThat(reparentOp.isReparent).isTrue()
        assertThat(reparentOp.newParent).isNull()
        assertThat(reparentOp.toTop).isTrue()

        alwaysOnTopOp = wct.hierarchyOps[1]
    } else {
        assertThat(wct.hierarchyOps.size).isEqualTo(1)
    val hierarchyOp = wct.hierarchyOps[0]
    assertThat(hierarchyOp.container).isEqualTo(taskToken)
    assertThat(hierarchyOp.isAlwaysOnTop).isTrue()
        alwaysOnTopOp = wct.hierarchyOps[0]
    }
    assertThat(alwaysOnTopOp.container).isEqualTo(taskToken)
    assertThat(alwaysOnTopOp.isAlwaysOnTop).isTrue()

    // Verify Change