Fix Restore transition

Don't replace a change transition type. This was happening
because the wallpaper was becoming visible and the transition
system seems to assume it will be the only thing visible and
replaced the transit with WALLPAPER_OPEN.

Also fixed some other exposed bugs:
- Animation was using stack bounds for freeform windows.
- Non-changing windows were using change anim spec.

Bug: 126956505
Test: atest AppWindowTokenTests AppTransitionControllerTest
      manual, restore a maximized window.

Change-Id: I49bc9bb6c4314e8eb5415a1e2aefc8d61fc0476e
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index bb5a221..af05a27 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -2237,6 +2237,10 @@
                 || transit == TRANSIT_ACTIVITY_RELAUNCH;
     }
 
+    static boolean isChangeTransit(int transit) {
+        return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
+    }
+
     /**
      * @return whether the transition should show the thumbnail being scaled down.
      */
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 8f0a7c0..f6326957 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -513,8 +513,11 @@
         // Given no app transition pass it through instead of a wallpaper transition.
         // Never convert the crashing transition.
         // Never update the transition for the wallpaper if we are just docking from recents
+        // Never convert a change transition since the top activity isn't changing and will likely
+        // still be above an opening wallpaper.
         if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
-                || transit == TRANSIT_DOCK_TASK_FROM_RECENTS) {
+                || transit == TRANSIT_DOCK_TASK_FROM_RECENTS
+                || AppTransition.isChangeTransit(transit)) {
             return transit;
         }
 
@@ -601,6 +604,10 @@
      */
     @VisibleForTesting
     int maybeUpdateTransitToTranslucentAnim(int transit) {
+        if (AppTransition.isChangeTransit(transit)) {
+            // There's no special animation to handle change animations with translucent apps
+            return transit;
+        }
         final boolean taskOrActivity = AppTransition.isTaskTransit(transit)
                 || AppTransition.isActivityTransit(transit);
         boolean allOpeningVisible = true;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 220370c..5ba6c76 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1747,7 +1747,7 @@
     }
 
     boolean isInChangeTransition() {
-        return mTransitChangeLeash != null || isChangeTransition(mTransit);
+        return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
     }
 
     @VisibleForTesting
@@ -2458,14 +2458,12 @@
         final Task task = getTask();
         if (task != null && task.inFreeformWindowingMode()) {
             task.getRelativeDisplayedPosition(outPosition);
+            task.getBounds(outBounds);
         } else if (stack != null) {
             stack.getRelativeDisplayedPosition(outPosition);
-        }
-
-        // Always use stack bounds in order to have the ability to animate outside the task region.
-        // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
-        // according to the bounds.
-        if (stack != null) {
+            // Use stack bounds in order to have the ability to animate outside the task region.
+            // Needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
+            // according to the bounds.
             stack.getBounds(outBounds);
         }
         // We have the relative position so the local position can be removed from bounds.
@@ -2484,10 +2482,6 @@
         return getBounds();
     }
 
-    private static boolean isChangeTransition(int transit) {
-        return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-    }
-
     boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
             boolean isVoiceInteraction) {
 
@@ -2509,7 +2503,8 @@
             AnimationAdapter thumbnailAdapter = null;
             getAnimationBounds(mTmpPoint, mTmpRect);
 
-            boolean isChanging = isChangeTransition(transit) && enter;
+            final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
+                    && getDisplayContent().mChangingApps.contains(this);
 
             // Delaying animation start isn't compatible with remote animations at all.
             if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 5e12a95..81133d1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.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.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 
@@ -77,4 +78,21 @@
                             TRANSIT_TASK_CLOSE));
         }
     }
+
+    @Test
+    public void testChangeIsNotOverwritten() {
+        synchronized (mWm.mGlobalLock) {
+            final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            translucentOpening.setFillsParent(false);
+            translucentOpening.setHidden(true);
+            mDisplayContent.mOpeningApps.add(behind);
+            mDisplayContent.mOpeningApps.add(translucentOpening);
+            assertEquals(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+                    mAppTransitionController.maybeUpdateTransitToTranslucentAnim(
+                            TRANSIT_TASK_CHANGE_WINDOWING_MODE));
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 68b40b9..468728f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -489,7 +489,9 @@
         mTask.setBounds(taskBounds);
 
         mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        assertTransitionAnimationPositionAndBounds(taskBounds.left, taskBounds.top, stackBounds);
+        final Rect taskBoundsSize = new Rect(taskBounds);
+        taskBoundsSize.offsetTo(0, 0);
+        assertTransitionAnimationPositionAndBounds(taskBounds.left, taskBounds.top, taskBoundsSize);
 
         mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertTransitionAnimationPositionAndBounds(stackBounds.left, stackBounds.top, stackBounds);