Merge "Do not prepare animation if no corresponding animator registered." into main
diff --git a/core/java/android/window/BackAnimationAdapter.java b/core/java/android/window/BackAnimationAdapter.java
index 5eb34e6..153e153 100644
--- a/core/java/android/window/BackAnimationAdapter.java
+++ b/core/java/android/window/BackAnimationAdapter.java
@@ -16,9 +16,12 @@
 
 package android.window;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.ArrayList;
+
 /**
  * Object that describes how to run a remote back animation.
  *
@@ -26,6 +29,7 @@
  */
 public class BackAnimationAdapter implements Parcelable {
     private final IBackAnimationRunner mRunner;
+    private int[] mSupportedAnimators;
 
     public BackAnimationAdapter(IBackAnimationRunner runner) {
         mRunner = runner;
@@ -33,12 +37,23 @@
 
     public BackAnimationAdapter(Parcel in) {
         mRunner = IBackAnimationRunner.Stub.asInterface(in.readStrongBinder());
+        mSupportedAnimators = new int[in.readInt()];
+        in.readIntArray(mSupportedAnimators);
     }
 
     public IBackAnimationRunner getRunner() {
         return mRunner;
     }
 
+    /** Update the latest animators in the system. */
+    public void updateSupportedAnimators(@NonNull ArrayList<Integer> animators) {
+        final int size = animators.size();
+        mSupportedAnimators = new int[size];
+        for (int i = size - 1; i >= 0; --i) {
+            mSupportedAnimators[i] = animators.get(i);
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -47,6 +62,8 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeStrongInterface(mRunner);
+        dest.writeInt(mSupportedAnimators.length);
+        dest.writeIntArray(mSupportedAnimators);
     }
 
     public static final @android.annotation.NonNull Creator<BackAnimationAdapter> CREATOR =
@@ -59,4 +76,19 @@
             return new BackAnimationAdapter[size];
         }
     };
+
+    /**
+     * Check if the back type is animatable.
+     */
+    public boolean isAnimatable(@BackNavigationInfo.BackTargetType int backType) {
+        if (mSupportedAnimators == null) {
+            return false;
+        }
+        for (int i = mSupportedAnimators.length - 1; i >= 0; --i) {
+            if (backType == mSupportedAnimators[i]) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 1b47054..7b3b207 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -573,8 +573,14 @@
     private void startBackNavigation(@NonNull BackTouchTracker touchTracker) {
         try {
             startLatencyTracking();
+            final BackAnimationAdapter adapter = mEnableAnimations.get()
+                    ? mBackAnimationAdapter : null;
+            if (adapter != null && mShellBackAnimationRegistry.hasSupportedAnimatorsChanged()) {
+                adapter.updateSupportedAnimators(
+                        mShellBackAnimationRegistry.getSupportedAnimators());
+            }
             mBackNavigationInfo = mActivityTaskManager.startBackNavigation(
-                    mNavigationObserver, mEnableAnimations.get() ? mBackAnimationAdapter : null);
+                    mNavigationObserver, adapter);
             onBackNavigationInfoReceived(mBackNavigationInfo, touchTracker);
         } catch (RemoteException remoteException) {
             Log.e(TAG, "Failed to initAnimation", remoteException);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
index 6fafa75..ae2c7b3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
@@ -23,6 +23,8 @@
 import android.util.SparseArray;
 import android.window.BackNavigationInfo;
 
+import java.util.ArrayList;
+
 /** Registry for all types of default back animations */
 public class ShellBackAnimationRegistry {
     private static final String TAG = "ShellBackPreview";
@@ -31,6 +33,8 @@
     private ShellBackAnimation mDefaultCrossActivityAnimation;
     private final ShellBackAnimation mCustomizeActivityAnimation;
     private final ShellBackAnimation mCrossTaskAnimation;
+    private boolean mSupportedAnimatorsChanged = false;
+    private final ArrayList<Integer> mSupportedAnimators = new ArrayList<>();
 
     public ShellBackAnimationRegistry(
             @ShellBackAnimation.CrossActivity @Nullable ShellBackAnimation crossActivityAnimation,
@@ -60,7 +64,7 @@
         mDefaultCrossActivityAnimation = crossActivityAnimation;
         mCustomizeActivityAnimation = customizeActivityAnimation;
         mCrossTaskAnimation = crossTaskAnimation;
-
+        updateSupportedAnimators();
         // TODO(b/236760237): register dialog close animation when it's completed.
     }
 
@@ -71,6 +75,7 @@
         if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
             mDefaultCrossActivityAnimation = null;
         }
+        updateSupportedAnimators();
     }
 
     void unregisterAnimation(@BackNavigationInfo.BackTargetType int type) {
@@ -79,6 +84,24 @@
         if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
             mDefaultCrossActivityAnimation = null;
         }
+        updateSupportedAnimators();
+    }
+
+    private void updateSupportedAnimators() {
+        mSupportedAnimators.clear();
+        for (int i = mAnimationDefinition.size() - 1; i >= 0; --i) {
+            mSupportedAnimators.add(mAnimationDefinition.keyAt(i));
+        }
+        mSupportedAnimatorsChanged = true;
+    }
+
+    boolean hasSupportedAnimatorsChanged() {
+        return mSupportedAnimatorsChanged;
+    }
+
+    ArrayList<Integer> getSupportedAnimators() {
+        mSupportedAnimatorsChanged = false;
+        return mSupportedAnimators;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 28dbc3a..4e4616d 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -339,13 +339,12 @@
                     removedWindowContainer,
                     BackNavigationInfo.typeToString(backType));
 
-            // For now, we only animate when going home, cross task or cross-activity.
             boolean prepareAnimation =
                     (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
                                     || backType == BackNavigationInfo.TYPE_CROSS_TASK
                                     || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY
                                     || backType == BackNavigationInfo.TYPE_DIALOG_CLOSE)
-                            && adapter != null;
+                            && (adapter != null && adapter.isAnimatable(backType));
 
             if (prepareAnimation) {
                 final AnimationHandler.ScheduleAnimationBuilder builder =
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index 44837d7..20dcdde 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -110,6 +110,7 @@
         mWindowManagerInternal = mock(WindowManagerInternal.class);
         LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
         mBackAnimationAdapter = mock(BackAnimationAdapter.class);
+        doReturn(true).when(mBackAnimationAdapter).isAnimatable(anyInt());
         mNavigationMonitor = mock(BackNavigationController.NavigationMonitor.class);
         mRootHomeTask = initHomeActivity();
     }