Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +36 −5 Original line number Diff line number Diff line Loading @@ -465,6 +465,30 @@ class DesktopTasksController( return isFreeformDisplay } /** Called when the recents transition that started while in desktop is finishing. */ fun onRecentsInDesktopAnimationFinishing( transition: IBinder, finishWct: WindowContainerTransaction, returnToApp: Boolean, ) { if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return logV("onRecentsInDesktopAnimationFinishing returnToApp=%b", returnToApp) if (returnToApp) return // Home/Recents only exists in the default display. val activeDesk = taskRepository.getActiveDeskId(DEFAULT_DISPLAY) ?: return // Not going back to the active desk, deactivate it. val runOnTransitStart = performDesktopExitCleanUp( wct = finishWct, deskId = activeDesk, displayId = DEFAULT_DISPLAY, willExitDesktop = true, shouldEndUpAtHome = true, fromRecentsTransition = true, ) runOnTransitStart?.invoke(transition) } /** Creates a new desk in the given display. */ fun createDesk(displayId: Int) { if (displayId == Display.INVALID_DISPLAY) { Loading Loading @@ -1937,17 +1961,24 @@ class DesktopTasksController( displayId: Int, willExitDesktop: Boolean, shouldEndUpAtHome: Boolean = true, fromRecentsTransition: Boolean = false, ): RunOnTransitStart? { if (!willExitDesktop) return null desktopModeEnterExitTransitionListener?.onExitDesktopModeTransitionStarted( FULLSCREEN_ANIMATION_DURATION ) // No need to clean up the wallpaper / reorder home when coming from a recents transition. if ( !fromRecentsTransition || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ) { removeWallpaperActivity(wct, displayId) if (shouldEndUpAtHome) { // If the transition should end up with user going to home, launch home with a pending // intent. // If the transition should end up with user going to home, launch home with a // pending intent. addLaunchHomePendingIntent(wct, displayId) } } return prepareDeskDeactivationIfNeeded(wct, deskId) } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DeskTransition.kt +17 −6 Original line number Diff line number Diff line Loading @@ -18,9 +18,12 @@ package com.android.wm.shell.desktopmode.multidesks import android.os.IBinder /** Represents shell-started transitions involving desks. */ sealed class DeskTransition { sealed interface DeskTransition { /** The transition token. */ abstract val token: IBinder val token: IBinder /** Returns a copy of this desk transition with a new transition token. */ fun copyWithToken(token: IBinder): DeskTransition /** A transition to remove a desk and its tasks from a display. */ data class RemoveDesk( Loading @@ -29,11 +32,15 @@ sealed class DeskTransition { val deskId: Int, val tasks: Set<Int>, val onDeskRemovedListener: OnDeskRemovedListener?, ) : DeskTransition() ) : DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } /** A transition to activate a desk in its display. */ data class ActivateDesk(override val token: IBinder, val displayId: Int, val deskId: Int) : DeskTransition() DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } /** A transition to activate a desk by moving an outside task to it. */ data class ActiveDeskWithTask( Loading @@ -41,8 +48,12 @@ sealed class DeskTransition { val displayId: Int, val deskId: Int, val enterTaskId: Int, ) : DeskTransition() ) : DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } /** A transition to deactivate a desk. */ data class DeactivateDesk(override val token: IBinder, val deskId: Int) : DeskTransition() data class DeactivateDesk(override val token: IBinder, val deskId: Int) : DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt +78 −27 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class DesksTransitionObserver( val transitions = deskTransitions[transition.token] ?: mutableSetOf() transitions += transition deskTransitions[transition.token] = transitions logD("Added pending desk transition: %s", transition) } /** Loading @@ -51,6 +52,43 @@ class DesksTransitionObserver( deskTransitions.forEach { deskTransition -> handleDeskTransition(info, deskTransition) } } /** * Called when a transition is merged with another transition, which may include transitions not * tracked by this observer. */ fun onTransitionMerged(merged: IBinder, playing: IBinder) { if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return val transitions = deskTransitions.remove(merged) ?: return deskTransitions[playing] = transitions .map { deskTransition -> deskTransition.copyWithToken(token = playing) } .toMutableSet() } /** * Called when any transition finishes, which may include transitions not tracked by this * observer. * * Most [DeskTransition]s are not handled here because [onTransitionReady] handles them and * removes them from the map. However, there can be cases where the transition was added after * [onTransitionReady] had already been called and they need to be handled here, such as the * swipe-to-home recents transition when there is no book-end transition. */ fun onTransitionFinished(transition: IBinder) { if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return val deskTransitions = deskTransitions.remove(transition) ?: return deskTransitions.forEach { deskTransition -> if (deskTransition is DeskTransition.DeactivateDesk) { handleDeactivateDeskTransition(null, deskTransition) } else { logW( "Unexpected desk transition finished without being handled: %s", deskTransition, ) } } } private fun handleDeskTransition(info: TransitionInfo, deskTransition: DeskTransition) { logD("Desk transition ready: %s", deskTransition) val desktopRepository = desktopUserRepositories.current Loading Loading @@ -102,12 +140,23 @@ class DesksTransitionObserver( ) } } is DeskTransition.DeactivateDesk -> { var visibleDeactivation = false for (change in info.changes) { is DeskTransition.DeactivateDesk -> handleDeactivateDeskTransition(info, deskTransition) } } private fun handleDeactivateDeskTransition( info: TransitionInfo?, deskTransition: DeskTransition.DeactivateDesk, ) { logD("handleDeactivateDeskTransition: %s", deskTransition) val desktopRepository = desktopUserRepositories.current var deskChangeFound = false val changes = info?.changes ?: emptyList() for (change in changes) { val isDeskChange = desksOrganizer.isDeskChange(change, deskTransition.deskId) if (isDeskChange) { visibleDeactivation = true deskChangeFound = true continue } val taskId = change.taskInfo?.taskId ?: continue Loading @@ -125,18 +174,20 @@ class DesksTransitionObserver( // deactivated. Some interactions, such as the desk deactivating because it's // occluded by a fullscreen task result in a transition change, but others, such // as transitioning from an empty desk to home may not. if (!visibleDeactivation) { if (!deskChangeFound) { logD("Deactivating desk without transition change") } desktopRepository.setDeskInactive(deskId = deskTransition.deskId) } } } private fun logD(msg: String, vararg arguments: Any?) { ProtoLog.d(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) } private companion object { private const val TAG = "DesksTransitionObserver" } Loading libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java +2 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs @Override public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) { mDesksTransitionObserver.ifPresent(o -> o.onTransitionMerged(merged, playing)); if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue()) { // TODO(b/367268953): Remove when DesktopTaskListener is introduced. mDesktopImmersiveController.ifPresent(h -> h.onTransitionMerged(merged, playing)); Loading @@ -232,6 +233,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs @Override public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) { mDesksTransitionObserver.ifPresent(o -> o.onTransitionFinished(transition)); if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue()) { // TODO(b/367268953): Remove when DesktopTaskListener is introduced. mDesktopImmersiveController.ifPresent(h -> h.onTransitionFinished(transition, aborted)); Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +3 −0 Original line number Diff line number Diff line Loading @@ -394,6 +394,9 @@ public class DefaultMixedHandler implements MixedTransitionHandler, if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) { ((RecentsMixedTransition) mixed).onAnimateRecentsDuringSplitFinishing( returnToApp, finishWct, finishT); } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) { ((RecentsMixedTransition) mixed).onAnimateRecentsDuringDesktopFinishing( returnToApp, finishWct); } } } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +36 −5 Original line number Diff line number Diff line Loading @@ -465,6 +465,30 @@ class DesktopTasksController( return isFreeformDisplay } /** Called when the recents transition that started while in desktop is finishing. */ fun onRecentsInDesktopAnimationFinishing( transition: IBinder, finishWct: WindowContainerTransaction, returnToApp: Boolean, ) { if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return logV("onRecentsInDesktopAnimationFinishing returnToApp=%b", returnToApp) if (returnToApp) return // Home/Recents only exists in the default display. val activeDesk = taskRepository.getActiveDeskId(DEFAULT_DISPLAY) ?: return // Not going back to the active desk, deactivate it. val runOnTransitStart = performDesktopExitCleanUp( wct = finishWct, deskId = activeDesk, displayId = DEFAULT_DISPLAY, willExitDesktop = true, shouldEndUpAtHome = true, fromRecentsTransition = true, ) runOnTransitStart?.invoke(transition) } /** Creates a new desk in the given display. */ fun createDesk(displayId: Int) { if (displayId == Display.INVALID_DISPLAY) { Loading Loading @@ -1937,17 +1961,24 @@ class DesktopTasksController( displayId: Int, willExitDesktop: Boolean, shouldEndUpAtHome: Boolean = true, fromRecentsTransition: Boolean = false, ): RunOnTransitStart? { if (!willExitDesktop) return null desktopModeEnterExitTransitionListener?.onExitDesktopModeTransitionStarted( FULLSCREEN_ANIMATION_DURATION ) // No need to clean up the wallpaper / reorder home when coming from a recents transition. if ( !fromRecentsTransition || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ) { removeWallpaperActivity(wct, displayId) if (shouldEndUpAtHome) { // If the transition should end up with user going to home, launch home with a pending // intent. // If the transition should end up with user going to home, launch home with a // pending intent. addLaunchHomePendingIntent(wct, displayId) } } return prepareDeskDeactivationIfNeeded(wct, deskId) } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DeskTransition.kt +17 −6 Original line number Diff line number Diff line Loading @@ -18,9 +18,12 @@ package com.android.wm.shell.desktopmode.multidesks import android.os.IBinder /** Represents shell-started transitions involving desks. */ sealed class DeskTransition { sealed interface DeskTransition { /** The transition token. */ abstract val token: IBinder val token: IBinder /** Returns a copy of this desk transition with a new transition token. */ fun copyWithToken(token: IBinder): DeskTransition /** A transition to remove a desk and its tasks from a display. */ data class RemoveDesk( Loading @@ -29,11 +32,15 @@ sealed class DeskTransition { val deskId: Int, val tasks: Set<Int>, val onDeskRemovedListener: OnDeskRemovedListener?, ) : DeskTransition() ) : DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } /** A transition to activate a desk in its display. */ data class ActivateDesk(override val token: IBinder, val displayId: Int, val deskId: Int) : DeskTransition() DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } /** A transition to activate a desk by moving an outside task to it. */ data class ActiveDeskWithTask( Loading @@ -41,8 +48,12 @@ sealed class DeskTransition { val displayId: Int, val deskId: Int, val enterTaskId: Int, ) : DeskTransition() ) : DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } /** A transition to deactivate a desk. */ data class DeactivateDesk(override val token: IBinder, val deskId: Int) : DeskTransition() data class DeactivateDesk(override val token: IBinder, val deskId: Int) : DeskTransition { override fun copyWithToken(token: IBinder): DeskTransition = copy(token) } }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt +78 −27 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class DesksTransitionObserver( val transitions = deskTransitions[transition.token] ?: mutableSetOf() transitions += transition deskTransitions[transition.token] = transitions logD("Added pending desk transition: %s", transition) } /** Loading @@ -51,6 +52,43 @@ class DesksTransitionObserver( deskTransitions.forEach { deskTransition -> handleDeskTransition(info, deskTransition) } } /** * Called when a transition is merged with another transition, which may include transitions not * tracked by this observer. */ fun onTransitionMerged(merged: IBinder, playing: IBinder) { if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return val transitions = deskTransitions.remove(merged) ?: return deskTransitions[playing] = transitions .map { deskTransition -> deskTransition.copyWithToken(token = playing) } .toMutableSet() } /** * Called when any transition finishes, which may include transitions not tracked by this * observer. * * Most [DeskTransition]s are not handled here because [onTransitionReady] handles them and * removes them from the map. However, there can be cases where the transition was added after * [onTransitionReady] had already been called and they need to be handled here, such as the * swipe-to-home recents transition when there is no book-end transition. */ fun onTransitionFinished(transition: IBinder) { if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return val deskTransitions = deskTransitions.remove(transition) ?: return deskTransitions.forEach { deskTransition -> if (deskTransition is DeskTransition.DeactivateDesk) { handleDeactivateDeskTransition(null, deskTransition) } else { logW( "Unexpected desk transition finished without being handled: %s", deskTransition, ) } } } private fun handleDeskTransition(info: TransitionInfo, deskTransition: DeskTransition) { logD("Desk transition ready: %s", deskTransition) val desktopRepository = desktopUserRepositories.current Loading Loading @@ -102,12 +140,23 @@ class DesksTransitionObserver( ) } } is DeskTransition.DeactivateDesk -> { var visibleDeactivation = false for (change in info.changes) { is DeskTransition.DeactivateDesk -> handleDeactivateDeskTransition(info, deskTransition) } } private fun handleDeactivateDeskTransition( info: TransitionInfo?, deskTransition: DeskTransition.DeactivateDesk, ) { logD("handleDeactivateDeskTransition: %s", deskTransition) val desktopRepository = desktopUserRepositories.current var deskChangeFound = false val changes = info?.changes ?: emptyList() for (change in changes) { val isDeskChange = desksOrganizer.isDeskChange(change, deskTransition.deskId) if (isDeskChange) { visibleDeactivation = true deskChangeFound = true continue } val taskId = change.taskInfo?.taskId ?: continue Loading @@ -125,18 +174,20 @@ class DesksTransitionObserver( // deactivated. Some interactions, such as the desk deactivating because it's // occluded by a fullscreen task result in a transition change, but others, such // as transitioning from an empty desk to home may not. if (!visibleDeactivation) { if (!deskChangeFound) { logD("Deactivating desk without transition change") } desktopRepository.setDeskInactive(deskId = deskTransition.deskId) } } } private fun logD(msg: String, vararg arguments: Any?) { ProtoLog.d(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) } private companion object { private const val TAG = "DesksTransitionObserver" } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java +2 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs @Override public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) { mDesksTransitionObserver.ifPresent(o -> o.onTransitionMerged(merged, playing)); if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue()) { // TODO(b/367268953): Remove when DesktopTaskListener is introduced. mDesktopImmersiveController.ifPresent(h -> h.onTransitionMerged(merged, playing)); Loading @@ -232,6 +233,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs @Override public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) { mDesksTransitionObserver.ifPresent(o -> o.onTransitionFinished(transition)); if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue()) { // TODO(b/367268953): Remove when DesktopTaskListener is introduced. mDesktopImmersiveController.ifPresent(h -> h.onTransitionFinished(transition, aborted)); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +3 −0 Original line number Diff line number Diff line Loading @@ -394,6 +394,9 @@ public class DefaultMixedHandler implements MixedTransitionHandler, if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) { ((RecentsMixedTransition) mixed).onAnimateRecentsDuringSplitFinishing( returnToApp, finishWct, finishT); } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) { ((RecentsMixedTransition) mixed).onAnimateRecentsDuringDesktopFinishing( returnToApp, finishWct); } } } Loading