From c58e1df6fba2c4589b82c6cc35a4f6ba43a3b5dd Mon Sep 17 00:00:00 2001 From: Yunfan Chen Date: Mon, 30 Jan 2023 18:25:35 +0900 Subject: Use the layout frame to decide whether to do a server sync When the shell side resize/reposition happens, the relayout won't happen until the next traversal happens. However, the mWinFrame will be updated directly before the relayout happens. When that's happening, the relayout may miss the actual resize/reposition from the shell. Test: See b/266582561. Check the unfold compat mode. Bug: 266582561 Change-Id: I059db87e0bb61ddc4efcc8e1f67e4fa532c4e5a9 --- core/java/android/view/ViewRootImpl.java | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 43bbcfb1e94a..544570954324 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -78,7 +78,6 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; -import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; @@ -712,6 +711,7 @@ public final class ViewRootImpl implements ViewParent, // These are accessed by multiple threads. final Rect mWinFrame; // frame given by window manager. + private final Rect mLastLayoutFrame; Rect mOverrideInsetsFrame; final Rect mPendingBackDropFrame = new Rect(); @@ -932,6 +932,7 @@ public final class ViewRootImpl implements ViewParent, mHeight = -1; mDirty = new Rect(); mWinFrame = new Rect(); + mLastLayoutFrame = new Rect(); mWindow = new W(this); mLeashToken = new Binder(); mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; @@ -1303,7 +1304,7 @@ public final class ViewRootImpl implements ViewParent, UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH, mInsetsController.getRequestedVisibilities(), 1f /* compactScale */, mTmpFrames); - setFrame(mTmpFrames.frame); + setFrame(mTmpFrames.frame, true /* withinRelayout */); registerBackCallbackOnWindow(); if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) { // For apps requesting legacy back behavior, we add a compat callback that @@ -1824,7 +1825,7 @@ public final class ViewRootImpl implements ViewParent, onMovedToDisplay(displayId, mLastConfigurationFromResources); } - setFrame(frame); + setFrame(frame, false /* withinRelayout */); mTmpFrames.displayFrame.set(displayFrame); if (mTmpFrames.attachedFrame != null && attachedFrame != null) { mTmpFrames.attachedFrame.set(attachedFrame); @@ -5740,7 +5741,7 @@ public final class ViewRootImpl implements ViewParent, mTmpFrames.frame.right = l + w; mTmpFrames.frame.top = t; mTmpFrames.frame.bottom = t + h; - setFrame(mTmpFrames.frame); + setFrame(mTmpFrames.frame, false /* withinRelayout */); maybeHandleWindowMove(mWinFrame); } break; @@ -8210,7 +8211,7 @@ public final class ViewRootImpl implements ViewParent, // If the position and the size of the frame are both changed, it will trigger a BLAST // sync, and we still need to call relayout to obtain the syncSeqId. Otherwise, we just // need to send attributes via relayoutAsync. - final Rect oldFrame = mWinFrame; + final Rect oldFrame = mLastLayoutFrame; final Rect newFrame = mTmpFrames.frame; final boolean positionChanged = newFrame.top != oldFrame.top || newFrame.left != oldFrame.left; @@ -8340,7 +8341,7 @@ public final class ViewRootImpl implements ViewParent, params.restore(); } - setFrame(mTmpFrames.frame); + setFrame(mTmpFrames.frame, true /* withinRelayout */); return relayoutResult; } @@ -8375,8 +8376,18 @@ public final class ViewRootImpl implements ViewParent, mIsSurfaceOpaque = opaque; } - private void setFrame(Rect frame) { + /** + * Set the mWinFrame of this window. + * @param frame the new frame of this window. + * @param withinRelayout {@code true} if this setting is within the relayout, or is the initial + * setting. That will make sure in the relayout process, we always compare + * the window frame with the last processed window frame. + */ + private void setFrame(Rect frame, boolean withinRelayout) { mWinFrame.set(frame); + if (withinRelayout) { + mLastLayoutFrame.set(frame); + } final WindowConfiguration winConfig = getCompatWindowConfiguration(); mPendingBackDropFrame.set(mPendingDragResizing && !winConfig.useWindowFrameForBackdrop() -- cgit v1.2.3-59-g8ed1b