Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt +4 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,10 @@ class DesktopModeEventLogger { FrameworkStatsLog .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_KEY_GESTURE ), MULTI_ACTIVITY_PIP( FrameworkStatsLog .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_MULTI_ACTIVITY_PIP ), } // Default value used when the task was not unminimized. Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopPipTransitionController.kt +16 −0 Original line number Diff line number Diff line Loading @@ -274,6 +274,22 @@ class DesktopPipTransitionController( val deskId = getDeskId(desktopRepository, displayId) if (deskId == INVALID_DESK_ID) return // For multi-activity PiP, minimize the parent/original task if (taskInfo.numActivities > 1) { logD( "handlePipTransition: minimizeMultiActivityPipTask, taskId=%d deskId=%d", taskInfo.taskId, deskId, ) val runOnTransitStart = desktopTasksController.minimizeMultiActivityPipTask( wct = wct, deskId = deskId, task = taskInfo, ) runOnTransitStart?.invoke(transition) } val isLastTask = desktopRepository.isOnlyVisibleNonClosingTaskInDesk( taskId = taskId, Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +44 −19 Original line number Diff line number Diff line Loading @@ -1372,16 +1372,10 @@ class DesktopTasksController( // parent task to the back so that it is not brought to the front and shown when the // child task breaks off into PiP. val isMultiActivityPip = taskInfo.numActivities > 1 var minimizeMultiActivityRunnable: RunOnTransitStart? = null if (isMultiActivityPip) { if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.minimizeTask( wct = wct, deskId = checkNotNull(deskId) { "Expected non-null deskId" }, task = taskInfo, ) } else { wct.reorder(taskInfo.token, /* onTop= */ false) } minimizeMultiActivityRunnable = minimizeMultiActivityPipTask(wct = wct, deskId = deskId, task = taskInfo) } // If the task minimizing to PiP is the last task, modify wct to perform Desktop cleanup Loading @@ -1397,16 +1391,7 @@ class DesktopTasksController( ) } val transition = freeformTaskTransitionStarter.startPipTransition(wct) if (isMultiActivityPip) { desktopTasksLimiter.ifPresent { it.addPendingMinimizeChange( transition = transition, displayId = displayId, taskId = taskId, minimizeReason = minimizeReason, ) } } minimizeMultiActivityRunnable?.invoke(transition) desktopExitRunnable?.invoke(transition) } else { val willExitDesktop = Loading Loading @@ -1458,6 +1443,46 @@ class DesktopTasksController( ) } /** * Called when a multi-activity PiP task needs to be minimized. * * @param wct WindowContainerTransaction that will apply minimization changes * @param deskId desk id that the multi-activity PiP is in * @param taskInfo of the task that is entering PiP * @return RunOnTransitStart runnable to be invoked after the transition has been started */ fun minimizeMultiActivityPipTask( wct: WindowContainerTransaction, deskId: Int?, task: RunningTaskInfo, ): RunOnTransitStart { logD( "minimizeMultiActivityPipTask taskId=%d deskId=%d displayId=%d", task.taskId, deskId, task.displayId, ) if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.minimizeTask( wct = wct, deskId = checkNotNull(deskId) { "Expected non-null deskId" }, task = task, ) } else { wct.reorder(task.token, /* onTop= */ false) } return { transition -> desktopTasksLimiter.ifPresent { it.addPendingMinimizeChange( transition = transition, displayId = task.displayId, taskId = task.taskId, minimizeReason = MinimizeReason.MULTI_ACTIVITY_PIP, ) } } } /** Checks whether the given [taskInfo] is allowed to enter PiP in AppOps. */ private fun isPipAllowedInAppOps(taskInfo: RunningTaskInfo): Boolean { val packageName = Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopPipTransitionControllerTest.kt +10 −0 Original line number Diff line number Diff line Loading @@ -291,6 +291,16 @@ class DesktopPipTransitionControllerTest(flags: FlagsParameterization) : ShellTe verifyPerformDesktopExitCleanupAfterPip(isCalled = true) } @Test fun handlePipTransition_multiActivityPip_minimizeMultiActivityPipTask() { taskInfo.numActivities = 2 controller.handlePipTransition(wct, transition, taskInfo) verify(mockDesktopTasksController) .minimizeMultiActivityPipTask(wct = wct, deskId = DESK_ID, task = taskInfo) } private fun verifyPerformDesktopExitCleanupAfterPip(isCalled: Boolean) { if (isCalled) { verify(mockDesktopTasksController) Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +18 −0 Original line number Diff line number Diff line Loading @@ -4979,6 +4979,24 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(anyBoolean()) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun minimizeMultiActivityPipTask_minimizesTask() { val deskId = DEFAULT_DISPLAY val task = setUpPipTask(autoEnterEnabled = true, deskId = deskId) val wct = WindowContainerTransaction() val transition = Binder() val runOnTransitStart = controller.minimizeMultiActivityPipTask(wct = wct, deskId = deskId, task = task) runOnTransitStart.invoke(transition) verify(desksOrganizer).minimizeTask(wct = wct, deskId = deskId, task = task) val minimizingTaskId = assertNotNull(desktopTasksLimiter.getMinimizingTask(transition)?.taskId) assertThat(minimizingTaskId).isEqualTo(task.taskId) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun handleRequest_fullscreenTask_switchToDesktop_movesTaskToDesk() { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt +4 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,10 @@ class DesktopModeEventLogger { FrameworkStatsLog .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_KEY_GESTURE ), MULTI_ACTIVITY_PIP( FrameworkStatsLog .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_MULTI_ACTIVITY_PIP ), } // Default value used when the task was not unminimized. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopPipTransitionController.kt +16 −0 Original line number Diff line number Diff line Loading @@ -274,6 +274,22 @@ class DesktopPipTransitionController( val deskId = getDeskId(desktopRepository, displayId) if (deskId == INVALID_DESK_ID) return // For multi-activity PiP, minimize the parent/original task if (taskInfo.numActivities > 1) { logD( "handlePipTransition: minimizeMultiActivityPipTask, taskId=%d deskId=%d", taskInfo.taskId, deskId, ) val runOnTransitStart = desktopTasksController.minimizeMultiActivityPipTask( wct = wct, deskId = deskId, task = taskInfo, ) runOnTransitStart?.invoke(transition) } val isLastTask = desktopRepository.isOnlyVisibleNonClosingTaskInDesk( taskId = taskId, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +44 −19 Original line number Diff line number Diff line Loading @@ -1372,16 +1372,10 @@ class DesktopTasksController( // parent task to the back so that it is not brought to the front and shown when the // child task breaks off into PiP. val isMultiActivityPip = taskInfo.numActivities > 1 var minimizeMultiActivityRunnable: RunOnTransitStart? = null if (isMultiActivityPip) { if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.minimizeTask( wct = wct, deskId = checkNotNull(deskId) { "Expected non-null deskId" }, task = taskInfo, ) } else { wct.reorder(taskInfo.token, /* onTop= */ false) } minimizeMultiActivityRunnable = minimizeMultiActivityPipTask(wct = wct, deskId = deskId, task = taskInfo) } // If the task minimizing to PiP is the last task, modify wct to perform Desktop cleanup Loading @@ -1397,16 +1391,7 @@ class DesktopTasksController( ) } val transition = freeformTaskTransitionStarter.startPipTransition(wct) if (isMultiActivityPip) { desktopTasksLimiter.ifPresent { it.addPendingMinimizeChange( transition = transition, displayId = displayId, taskId = taskId, minimizeReason = minimizeReason, ) } } minimizeMultiActivityRunnable?.invoke(transition) desktopExitRunnable?.invoke(transition) } else { val willExitDesktop = Loading Loading @@ -1458,6 +1443,46 @@ class DesktopTasksController( ) } /** * Called when a multi-activity PiP task needs to be minimized. * * @param wct WindowContainerTransaction that will apply minimization changes * @param deskId desk id that the multi-activity PiP is in * @param taskInfo of the task that is entering PiP * @return RunOnTransitStart runnable to be invoked after the transition has been started */ fun minimizeMultiActivityPipTask( wct: WindowContainerTransaction, deskId: Int?, task: RunningTaskInfo, ): RunOnTransitStart { logD( "minimizeMultiActivityPipTask taskId=%d deskId=%d displayId=%d", task.taskId, deskId, task.displayId, ) if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) { desksOrganizer.minimizeTask( wct = wct, deskId = checkNotNull(deskId) { "Expected non-null deskId" }, task = task, ) } else { wct.reorder(task.token, /* onTop= */ false) } return { transition -> desktopTasksLimiter.ifPresent { it.addPendingMinimizeChange( transition = transition, displayId = task.displayId, taskId = task.taskId, minimizeReason = MinimizeReason.MULTI_ACTIVITY_PIP, ) } } } /** Checks whether the given [taskInfo] is allowed to enter PiP in AppOps. */ private fun isPipAllowedInAppOps(taskInfo: RunningTaskInfo): Boolean { val packageName = Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopPipTransitionControllerTest.kt +10 −0 Original line number Diff line number Diff line Loading @@ -291,6 +291,16 @@ class DesktopPipTransitionControllerTest(flags: FlagsParameterization) : ShellTe verifyPerformDesktopExitCleanupAfterPip(isCalled = true) } @Test fun handlePipTransition_multiActivityPip_minimizeMultiActivityPipTask() { taskInfo.numActivities = 2 controller.handlePipTransition(wct, transition, taskInfo) verify(mockDesktopTasksController) .minimizeMultiActivityPipTask(wct = wct, deskId = DESK_ID, task = taskInfo) } private fun verifyPerformDesktopExitCleanupAfterPip(isCalled: Boolean) { if (isCalled) { verify(mockDesktopTasksController) Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +18 −0 Original line number Diff line number Diff line Loading @@ -4979,6 +4979,24 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(anyBoolean()) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun minimizeMultiActivityPipTask_minimizesTask() { val deskId = DEFAULT_DISPLAY val task = setUpPipTask(autoEnterEnabled = true, deskId = deskId) val wct = WindowContainerTransaction() val transition = Binder() val runOnTransitStart = controller.minimizeMultiActivityPipTask(wct = wct, deskId = deskId, task = task) runOnTransitStart.invoke(transition) verify(desksOrganizer).minimizeTask(wct = wct, deskId = deskId, task = task) val minimizingTaskId = assertNotNull(desktopTasksLimiter.getMinimizingTask(transition)?.taskId) assertThat(minimizingTaskId).isEqualTo(task.taskId) } @Test @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND) fun handleRequest_fullscreenTask_switchToDesktop_movesTaskToDesk() { Loading