Don't apply some custom animation cases from app in WindowStateAnimator

In general, app main window the animation should applied by
AppWindowToken#applyAnimationLocked through app transition.

We should avoid application can apply animation through
WM.LayoutParams.windowAnimation for app main window.

We also ignore application to customize starting window animation,
since starting window is a special window for displaying while app
starting, application should not use or change animation directly.

Bug: 133274628
Test: atest AppTransitionTests
Test: manual, as below steps:
    1) Launch apps (i.e. Pocketcasts) that override windowAnimation style
       with custom animation for app main window or starting window
       (TYPE_BASE_APPLICATION | TYPE_APPLICATION_STARTING).
    2) In gesture nav, swipe left & right back on nav bar.
    3) Expect the app's main window should not have animation or flick.

Change-Id: Ibeac1e513023ab19bcfb7ee412f41a570e917a17
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index ddd5c0a..e6a83de 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -87,6 +87,7 @@
 import android.content.res.ResourceId;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
+import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -258,6 +259,8 @@
     private final boolean mGridLayoutRecentsEnabled;
     private final boolean mLowRamRecentsEnabled;
 
+    private final int mDefaultWindowAnimationStyleResId;
+
     private RemoteAnimationController mRemoteAnimationController;
 
     final Handler mHandler;
@@ -305,6 +308,12 @@
                 * mContext.getResources().getDisplayMetrics().density);
         mGridLayoutRecentsEnabled = SystemProperties.getBoolean("ro.recents.grid", false);
         mLowRamRecentsEnabled = ActivityManager.isLowRamDeviceStatic();
+
+        final TypedArray windowStyle = mContext.getTheme().obtainStyledAttributes(
+                com.android.internal.R.styleable.Window);
+        mDefaultWindowAnimationStyleResId = windowStyle.getResourceId(
+                com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
+        windowStyle.recycle();
     }
 
     boolean isTransitionSet() {
@@ -523,6 +532,25 @@
         return redoLayout;
     }
 
+    @VisibleForTesting
+    int getDefaultWindowAnimationStyleResId() {
+        return mDefaultWindowAnimationStyleResId;
+    }
+
+    /** Returns window animation style ID from {@link LayoutParams} or from system in some cases */
+    @VisibleForTesting
+    int getAnimationStyleResId(@NonNull LayoutParams lp) {
+        int resId = lp.windowAnimations;
+        if (lp.type == LayoutParams.TYPE_APPLICATION_STARTING) {
+            // Note that we don't want application to customize starting window animation.
+            // Since this window is specific for displaying while app starting,
+            // application should not change its animation directly.
+            // In this case, it will use system resource to get default animation.
+            resId = mDefaultWindowAnimationStyleResId;
+        }
+        return resId;
+    }
+
     private AttributeCache.Entry getCachedAnimations(LayoutParams lp) {
         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
                 + (lp != null ? lp.packageName : null)
@@ -532,7 +560,7 @@
             // application resources.  It is nice to avoid loading application
             // resources if we can.
             String packageName = lp.packageName != null ? lp.packageName : "android";
-            int resId = lp.windowAnimations;
+            int resId = getAnimationStyleResId(lp);
             if ((resId&0xFF000000) == 0x01000000) {
                 packageName = "android";
             }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 10a63ee..dc94d16 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_NONE;
@@ -1294,6 +1295,13 @@
         if (mWin.mSkipEnterAnimationForSeamlessReplacement) {
             return;
         }
+
+        // We don't apply animation for application main window here since this window type
+        // should be controlled by AppWindowToken in general.
+        if (mAttrType == TYPE_BASE_APPLICATION) {
+            return;
+        }
+
         final int transit;
         if (mEnterAnimationPending) {
             mEnterAnimationPending = false;
@@ -1365,6 +1373,7 @@
                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
                     + " a=" + a
                     + " transit=" + transit
+                    + " type=" + mAttrType
                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
             if (a != null) {
                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 5a72a58..f602418 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
@@ -45,6 +46,7 @@
 import android.view.IRemoteAnimationRunner;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
+import android.view.WindowManager;
 
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
@@ -224,6 +226,21 @@
         assertTrue(runner.mCancelled);
     }
 
+    @Test
+    public void testGetAnimationStyleResId() {
+        // Verify getAnimationStyleResId will return as LayoutParams.windowAnimations when without
+        // specifying window type.
+        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
+        attrs.windowAnimations = 0x12345678;
+        assertEquals(attrs.windowAnimations, mDc.mAppTransition.getAnimationStyleResId(attrs));
+
+        // Verify getAnimationStyleResId will return system resource Id when the window type is
+        // starting window.
+        attrs.type = TYPE_APPLICATION_STARTING;
+        assertEquals(mDc.mAppTransition.getDefaultWindowAnimationStyleResId(),
+                mDc.mAppTransition.getAnimationStyleResId(attrs));
+    }
+
     private class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
         boolean mCancelled = false;
         @Override