Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -703,6 +703,7 @@ public abstract class WMShellModule { Transitions transitions, Transitions transitions, KeyguardManager keyguardManager, KeyguardManager keyguardManager, ReturnToDragStartAnimator returnToDragStartAnimator, ReturnToDragStartAnimator returnToDragStartAnimator, Optional<DesktopMixedTransitionHandler> desktopMixedTransitionHandler, EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler, EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler, ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler, ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler, DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler, DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler, Loading Loading @@ -736,6 +737,7 @@ public abstract class WMShellModule { transitions, transitions, keyguardManager, keyguardManager, returnToDragStartAnimator, returnToDragStartAnimator, desktopMixedTransitionHandler.get(), enterDesktopTransitionHandler, enterDesktopTransitionHandler, exitDesktopTransitionHandler, exitDesktopTransitionHandler, desktopModeDragAndDropTransitionHandler, desktopModeDragAndDropTransitionHandler, Loading Loading @@ -960,6 +962,7 @@ public abstract class WMShellModule { @DynamicOverride DesktopRepository desktopRepository, @DynamicOverride DesktopRepository desktopRepository, FreeformTaskTransitionHandler freeformTaskTransitionHandler, FreeformTaskTransitionHandler freeformTaskTransitionHandler, CloseDesktopTaskTransitionHandler closeDesktopTaskTransitionHandler, CloseDesktopTaskTransitionHandler closeDesktopTaskTransitionHandler, Optional<DesktopImmersiveController> desktopImmersiveController, InteractionJankMonitor interactionJankMonitor, InteractionJankMonitor interactionJankMonitor, @ShellMainThread Handler handler) { @ShellMainThread Handler handler) { if (!DesktopModeStatus.canEnterDesktopMode(context)) { if (!DesktopModeStatus.canEnterDesktopMode(context)) { Loading @@ -972,6 +975,7 @@ public abstract class WMShellModule { desktopRepository, desktopRepository, freeformTaskTransitionHandler, freeformTaskTransitionHandler, closeDesktopTaskTransitionHandler, closeDesktopTaskTransitionHandler, desktopImmersiveController.get(), interactionJankMonitor, interactionJankMonitor, handler)); handler)); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopImmersiveController.kt +42 −17 Original line number Original line Diff line number Diff line Loading @@ -130,7 +130,8 @@ class DesktopImmersiveController( displayId: Int displayId: Int ) { ) { if (!Flags.enableFullyImmersiveInDesktop()) return if (!Flags.enableFullyImmersiveInDesktop()) return exitImmersiveIfApplicable(wct, displayId)?.invoke(transition) val result = exitImmersiveIfApplicable(wct, displayId) result.asExit()?.runOnTransitionStart?.invoke(transition) } } /** /** Loading @@ -145,16 +146,23 @@ class DesktopImmersiveController( wct: WindowContainerTransaction, wct: WindowContainerTransaction, displayId: Int, displayId: Int, excludeTaskId: Int? = null, excludeTaskId: Int? = null, ): ((IBinder) -> Unit)? { ): ExitResult { if (!Flags.enableFullyImmersiveInDesktop()) return null if (!Flags.enableFullyImmersiveInDesktop()) return ExitResult.NoExit val immersiveTask = desktopRepository.getTaskInFullImmersiveState(displayId) ?: return null val immersiveTask = desktopRepository.getTaskInFullImmersiveState(displayId) ?: return ExitResult.NoExit if (immersiveTask == excludeTaskId) { if (immersiveTask == excludeTaskId) { return null return ExitResult.NoExit } } val taskInfo = shellTaskOrganizer.getRunningTaskInfo(immersiveTask) ?: return null val taskInfo = shellTaskOrganizer.getRunningTaskInfo(immersiveTask) ?: return ExitResult.NoExit logV("Appending immersive exit for task: $immersiveTask in display: $displayId") logV("Appending immersive exit for task: $immersiveTask in display: $displayId") wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) return { transition -> addPendingImmersiveExit(immersiveTask, displayId, transition) } return ExitResult.Exit( exitingTask = immersiveTask, runOnTransitionStart = { transition -> addPendingImmersiveExit(immersiveTask, displayId, transition) } ) } } /** /** Loading @@ -167,22 +175,25 @@ class DesktopImmersiveController( fun exitImmersiveIfApplicable( fun exitImmersiveIfApplicable( wct: WindowContainerTransaction, wct: WindowContainerTransaction, taskInfo: RunningTaskInfo taskInfo: RunningTaskInfo ): ((IBinder) -> Unit)? { ): ExitResult { if (!Flags.enableFullyImmersiveInDesktop()) return null if (!Flags.enableFullyImmersiveInDesktop()) return ExitResult.NoExit if (desktopRepository.isTaskInFullImmersiveState(taskInfo.taskId)) { if (desktopRepository.isTaskInFullImmersiveState(taskInfo.taskId)) { // A full immersive task is being minimized, make sure the immersive state is broken // A full immersive task is being minimized, make sure the immersive state is broken // (i.e. resize back to max bounds). // (i.e. resize back to max bounds). wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) logV("Appending immersive exit for task: ${taskInfo.taskId}") logV("Appending immersive exit for task: ${taskInfo.taskId}") return { transition -> return ExitResult.Exit( exitingTask = taskInfo.taskId, runOnTransitionStart = { transition -> addPendingImmersiveExit( addPendingImmersiveExit( taskId = taskInfo.taskId, taskId = taskInfo.taskId, displayId = taskInfo.displayId, displayId = taskInfo.displayId, transition = transition transition = transition ) ) } } ) } } return null return ExitResult.NoExit } } Loading Loading @@ -461,6 +472,20 @@ class DesktopImmersiveController( var transition: IBinder, var transition: IBinder, ) ) /** The result of an external exit request. */ sealed class ExitResult { /** An immersive task exit (meaning, resize) was appended to the request. */ data class Exit( val exitingTask: Int, val runOnTransitionStart: ((IBinder) -> Unit) ) : ExitResult() /** There was no exit appended to the request. */ data object NoExit : ExitResult() /** Returns the result as an [Exit] or null if it isn't of that type. */ fun asExit(): Exit? = if (this is Exit) this else null } private enum class Direction { private enum class Direction { ENTER, EXIT ENTER, EXIT } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt +202 −4 Original line number Original line Diff line number Diff line Loading @@ -27,15 +27,18 @@ import android.window.DesktopModeFlags import android.window.TransitionInfo import android.window.TransitionInfo import android.window.TransitionRequestInfo import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction import androidx.annotation.VisibleForTesting import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags import com.android.wm.shell.freeform.FreeformTaskTransitionHandler import com.android.wm.shell.freeform.FreeformTaskTransitionHandler import com.android.wm.shell.freeform.FreeformTaskTransitionStarter import com.android.wm.shell.freeform.FreeformTaskTransitionStarter import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.MixedTransitionHandler import com.android.wm.shell.transition.MixedTransitionHandler import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TransitionFinishCallback /** The [Transitions.TransitionHandler] coordinates transition handlers in desktop windowing. */ /** The [Transitions.TransitionHandler] coordinates transition handlers in desktop windowing. */ class DesktopMixedTransitionHandler( class DesktopMixedTransitionHandler( Loading @@ -44,10 +47,14 @@ class DesktopMixedTransitionHandler( private val desktopRepository: DesktopRepository, private val desktopRepository: DesktopRepository, private val freeformTaskTransitionHandler: FreeformTaskTransitionHandler, private val freeformTaskTransitionHandler: FreeformTaskTransitionHandler, private val closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler, private val closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler, private val desktopImmersiveController: DesktopImmersiveController, private val interactionJankMonitor: InteractionJankMonitor, private val interactionJankMonitor: InteractionJankMonitor, @ShellMainThread private val handler: Handler, @ShellMainThread private val handler: Handler, ) : MixedTransitionHandler, FreeformTaskTransitionStarter { ) : MixedTransitionHandler, FreeformTaskTransitionStarter { @VisibleForTesting val pendingMixedTransitions = mutableListOf<PendingMixedTransition>() /** Delegates starting transition to [FreeformTaskTransitionHandler]. */ /** Delegates starting transition to [FreeformTaskTransitionHandler]. */ override fun startWindowingModeTransition( override fun startWindowingModeTransition( targetWindowingMode: Int, targetWindowingMode: Int, Loading @@ -65,6 +72,40 @@ class DesktopMixedTransitionHandler( } } requireNotNull(wct) requireNotNull(wct) return transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, /* handler= */ this) return transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, /* handler= */ this) .also { transition -> pendingMixedTransitions.add(PendingMixedTransition.Close(transition)) } } /** * Starts a launch transition for [taskId], with an optional [exitingImmersiveTask] if it was * included in the [wct] and is expected to be animated by this handler. */ fun startLaunchTransition( @WindowManager.TransitionType transitionType: Int, wct: WindowContainerTransaction, taskId: Int, exitingImmersiveTask: Int? = null, ): IBinder { if (!Flags.enableFullyImmersiveInDesktop()) { return transitions.startTransition(transitionType, wct, /* handler= */ null) } if (exitingImmersiveTask == null) { logV("Starting mixed launch transition for task#%d", taskId) } else { logV( "Starting mixed launch transition for task#%d with immersive exit of task#%d", taskId, exitingImmersiveTask ) } return transitions.startTransition(transitionType, wct, /* handler= */ this) .also { transition -> pendingMixedTransitions.add(PendingMixedTransition.Launch( transition = transition, launchingTask = taskId, exitingImmersiveTask = exitingImmersiveTask )) } } } /** Returns null, as it only handles transitions started from Shell. */ /** Returns null, as it only handles transitions started from Shell. */ Loading @@ -78,11 +119,43 @@ class DesktopMixedTransitionHandler( info: TransitionInfo, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: Transitions.TransitionFinishCallback, finishCallback: TransitionFinishCallback, ): Boolean { val pending = pendingMixedTransitions.find { pending -> pending.transition == transition } ?: return false.also { logW("Should have pending desktop transition") } pendingMixedTransitions.remove(pending) logV("Animating pending mixed transition: %s", pending) return when (pending) { is PendingMixedTransition.Close -> animateCloseTransition( transition, info, startTransaction, finishTransaction, finishCallback ) is PendingMixedTransition.Launch -> animateLaunchTransition( pending, transition, info, startTransaction, finishTransaction, finishCallback ) } } private fun animateCloseTransition( transition: IBinder, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: TransitionFinishCallback, ): Boolean { ): Boolean { val closeChange = findCloseDesktopTaskChange(info) val closeChange = findCloseDesktopTaskChange(info) if (closeChange == null) { if (closeChange == null) { ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: Should have closing desktop task", TAG) logW("Should have closing desktop task") return false return false } } if (isLastDesktopTask(closeChange)) { if (isLastDesktopTask(closeChange)) { Loading @@ -106,6 +179,74 @@ class DesktopMixedTransitionHandler( ) ) } } private fun animateLaunchTransition( pending: PendingMixedTransition.Launch, transition: IBinder, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: TransitionFinishCallback, ): Boolean { // Check if there's also an immersive change during this launch. val immersiveExitChange = pending.exitingImmersiveTask?.let { exitingTask -> findDesktopTaskChange(info, exitingTask) } val launchChange = findDesktopTaskChange(info, pending.launchingTask) ?: error("Should have pending launching task change") var subAnimationCount = -1 var combinedWct: WindowContainerTransaction? = null val finishCb = TransitionFinishCallback { wct -> --subAnimationCount combinedWct = combinedWct.merge(wct) if (subAnimationCount > 0) return@TransitionFinishCallback finishCallback.onTransitionFinished(combinedWct) } logV( "Animating pending mixed launch transition task#%d immersiveExitTask#%s", launchChange.taskInfo!!.taskId, immersiveExitChange?.taskInfo?.taskId ) if (immersiveExitChange != null) { subAnimationCount = 2 // Animate the immersive exit change separately. info.changes.remove(immersiveExitChange) desktopImmersiveController.animateResizeChange( immersiveExitChange, startTransaction, finishTransaction, finishCb ) // Let the leftover/default handler animate the remaining changes. return dispatchToLeftoverHandler( transition, info, startTransaction, finishTransaction, finishCb ) } // There's nothing to animate separately, so let the left over handler animate // the entire transition. subAnimationCount = 1 return dispatchToLeftoverHandler( transition, info, startTransaction, finishTransaction, finishCb ) } override fun onTransitionConsumed( transition: IBinder, aborted: Boolean, finishTransaction: SurfaceControl.Transaction? ) { pendingMixedTransitions.removeAll { pending -> pending.transition == transition } super.onTransitionConsumed(transition, aborted, finishTransaction) } /** /** * Dispatch close desktop task animation to the default transition handlers. Allows delegating * Dispatch close desktop task animation to the default transition handlers. Allows delegating * it to Launcher to animate in sync with show Home transition. * it to Launcher to animate in sync with show Home transition. Loading @@ -126,14 +267,34 @@ class DesktopMixedTransitionHandler( CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE, CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE, ) ) // Dispatch the last desktop task closing animation. // Dispatch the last desktop task closing animation. return dispatchToLeftoverHandler( transition = transition, info = info, startTransaction = startTransaction, finishTransaction = finishTransaction, finishCallback = finishCallback, doOnFinishCallback = { // Finish the jank trace when closing the last window in desktop mode. interactionJankMonitor.end(CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE) } ) } private fun dispatchToLeftoverHandler( transition: IBinder, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: TransitionFinishCallback, doOnFinishCallback: (() -> Unit)? = null, ): Boolean { return transitions.dispatchTransition( return transitions.dispatchTransition( transition, transition, info, info, startTransaction, startTransaction, finishTransaction, finishTransaction, { wct -> { wct -> // Finish the jank trace when closing the last window in desktop mode. doOnFinishCallback?.invoke() interactionJankMonitor.end(CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE) finishCallback.onTransitionFinished(wct) finishCallback.onTransitionFinished(wct) }, }, /* skip= */ this /* skip= */ this Loading @@ -155,6 +316,43 @@ class DesktopMixedTransitionHandler( } } } } private fun findDesktopTaskChange(info: TransitionInfo, taskId: Int): TransitionInfo.Change? { return info.changes.firstOrNull { change -> change.taskInfo?.taskId == taskId } } private fun WindowContainerTransaction?.merge( wct: WindowContainerTransaction? ): WindowContainerTransaction? { if (wct == null) return this if (this == null) return wct return this.merge(wct) } /** A scheduled transition that will potentially be animated by more than one handler */ sealed class PendingMixedTransition { abstract val transition: IBinder /** A task is closing. */ data class Close( override val transition: IBinder, ) : PendingMixedTransition() /** A task is opening or moving to front. */ data class Launch( override val transition: IBinder, val launchingTask: Int, val exitingImmersiveTask: Int?, ) : PendingMixedTransition() } private fun logV(msg: String, vararg arguments: Any?) { ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } private fun logW(msg: String, vararg arguments: Any?) { ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } companion object { companion object { private const val TAG = "DesktopMixedTransitionHandler" private const val TAG = "DesktopMixedTransitionHandler" } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +46 −30 Original line number Original line Diff line number Diff line Loading @@ -87,6 +87,7 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.DesktopImmersiveController.ExitResult import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener Loading Loading @@ -146,6 +147,7 @@ class DesktopTasksController( private val transitions: Transitions, private val transitions: Transitions, private val keyguardManager: KeyguardManager, private val keyguardManager: KeyguardManager, private val returnToDragStartAnimator: ReturnToDragStartAnimator, private val returnToDragStartAnimator: ReturnToDragStartAnimator, private val desktopMixedTransitionHandler: DesktopMixedTransitionHandler, private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler, private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler, private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler, private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler, Loading Loading @@ -379,7 +381,7 @@ class DesktopTasksController( // TODO(342378842): Instead of using default display, support multiple displays // TODO(342378842): Instead of using default display, support multiple displays val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( DEFAULT_DISPLAY, wct, taskId) DEFAULT_DISPLAY, wct, taskId) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = DEFAULT_DISPLAY, displayId = DEFAULT_DISPLAY, excludeTaskId = taskId, excludeTaskId = taskId, Loading @@ -393,7 +395,7 @@ class DesktopTasksController( // TODO(343149901): Add DPI changes for task launch // TODO(343149901): Add DPI changes for task launch val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) return true return true } } Loading @@ -410,7 +412,7 @@ class DesktopTasksController( } } logV("moveRunningTaskToDesktop taskId=%d", task.taskId) logV("moveRunningTaskToDesktop taskId=%d", task.taskId) exitSplitIfApplicable(wct, task) exitSplitIfApplicable(wct, task) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = task.displayId, displayId = task.displayId, excludeTaskId = task.taskId, excludeTaskId = task.taskId, Loading @@ -422,7 +424,7 @@ class DesktopTasksController( val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } /** /** Loading Loading @@ -459,12 +461,12 @@ class DesktopTasksController( val taskIdToMinimize = val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask(taskInfo.displayId, wct, taskInfo.taskId) bringDesktopAppsToFrontBeforeShowingNewTask(taskInfo.displayId, wct, taskInfo.taskId) addMoveToDesktopChanges(wct, taskInfo) addMoveToDesktopChanges(wct, taskInfo) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct, taskInfo.displayId) wct, taskInfo.displayId) val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct) val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct) transition?.let { transition?.let { taskIdToMinimize?.let { taskId -> addPendingMinimizeTransition(it, taskId) } taskIdToMinimize?.let { taskId -> addPendingMinimizeTransition(it, taskId) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } } } Loading Loading @@ -507,7 +509,8 @@ class DesktopTasksController( taskId taskId ) ) ) ) return desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) return desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo).asExit() ?.runOnTransitionStart } } fun minimizeTask(taskInfo: RunningTaskInfo) { fun minimizeTask(taskInfo: RunningTaskInfo) { Loading @@ -520,7 +523,7 @@ class DesktopTasksController( removeWallpaperActivity(wct) removeWallpaperActivity(wct) } } // Notify immersive handler as it might need to exit immersive state. // Notify immersive handler as it might need to exit immersive state. val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) val exitResult = desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) wct.reorder(taskInfo.token, false) wct.reorder(taskInfo.token, false) val transition = freeformTaskTransitionStarter.startMinimizedModeTransition(wct) val transition = freeformTaskTransitionStarter.startMinimizedModeTransition(wct) Loading @@ -531,7 +534,7 @@ class DesktopTasksController( taskId = taskId taskId = taskId ) ) } } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } /** Move a task with given `taskId` to fullscreen */ /** Move a task with given `taskId` to fullscreen */ Loading Loading @@ -627,7 +630,7 @@ class DesktopTasksController( logV("moveBackgroundTaskToFront taskId=%s", taskId) logV("moveBackgroundTaskToFront taskId=%s", taskId) val wct = WindowContainerTransaction() val wct = WindowContainerTransaction() // TODO: b/342378842 - Instead of using default display, support multiple displays // TODO: b/342378842 - Instead of using default display, support multiple displays val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = DEFAULT_DISPLAY, displayId = DEFAULT_DISPLAY, excludeTaskId = taskId, excludeTaskId = taskId, Loading @@ -638,8 +641,13 @@ class DesktopTasksController( launchWindowingMode = WINDOWING_MODE_FREEFORM launchWindowingMode = WINDOWING_MODE_FREEFORM }.toBundle(), }.toBundle(), ) ) val transition = startLaunchTransition(TRANSIT_OPEN, wct, taskId, remoteTransition) val transition = startLaunchTransition( runOnTransit?.invoke(transition) TRANSIT_OPEN, wct, taskId, remoteTransition = remoteTransition ) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } /** /** Loading @@ -658,32 +666,39 @@ class DesktopTasksController( } } val wct = WindowContainerTransaction() val wct = WindowContainerTransaction() wct.reorder(taskInfo.token, true /* onTop */, true /* includingParents */) wct.reorder(taskInfo.token, true /* onTop */, true /* includingParents */) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val result = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = taskInfo.displayId, displayId = taskInfo.displayId, excludeTaskId = taskInfo.taskId, excludeTaskId = taskInfo.taskId, ) ) val transition = val exitResult = if (result is ExitResult.Exit) { result } else { null } startLaunchTransition( val transition = startLaunchTransition( TRANSIT_TO_FRONT, transitionType = TRANSIT_TO_FRONT, wct, wct = wct, taskInfo.taskId, taskId = taskInfo.taskId, remoteTransition, exitingImmersiveTask = exitResult?.exitingTask, taskInfo.displayId remoteTransition = remoteTransition, displayId = taskInfo.displayId, ) ) runOnTransit?.invoke(transition) exitResult?.runOnTransitionStart?.invoke(transition) } } private fun startLaunchTransition( private fun startLaunchTransition( transitionType: Int, transitionType: Int, wct: WindowContainerTransaction, wct: WindowContainerTransaction, taskId: Int, taskId: Int, remoteTransition: RemoteTransition?, exitingImmersiveTask: Int? = null, remoteTransition: RemoteTransition? = null, displayId: Int = DEFAULT_DISPLAY, displayId: Int = DEFAULT_DISPLAY, ): IBinder { ): IBinder { val taskIdToMinimize = addAndGetMinimizeChanges(displayId, wct, taskId) val taskIdToMinimize = addAndGetMinimizeChanges(displayId, wct, taskId) if (remoteTransition == null) { if (remoteTransition == null) { val t = transitions.startTransition(transitionType, wct, null /* handler */) val t = desktopMixedTransitionHandler.startLaunchTransition( transitionType = transitionType, wct = wct, taskId = taskId, exitingImmersiveTask = exitingImmersiveTask, ) taskIdToMinimize?.let { addPendingMinimizeTransition(t, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(t, it) } return t return t } } Loading Loading @@ -1373,14 +1388,15 @@ class DesktopTasksController( wct.startTask(requestedTaskId, options.toBundle()) wct.startTask(requestedTaskId, options.toBundle()) val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( callingTask.displayId, wct, requestedTaskId) callingTask.displayId, wct, requestedTaskId) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController .exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = callingTask.displayId, displayId = callingTask.displayId, excludeTaskId = requestedTaskId, excludeTaskId = requestedTaskId, ) ) val transition = transitions.startTransition(TRANSIT_OPEN, wct, null) val transition = transitions.startTransition(TRANSIT_OPEN, wct, null) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } else { } else { val splitPosition = splitScreenController.determineNewInstancePosition(callingTask) val splitPosition = splitScreenController.determineNewInstancePosition(callingTask) splitScreenController.startTask(requestedTaskId, splitPosition, splitScreenController.startTask(requestedTaskId, splitPosition, Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt +26 −11 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -703,6 +703,7 @@ public abstract class WMShellModule { Transitions transitions, Transitions transitions, KeyguardManager keyguardManager, KeyguardManager keyguardManager, ReturnToDragStartAnimator returnToDragStartAnimator, ReturnToDragStartAnimator returnToDragStartAnimator, Optional<DesktopMixedTransitionHandler> desktopMixedTransitionHandler, EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler, EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler, ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler, ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler, DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler, DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler, Loading Loading @@ -736,6 +737,7 @@ public abstract class WMShellModule { transitions, transitions, keyguardManager, keyguardManager, returnToDragStartAnimator, returnToDragStartAnimator, desktopMixedTransitionHandler.get(), enterDesktopTransitionHandler, enterDesktopTransitionHandler, exitDesktopTransitionHandler, exitDesktopTransitionHandler, desktopModeDragAndDropTransitionHandler, desktopModeDragAndDropTransitionHandler, Loading Loading @@ -960,6 +962,7 @@ public abstract class WMShellModule { @DynamicOverride DesktopRepository desktopRepository, @DynamicOverride DesktopRepository desktopRepository, FreeformTaskTransitionHandler freeformTaskTransitionHandler, FreeformTaskTransitionHandler freeformTaskTransitionHandler, CloseDesktopTaskTransitionHandler closeDesktopTaskTransitionHandler, CloseDesktopTaskTransitionHandler closeDesktopTaskTransitionHandler, Optional<DesktopImmersiveController> desktopImmersiveController, InteractionJankMonitor interactionJankMonitor, InteractionJankMonitor interactionJankMonitor, @ShellMainThread Handler handler) { @ShellMainThread Handler handler) { if (!DesktopModeStatus.canEnterDesktopMode(context)) { if (!DesktopModeStatus.canEnterDesktopMode(context)) { Loading @@ -972,6 +975,7 @@ public abstract class WMShellModule { desktopRepository, desktopRepository, freeformTaskTransitionHandler, freeformTaskTransitionHandler, closeDesktopTaskTransitionHandler, closeDesktopTaskTransitionHandler, desktopImmersiveController.get(), interactionJankMonitor, interactionJankMonitor, handler)); handler)); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopImmersiveController.kt +42 −17 Original line number Original line Diff line number Diff line Loading @@ -130,7 +130,8 @@ class DesktopImmersiveController( displayId: Int displayId: Int ) { ) { if (!Flags.enableFullyImmersiveInDesktop()) return if (!Flags.enableFullyImmersiveInDesktop()) return exitImmersiveIfApplicable(wct, displayId)?.invoke(transition) val result = exitImmersiveIfApplicable(wct, displayId) result.asExit()?.runOnTransitionStart?.invoke(transition) } } /** /** Loading @@ -145,16 +146,23 @@ class DesktopImmersiveController( wct: WindowContainerTransaction, wct: WindowContainerTransaction, displayId: Int, displayId: Int, excludeTaskId: Int? = null, excludeTaskId: Int? = null, ): ((IBinder) -> Unit)? { ): ExitResult { if (!Flags.enableFullyImmersiveInDesktop()) return null if (!Flags.enableFullyImmersiveInDesktop()) return ExitResult.NoExit val immersiveTask = desktopRepository.getTaskInFullImmersiveState(displayId) ?: return null val immersiveTask = desktopRepository.getTaskInFullImmersiveState(displayId) ?: return ExitResult.NoExit if (immersiveTask == excludeTaskId) { if (immersiveTask == excludeTaskId) { return null return ExitResult.NoExit } } val taskInfo = shellTaskOrganizer.getRunningTaskInfo(immersiveTask) ?: return null val taskInfo = shellTaskOrganizer.getRunningTaskInfo(immersiveTask) ?: return ExitResult.NoExit logV("Appending immersive exit for task: $immersiveTask in display: $displayId") logV("Appending immersive exit for task: $immersiveTask in display: $displayId") wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) return { transition -> addPendingImmersiveExit(immersiveTask, displayId, transition) } return ExitResult.Exit( exitingTask = immersiveTask, runOnTransitionStart = { transition -> addPendingImmersiveExit(immersiveTask, displayId, transition) } ) } } /** /** Loading @@ -167,22 +175,25 @@ class DesktopImmersiveController( fun exitImmersiveIfApplicable( fun exitImmersiveIfApplicable( wct: WindowContainerTransaction, wct: WindowContainerTransaction, taskInfo: RunningTaskInfo taskInfo: RunningTaskInfo ): ((IBinder) -> Unit)? { ): ExitResult { if (!Flags.enableFullyImmersiveInDesktop()) return null if (!Flags.enableFullyImmersiveInDesktop()) return ExitResult.NoExit if (desktopRepository.isTaskInFullImmersiveState(taskInfo.taskId)) { if (desktopRepository.isTaskInFullImmersiveState(taskInfo.taskId)) { // A full immersive task is being minimized, make sure the immersive state is broken // A full immersive task is being minimized, make sure the immersive state is broken // (i.e. resize back to max bounds). // (i.e. resize back to max bounds). wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) wct.setBounds(taskInfo.token, getExitDestinationBounds(taskInfo)) logV("Appending immersive exit for task: ${taskInfo.taskId}") logV("Appending immersive exit for task: ${taskInfo.taskId}") return { transition -> return ExitResult.Exit( exitingTask = taskInfo.taskId, runOnTransitionStart = { transition -> addPendingImmersiveExit( addPendingImmersiveExit( taskId = taskInfo.taskId, taskId = taskInfo.taskId, displayId = taskInfo.displayId, displayId = taskInfo.displayId, transition = transition transition = transition ) ) } } ) } } return null return ExitResult.NoExit } } Loading Loading @@ -461,6 +472,20 @@ class DesktopImmersiveController( var transition: IBinder, var transition: IBinder, ) ) /** The result of an external exit request. */ sealed class ExitResult { /** An immersive task exit (meaning, resize) was appended to the request. */ data class Exit( val exitingTask: Int, val runOnTransitionStart: ((IBinder) -> Unit) ) : ExitResult() /** There was no exit appended to the request. */ data object NoExit : ExitResult() /** Returns the result as an [Exit] or null if it isn't of that type. */ fun asExit(): Exit? = if (this is Exit) this else null } private enum class Direction { private enum class Direction { ENTER, EXIT ENTER, EXIT } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt +202 −4 Original line number Original line Diff line number Diff line Loading @@ -27,15 +27,18 @@ import android.window.DesktopModeFlags import android.window.TransitionInfo import android.window.TransitionInfo import android.window.TransitionRequestInfo import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction import androidx.annotation.VisibleForTesting import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags import com.android.wm.shell.freeform.FreeformTaskTransitionHandler import com.android.wm.shell.freeform.FreeformTaskTransitionHandler import com.android.wm.shell.freeform.FreeformTaskTransitionStarter import com.android.wm.shell.freeform.FreeformTaskTransitionStarter import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.MixedTransitionHandler import com.android.wm.shell.transition.MixedTransitionHandler import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TransitionFinishCallback /** The [Transitions.TransitionHandler] coordinates transition handlers in desktop windowing. */ /** The [Transitions.TransitionHandler] coordinates transition handlers in desktop windowing. */ class DesktopMixedTransitionHandler( class DesktopMixedTransitionHandler( Loading @@ -44,10 +47,14 @@ class DesktopMixedTransitionHandler( private val desktopRepository: DesktopRepository, private val desktopRepository: DesktopRepository, private val freeformTaskTransitionHandler: FreeformTaskTransitionHandler, private val freeformTaskTransitionHandler: FreeformTaskTransitionHandler, private val closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler, private val closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler, private val desktopImmersiveController: DesktopImmersiveController, private val interactionJankMonitor: InteractionJankMonitor, private val interactionJankMonitor: InteractionJankMonitor, @ShellMainThread private val handler: Handler, @ShellMainThread private val handler: Handler, ) : MixedTransitionHandler, FreeformTaskTransitionStarter { ) : MixedTransitionHandler, FreeformTaskTransitionStarter { @VisibleForTesting val pendingMixedTransitions = mutableListOf<PendingMixedTransition>() /** Delegates starting transition to [FreeformTaskTransitionHandler]. */ /** Delegates starting transition to [FreeformTaskTransitionHandler]. */ override fun startWindowingModeTransition( override fun startWindowingModeTransition( targetWindowingMode: Int, targetWindowingMode: Int, Loading @@ -65,6 +72,40 @@ class DesktopMixedTransitionHandler( } } requireNotNull(wct) requireNotNull(wct) return transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, /* handler= */ this) return transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, /* handler= */ this) .also { transition -> pendingMixedTransitions.add(PendingMixedTransition.Close(transition)) } } /** * Starts a launch transition for [taskId], with an optional [exitingImmersiveTask] if it was * included in the [wct] and is expected to be animated by this handler. */ fun startLaunchTransition( @WindowManager.TransitionType transitionType: Int, wct: WindowContainerTransaction, taskId: Int, exitingImmersiveTask: Int? = null, ): IBinder { if (!Flags.enableFullyImmersiveInDesktop()) { return transitions.startTransition(transitionType, wct, /* handler= */ null) } if (exitingImmersiveTask == null) { logV("Starting mixed launch transition for task#%d", taskId) } else { logV( "Starting mixed launch transition for task#%d with immersive exit of task#%d", taskId, exitingImmersiveTask ) } return transitions.startTransition(transitionType, wct, /* handler= */ this) .also { transition -> pendingMixedTransitions.add(PendingMixedTransition.Launch( transition = transition, launchingTask = taskId, exitingImmersiveTask = exitingImmersiveTask )) } } } /** Returns null, as it only handles transitions started from Shell. */ /** Returns null, as it only handles transitions started from Shell. */ Loading @@ -78,11 +119,43 @@ class DesktopMixedTransitionHandler( info: TransitionInfo, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: Transitions.TransitionFinishCallback, finishCallback: TransitionFinishCallback, ): Boolean { val pending = pendingMixedTransitions.find { pending -> pending.transition == transition } ?: return false.also { logW("Should have pending desktop transition") } pendingMixedTransitions.remove(pending) logV("Animating pending mixed transition: %s", pending) return when (pending) { is PendingMixedTransition.Close -> animateCloseTransition( transition, info, startTransaction, finishTransaction, finishCallback ) is PendingMixedTransition.Launch -> animateLaunchTransition( pending, transition, info, startTransaction, finishTransaction, finishCallback ) } } private fun animateCloseTransition( transition: IBinder, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: TransitionFinishCallback, ): Boolean { ): Boolean { val closeChange = findCloseDesktopTaskChange(info) val closeChange = findCloseDesktopTaskChange(info) if (closeChange == null) { if (closeChange == null) { ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: Should have closing desktop task", TAG) logW("Should have closing desktop task") return false return false } } if (isLastDesktopTask(closeChange)) { if (isLastDesktopTask(closeChange)) { Loading @@ -106,6 +179,74 @@ class DesktopMixedTransitionHandler( ) ) } } private fun animateLaunchTransition( pending: PendingMixedTransition.Launch, transition: IBinder, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: TransitionFinishCallback, ): Boolean { // Check if there's also an immersive change during this launch. val immersiveExitChange = pending.exitingImmersiveTask?.let { exitingTask -> findDesktopTaskChange(info, exitingTask) } val launchChange = findDesktopTaskChange(info, pending.launchingTask) ?: error("Should have pending launching task change") var subAnimationCount = -1 var combinedWct: WindowContainerTransaction? = null val finishCb = TransitionFinishCallback { wct -> --subAnimationCount combinedWct = combinedWct.merge(wct) if (subAnimationCount > 0) return@TransitionFinishCallback finishCallback.onTransitionFinished(combinedWct) } logV( "Animating pending mixed launch transition task#%d immersiveExitTask#%s", launchChange.taskInfo!!.taskId, immersiveExitChange?.taskInfo?.taskId ) if (immersiveExitChange != null) { subAnimationCount = 2 // Animate the immersive exit change separately. info.changes.remove(immersiveExitChange) desktopImmersiveController.animateResizeChange( immersiveExitChange, startTransaction, finishTransaction, finishCb ) // Let the leftover/default handler animate the remaining changes. return dispatchToLeftoverHandler( transition, info, startTransaction, finishTransaction, finishCb ) } // There's nothing to animate separately, so let the left over handler animate // the entire transition. subAnimationCount = 1 return dispatchToLeftoverHandler( transition, info, startTransaction, finishTransaction, finishCb ) } override fun onTransitionConsumed( transition: IBinder, aborted: Boolean, finishTransaction: SurfaceControl.Transaction? ) { pendingMixedTransitions.removeAll { pending -> pending.transition == transition } super.onTransitionConsumed(transition, aborted, finishTransaction) } /** /** * Dispatch close desktop task animation to the default transition handlers. Allows delegating * Dispatch close desktop task animation to the default transition handlers. Allows delegating * it to Launcher to animate in sync with show Home transition. * it to Launcher to animate in sync with show Home transition. Loading @@ -126,14 +267,34 @@ class DesktopMixedTransitionHandler( CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE, CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE, ) ) // Dispatch the last desktop task closing animation. // Dispatch the last desktop task closing animation. return dispatchToLeftoverHandler( transition = transition, info = info, startTransaction = startTransaction, finishTransaction = finishTransaction, finishCallback = finishCallback, doOnFinishCallback = { // Finish the jank trace when closing the last window in desktop mode. interactionJankMonitor.end(CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE) } ) } private fun dispatchToLeftoverHandler( transition: IBinder, info: TransitionInfo, startTransaction: SurfaceControl.Transaction, finishTransaction: SurfaceControl.Transaction, finishCallback: TransitionFinishCallback, doOnFinishCallback: (() -> Unit)? = null, ): Boolean { return transitions.dispatchTransition( return transitions.dispatchTransition( transition, transition, info, info, startTransaction, startTransaction, finishTransaction, finishTransaction, { wct -> { wct -> // Finish the jank trace when closing the last window in desktop mode. doOnFinishCallback?.invoke() interactionJankMonitor.end(CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE) finishCallback.onTransitionFinished(wct) finishCallback.onTransitionFinished(wct) }, }, /* skip= */ this /* skip= */ this Loading @@ -155,6 +316,43 @@ class DesktopMixedTransitionHandler( } } } } private fun findDesktopTaskChange(info: TransitionInfo, taskId: Int): TransitionInfo.Change? { return info.changes.firstOrNull { change -> change.taskInfo?.taskId == taskId } } private fun WindowContainerTransaction?.merge( wct: WindowContainerTransaction? ): WindowContainerTransaction? { if (wct == null) return this if (this == null) return wct return this.merge(wct) } /** A scheduled transition that will potentially be animated by more than one handler */ sealed class PendingMixedTransition { abstract val transition: IBinder /** A task is closing. */ data class Close( override val transition: IBinder, ) : PendingMixedTransition() /** A task is opening or moving to front. */ data class Launch( override val transition: IBinder, val launchingTask: Int, val exitingImmersiveTask: Int?, ) : PendingMixedTransition() } private fun logV(msg: String, vararg arguments: Any?) { ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } private fun logW(msg: String, vararg arguments: Any?) { ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } companion object { companion object { private const val TAG = "DesktopMixedTransitionHandler" private const val TAG = "DesktopMixedTransitionHandler" } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +46 −30 Original line number Original line Diff line number Diff line Loading @@ -87,6 +87,7 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.DesktopImmersiveController.ExitResult import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener Loading Loading @@ -146,6 +147,7 @@ class DesktopTasksController( private val transitions: Transitions, private val transitions: Transitions, private val keyguardManager: KeyguardManager, private val keyguardManager: KeyguardManager, private val returnToDragStartAnimator: ReturnToDragStartAnimator, private val returnToDragStartAnimator: ReturnToDragStartAnimator, private val desktopMixedTransitionHandler: DesktopMixedTransitionHandler, private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler, private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler, private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler, private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler, Loading Loading @@ -379,7 +381,7 @@ class DesktopTasksController( // TODO(342378842): Instead of using default display, support multiple displays // TODO(342378842): Instead of using default display, support multiple displays val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( DEFAULT_DISPLAY, wct, taskId) DEFAULT_DISPLAY, wct, taskId) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = DEFAULT_DISPLAY, displayId = DEFAULT_DISPLAY, excludeTaskId = taskId, excludeTaskId = taskId, Loading @@ -393,7 +395,7 @@ class DesktopTasksController( // TODO(343149901): Add DPI changes for task launch // TODO(343149901): Add DPI changes for task launch val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) return true return true } } Loading @@ -410,7 +412,7 @@ class DesktopTasksController( } } logV("moveRunningTaskToDesktop taskId=%d", task.taskId) logV("moveRunningTaskToDesktop taskId=%d", task.taskId) exitSplitIfApplicable(wct, task) exitSplitIfApplicable(wct, task) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = task.displayId, displayId = task.displayId, excludeTaskId = task.taskId, excludeTaskId = task.taskId, Loading @@ -422,7 +424,7 @@ class DesktopTasksController( val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } /** /** Loading Loading @@ -459,12 +461,12 @@ class DesktopTasksController( val taskIdToMinimize = val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask(taskInfo.displayId, wct, taskInfo.taskId) bringDesktopAppsToFrontBeforeShowingNewTask(taskInfo.displayId, wct, taskInfo.taskId) addMoveToDesktopChanges(wct, taskInfo) addMoveToDesktopChanges(wct, taskInfo) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct, taskInfo.displayId) wct, taskInfo.displayId) val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct) val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct) transition?.let { transition?.let { taskIdToMinimize?.let { taskId -> addPendingMinimizeTransition(it, taskId) } taskIdToMinimize?.let { taskId -> addPendingMinimizeTransition(it, taskId) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } } } Loading Loading @@ -507,7 +509,8 @@ class DesktopTasksController( taskId taskId ) ) ) ) return desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) return desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo).asExit() ?.runOnTransitionStart } } fun minimizeTask(taskInfo: RunningTaskInfo) { fun minimizeTask(taskInfo: RunningTaskInfo) { Loading @@ -520,7 +523,7 @@ class DesktopTasksController( removeWallpaperActivity(wct) removeWallpaperActivity(wct) } } // Notify immersive handler as it might need to exit immersive state. // Notify immersive handler as it might need to exit immersive state. val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) val exitResult = desktopImmersiveController.exitImmersiveIfApplicable(wct, taskInfo) wct.reorder(taskInfo.token, false) wct.reorder(taskInfo.token, false) val transition = freeformTaskTransitionStarter.startMinimizedModeTransition(wct) val transition = freeformTaskTransitionStarter.startMinimizedModeTransition(wct) Loading @@ -531,7 +534,7 @@ class DesktopTasksController( taskId = taskId taskId = taskId ) ) } } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } /** Move a task with given `taskId` to fullscreen */ /** Move a task with given `taskId` to fullscreen */ Loading Loading @@ -627,7 +630,7 @@ class DesktopTasksController( logV("moveBackgroundTaskToFront taskId=%s", taskId) logV("moveBackgroundTaskToFront taskId=%s", taskId) val wct = WindowContainerTransaction() val wct = WindowContainerTransaction() // TODO: b/342378842 - Instead of using default display, support multiple displays // TODO: b/342378842 - Instead of using default display, support multiple displays val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = DEFAULT_DISPLAY, displayId = DEFAULT_DISPLAY, excludeTaskId = taskId, excludeTaskId = taskId, Loading @@ -638,8 +641,13 @@ class DesktopTasksController( launchWindowingMode = WINDOWING_MODE_FREEFORM launchWindowingMode = WINDOWING_MODE_FREEFORM }.toBundle(), }.toBundle(), ) ) val transition = startLaunchTransition(TRANSIT_OPEN, wct, taskId, remoteTransition) val transition = startLaunchTransition( runOnTransit?.invoke(transition) TRANSIT_OPEN, wct, taskId, remoteTransition = remoteTransition ) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } } /** /** Loading @@ -658,32 +666,39 @@ class DesktopTasksController( } } val wct = WindowContainerTransaction() val wct = WindowContainerTransaction() wct.reorder(taskInfo.token, true /* onTop */, true /* includingParents */) wct.reorder(taskInfo.token, true /* onTop */, true /* includingParents */) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val result = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = taskInfo.displayId, displayId = taskInfo.displayId, excludeTaskId = taskInfo.taskId, excludeTaskId = taskInfo.taskId, ) ) val transition = val exitResult = if (result is ExitResult.Exit) { result } else { null } startLaunchTransition( val transition = startLaunchTransition( TRANSIT_TO_FRONT, transitionType = TRANSIT_TO_FRONT, wct, wct = wct, taskInfo.taskId, taskId = taskInfo.taskId, remoteTransition, exitingImmersiveTask = exitResult?.exitingTask, taskInfo.displayId remoteTransition = remoteTransition, displayId = taskInfo.displayId, ) ) runOnTransit?.invoke(transition) exitResult?.runOnTransitionStart?.invoke(transition) } } private fun startLaunchTransition( private fun startLaunchTransition( transitionType: Int, transitionType: Int, wct: WindowContainerTransaction, wct: WindowContainerTransaction, taskId: Int, taskId: Int, remoteTransition: RemoteTransition?, exitingImmersiveTask: Int? = null, remoteTransition: RemoteTransition? = null, displayId: Int = DEFAULT_DISPLAY, displayId: Int = DEFAULT_DISPLAY, ): IBinder { ): IBinder { val taskIdToMinimize = addAndGetMinimizeChanges(displayId, wct, taskId) val taskIdToMinimize = addAndGetMinimizeChanges(displayId, wct, taskId) if (remoteTransition == null) { if (remoteTransition == null) { val t = transitions.startTransition(transitionType, wct, null /* handler */) val t = desktopMixedTransitionHandler.startLaunchTransition( transitionType = transitionType, wct = wct, taskId = taskId, exitingImmersiveTask = exitingImmersiveTask, ) taskIdToMinimize?.let { addPendingMinimizeTransition(t, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(t, it) } return t return t } } Loading Loading @@ -1373,14 +1388,15 @@ class DesktopTasksController( wct.startTask(requestedTaskId, options.toBundle()) wct.startTask(requestedTaskId, options.toBundle()) val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( val taskIdToMinimize = bringDesktopAppsToFrontBeforeShowingNewTask( callingTask.displayId, wct, requestedTaskId) callingTask.displayId, wct, requestedTaskId) val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable( val exitResult = desktopImmersiveController .exitImmersiveIfApplicable( wct = wct, wct = wct, displayId = callingTask.displayId, displayId = callingTask.displayId, excludeTaskId = requestedTaskId, excludeTaskId = requestedTaskId, ) ) val transition = transitions.startTransition(TRANSIT_OPEN, wct, null) val transition = transitions.startTransition(TRANSIT_OPEN, wct, null) taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } taskIdToMinimize?.let { addPendingMinimizeTransition(transition, it) } runOnTransit?.invoke(transition) exitResult.asExit()?.runOnTransitionStart?.invoke(transition) } else { } else { val splitPosition = splitScreenController.determineNewInstancePosition(callingTask) val splitPosition = splitScreenController.determineNewInstancePosition(callingTask) splitScreenController.startTask(requestedTaskId, splitPosition, splitScreenController.startTask(requestedTaskId, splitPosition, Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt +26 −11 File changed.Preview size limit exceeded, changes collapsed. Show changes