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
Merged-In: I21a0f10d4c83b6e7137ea0b389f2bbe1a4c82c2f
Change-Id: I21a0f10d4c83b6e7137ea0b389f2bbe1a4c82c2f
(cherry picked from commit a1d5520a09ed346a8047584e582c714901db4bc8)
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index 6ed8967..7116b0a 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 89c5a17..6518f2a 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -350,42 +350,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 ce890f6..f76491a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1232,7 +1232,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(),
@@ -1278,11 +1280,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,