Merge "Add animation override to TaskFragmentAnimationParams" into main
diff --git a/core/java/android/window/TaskFragmentAnimationParams.java b/core/java/android/window/TaskFragmentAnimationParams.java
index c8f6327..85e96c9 100644
--- a/core/java/android/window/TaskFragmentAnimationParams.java
+++ b/core/java/android/window/TaskFragmentAnimationParams.java
@@ -16,17 +16,21 @@
 
 package android.window;
 
+import static android.window.TransitionInfo.AnimationOptions.DEFAULT_ANIMATION_RESOURCES_ID;
+
+import android.annotation.AnimRes;
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Objects;
+
 /**
  * Data object for animation related override of TaskFragment.
  * @hide
  */
-// TODO(b/206557124): Add more animation customization options.
 public final class TaskFragmentAnimationParams implements Parcelable {
 
     /** The default {@link TaskFragmentAnimationParams} to use when there is no app override. */
@@ -43,8 +47,22 @@
     @ColorInt
     private final int mAnimationBackgroundColor;
 
-    private TaskFragmentAnimationParams(@ColorInt int animationBackgroundColor) {
+    @AnimRes
+    private final int mOpenAnimationResId;
+
+    @AnimRes
+    private final int mChangeAnimationResId;
+
+    @AnimRes
+    private final int mCloseAnimationResId;
+
+    private TaskFragmentAnimationParams(@ColorInt int animationBackgroundColor,
+            @AnimRes int openAnimationResId, @AnimRes int changeAnimationResId,
+            @AnimRes int closeAnimationResId) {
         mAnimationBackgroundColor = animationBackgroundColor;
+        mOpenAnimationResId = openAnimationResId;
+        mChangeAnimationResId = changeAnimationResId;
+        mCloseAnimationResId = closeAnimationResId;
     }
 
     /**
@@ -58,13 +76,52 @@
         return mAnimationBackgroundColor;
     }
 
+    /**
+     * Returns the resources ID of open animation that applies to this TaskFragment.
+     * <p>
+     * The default value is {@link DEFAULT_ANIMATION_RESOURCES_ID}, which is to use the system
+     * default animation.
+     */
+    @AnimRes
+    public int getOpenAnimationResId() {
+        return mOpenAnimationResId;
+    }
+
+    /**
+     * Returns the resources ID of change animation that applies to this TaskFragment.
+     * <p>
+     * The default value is {@link DEFAULT_ANIMATION_RESOURCES_ID}, which is to use the system
+     * default animation.
+     */
+    @AnimRes
+    public int getChangeAnimationResId() {
+        return mChangeAnimationResId;
+    }
+
+    /**
+     * Returns the resources ID of close animation that applies to this TaskFragment.
+     * <p>
+     * The default value is {@link DEFAULT_ANIMATION_RESOURCES_ID}, which is to use the system
+     * default animation.
+     */
+    @AnimRes
+    public int getCloseAnimationResId() {
+        return mCloseAnimationResId;
+    }
+
     private TaskFragmentAnimationParams(Parcel in) {
         mAnimationBackgroundColor = in.readInt();
+        mOpenAnimationResId = in.readInt();
+        mChangeAnimationResId = in.readInt();
+        mCloseAnimationResId = in.readInt();
     }
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mAnimationBackgroundColor);
+        dest.writeInt(mOpenAnimationResId);
+        dest.writeInt(mChangeAnimationResId);
+        dest.writeInt(mCloseAnimationResId);
     }
 
     @NonNull
@@ -85,21 +142,37 @@
     public String toString() {
         return "TaskFragmentAnimationParams{"
                 + " animationBgColor=" + Integer.toHexString(mAnimationBackgroundColor)
+                + " openAnimResId=" + mOpenAnimationResId
+                + " changeAnimResId=" + mChangeAnimationResId
+                + " closeAnimResId=" + mCloseAnimationResId
                 + "}";
     }
 
     @Override
     public int hashCode() {
-        return mAnimationBackgroundColor;
+        return Objects.hash(mAnimationBackgroundColor, mOpenAnimationResId, mChangeAnimationResId,
+                mCloseAnimationResId);
     }
 
     @Override
     public boolean equals(@Nullable Object obj) {
-        if (!(obj instanceof TaskFragmentAnimationParams)) {
+        if (!(obj instanceof TaskFragmentAnimationParams other)) {
             return false;
         }
-        final TaskFragmentAnimationParams other = (TaskFragmentAnimationParams) obj;
-        return mAnimationBackgroundColor == other.mAnimationBackgroundColor;
+        return mAnimationBackgroundColor == other.mAnimationBackgroundColor
+                && mOpenAnimationResId == other.mOpenAnimationResId
+                && mChangeAnimationResId == other.mChangeAnimationResId
+                && mCloseAnimationResId == other.mCloseAnimationResId;
+    }
+
+    /**
+     * Returns {@code true} if one of {@link #getOpenAnimationResId()},
+     * {@link #getChangeAnimationResId()} or {@link #getCloseAnimationResId()} is specified.
+     */
+    public boolean hasOverrideAnimation() {
+        return mOpenAnimationResId != DEFAULT_ANIMATION_RESOURCES_ID
+                || mChangeAnimationResId != DEFAULT_ANIMATION_BACKGROUND_COLOR
+                || mCloseAnimationResId != DEFAULT_ANIMATION_RESOURCES_ID;
     }
 
     @Override
@@ -113,6 +186,15 @@
         @ColorInt
         private int mAnimationBackgroundColor = DEFAULT_ANIMATION_BACKGROUND_COLOR;
 
+        @AnimRes
+        private int mOpenAnimationResId = DEFAULT_ANIMATION_RESOURCES_ID;
+
+        @AnimRes
+        private int mChangeAnimationResId = DEFAULT_ANIMATION_RESOURCES_ID;
+
+        @AnimRes
+        private int mCloseAnimationResId = DEFAULT_ANIMATION_RESOURCES_ID;
+
         /**
          * Sets the {@link ColorInt} to use for the background during the animation with this
          * TaskFragment if the animation requires a background. The default value is
@@ -128,10 +210,50 @@
             return this;
         }
 
+        /**
+         * Sets the open animation resources ID this TaskFragment. The default value is
+         * {@link DEFAULT_ANIMATION_RESOURCES_ID}, which is to use the system default animation.
+         *
+         * @param resId the open animation resources ID.
+         * @return this {@link Builder}.
+         */
+        @NonNull
+        public Builder setOpenAnimationResId(@AnimRes int resId) {
+            mOpenAnimationResId = resId;
+            return this;
+        }
+
+        /**
+         * Sets the change animation resources ID this TaskFragment. The default value is
+         * {@link DEFAULT_ANIMATION_RESOURCES_ID}, which is to use the system default animation.
+         *
+         * @param resId the change animation resources ID.
+         * @return this {@link Builder}.
+         */
+        @NonNull
+        public Builder setChangeAnimationResId(@AnimRes int resId) {
+            mChangeAnimationResId = resId;
+            return this;
+        }
+
+        /**
+         * Sets the close animation resources ID this TaskFragment. The default value is
+         * {@link DEFAULT_ANIMATION_RESOURCES_ID}, which is to use the system default animation.
+         *
+         * @param resId the close animation resources ID.
+         * @return this {@link Builder}.
+         */
+        @NonNull
+        public Builder setCloseAnimationResId(@AnimRes int resId) {
+            mCloseAnimationResId = resId;
+            return this;
+        }
+
         /** Constructs the {@link TaskFragmentAnimationParams}. */
         @NonNull
         public TaskFragmentAnimationParams build() {
-            return new TaskFragmentAnimationParams(mAnimationBackgroundColor);
+            return new TaskFragmentAnimationParams(mAnimationBackgroundColor,
+                    mOpenAnimationResId, mChangeAnimationResId, mCloseAnimationResId);
         }
     }
 }
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 8a79754..1d42c93 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -1107,6 +1107,7 @@
 
         private int mType;
         private @AnimRes int mEnterResId = DEFAULT_ANIMATION_RESOURCES_ID;
+        private @AnimRes int mChangeResId = DEFAULT_ANIMATION_RESOURCES_ID;
         private @AnimRes int mExitResId = DEFAULT_ANIMATION_RESOURCES_ID;
         private boolean mOverrideTaskTransition;
         private String mPackageName;
@@ -1126,6 +1127,7 @@
         private AnimationOptions(Parcel in) {
             mType = in.readInt();
             mEnterResId = in.readInt();
+            mChangeResId = in.readInt();
             mExitResId = in.readInt();
             mBackgroundColor = in.readInt();
             mOverrideTaskTransition = in.readBoolean();
@@ -1189,9 +1191,27 @@
         public static AnimationOptions makeCustomAnimOptions(@NonNull String packageName,
                 @AnimRes int enterResId, @AnimRes int exitResId, @ColorInt int backgroundColor,
                 boolean overrideTaskTransition) {
+            return makeCustomAnimOptions(packageName, enterResId, DEFAULT_ANIMATION_RESOURCES_ID,
+                    exitResId, backgroundColor, overrideTaskTransition);
+        }
+
+        /**
+         * Creates a {@link android.app.ActivityOptions#ANIM_CUSTOM} {@link AnimationOptions}.
+         *
+         * @param packageName the package name that includes the animation resources.
+         * @param enterResId the resources ID of open animation.
+         * @param changeResId the resources ID of change animation.
+         * @param exitResId the resources ID of close animation.
+         * @param overrideTaskTransition indicates whether to override task transition.
+         */
+        @NonNull
+        public static AnimationOptions makeCustomAnimOptions(@NonNull String packageName,
+                @AnimRes int enterResId, @AnimRes int changeResId, @AnimRes int exitResId,
+                @ColorInt int backgroundColor, boolean overrideTaskTransition) {
             AnimationOptions options = new AnimationOptions(ANIM_CUSTOM);
             options.mPackageName = packageName;
             options.mEnterResId = enterResId;
+            options.mChangeResId = changeResId;
             options.mExitResId = exitResId;
             options.mBackgroundColor = backgroundColor;
             options.mOverrideTaskTransition = overrideTaskTransition;
@@ -1251,6 +1271,11 @@
         }
 
         @AnimRes
+        public int getChangeResId() {
+            return mChangeResId;
+        }
+
+        @AnimRes
         public int getExitResId() {
             return mExitResId;
         }
@@ -1292,6 +1317,7 @@
         public void writeToParcel(@NonNull Parcel dest, int flags) {
             dest.writeInt(mType);
             dest.writeInt(mEnterResId);
+            dest.writeInt(mChangeResId);
             dest.writeInt(mExitResId);
             dest.writeInt(mBackgroundColor);
             dest.writeBoolean(mOverrideTaskTransition);
@@ -1352,6 +1378,9 @@
             if (mEnterResId != DEFAULT_ANIMATION_RESOURCES_ID) {
                 sb.append(" enterResId=").append(mEnterResId);
             }
+            if (mChangeResId != DEFAULT_ANIMATION_RESOURCES_ID) {
+                sb.append(" changeResId=").append(mChangeResId);
+            }
             if (mExitResId != DEFAULT_ANIMATION_RESOURCES_ID) {
                 sb.append(" exitResId=").append(mExitResId);
             }
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 218334e..4c7582f 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -95,6 +95,7 @@
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.ScreenCapture;
+import android.window.TaskFragmentAnimationParams;
 import android.window.TransitionInfo;
 import android.window.WindowContainerTransaction;
 
@@ -2728,10 +2729,10 @@
             return out;
         }
 
-        final AnimationOptions animOptions = calculateAnimationOptionsForActivityTransition(type,
-                sortedTargets);
-        if (!Flags.moveAnimationOptionsToChange() && animOptions != null) {
-            out.setAnimationOptions(animOptions);
+        final AnimationOptions animOptionsForActivityTransition =
+                calculateAnimationOptionsForActivityTransition(type, sortedTargets);
+        if (!Flags.moveAnimationOptionsToChange() && animOptionsForActivityTransition != null) {
+            out.setAnimationOptions(animOptionsForActivityTransition);
         }
 
         // Convert all the resolved ChangeInfos into TransactionInfo.Change objects in order.
@@ -2759,6 +2760,8 @@
 
             final Task task = target.asTask();
             final TaskFragment taskFragment = target.asTaskFragment();
+            final boolean isEmbeddedTaskFragment = taskFragment != null
+                    && taskFragment.isEmbedded();
             final ActivityRecord activityRecord = target.asActivityRecord();
 
             if (task != null) {
@@ -2798,7 +2801,7 @@
                 change.setEndAbsBounds(bounds);
             }
 
-            if (activityRecord != null || (taskFragment != null && taskFragment.isEmbedded())) {
+            if (activityRecord != null || isEmbeddedTaskFragment) {
                 final int backgroundColor;
                 final TaskFragment organizedTf = activityRecord != null
                         ? activityRecord.getOrganizedTaskFragment()
@@ -2823,9 +2826,27 @@
                 change.setBackgroundColor(ColorUtils.setAlphaComponent(backgroundColor, 255));
             }
 
-            if (Flags.moveAnimationOptionsToChange() && activityRecord != null
-                    && animOptions != null) {
-                change.setAnimationOptions(animOptions);
+            AnimationOptions animOptions = null;
+            if (Flags.moveAnimationOptionsToChange()) {
+                if (activityRecord != null && animOptionsForActivityTransition != null) {
+                    animOptions = animOptionsForActivityTransition;
+                } else if (Flags.activityEmbeddingOverlayPresentationFlag()
+                        && isEmbeddedTaskFragment) {
+                    final TaskFragmentAnimationParams params = taskFragment.getAnimationParams();
+                    if (params.hasOverrideAnimation()) {
+                        // Only set AnimationOptions if there's any animation override.
+                        // We use separated field for backgroundColor, and
+                        // AnimationOptions#backgroundColor will be removed in long term.
+                        animOptions = AnimationOptions.makeCustomAnimOptions(
+                                taskFragment.getTask().getBasePackageName(),
+                                params.getOpenAnimationResId(), params.getChangeAnimationResId(),
+                                params.getCloseAnimationResId(), 0 /* backgroundColor */,
+                                false /* overrideTaskTransition */);
+                    }
+                }
+                if (animOptions != null) {
+                    change.setAnimationOptions(animOptions);
+                }
             }
 
             if (activityRecord != null) {