diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 11aa054676cb9f528ea313c7224eb2ef8f6fdd71..5dfba5e7ff1d5cf9faccebea8052d537710ebb4d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -494,13 +494,14 @@ public abstract class WMShellModule { ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, LaunchAdjacentController launchAdjacentController, + RecentsTransitionHandler recentsTransitionHandler, @ShellMainThread ShellExecutor mainExecutor ) { return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController, displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, transitions, enterDesktopTransitionHandler, exitDesktopTransitionHandler, toggleResizeDesktopTaskTransitionHandler, desktopModeTaskRepository, - launchAdjacentController, mainExecutor); + launchAdjacentController, recentsTransitionHandler, mainExecutor); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 09ba4f79326ecde091bae099e7d46dec4053056f..412a5b5a6997a73dc307cb88a81e5ba903aeb9ba 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -60,6 +60,8 @@ import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.TO_DESKTOP_INDICATOR import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE +import com.android.wm.shell.recents.RecentsTransitionHandler +import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ENTER_DESKTOP import com.android.wm.shell.sysui.ShellCommandHandler @@ -68,7 +70,6 @@ import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.sysui.ShellSharedConstants import com.android.wm.shell.transition.OneShotRemoteHandler import com.android.wm.shell.transition.Transitions -import com.android.wm.shell.transition.Transitions.TransitionHandler import com.android.wm.shell.util.KtProtoLog import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration import com.android.wm.shell.windowdecor.MoveToDesktopAnimator @@ -93,6 +94,7 @@ class DesktopTasksController( ToggleResizeDesktopTaskTransitionHandler, private val desktopModeTaskRepository: DesktopModeTaskRepository, private val launchAdjacentController: LaunchAdjacentController, + private val recentsTransitionHandler: RecentsTransitionHandler, @ShellMainThread private val mainExecutor: ShellExecutor ) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler { @@ -119,6 +121,8 @@ class DesktopTasksController( com.android.wm.shell.R.dimen.desktop_mode_transition_area_width ) + private var recentsAnimationRunning = false + // This is public to avoid cyclic dependency; it is set by SplitScreenController lateinit var splitScreenController: SplitScreenController @@ -139,6 +143,19 @@ class DesktopTasksController( ) transitions.addHandler(this) desktopModeTaskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor) + + recentsTransitionHandler.addTransitionStateListener( + object : RecentsTransitionStateListener { + override fun onAnimationStateChanged(running: Boolean) { + KtProtoLog.v( + WM_SHELL_DESKTOP_MODE, + "DesktopTasksController: recents animation state changed running=%b", + running + ) + recentsAnimationRunning = running + } + } + ) } /** Show all tasks, that are part of the desktop, on top of launcher */ @@ -644,6 +661,10 @@ class DesktopTasksController( val triggerTask = request.triggerTask val shouldHandleRequest = when { + recentsAnimationRunning -> { + reason = "recents animation is running" + false + } // Only handle open or to front transitions request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> { reason = "transition type not handled (${request.type})" diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 83dc7fa5e869aaa478e505ad2d52983d088e4fd8..e828eedc275c7671c262567180a4da14cdc55fd5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -23,6 +23,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; + import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA; @@ -693,9 +694,19 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { + Transitions.TransitionFinishCallback finishCB = wct -> { + mixed.mInFlightSubAnimations--; + if (mixed.mInFlightSubAnimations == 0) { + mActiveTransitions.remove(mixed); + finishCallback.onTransitionFinished(wct); + } + }; + + mixed.mInFlightSubAnimations++; boolean consumed = mRecentsHandler.startAnimation( - mixed.mTransition, info, startTransaction, finishTransaction, finishCallback); + mixed.mTransition, info, startTransaction, finishTransaction, finishCB); if (!consumed) { + mixed.mInFlightSubAnimations--; return false; } if (mDesktopTasksController != null) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index dea161786da2825abda381ba16932ca8c8bcc9c7..ebcb6407a6fd913da1086c88c61dc06c487a88c5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -54,6 +54,8 @@ import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreef import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSplitScreenTask +import com.android.wm.shell.recents.RecentsTransitionHandler +import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.sysui.ShellCommandHandler import com.android.wm.shell.sysui.ShellController @@ -101,11 +103,13 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock lateinit var launchAdjacentController: LaunchAdjacentController @Mock lateinit var desktopModeWindowDecoration: DesktopModeWindowDecoration @Mock lateinit var splitScreenController: SplitScreenController + @Mock lateinit var recentsTransitionHandler: RecentsTransitionHandler private lateinit var mockitoSession: StaticMockitoSession private lateinit var controller: DesktopTasksController private lateinit var shellInit: ShellInit private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository + private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener private val shellExecutor = TestShellExecutor() // Mock running tasks are registered here so we can get the list from mock shell task organizer @@ -126,6 +130,10 @@ class DesktopTasksControllerTest : ShellTestCase() { controller.splitScreenController = splitScreenController shellInit.init() + + val captor = ArgumentCaptor.forClass(RecentsTransitionStateListener::class.java) + verify(recentsTransitionHandler).addTransitionStateListener(captor.capture()) + recentsTransitionStateListener = captor.value } private fun createController(): DesktopTasksController { @@ -144,6 +152,7 @@ class DesktopTasksControllerTest : ShellTestCase() { mToggleResizeDesktopTaskTransitionHandler, desktopModeTaskRepository, launchAdjacentController, + recentsTransitionHandler, shellExecutor ) } @@ -355,7 +364,7 @@ class DesktopTasksControllerTest : ShellTestCase() { @Test fun moveToDesktop_splitTaskExitsSplit() { - var task = setUpSplitScreenTask() + val task = setUpSplitScreenTask() controller.moveToDesktop(desktopModeWindowDecoration, task) val wct = getLatestMoveToDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode) @@ -367,7 +376,7 @@ class DesktopTasksControllerTest : ShellTestCase() { @Test fun moveToDesktop_fullscreenTaskDoesNotExitSplit() { - var task = setUpFullscreenTask() + val task = setUpFullscreenTask() controller.moveToDesktop(desktopModeWindowDecoration, task) val wct = getLatestMoveToDesktopWct() assertThat(wct.changes[task.token.asBinder()]?.windowingMode) @@ -665,6 +674,20 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(controller.handleRequest(Binder(), createTransition(task))).isNull() } + @Test + fun handleRequest_recentsAnimationRunning_returnNull() { + // Set up a visible freeform task so a fullscreen task should be converted to freeform + val freeformTask = setUpFreeformTask() + markTaskVisible(freeformTask) + + // Mark recents animation running + recentsTransitionStateListener.onAnimationStateChanged(true) + + // Open a fullscreen task, check that it does not result in a WCT with changes to it + val fullscreenTask = createFullscreenTask() + assertThat(controller.handleRequest(Binder(), createTransition(fullscreenTask))).isNull() + } + @Test fun stashDesktopApps_stateUpdates() { whenever(DesktopModeStatus.isStashingEnabled()).thenReturn(true)