Merge "[PiP2 on Desktop] Enter PiP with bounds change animation." into main
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 7764688..50187d5 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 @@
     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 (
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 1ec8684..1a48404 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_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
@@ -220,6 +221,7 @@
     // 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()
@@ -557,6 +559,26 @@
     }
 
     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()
@@ -1335,6 +1357,21 @@
         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 2ae9828..52b6c62 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 @@
 
 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 @@
         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 5984d48..a874a5b 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 @@
      * @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 1efe2ff..dae3c21 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
@@ -55,6 +55,7 @@
 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;
@@ -729,6 +730,10 @@
                     && 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 3bee588..6a4ad2e 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.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 @@
   }
 
   @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()
@@ -4228,6 +4257,14 @@
     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 4ed1206..810aa04 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4489,7 +4489,7 @@
     }
 
     void onPictureInPictureParamsChanged() {
-        if (inPinnedWindowingMode()) {
+        if (inPinnedWindowingMode() || Flags.enableDesktopWindowingPip()) {
             dispatchTaskInfoChangedIfNeeded(true /* force */);
         }
     }