Merge "Break tiling on entering pip mode." into main
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt
index c3d15df..9c55f0e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt
@@ -17,6 +17,7 @@
package com.android.wm.shell.windowdecor.tiling
import android.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
@@ -28,9 +29,11 @@
import android.view.SurfaceControl.Transaction
import android.view.WindowManager.TRANSIT_CHANGE
import android.view.WindowManager.TRANSIT_OPEN
+import android.view.WindowManager.TRANSIT_PIP
import android.view.WindowManager.TRANSIT_TO_BACK
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.TransitionInfo
+import android.window.TransitionInfo.Change
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import com.android.internal.annotations.VisibleForTesting
@@ -422,6 +425,8 @@
change.taskInfo?.let {
if (it.isFullscreen || isMinimized(change.mode, info.type)) {
removeTaskIfTiled(it.taskId, /* taskVanished= */ false, it.isFullscreen)
+ } else if (isEnteringPip(change, info.type)) {
+ removeTaskIfTiled(it.taskId, /* taskVanished= */ true, it.isFullscreen)
}
}
}
@@ -434,6 +439,27 @@
infoType == TRANSIT_OPEN))
}
+ private fun isEnteringPip(change: Change, transitType: Int): Boolean {
+ if (change.taskInfo != null && change.taskInfo?.windowingMode == WINDOWING_MODE_PINNED) {
+ // - TRANSIT_PIP: type (from RootWindowContainer)
+ // - TRANSIT_OPEN (from apps that enter PiP instantly on opening, mostly from
+ // CTS/Flicker tests).
+ // - TRANSIT_TO_FRONT, though uncommon with triggering PiP, should semantically also
+ // be allowed to animate if the task in question is pinned already - see b/308054074.
+ // - TRANSIT_CHANGE: This can happen if the request to enter PIP happens when we are
+ // collecting for another transition, such as TRANSIT_CHANGE (display rotation).
+ if (
+ transitType == TRANSIT_PIP ||
+ transitType == TRANSIT_OPEN ||
+ transitType == TRANSIT_TO_FRONT ||
+ transitType == TRANSIT_CHANGE
+ ) {
+ return true
+ }
+ }
+ return false
+ }
+
class AppResizingHelper(
val taskInfo: RunningTaskInfo,
val desktopModeWindowDecoration: DesktopModeWindowDecoration,
@@ -550,12 +576,16 @@
taskVanished: Boolean = false,
shouldDelayUpdate: Boolean = false,
) {
+ val taskRepository = desktopUserRepositories.current
if (taskId == leftTaskResizingHelper?.taskInfo?.taskId) {
removeTask(leftTaskResizingHelper, taskVanished, shouldDelayUpdate)
leftTaskResizingHelper = null
- rightTaskResizingHelper
- ?.desktopModeWindowDecoration
- ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate)
+ val taskId = rightTaskResizingHelper?.taskInfo?.taskId
+ if (taskId != null && taskRepository.isVisibleTask(taskId)) {
+ rightTaskResizingHelper
+ ?.desktopModeWindowDecoration
+ ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate)
+ }
tearDownTiling()
return
}
@@ -563,9 +593,12 @@
if (taskId == rightTaskResizingHelper?.taskInfo?.taskId) {
removeTask(rightTaskResizingHelper, taskVanished, shouldDelayUpdate)
rightTaskResizingHelper = null
- leftTaskResizingHelper
- ?.desktopModeWindowDecoration
- ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate)
+ val taskId = leftTaskResizingHelper?.taskInfo?.taskId
+ if (taskId != null && taskRepository.isVisibleTask(taskId)) {
+ leftTaskResizingHelper
+ ?.desktopModeWindowDecoration
+ ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate)
+ }
tearDownTiling()
}
}
@@ -600,7 +633,6 @@
fun onOverviewAnimationStateChange(isRunning: Boolean) {
if (!isTilingManagerInitialised) return
-
if (isRunning) {
desktopTilingDividerWindowManager?.hideDividerBar()
} else if (allTiledTasksVisible()) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt
index c40a04c..b511fc3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt
@@ -22,6 +22,7 @@
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
+import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
import android.content.ComponentName
import android.graphics.Rect
import android.view.Display.DEFAULT_DISPLAY
@@ -45,6 +46,17 @@
.apply { bounds?.let { setBounds(it) } }
.build()
+ fun createPinnedTask(displayId: Int = DEFAULT_DISPLAY, bounds: Rect? = null): RunningTaskInfo =
+ TestRunningTaskInfoBuilder()
+ .setDisplayId(displayId)
+ .setParentTaskId(displayId)
+ .setToken(MockToken().token())
+ .setActivityType(ACTIVITY_TYPE_STANDARD)
+ .setWindowingMode(WINDOWING_MODE_PINNED)
+ .setLastActiveTime(100)
+ .apply { bounds?.let { setBounds(it) } }
+ .build()
+
fun createFullscreenTaskBuilder(displayId: Int = DEFAULT_DISPLAY): TestRunningTaskInfoBuilder =
TestRunningTaskInfoBuilder()
.setDisplayId(displayId)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt
index bc8faed..e4424f3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.windowdecor.tiling
import android.app.ActivityManager
+import android.app.ActivityManager.RunningTaskInfo
import android.content.Context
import android.content.res.Resources
import android.graphics.Rect
@@ -24,8 +25,10 @@
import android.view.MotionEvent
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_CHANGE
+import android.view.WindowManager.TRANSIT_PIP
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.TransitionInfo
+import android.window.TransitionInfo.Change
import android.window.WindowContainerTransaction
import androidx.test.filters.SmallTest
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
@@ -40,6 +43,7 @@
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
+import com.android.wm.shell.desktopmode.DesktopTestHelpers.createPinnedTask
import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
@@ -552,6 +556,37 @@
}
@Test
+ fun taskTiled_shouldBeRemoved_whenEnteringPip() {
+ val task1 = createPipTask()
+ val stableBounds = STABLE_BOUNDS_MOCK
+ whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout)
+ whenever(displayLayout.getStableBounds(any())).thenAnswer { i ->
+ (i.arguments.first() as Rect).set(stableBounds)
+ }
+ whenever(context.resources).thenReturn(resources)
+ whenever(resources.getDimensionPixelSize(any())).thenReturn(split_divider_width)
+ whenever(tiledTaskHelper.taskInfo).thenReturn(task1)
+ whenever(tiledTaskHelper.desktopModeWindowDecoration).thenReturn(desktopWindowDecoration)
+ tilingDecoration.onAppTiled(
+ task1,
+ desktopWindowDecoration,
+ DesktopTasksController.SnapPosition.LEFT,
+ BOUNDS,
+ )
+ tilingDecoration.leftTaskResizingHelper = tiledTaskHelper
+ val changeInfo = createPipChangeTransition(task1)
+ tilingDecoration.onTransitionReady(
+ transition = mock(),
+ info = changeInfo,
+ startTransaction = mock(),
+ finishTransaction = mock(),
+ )
+
+ assertThat(tilingDecoration.leftTaskResizingHelper).isNull()
+ verify(tiledTaskHelper, times(1)).dispose()
+ }
+
+ @Test
fun taskNotTiled_shouldNotBeRemoved_whenNotTiled() {
val task1 = createVisibleTask()
val task2 = createVisibleTask()
@@ -652,6 +687,23 @@
whenever(userRepositories.current.isVisibleTask(eq(it.taskId))).thenReturn(true)
}
+ private fun createPipTask() =
+ createPinnedTask().also {
+ whenever(userRepositories.current.isVisibleTask(eq(it.taskId))).thenReturn(true)
+ }
+
+ private fun createPipChangeTransition(task: RunningTaskInfo?, type: Int = TRANSIT_PIP) =
+ TransitionInfo(type, /* flags= */ 0).apply {
+ addChange(
+ Change(mock(), mock()).apply {
+ mode = TRANSIT_PIP
+ parent = null
+ taskInfo = task
+ flags = flags
+ }
+ )
+ }
+
companion object {
private val NON_STABLE_BOUNDS_MOCK = Rect(50, 55, 100, 100)
private val STABLE_BOUNDS_MOCK = Rect(0, 0, 100, 100)