Add per-display RemoteAnimation overrides and flag to disable snapshots

This CL adds a display-level fallback for remoteanimation overrides
and a property to RemoteAnimationAdapter specifying whether it needs
a snapshot for change transitions or not.

During a mode-change, this check for an override and then asks it
whether it needs a snapshot before creating one.

Bug: 113252739
Test: Added AppChangeTransitionTests
Change-Id: I47c933bd08fe512dc6cf029607819e2c908ab4cd
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 65b36a0..d915e10 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -105,6 +105,7 @@
 import android.view.DisplayInfo;
 import android.view.IApplicationToken;
 import android.view.InputApplicationHandle;
+import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
@@ -1621,6 +1622,17 @@
         t.reparent(getSurfaceControl(), mTransitChangeLeash);
         onAnimationLeashCreated(t, mTransitChangeLeash);
 
+        // Skip creating snapshot if this transition is controlled by a remote animator which
+        // doesn't need it.
+        ArraySet<Integer> activityTypes = new ArraySet<>();
+        activityTypes.add(getActivityType());
+        RemoteAnimationAdapter adapter =
+                mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
+                        this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
+        if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
+            return;
+        }
+
         if (mThumbnail == null && getTask() != null) {
             final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
             final ArraySet<Task> tasks = new ArraySet<>();
@@ -1639,6 +1651,11 @@
         return mTransitChangeLeash != null || isChangeTransition(mTransit);
     }
 
+    @VisibleForTesting
+    AppWindowThumbnail getThumbnail() {
+        return mThumbnail;
+    }
+
     @Override
     void checkAppWindowsReadyToShow() {
         if (allDrawn == mLastAllDrawn) {
@@ -2349,7 +2366,7 @@
             AnimationAdapter thumbnailAdapter = null;
             getAnimationBounds(mTmpPoint, mTmpRect);
 
-            boolean isChanging = isChangeTransition(transit) && mThumbnail != null;
+            boolean isChanging = isChangeTransition(transit) && enter;
 
             // Delaying animation start isn't compatible with remote animations at all.
             if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
@@ -2368,11 +2385,13 @@
                                 getDisplayContent().getDisplayInfo(), duration,
                                 true /* isAppAnimation */, false /* isThumbnail */),
                         mWmService.mSurfaceAnimationRunner);
-                thumbnailAdapter = new LocalAnimationAdapter(
-                        new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
-                                getDisplayContent().getDisplayInfo(), duration,
-                                true /* isAppAnimation */, true /* isThumbnail */),
-                        mWmService.mSurfaceAnimationRunner);
+                if (mThumbnail != null) {
+                    thumbnailAdapter = new LocalAnimationAdapter(
+                            new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
+                                    getDisplayContent().getDisplayInfo(), duration,
+                                    true /* isAppAnimation */, true /* isThumbnail */),
+                            mWmService.mSurfaceAnimationRunner);
+                }
                 mTransit = transit;
                 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
             } else {