Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt +39 −7 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) } } } Loading @@ -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, Loading Loading @@ -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 val taskId = rightTaskResizingHelper?.taskInfo?.taskId if (taskId != null && taskRepository.isVisibleTask(taskId)) { rightTaskResizingHelper ?.desktopModeWindowDecoration ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate) } tearDownTiling() return } Loading @@ -563,9 +593,12 @@ class DesktopTilingWindowDecoration( if (taskId == rightTaskResizingHelper?.taskInfo?.taskId) { removeTask(rightTaskResizingHelper, taskVanished, shouldDelayUpdate) rightTaskResizingHelper = null val taskId = leftTaskResizingHelper?.taskInfo?.taskId if (taskId != null && taskRepository.isVisibleTask(taskId)) { leftTaskResizingHelper ?.desktopModeWindowDecoration ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate) } tearDownTiling() } } Loading Loading @@ -600,7 +633,6 @@ class DesktopTilingWindowDecoration( fun onOverviewAnimationStateChange(isRunning: Boolean) { if (!isTilingManagerInitialised) return if (isRunning) { desktopTilingDividerWindowManager?.hideDividerBar() } else if (allTiledTasksVisible()) { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt +12 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt +52 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -551,6 +555,37 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { verify(tiledTaskHelper, times(1)).dispose() } @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() Loading Loading @@ -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) Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt +39 −7 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) } } } Loading @@ -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, Loading Loading @@ -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 val taskId = rightTaskResizingHelper?.taskInfo?.taskId if (taskId != null && taskRepository.isVisibleTask(taskId)) { rightTaskResizingHelper ?.desktopModeWindowDecoration ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate) } tearDownTiling() return } Loading @@ -563,9 +593,12 @@ class DesktopTilingWindowDecoration( if (taskId == rightTaskResizingHelper?.taskInfo?.taskId) { removeTask(rightTaskResizingHelper, taskVanished, shouldDelayUpdate) rightTaskResizingHelper = null val taskId = leftTaskResizingHelper?.taskInfo?.taskId if (taskId != null && taskRepository.isVisibleTask(taskId)) { leftTaskResizingHelper ?.desktopModeWindowDecoration ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate) } tearDownTiling() } } Loading Loading @@ -600,7 +633,6 @@ class DesktopTilingWindowDecoration( fun onOverviewAnimationStateChange(isRunning: Boolean) { if (!isTilingManagerInitialised) return if (isRunning) { desktopTilingDividerWindowManager?.hideDividerBar() } else if (allTiledTasksVisible()) { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt +12 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt +52 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -551,6 +555,37 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { verify(tiledTaskHelper, times(1)).dispose() } @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() Loading Loading @@ -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) Loading