diff options
3 files changed, 103 insertions, 7 deletions
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 c3d15df6eae5..9c55f0ecda93 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 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 @@ class DesktopTilingWindowDecoration( 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 @@ class DesktopTilingWindowDecoration( 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 @@ class DesktopTilingWindowDecoration( 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 @@ class DesktopTilingWindowDecoration( 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 @@ class DesktopTilingWindowDecoration( 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 c40a04c47b9b..b511fc34fa89 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.ACTIVITY_TYPE_STANDARD 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 @@ object DesktopTestHelpers { .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 bc8faedd77a9..e4424f3c57f2 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.testing.AndroidTestingRunner 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.DesktopModeEventLogger.Companion.ResizeT 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 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { } @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 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { 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) |