Cancel Pip animation if stack is already removed

It is possible for the pinned stack to be removed before the system has
a chance to run the scheduled bounds animation on it. In this case we
should just cancel the animation.
Also fixed:
- Issue where we are synchronizing on the wrong object in
PinnedActivityStack.updatePictureInPictureModeForPinnedStackAnimation
- Issue where the enterPipRunnable in
ActivityTaskManagerService.enterPictureInPictureMode wasn't synchronized

Change-Id: I9717ac4b5849eafa6332fb0043310a0e8387a05f
Fixes: 110255768
Test: atest ActivityManagerActivityVisibilityTests#testHomeVisibleOnActivityTaskPinned
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index c6edfe5..d032e1b 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -2807,20 +2807,23 @@
                 }
 
                 final Runnable enterPipRunnable = () -> {
-                    // Only update the saved args from the args that are set
-                    r.pictureInPictureArgs.copyOnlySet(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());
-                    mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio,
-                            "enterPictureInPictureMode");
-                    final PinnedActivityStack stack = r.getStack();
-                    stack.setPictureInPictureAspectRatio(aspectRatio);
-                    stack.setPictureInPictureActions(actions);
-                    MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid,
-                            r.shortComponentName, r.supportsEnterPipOnTaskSwitch);
-                    logPictureInPictureArgs(params);
+                    synchronized (mGlobalLock) {
+                        // Only update the saved args from the args that are set
+                        r.pictureInPictureArgs.copyOnlySet(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());
+                        mStackSupervisor.moveActivityToPinnedStackLocked(
+                                r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
+                        final PinnedActivityStack stack = r.getStack();
+                        stack.setPictureInPictureAspectRatio(aspectRatio);
+                        stack.setPictureInPictureActions(actions);
+                        MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid,
+                                r.shortComponentName, r.supportsEnterPipOnTaskSwitch);
+                        logPictureInPictureArgs(params);
+                    }
                 };
 
                 if (mAm.isKeyguardLocked()) {
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 4062f45..29898b1 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -100,7 +100,7 @@
         // It is guaranteed that the activities requiring the update will be in the pinned stack at
         // this point (either reparented before the animation into PiP, or before reparenting after
         // the animation out of PiP)
-        synchronized(this) {
+        synchronized (mService) {
             ArrayList<TaskRecord> tasks = getAllTasks();
             for (int i = 0; i < tasks.size(); i++ ) {
                 mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds,
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index b2a12be..0a49c13 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -196,6 +196,12 @@
 
         @Override
         public void onAnimationStart(Animator animation) {
+            if (!mTarget.isAttached()) {
+                // No point of trying to animate something that isn't attached to the hierarchy
+                // anymore.
+                cancel();
+            }
+
             if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
                     + " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState
                     + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
index 68be4e8..d66b42f 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -65,4 +65,9 @@
      */
     void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
             boolean moveToFullscreen);
+
+    /** @return True if the target is attached to the window hierarchy. */
+    default boolean isAttached() {
+        return true;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index e6db6d9..76a060e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1703,6 +1703,11 @@
         }
     }
 
+    @Override
+    public boolean isAttached() {
+        return mDisplayContent != null;
+    }
+
     /**
      * Called immediately prior to resizing the tasks at the end of the pinned stack animation.
      */