Ensure TaskOrganizer works for newly created pinned stack

Steps to reproduce the bug:
- Restart the device
- Open Duo app and make a call
- When in call, try entering PiP

Duo application contains multiple activities and we create a new stack
from its top activity when moving it to pinned mode. This newly created
stack does not carry on the existing PictureInPictureParams, nor it is
marked as visible. Therefore, no onTaskAppeared would be sent to the
task organizer.

Also in this change:
- Removed aspectRatio and sourceHintBounds used to be passed into
  RootWindowContainer#moveActivityToPinnedStack, they are used in
  moveActivityToPinnedStack and one should refer to the
  PictureInPictureParams set on ActivityRecord
- Added a null check for existing token when onTaskInfoChanged is
  invoked in PipTaskOrganizer, it should be a fatal error that
  onTaskInfoChanged is called ahead of onTaskAppeared

Bug: 152933995
Test: manually enter/exit PiP mode for Duo app
Test: atest RootActivityContainerTests
Test: atest ActivityRecordTests
Change-Id: Ifa9ad8768ba47ce043b8dd86cadc729931edcb14
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ed9b019..0b33cbd 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1298,6 +1298,19 @@
         if (newTask != null && isState(RESUMED)) {
             newTask.setResumedActivity(this, "onParentChanged");
         }
+
+        if (stack != null && stack.topRunningActivity() == this) {
+            // carry over the PictureInPictureParams to the parent stack without calling
+            // TaskOrganizerController#dispatchTaskInfoChanged.
+            // this is to ensure the stack holding up-to-dated pinned stack information
+            // when activity is re-parented to enter pip mode, see also
+            // RootWindowContainer#moveActivityToPinnedStack
+            stack.mPictureInPictureParams.copyOnlySet(pictureInPictureArgs);
+            // make ensure the TaskOrganizer still works after re-parenting
+            if (firstWindowDrawn) {
+                stack.setHasBeenVisible(true);
+            }
+        }
     }
 
     private void updateColorTransform() {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c253cd2..08683ca 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4095,11 +4095,8 @@
                         r.setPictureInPictureParams(params);
                         final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
                         final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
-                        // Adjust the source bounds by the insets for the transition down
-                        final Rect sourceBounds = new Rect(
-                                r.pictureInPictureArgs.getSourceRectHint());
                         mRootWindowContainer.moveActivityToPinnedStack(
-                                r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
+                                r, "enterPictureInPictureMode");
                         final ActivityStack stack = r.getRootTask();
                         stack.setPictureInPictureAspectRatio(aspectRatio);
                         stack.setPictureInPictureActions(actions);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1a70de7..e8f7ba5 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2147,13 +2147,11 @@
             return false;
         }
 
-        moveActivityToPinnedStack(r, null /* sourceBounds */, 0f /* aspectRatio */,
-                "moveTopActivityToPinnedStack");
+        moveActivityToPinnedStack(r, "moveTopActivityToPinnedStack");
         return true;
     }
 
-    void moveActivityToPinnedStack(ActivityRecord r, Rect sourceHintBounds, float aspectRatio,
-            String reason) {
+    void moveActivityToPinnedStack(ActivityRecord r, String reason) {
         mService.deferWindowLayout();
 
         final TaskDisplayArea taskDisplayArea = r.getDisplayArea();
@@ -2176,17 +2174,19 @@
             final ActivityStack stack;
             if (singleActivity) {
                 stack = r.getRootTask();
-                stack.setWindowingMode(WINDOWING_MODE_PINNED);
             } else {
                 // In the case of multiple activities, we will create a new task for it and then
                 // move the PIP activity into the task.
-                stack = taskDisplayArea.createStack(WINDOWING_MODE_PINNED, r.getActivityType(),
+                stack = taskDisplayArea.createStack(WINDOWING_MODE_UNDEFINED, r.getActivityType(),
                         ON_TOP, r.info, r.intent, false /* createdByOrganizer */);
 
                 // There are multiple activities in the task and moving the top activity should
                 // reveal/leave the other activities in their original task.
-                r.reparent(stack, MAX_VALUE, "moveActivityToStack");
+                // On the other hand, ActivityRecord#onParentChanged takes care of setting the
+                // up-to-dated pinned stack information on this newly created stack.
+                r.reparent(stack, MAX_VALUE, reason);
             }
+            stack.setWindowingMode(WINDOWING_MODE_PINNED);
 
             // Reset the state that indicates it can enter PiP while pausing after we've moved it
             // to the pinned stack