Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +5 −6 Original line number Diff line number Diff line Loading @@ -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(); Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/util/BubbleUtils.kt +12 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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, ) } Loading @@ -87,6 +98,7 @@ fun getExitBubbleTransaction( toBubble = false, // Everything will be reset, so doesn't matter for exit. isAppBubble = true, reparentToTda = false, ) } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/util/BubbleUtilsTest.kt +19 −1 Original line number Diff line number Diff line Loading @@ -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, Loading libs/WindowManager/Shell/tests/util/src/com/android/wm/shell/bubbles/util/BubbleTestUtils.kt +21 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +5 −6 Original line number Diff line number Diff line Loading @@ -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(); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/util/BubbleUtils.kt +12 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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, ) } Loading @@ -87,6 +98,7 @@ fun getExitBubbleTransaction( toBubble = false, // Everything will be reset, so doesn't matter for exit. isAppBubble = true, reparentToTda = false, ) }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/util/BubbleUtilsTest.kt +19 −1 Original line number Diff line number Diff line Loading @@ -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, Loading
libs/WindowManager/Shell/tests/util/src/com/android/wm/shell/bubbles/util/BubbleTestUtils.kt +21 −5 Original line number Diff line number Diff line Loading @@ -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 Loading