Merge "Notify remote rotation with fixed rotation transform" into rvc-dev
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 068a434..a90016a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1317,8 +1317,6 @@
         if (mDisplayRotation.isWaitingForRemoteRotation()) {
             return;
         }
-        // Clear the record because the display will sync to current rotation.
-        mFixedRotationLaunchingApp = null;
 
         final boolean configUpdated = updateDisplayOverrideConfigurationLocked();
         if (configUpdated) {
@@ -1509,7 +1507,7 @@
         startFixedRotationTransform(r, rotation);
         mAppTransition.registerListenerLocked(new WindowManagerInternal.AppTransitionListener() {
             void done() {
-                r.clearFixedRotationTransform();
+                r.finishFixedRotationTransform();
                 mAppTransition.unregisterListener(this);
             }
 
@@ -1538,7 +1536,8 @@
         if (token != mFixedRotationLaunchingApp) {
             return false;
         }
-        if (updateOrientation()) {
+        // Update directly because the app which will change the orientation of display is ready.
+        if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) {
             sendNewConfiguration();
             return true;
         }
@@ -1584,7 +1583,7 @@
      * @param oldRotation the rotation we are coming from.
      * @param rotation the rotation to apply.
      */
-    void applyRotationLocked(final int oldRotation, final int rotation) {
+    private void applyRotation(final int oldRotation, final int rotation) {
         mDisplayRotation.applyCurrentRotation(rotation);
         final boolean rotateSeamlessly = mDisplayRotation.isRotatingSeamlessly();
         final Transaction transaction = getPendingTransaction();
@@ -6493,15 +6492,20 @@
 
     @Override
     public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
-        final int currRotation =
-                getRequestedOverrideConfiguration().windowConfiguration.getRotation();
-        if (currRotation != ROTATION_UNDEFINED
-                && currRotation != overrideConfiguration.windowConfiguration.getRotation()) {
-            applyRotationLocked(currRotation,
-                    overrideConfiguration.windowConfiguration.getRotation());
+        final Configuration currOverrideConfig = getRequestedOverrideConfiguration();
+        final int currRotation = currOverrideConfig.windowConfiguration.getRotation();
+        final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation();
+        if (currRotation != ROTATION_UNDEFINED && currRotation != overrideRotation) {
+            if (mFixedRotationLaunchingApp != null) {
+                mFixedRotationLaunchingApp.clearFixedRotationTransform(
+                        () -> applyRotation(currRotation, overrideRotation));
+                // Clear the record because the display will sync to current rotation.
+                mFixedRotationLaunchingApp = null;
+            } else {
+                applyRotation(currRotation, overrideRotation);
+            }
         }
-        mCurrentOverrideConfigurationChanges =
-            getRequestedOverrideConfiguration().diff(overrideConfiguration);
+        mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration);
         super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
         mCurrentOverrideConfigurationChanges = 0;
         mWmService.setNewDisplayOverrideConfiguration(overrideConfiguration, this);
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 60b817c..af89a05 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -484,11 +484,8 @@
             prepareNormalRotationAnimation();
         }
 
-        // TODO(b/147469351): Remove the restriction.
-        if (mDisplayContent.mFixedRotationLaunchingApp == null) {
-            // Give a remote handler (system ui) some time to reposition things.
-            startRemoteRotation(oldRotation, mRotation);
-        }
+        // Give a remote handler (system ui) some time to reposition things.
+        startRemoteRotation(oldRotation, mRotation);
 
         return true;
     }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 3e5cb50..a30b70d 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -667,7 +667,7 @@
                         mTargetActivityRecord.token);
             }
             if (mTargetActivityRecord.hasFixedRotationTransform()) {
-                mTargetActivityRecord.clearFixedRotationTransform();
+                mTargetActivityRecord.finishFixedRotationTransform();
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 850c362..3c2b6ec 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -480,26 +480,42 @@
     }
 
     /**
-     * Clears the transformation and continue updating the orientation change of display. Only the
-     * state owner can clear the transform state.
+     * Finishes the transform and continue updating the orientation change of display. Only the
+     * state owner can finish the transform state.
      */
-    void clearFixedRotationTransform() {
-        final FixedRotationTransformState state = mFixedRotationTransformState;
-        if (state == null || state.mOwner != this) {
+    void finishFixedRotationTransform() {
+        if (mFixedRotationTransformState == null || mFixedRotationTransformState.mOwner != this) {
             return;
         }
-        state.resetTransform();
-        // Clear the flag so if the display will be updated to the same orientation, the transform
-        // won't take effect. The state is cleared at the end, because it is used to indicate that
-        // other windows can use seamless rotation when applying rotation to display.
-        state.mIsTransforming = false;
         final boolean changed =
                 mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp(this);
-        // If it is not the launching app or the display is not rotated, make sure the merged
-        // override configuration is restored from parent.
+        // If it is not the launching app or the display is not rotated, make sure the transform is
+        // cleared and the configuration is restored from parent.
         if (!changed) {
-            onMergedOverrideConfigurationChanged();
+            clearFixedRotationTransform(null /* applyDisplayRotation */);
+            onConfigurationChanged(getParent().getConfiguration());
         }
+    }
+
+    /**
+     * Clears the transform and apply display rotation if the action is given. The caller needs to
+     * refresh the configuration of this container after this method call.
+     */
+    void clearFixedRotationTransform(Runnable applyDisplayRotation) {
+        final FixedRotationTransformState state = mFixedRotationTransformState;
+        if (state == null) {
+            return;
+        }
+
+        state.resetTransform();
+        // Clear the flag so if the display will be updated to the same orientation, the transform
+        // won't take effect.
+        state.mIsTransforming = false;
+        if (applyDisplayRotation != null) {
+            applyDisplayRotation.run();
+        }
+        // The state is cleared at the end, because it is used to indicate that other windows can
+        // use seamless rotation when applying rotation to display.
         for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
             state.mAssociatedTokens.get(i).mFixedRotationTransformState = null;
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 406affc..f242989 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -403,11 +403,11 @@
                 wallpapers.get(0).getConfiguration().orientation);
 
         // Wallpaper's transform state is controlled by home, so the invocation should be no-op.
-        wallpaperWindowToken.clearFixedRotationTransform();
+        wallpaperWindowToken.finishFixedRotationTransform();
         assertTrue(wallpaperWindowToken.hasFixedRotationTransform());
 
         // Wallpaper's transform state should be cleared with home.
-        homeActivity.clearFixedRotationTransform();
+        homeActivity.finishFixedRotationTransform();
         assertFalse(wallpaperWindowToken.hasFixedRotationTransform());
     }