diff options
| author | 2024-11-18 11:58:30 -0800 | |
|---|---|---|
| committer | 2024-12-02 15:55:40 -0800 | |
| commit | 51f099fa7e5c6b25c849b0c0f72467e7ffe79709 (patch) | |
| tree | 9ca482e312a670c9e96303713b4baf3b574b0da2 | |
| parent | 72061cd007bf3abcaae3fcf047390109acb96bf4 (diff) | |
[PiP2 on Desktop] Enter PiP with bounds change animation.
Recall: http://recall/clips/d4b0542f-424a-436a-8f17-a1eeb0d9e91b
This CL allows enter PiP on Desktop mode with bounds change animation.
If the task is minimizing to PiP, a PiP transition is started instead of
a minimize transition. If the PiP transition is aborted down the line, a
minimize transition will then be started.
Bug: 378745750
Bug: 377582265
Test: atest DesktopTasksControllerTest
Flag: com.android.window.flags.enable_desktop_windowing_pip
Change-Id: Icf309eaa4aa5092839b221ee2774eb309f112202
7 files changed, 100 insertions, 1 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt index 96bbd58949bd..f7d005cd55b4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt @@ -77,6 +77,10 @@ class DesktopMixedTransitionHandler( override fun startMinimizedModeTransition(wct: WindowContainerTransaction?): IBinder = freeformTaskTransitionHandler.startMinimizedModeTransition(wct) + /** Delegates starting PiP transition to [FreeformTaskTransitionHandler]. */ + override fun startPipTransition(wct: WindowContainerTransaction?): IBinder = + freeformTaskTransitionHandler.startPipTransition(wct) + /** Starts close transition and handles or delegates desktop task close animation. */ override fun startRemoveTransition(wct: WindowContainerTransaction?): IBinder { if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 5cb94f870a2d..017f6043415b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -50,6 +50,7 @@ import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_CLOSE import android.view.WindowManager.TRANSIT_NONE import android.view.WindowManager.TRANSIT_OPEN +import android.view.WindowManager.TRANSIT_PIP import android.view.WindowManager.TRANSIT_TO_FRONT import android.widget.Toast import android.window.DesktopModeFlags @@ -223,6 +224,7 @@ 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() @@ -536,6 +538,26 @@ class DesktopTasksController( } fun minimizeTask(taskInfo: RunningTaskInfo) { + val wct = WindowContainerTransaction() + + val isMinimizingToPip = taskInfo.pictureInPictureParams?.isAutoEnterEnabled() ?: false + // If task is going to PiP, start a PiP transition instead of a minimize transition + if (isMinimizingToPip) { + val requestInfo = TransitionRequestInfo( + TRANSIT_PIP, /* triggerTask= */ null, taskInfo, /* remoteTransition= */ null, + /* displayChange= */ null, /* flags= */ 0 + ) + val requestRes = transitions.dispatchRequest(Binder(), requestInfo, /* skip= */ null) + wct.merge(requestRes.second, true) + pendingPipTransitionAndTask = + freeformTaskTransitionStarter.startPipTransition(wct) to taskInfo.taskId + return + } + + minimizeTaskInner(taskInfo) + } + + private fun minimizeTaskInner(taskInfo: RunningTaskInfo) { val taskId = taskInfo.taskId val displayId = taskInfo.displayId val wct = WindowContainerTransaction() @@ -1298,6 +1320,21 @@ 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 diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java index 2ae9828ca0db..52b6c62b0721 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java @@ -18,6 +18,7 @@ package com.android.wm.shell.freeform; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.view.WindowManager.TRANSIT_PIP; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -99,6 +100,12 @@ public class FreeformTaskTransitionHandler return token; } + @Override + public IBinder startPipTransition(WindowContainerTransaction wct) { + final IBinder token = mTransitions.startTransition(TRANSIT_PIP, wct, null); + mPendingTransitionTokens.add(token); + return token; + } @Override public IBinder startRemoveTransition(WindowContainerTransaction wct) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java index 5984d486f838..a874a5be426d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java @@ -51,4 +51,13 @@ public interface FreeformTaskTransitionStarter { * @return the started transition */ IBinder startRemoveTransition(WindowContainerTransaction wct); + + /** + * Starts PiP transition + * + * @param wct the {@link WindowContainerTransaction} that launches the PiP + * + * @return the started transition + */ + IBinder startPipTransition(WindowContainerTransaction wct); }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java index b171db2c3793..7acb99643282 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java @@ -52,6 +52,7 @@ import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; import com.android.internal.util.Preconditions; +import com.android.window.flags.Flags; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; @@ -713,6 +714,10 @@ public class PipTransition extends PipTransitionController implements && getFixedRotationDelta(info, pipTaskChange) == ROTATION_90) { adjustedSourceRectHint.offset(cutoutInsets.left, cutoutInsets.top); } + if (Flags.enableDesktopWindowingPip()) { + adjustedSourceRectHint.offset(-pipActivityChange.getStartAbsBounds().left, + -pipActivityChange.getStartAbsBounds().top); + } } else { // For non-valid app provided src-rect-hint, calculate one to crop into during // app icon overlay animation. diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index c10434aa6d6f..8313c4cea78e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -21,6 +21,7 @@ import android.app.ActivityManager.RunningTaskInfo import android.app.ActivityOptions import android.app.KeyguardManager import android.app.PendingIntent +import android.app.PictureInPictureParams import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM @@ -1724,6 +1725,34 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test + fun onDesktopWindowMinimize_pipTask_autoEnterEnabled_startPipTransition() { + val task = setUpPipTask(autoEnterEnabled = true) + val handler = mock(TransitionHandler::class.java) + whenever(freeformTaskTransitionStarter.startPipTransition(any())) + .thenReturn(Binder()) + whenever(transitions.dispatchRequest(any(), any(), anyOrNull())) + .thenReturn(android.util.Pair(handler, WindowContainerTransaction()) + ) + + controller.minimizeTask(task) + + verify(freeformTaskTransitionStarter).startPipTransition(any()) + verify(freeformTaskTransitionStarter, never()).startMinimizedModeTransition(any()) + } + + @Test + fun onDesktopWindowMinimize_pipTask_autoEnterDisabled_startMinimizeTransition() { + val task = setUpPipTask(autoEnterEnabled = false) + whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any())) + .thenReturn(Binder()) + + controller.minimizeTask(task) + + verify(freeformTaskTransitionStarter).startMinimizedModeTransition(any()) + verify(freeformTaskTransitionStarter, never()).startPipTransition(any()) + } + + @Test fun onDesktopWindowMinimize_singleActiveTask_noWallpaperActivityToken_doesntRemoveWallpaper() { val task = setUpFreeformTask(active = true) val transition = Binder() @@ -4229,6 +4258,14 @@ class DesktopTasksControllerTest : ShellTestCase() { return task } + private fun setUpPipTask(autoEnterEnabled: Boolean): RunningTaskInfo { + return setUpFreeformTask().apply { + pictureInPictureParams = PictureInPictureParams.Builder() + .setAutoEnterEnabled(autoEnterEnabled) + .build() + } + } + private fun setUpHomeTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createHomeTask(displayId) whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 87e472ab7aa6..79d6ee00deaf 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4488,7 +4488,7 @@ class Task extends TaskFragment { } void onPictureInPictureParamsChanged() { - if (inPinnedWindowingMode()) { + if (inPinnedWindowingMode() || Flags.enableDesktopWindowingPip()) { dispatchTaskInfoChangedIfNeeded(true /* force */); } } |