Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +19 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import com.android.wm.shell.compatui.impl.DefaultComponentIdGenerator; import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; import com.android.wm.shell.displayareahelper.DisplayAreaHelperController; import com.android.wm.shell.freeform.FreeformComponents; Loading Loading @@ -1031,6 +1032,24 @@ public abstract class WMShellBaseModule { }); } @WMSingleton @Provides static DesktopWallpaperActivityTokenProvider provideDesktopWallpaperActivityTokenProvider() { return new DesktopWallpaperActivityTokenProvider(); } @WMSingleton @Provides static Optional<DesktopWallpaperActivityTokenProvider> provideOptionalDesktopWallpaperActivityTokenProvider( Context context, DesktopWallpaperActivityTokenProvider desktopWallpaperActivityTokenProvider) { if (DesktopModeStatus.canEnterDesktopMode(context)) { return Optional.of(desktopWallpaperActivityTokenProvider); } return Optional.empty(); } // // Task Stack // Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +0 −6 Original line number Diff line number Diff line Loading @@ -1312,12 +1312,6 @@ public abstract class WMShellModule { return new DesktopModeUiEventLogger(uiEventLogger, packageManager); } @WMSingleton @Provides static DesktopWallpaperActivityTokenProvider provideDesktopWallpaperActivityTokenProvider() { return new DesktopWallpaperActivityTokenProvider(); } // // Drag and drop // Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +10 −3 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import com.android.wm.shell.common.pip.SizeSpecSource; import com.android.wm.shell.dagger.WMShellBaseModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider; import com.android.wm.shell.pip2.phone.PhonePipMenuController; import com.android.wm.shell.pip2.phone.PipController; import com.android.wm.shell.pip2.phone.PipMotionHelper; Loading Loading @@ -82,11 +83,14 @@ public abstract class Pip2Module { @NonNull PipTransitionState pipStackListenerController, @NonNull PipDisplayLayoutState pipDisplayLayoutState, @NonNull PipUiStateChangeController pipUiStateChangeController, Optional<DesktopUserRepositories> desktopUserRepositoriesOptional) { Optional<DesktopUserRepositories> desktopUserRepositoriesOptional, Optional<DesktopWallpaperActivityTokenProvider> desktopWallpaperActivityTokenProviderOptional) { return new PipTransition(context, shellInit, shellTaskOrganizer, transitions, pipBoundsState, null, pipBoundsAlgorithm, pipTaskListener, pipScheduler, pipStackListenerController, pipDisplayLayoutState, pipUiStateChangeController, desktopUserRepositoriesOptional); pipUiStateChangeController, desktopUserRepositoriesOptional, desktopWallpaperActivityTokenProviderOptional); } @WMSingleton Loading Loading @@ -138,9 +142,12 @@ public abstract class Pip2Module { @ShellMainThread ShellExecutor mainExecutor, PipTransitionState pipTransitionState, Optional<DesktopUserRepositories> desktopUserRepositoriesOptional, Optional<DesktopWallpaperActivityTokenProvider> desktopWallpaperActivityTokenProviderOptional, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) { return new PipScheduler(context, pipBoundsState, mainExecutor, pipTransitionState, desktopUserRepositoriesOptional, rootTaskDisplayAreaOrganizer); desktopUserRepositoriesOptional, desktopWallpaperActivityTokenProviderOptional, rootTaskDisplayAreaOrganizer); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +67 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.core.util.forEach import androidx.core.util.keyIterator import androidx.core.util.valueIterator import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread Loading Loading @@ -56,6 +57,10 @@ class DesktopRepository( * @property topTransparentFullscreenTaskId the task id of any current top transparent * fullscreen task launched on top of Desktop Mode. Cleared when the transparent task is * closed or sent to back. (top is at index 0). * @property pipTaskId the task id of PiP task entered while in Desktop Mode. * @property pipShouldKeepDesktopActive whether an active PiP window should keep the Desktop * Mode session active. Only false when we are explicitly exiting Desktop Mode (via user * action) while there is an active PiP window. */ private data class DesktopTaskData( val activeTasks: ArraySet<Int> = ArraySet(), Loading @@ -66,6 +71,8 @@ class DesktopRepository( val freeformTasksInZOrder: ArrayList<Int> = ArrayList(), var fullImmersiveTaskId: Int? = null, var topTransparentFullscreenTaskId: Int? = null, var pipTaskId: Int? = null, var pipShouldKeepDesktopActive: Boolean = true, ) { fun deepCopy(): DesktopTaskData = DesktopTaskData( Loading @@ -76,6 +83,8 @@ class DesktopRepository( freeformTasksInZOrder = ArrayList(freeformTasksInZOrder), fullImmersiveTaskId = fullImmersiveTaskId, topTransparentFullscreenTaskId = topTransparentFullscreenTaskId, pipTaskId = pipTaskId, pipShouldKeepDesktopActive = pipShouldKeepDesktopActive, ) fun clear() { Loading @@ -86,6 +95,8 @@ class DesktopRepository( freeformTasksInZOrder.clear() fullImmersiveTaskId = null topTransparentFullscreenTaskId = null pipTaskId = null pipShouldKeepDesktopActive = true } } Loading @@ -104,6 +115,9 @@ class DesktopRepository( /* Tracks last bounds of task before toggled to immersive state. */ private val boundsBeforeFullImmersiveByTaskId = SparseArray<Rect>() /* Callback for when a pending PiP transition has been aborted. */ private var onPipAbortedCallback: ((Int, Int) -> Unit)? = null private var desktopGestureExclusionListener: Consumer<Region>? = null private var desktopGestureExclusionExecutor: Executor? = null Loading Loading @@ -302,6 +316,54 @@ class DesktopRepository( } } /** Set whether the given task is the Desktop-entered PiP task in this display. */ fun setTaskInPip(displayId: Int, taskId: Int, enterPip: Boolean) { val desktopData = desktopTaskDataByDisplayId.getOrCreate(displayId) if (enterPip) { desktopData.pipTaskId = taskId desktopData.pipShouldKeepDesktopActive = true } else { desktopData.pipTaskId = if (desktopData.pipTaskId == taskId) null else { logW( "setTaskInPip: taskId=$taskId did not match saved taskId=${desktopData.pipTaskId}" ) desktopData.pipTaskId } } notifyVisibleTaskListeners(displayId, getVisibleTaskCount(displayId)) } /** Returns whether there is a PiP that was entered/minimized from Desktop in this display. */ fun isMinimizedPipPresentInDisplay(displayId: Int): Boolean = desktopTaskDataByDisplayId.getOrCreate(displayId).pipTaskId != null /** Returns whether the given task is the Desktop-entered PiP task in this display. */ fun isTaskMinimizedPipInDisplay(displayId: Int, taskId: Int): Boolean = desktopTaskDataByDisplayId.getOrCreate(displayId).pipTaskId == taskId /** Returns whether Desktop session should be active in this display due to active PiP. */ fun shouldDesktopBeActiveForPip(displayId: Int): Boolean = Flags.enableDesktopWindowingPip() && isMinimizedPipPresentInDisplay(displayId) && desktopTaskDataByDisplayId.getOrCreate(displayId).pipShouldKeepDesktopActive /** Saves whether a PiP window should keep Desktop session active in this display. */ fun setPipShouldKeepDesktopActive(displayId: Int, keepActive: Boolean) { desktopTaskDataByDisplayId.getOrCreate(displayId).pipShouldKeepDesktopActive = keepActive } /** Saves callback to handle a pending PiP transition being aborted. */ fun setOnPipAbortedCallback(callbackIfPipAborted: ((Int, Int) -> Unit)?) { onPipAbortedCallback = callbackIfPipAborted } /** Invokes callback to handle a pending PiP transition with the given task id being aborted. */ fun onPipAborted(displayId: Int, pipTaskId: Int) { onPipAbortedCallback?.invoke(displayId, pipTaskId) } /** Set whether the given task is the full-immersive task in this display. */ fun setTaskInFullImmersiveState(displayId: Int, taskId: Int, immersive: Boolean) { val desktopData = desktopTaskDataByDisplayId.getOrCreate(displayId) Loading Loading @@ -338,8 +400,12 @@ class DesktopRepository( } private fun notifyVisibleTaskListeners(displayId: Int, visibleTasksCount: Int) { val visibleAndPipTasksCount = if (shouldDesktopBeActiveForPip(displayId)) visibleTasksCount + 1 else visibleTasksCount visibleTasksListeners.forEach { (listener, executor) -> executor.execute { listener.onTasksVisibilityChanged(displayId, visibleTasksCount) } executor.execute { listener.onTasksVisibilityChanged(displayId, visibleAndPipTasksCount) } } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +56 −29 Original line number Diff line number Diff line Loading @@ -225,7 +225,6 @@ class DesktopTasksController( // Launch cookie used to identify a drag and drop transition to fullscreen after it has begun. // Used to prevent handleRequest from moving the new fullscreen task to freeform. private var dragAndDropFullscreenCookie: Binder? = null private var pendingPipTransitionAndTask: Pair<IBinder, Int>? = null init { desktopMode = DesktopModeImpl() Loading Loading @@ -321,18 +320,29 @@ class DesktopTasksController( fun visibleTaskCount(displayId: Int): Int = taskRepository.getVisibleTaskCount(displayId) /** * Returns true if any freeform tasks are visible or if a transparent fullscreen task exists on * top in Desktop Mode. * Returns true if any of the following is true: * - Any freeform tasks are visible * - A transparent fullscreen task exists on top in Desktop Mode * - PiP on Desktop Windowing is enabled, there is an active PiP window and the desktop * wallpaper is visible. */ fun isDesktopModeShowing(displayId: Int): Boolean { val hasVisibleTasks = visibleTaskCount(displayId) > 0 val hasTopTransparentFullscreenTask = taskRepository.getTopTransparentFullscreenTaskId(displayId) != null val hasMinimizedPip = Flags.enableDesktopWindowingPip() && taskRepository.isMinimizedPipPresentInDisplay(displayId) && desktopWallpaperActivityTokenProvider.isWallpaperActivityVisible(displayId) if ( DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC .isTrue() && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue() ) { return visibleTaskCount(displayId) > 0 || taskRepository.getTopTransparentFullscreenTaskId(displayId) != null return hasVisibleTasks || hasTopTransparentFullscreenTask || hasMinimizedPip } else if (Flags.enableDesktopWindowingPip()) { return hasVisibleTasks || hasMinimizedPip } return visibleTaskCount(displayId) > 0 return hasVisibleTasks } /** Moves focused task to desktop mode for given [displayId]. */ Loading Loading @@ -592,7 +602,7 @@ class DesktopTasksController( ): ((IBinder) -> Unit)? { val taskId = taskInfo.taskId desktopTilingDecorViewModel.removeTaskIfTiled(displayId, taskId) performDesktopExitCleanupIfNeeded(taskId, displayId, wct) performDesktopExitCleanupIfNeeded(taskId, displayId, wct, forceToFullscreen = false) taskRepository.addClosingTask(displayId, taskId) taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate( doesAnyTaskRequireTaskbarRounding(displayId, taskId) Loading Loading @@ -624,8 +634,12 @@ class DesktopTasksController( ) val requestRes = transitions.dispatchRequest(Binder(), requestInfo, /* skip= */ null) wct.merge(requestRes.second, true) pendingPipTransitionAndTask = freeformTaskTransitionStarter.startPipTransition(wct) to taskInfo.taskId freeformTaskTransitionStarter.startPipTransition(wct) taskRepository.setTaskInPip(taskInfo.displayId, taskInfo.taskId, enterPip = true) taskRepository.setOnPipAbortedCallback { displayId, taskId -> minimizeTaskInner(shellTaskOrganizer.getRunningTaskInfo(taskId)!!) taskRepository.setTaskInPip(displayId, taskId, enterPip = false) } return } Loading @@ -636,7 +650,7 @@ class DesktopTasksController( val taskId = taskInfo.taskId val displayId = taskInfo.displayId val wct = WindowContainerTransaction() performDesktopExitCleanupIfNeeded(taskId, displayId, wct) performDesktopExitCleanupIfNeeded(taskId, displayId, wct, forceToFullscreen = false) // Notify immersive handler as it might need to exit immersive state. val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( Loading Loading @@ -898,7 +912,12 @@ class DesktopTasksController( } if (Flags.enablePerDisplayDesktopWallpaperActivity()) { performDesktopExitCleanupIfNeeded(task.taskId, task.displayId, wct) performDesktopExitCleanupIfNeeded( task.taskId, task.displayId, wct, forceToFullscreen = false, ) } transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null) Loading Loading @@ -1414,7 +1433,9 @@ class DesktopTasksController( taskId: Int, displayId: Int, wct: WindowContainerTransaction, forceToFullscreen: Boolean, ) { taskRepository.setPipShouldKeepDesktopActive(displayId, !forceToFullscreen) if (Flags.enablePerDisplayDesktopWallpaperActivity()) { if (!taskRepository.isOnlyVisibleNonClosingTask(taskId, displayId)) { return Loading @@ -1422,6 +1443,12 @@ class DesktopTasksController( if (displayId != DEFAULT_DISPLAY) { return } } else if ( Flags.enableDesktopWindowingPip() && taskRepository.isMinimizedPipPresentInDisplay(displayId) && !forceToFullscreen ) { return } else { if (!taskRepository.isOnlyVisibleNonClosingTask(taskId)) { return Loading Loading @@ -1462,21 +1489,6 @@ class DesktopTasksController( return false } override fun onTransitionConsumed( transition: IBinder, aborted: Boolean, finishT: Transaction?, ) { pendingPipTransitionAndTask?.let { (pipTransition, taskId) -> if (transition == pipTransition) { if (aborted) { shellTaskOrganizer.getRunningTaskInfo(taskId)?.let { minimizeTaskInner(it) } } pendingPipTransitionAndTask = null } } } override fun handleRequest( transition: IBinder, request: TransitionRequestInfo, Loading Loading @@ -1926,7 +1938,12 @@ class DesktopTasksController( if (!isDesktopModeShowing(task.displayId)) return null val wct = WindowContainerTransaction() performDesktopExitCleanupIfNeeded(task.taskId, task.displayId, wct) performDesktopExitCleanupIfNeeded( task.taskId, task.displayId, wct, forceToFullscreen = false, ) if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) { taskRepository.addClosingTask(task.displayId, task.taskId) Loading Loading @@ -2053,7 +2070,12 @@ class DesktopTasksController( wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) } performDesktopExitCleanupIfNeeded(taskInfo.taskId, taskInfo.displayId, wct) performDesktopExitCleanupIfNeeded( taskInfo.taskId, taskInfo.displayId, wct, forceToFullscreen = true, ) } private fun cascadeWindow(bounds: Rect, displayLayout: DisplayLayout, displayId: Int) { Loading Loading @@ -2087,7 +2109,12 @@ class DesktopTasksController( // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) performDesktopExitCleanupIfNeeded(taskInfo.taskId, taskInfo.displayId, wct) performDesktopExitCleanupIfNeeded( taskInfo.taskId, taskInfo.displayId, wct, forceToFullscreen = false, ) } /** Returns the ID of the Task that will be minimized, or null if no task will be minimized. */ Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +19 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import com.android.wm.shell.compatui.impl.DefaultComponentIdGenerator; import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; import com.android.wm.shell.displayareahelper.DisplayAreaHelperController; import com.android.wm.shell.freeform.FreeformComponents; Loading Loading @@ -1031,6 +1032,24 @@ public abstract class WMShellBaseModule { }); } @WMSingleton @Provides static DesktopWallpaperActivityTokenProvider provideDesktopWallpaperActivityTokenProvider() { return new DesktopWallpaperActivityTokenProvider(); } @WMSingleton @Provides static Optional<DesktopWallpaperActivityTokenProvider> provideOptionalDesktopWallpaperActivityTokenProvider( Context context, DesktopWallpaperActivityTokenProvider desktopWallpaperActivityTokenProvider) { if (DesktopModeStatus.canEnterDesktopMode(context)) { return Optional.of(desktopWallpaperActivityTokenProvider); } return Optional.empty(); } // // Task Stack // Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +0 −6 Original line number Diff line number Diff line Loading @@ -1312,12 +1312,6 @@ public abstract class WMShellModule { return new DesktopModeUiEventLogger(uiEventLogger, packageManager); } @WMSingleton @Provides static DesktopWallpaperActivityTokenProvider provideDesktopWallpaperActivityTokenProvider() { return new DesktopWallpaperActivityTokenProvider(); } // // Drag and drop // Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +10 −3 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import com.android.wm.shell.common.pip.SizeSpecSource; import com.android.wm.shell.dagger.WMShellBaseModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider; import com.android.wm.shell.pip2.phone.PhonePipMenuController; import com.android.wm.shell.pip2.phone.PipController; import com.android.wm.shell.pip2.phone.PipMotionHelper; Loading Loading @@ -82,11 +83,14 @@ public abstract class Pip2Module { @NonNull PipTransitionState pipStackListenerController, @NonNull PipDisplayLayoutState pipDisplayLayoutState, @NonNull PipUiStateChangeController pipUiStateChangeController, Optional<DesktopUserRepositories> desktopUserRepositoriesOptional) { Optional<DesktopUserRepositories> desktopUserRepositoriesOptional, Optional<DesktopWallpaperActivityTokenProvider> desktopWallpaperActivityTokenProviderOptional) { return new PipTransition(context, shellInit, shellTaskOrganizer, transitions, pipBoundsState, null, pipBoundsAlgorithm, pipTaskListener, pipScheduler, pipStackListenerController, pipDisplayLayoutState, pipUiStateChangeController, desktopUserRepositoriesOptional); pipUiStateChangeController, desktopUserRepositoriesOptional, desktopWallpaperActivityTokenProviderOptional); } @WMSingleton Loading Loading @@ -138,9 +142,12 @@ public abstract class Pip2Module { @ShellMainThread ShellExecutor mainExecutor, PipTransitionState pipTransitionState, Optional<DesktopUserRepositories> desktopUserRepositoriesOptional, Optional<DesktopWallpaperActivityTokenProvider> desktopWallpaperActivityTokenProviderOptional, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) { return new PipScheduler(context, pipBoundsState, mainExecutor, pipTransitionState, desktopUserRepositoriesOptional, rootTaskDisplayAreaOrganizer); desktopUserRepositoriesOptional, desktopWallpaperActivityTokenProviderOptional, rootTaskDisplayAreaOrganizer); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +67 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.core.util.forEach import androidx.core.util.keyIterator import androidx.core.util.valueIterator import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread Loading Loading @@ -56,6 +57,10 @@ class DesktopRepository( * @property topTransparentFullscreenTaskId the task id of any current top transparent * fullscreen task launched on top of Desktop Mode. Cleared when the transparent task is * closed or sent to back. (top is at index 0). * @property pipTaskId the task id of PiP task entered while in Desktop Mode. * @property pipShouldKeepDesktopActive whether an active PiP window should keep the Desktop * Mode session active. Only false when we are explicitly exiting Desktop Mode (via user * action) while there is an active PiP window. */ private data class DesktopTaskData( val activeTasks: ArraySet<Int> = ArraySet(), Loading @@ -66,6 +71,8 @@ class DesktopRepository( val freeformTasksInZOrder: ArrayList<Int> = ArrayList(), var fullImmersiveTaskId: Int? = null, var topTransparentFullscreenTaskId: Int? = null, var pipTaskId: Int? = null, var pipShouldKeepDesktopActive: Boolean = true, ) { fun deepCopy(): DesktopTaskData = DesktopTaskData( Loading @@ -76,6 +83,8 @@ class DesktopRepository( freeformTasksInZOrder = ArrayList(freeformTasksInZOrder), fullImmersiveTaskId = fullImmersiveTaskId, topTransparentFullscreenTaskId = topTransparentFullscreenTaskId, pipTaskId = pipTaskId, pipShouldKeepDesktopActive = pipShouldKeepDesktopActive, ) fun clear() { Loading @@ -86,6 +95,8 @@ class DesktopRepository( freeformTasksInZOrder.clear() fullImmersiveTaskId = null topTransparentFullscreenTaskId = null pipTaskId = null pipShouldKeepDesktopActive = true } } Loading @@ -104,6 +115,9 @@ class DesktopRepository( /* Tracks last bounds of task before toggled to immersive state. */ private val boundsBeforeFullImmersiveByTaskId = SparseArray<Rect>() /* Callback for when a pending PiP transition has been aborted. */ private var onPipAbortedCallback: ((Int, Int) -> Unit)? = null private var desktopGestureExclusionListener: Consumer<Region>? = null private var desktopGestureExclusionExecutor: Executor? = null Loading Loading @@ -302,6 +316,54 @@ class DesktopRepository( } } /** Set whether the given task is the Desktop-entered PiP task in this display. */ fun setTaskInPip(displayId: Int, taskId: Int, enterPip: Boolean) { val desktopData = desktopTaskDataByDisplayId.getOrCreate(displayId) if (enterPip) { desktopData.pipTaskId = taskId desktopData.pipShouldKeepDesktopActive = true } else { desktopData.pipTaskId = if (desktopData.pipTaskId == taskId) null else { logW( "setTaskInPip: taskId=$taskId did not match saved taskId=${desktopData.pipTaskId}" ) desktopData.pipTaskId } } notifyVisibleTaskListeners(displayId, getVisibleTaskCount(displayId)) } /** Returns whether there is a PiP that was entered/minimized from Desktop in this display. */ fun isMinimizedPipPresentInDisplay(displayId: Int): Boolean = desktopTaskDataByDisplayId.getOrCreate(displayId).pipTaskId != null /** Returns whether the given task is the Desktop-entered PiP task in this display. */ fun isTaskMinimizedPipInDisplay(displayId: Int, taskId: Int): Boolean = desktopTaskDataByDisplayId.getOrCreate(displayId).pipTaskId == taskId /** Returns whether Desktop session should be active in this display due to active PiP. */ fun shouldDesktopBeActiveForPip(displayId: Int): Boolean = Flags.enableDesktopWindowingPip() && isMinimizedPipPresentInDisplay(displayId) && desktopTaskDataByDisplayId.getOrCreate(displayId).pipShouldKeepDesktopActive /** Saves whether a PiP window should keep Desktop session active in this display. */ fun setPipShouldKeepDesktopActive(displayId: Int, keepActive: Boolean) { desktopTaskDataByDisplayId.getOrCreate(displayId).pipShouldKeepDesktopActive = keepActive } /** Saves callback to handle a pending PiP transition being aborted. */ fun setOnPipAbortedCallback(callbackIfPipAborted: ((Int, Int) -> Unit)?) { onPipAbortedCallback = callbackIfPipAborted } /** Invokes callback to handle a pending PiP transition with the given task id being aborted. */ fun onPipAborted(displayId: Int, pipTaskId: Int) { onPipAbortedCallback?.invoke(displayId, pipTaskId) } /** Set whether the given task is the full-immersive task in this display. */ fun setTaskInFullImmersiveState(displayId: Int, taskId: Int, immersive: Boolean) { val desktopData = desktopTaskDataByDisplayId.getOrCreate(displayId) Loading Loading @@ -338,8 +400,12 @@ class DesktopRepository( } private fun notifyVisibleTaskListeners(displayId: Int, visibleTasksCount: Int) { val visibleAndPipTasksCount = if (shouldDesktopBeActiveForPip(displayId)) visibleTasksCount + 1 else visibleTasksCount visibleTasksListeners.forEach { (listener, executor) -> executor.execute { listener.onTasksVisibilityChanged(displayId, visibleTasksCount) } executor.execute { listener.onTasksVisibilityChanged(displayId, visibleAndPipTasksCount) } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +56 −29 Original line number Diff line number Diff line Loading @@ -225,7 +225,6 @@ class DesktopTasksController( // Launch cookie used to identify a drag and drop transition to fullscreen after it has begun. // Used to prevent handleRequest from moving the new fullscreen task to freeform. private var dragAndDropFullscreenCookie: Binder? = null private var pendingPipTransitionAndTask: Pair<IBinder, Int>? = null init { desktopMode = DesktopModeImpl() Loading Loading @@ -321,18 +320,29 @@ class DesktopTasksController( fun visibleTaskCount(displayId: Int): Int = taskRepository.getVisibleTaskCount(displayId) /** * Returns true if any freeform tasks are visible or if a transparent fullscreen task exists on * top in Desktop Mode. * Returns true if any of the following is true: * - Any freeform tasks are visible * - A transparent fullscreen task exists on top in Desktop Mode * - PiP on Desktop Windowing is enabled, there is an active PiP window and the desktop * wallpaper is visible. */ fun isDesktopModeShowing(displayId: Int): Boolean { val hasVisibleTasks = visibleTaskCount(displayId) > 0 val hasTopTransparentFullscreenTask = taskRepository.getTopTransparentFullscreenTaskId(displayId) != null val hasMinimizedPip = Flags.enableDesktopWindowingPip() && taskRepository.isMinimizedPipPresentInDisplay(displayId) && desktopWallpaperActivityTokenProvider.isWallpaperActivityVisible(displayId) if ( DesktopModeFlags.INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC .isTrue() && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue() ) { return visibleTaskCount(displayId) > 0 || taskRepository.getTopTransparentFullscreenTaskId(displayId) != null return hasVisibleTasks || hasTopTransparentFullscreenTask || hasMinimizedPip } else if (Flags.enableDesktopWindowingPip()) { return hasVisibleTasks || hasMinimizedPip } return visibleTaskCount(displayId) > 0 return hasVisibleTasks } /** Moves focused task to desktop mode for given [displayId]. */ Loading Loading @@ -592,7 +602,7 @@ class DesktopTasksController( ): ((IBinder) -> Unit)? { val taskId = taskInfo.taskId desktopTilingDecorViewModel.removeTaskIfTiled(displayId, taskId) performDesktopExitCleanupIfNeeded(taskId, displayId, wct) performDesktopExitCleanupIfNeeded(taskId, displayId, wct, forceToFullscreen = false) taskRepository.addClosingTask(displayId, taskId) taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate( doesAnyTaskRequireTaskbarRounding(displayId, taskId) Loading Loading @@ -624,8 +634,12 @@ class DesktopTasksController( ) val requestRes = transitions.dispatchRequest(Binder(), requestInfo, /* skip= */ null) wct.merge(requestRes.second, true) pendingPipTransitionAndTask = freeformTaskTransitionStarter.startPipTransition(wct) to taskInfo.taskId freeformTaskTransitionStarter.startPipTransition(wct) taskRepository.setTaskInPip(taskInfo.displayId, taskInfo.taskId, enterPip = true) taskRepository.setOnPipAbortedCallback { displayId, taskId -> minimizeTaskInner(shellTaskOrganizer.getRunningTaskInfo(taskId)!!) taskRepository.setTaskInPip(displayId, taskId, enterPip = false) } return } Loading @@ -636,7 +650,7 @@ class DesktopTasksController( val taskId = taskInfo.taskId val displayId = taskInfo.displayId val wct = WindowContainerTransaction() performDesktopExitCleanupIfNeeded(taskId, displayId, wct) performDesktopExitCleanupIfNeeded(taskId, displayId, wct, forceToFullscreen = false) // Notify immersive handler as it might need to exit immersive state. val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( Loading Loading @@ -898,7 +912,12 @@ class DesktopTasksController( } if (Flags.enablePerDisplayDesktopWallpaperActivity()) { performDesktopExitCleanupIfNeeded(task.taskId, task.displayId, wct) performDesktopExitCleanupIfNeeded( task.taskId, task.displayId, wct, forceToFullscreen = false, ) } transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null) Loading Loading @@ -1414,7 +1433,9 @@ class DesktopTasksController( taskId: Int, displayId: Int, wct: WindowContainerTransaction, forceToFullscreen: Boolean, ) { taskRepository.setPipShouldKeepDesktopActive(displayId, !forceToFullscreen) if (Flags.enablePerDisplayDesktopWallpaperActivity()) { if (!taskRepository.isOnlyVisibleNonClosingTask(taskId, displayId)) { return Loading @@ -1422,6 +1443,12 @@ class DesktopTasksController( if (displayId != DEFAULT_DISPLAY) { return } } else if ( Flags.enableDesktopWindowingPip() && taskRepository.isMinimizedPipPresentInDisplay(displayId) && !forceToFullscreen ) { return } else { if (!taskRepository.isOnlyVisibleNonClosingTask(taskId)) { return Loading Loading @@ -1462,21 +1489,6 @@ class DesktopTasksController( return false } override fun onTransitionConsumed( transition: IBinder, aborted: Boolean, finishT: Transaction?, ) { pendingPipTransitionAndTask?.let { (pipTransition, taskId) -> if (transition == pipTransition) { if (aborted) { shellTaskOrganizer.getRunningTaskInfo(taskId)?.let { minimizeTaskInner(it) } } pendingPipTransitionAndTask = null } } } override fun handleRequest( transition: IBinder, request: TransitionRequestInfo, Loading Loading @@ -1926,7 +1938,12 @@ class DesktopTasksController( if (!isDesktopModeShowing(task.displayId)) return null val wct = WindowContainerTransaction() performDesktopExitCleanupIfNeeded(task.taskId, task.displayId, wct) performDesktopExitCleanupIfNeeded( task.taskId, task.displayId, wct, forceToFullscreen = false, ) if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) { taskRepository.addClosingTask(task.displayId, task.taskId) Loading Loading @@ -2053,7 +2070,12 @@ class DesktopTasksController( wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) } performDesktopExitCleanupIfNeeded(taskInfo.taskId, taskInfo.displayId, wct) performDesktopExitCleanupIfNeeded( taskInfo.taskId, taskInfo.displayId, wct, forceToFullscreen = true, ) } private fun cascadeWindow(bounds: Rect, displayLayout: DisplayLayout, displayId: Int) { Loading Loading @@ -2087,7 +2109,12 @@ class DesktopTasksController( // want it overridden in multi-window. wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) performDesktopExitCleanupIfNeeded(taskInfo.taskId, taskInfo.displayId, wct) performDesktopExitCleanupIfNeeded( taskInfo.taskId, taskInfo.displayId, wct, forceToFullscreen = false, ) } /** Returns the ID of the Task that will be minimized, or null if no task will be minimized. */ Loading