Update insets position after rotation change is done

Otherwise because getWindowFrameSurfacePosition returns old position
before the display rotation transform is applied, if the position
doesn't update after the transform is done, it will show old position
in new rotation around a few frames. Such as the handle of navigation
bar may be flickering at screen center.

Bug: 338091119
Test: atest TransitionTests#testAppTransitionWithRotationChange

Change-Id: I21a0f10d4c83b6e7137ea0b389f2bbe1a4c82c2f
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index e7fb265..24d4be8 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -288,6 +288,17 @@
             final SurfaceControl.Transaction t = windowToken.getSyncTransaction();
             clearTransform(t, op.mLeash);
         }
+        // The insets position may be frozen by shouldFreezeInsetsPosition(), so refresh the
+        // position to the latest state when it is ready to show in new rotation.
+        if (mTransitionOp == OP_APP_SWITCH) {
+            for (int i = windowToken.getChildCount() - 1; i >= 0; i--) {
+                final WindowState w = windowToken.getChildAt(i);
+                final InsetsSourceProvider insetsProvider = w.getControllableInsetProvider();
+                if (insetsProvider != null) {
+                    insetsProvider.updateInsetsControlPosition(w);
+                }
+            }
+        }
     }
 
     private static void clearTransform(SurfaceControl.Transaction t, SurfaceControl sc) {
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 8858766..4400ed2 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -351,42 +351,47 @@
                 ? windowState.wouldBeVisibleIfPolicyIgnored() && windowState.isVisibleByPolicy()
                 : mWindowContainer.isVisibleRequested();
         setServerVisible(isServerVisible);
-        if (mControl != null) {
-            boolean changed = false;
-            final Point position = getWindowFrameSurfacePosition();
-            if (mControl.setSurfacePosition(position.x, position.y) && mControlTarget != null) {
-                changed = true;
-                if (windowState != null && windowState.getWindowFrames().didFrameSizeChange()
-                        && windowState.mWinAnimator.getShown() && mWindowContainer.okToDisplay()) {
-                    mHasPendingPosition = true;
-                    windowState.applyWithNextDraw(mSetLeashPositionConsumer);
-                } else {
-                    Transaction t = mWindowContainer.getSyncTransaction();
-                    if (windowState != null) {
-                        // Make the buffer, token transformation, and leash position to be updated
-                        // together when the window is drawn for new rotation. Otherwise the window
-                        // may be outside the screen by the inconsistent orientations.
-                        final AsyncRotationController rotationController =
-                                mDisplayContent.getAsyncRotationController();
-                        if (rotationController != null) {
-                            final Transaction drawT =
-                                    rotationController.getDrawTransaction(windowState.mToken);
-                            if (drawT != null) {
-                                t = drawT;
-                            }
+        updateInsetsControlPosition(windowState);
+    }
+
+    void updateInsetsControlPosition(WindowState windowState) {
+        if (mControl == null) {
+            return;
+        }
+        boolean changed = false;
+        final Point position = getWindowFrameSurfacePosition();
+        if (mControl.setSurfacePosition(position.x, position.y) && mControlTarget != null) {
+            changed = true;
+            if (windowState != null && windowState.getWindowFrames().didFrameSizeChange()
+                    && windowState.mWinAnimator.getShown() && mWindowContainer.okToDisplay()) {
+                mHasPendingPosition = true;
+                windowState.applyWithNextDraw(mSetLeashPositionConsumer);
+            } else {
+                Transaction t = mWindowContainer.getSyncTransaction();
+                if (windowState != null) {
+                    // Make the buffer, token transformation, and leash position to be updated
+                    // together when the window is drawn for new rotation. Otherwise the window
+                    // may be outside the screen by the inconsistent orientations.
+                    final AsyncRotationController rotationController =
+                            mDisplayContent.getAsyncRotationController();
+                    if (rotationController != null) {
+                        final Transaction drawT =
+                                rotationController.getDrawTransaction(windowState.mToken);
+                        if (drawT != null) {
+                            t = drawT;
                         }
                     }
-                    mSetLeashPositionConsumer.accept(t);
                 }
+                mSetLeashPositionConsumer.accept(t);
             }
-            final Insets insetsHint = getInsetsHint();
-            if (!mControl.getInsetsHint().equals(insetsHint)) {
-                mControl.setInsetsHint(insetsHint);
-                changed = true;
-            }
-            if (changed) {
-                mStateController.notifyControlChanged(mControlTarget);
-            }
+        }
+        final Insets insetsHint = getInsetsHint();
+        if (!mControl.getInsetsHint().equals(insetsHint)) {
+            mControl.setInsetsHint(insetsHint);
+            changed = true;
+        }
+        if (changed) {
+            mStateController.notifyControlChanged(mControlTarget);
         }
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 3288788..80c066d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1236,7 +1236,9 @@
         final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
         makeWindowVisible(statusBar);
         mDisplayContent.getDisplayPolicy().addWindowLw(statusBar, statusBar.mAttrs);
-        final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
+        final WindowState navBar = createNavBarWithProvidedInsets(mDisplayContent);
+        final InsetsSourceProvider navBarInsetsProvider = navBar.getControllableInsetProvider();
+        assertNotNull(navBarInsetsProvider);
         final ActivityRecord app = createActivityRecord(mDisplayContent);
         final Transition transition = app.mTransitionController.createTransition(TRANSIT_OPEN);
         app.mTransitionController.requestStartTransition(transition, app.getTask(),
@@ -1282,11 +1284,15 @@
         onRotationTransactionReady(player, mWm.mTransactionFactory.get()).onTransactionCommitted();
         assertEquals(ROTATION_ANIMATION_SEAMLESS, player.mLastReady.getChange(
                 mDisplayContent.mRemoteToken.toWindowContainerToken()).getRotationAnimation());
+        spyOn(navBarInsetsProvider);
         player.finish();
 
         // The controller should be cleared if the target windows are drawn.
         statusBar.finishDrawing(mWm.mTransactionFactory.get(), Integer.MAX_VALUE);
         assertNull(mDisplayContent.getAsyncRotationController());
+        // The shouldFreezeInsetsPosition for navBar was true, so its insets position should be
+        // updated if the transition is done.
+        verify(navBarInsetsProvider).updateInsetsControlPosition(navBar);
     }
 
     private static void assertShouldFreezeInsetsPosition(AsyncRotationController controller,