From a93fcc9e3391beb48caa45074b1b4b6d967b5d1a Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Thu, 8 Jul 2021 10:19:34 -0700 Subject: ViewRootImpl: Fix issue with early draw report in seamless rotation When we receive RELAYOUT_RES_BLAST_SYNC from the WindowManager, we trigger reportNextDraw, incrementing the pending draw count by one. At the moment we unfortunately do this after dispatching callbacks to SurfaceView. In the span of these callbacks, SurfaceView may increment and decrement pending draw count, once it reaches zero we will notify the WM of draw early, terminating the sync operation without ever waiting for the ViewRootImpl to draw. By processing RELAYOUT_RES_BLAST_SYNC before emitting the SurfaceView callbacks we can avoid this issue. Bug: 191921061 Test: Existing tests pass Change-Id: I2f1096c9cdc79b89413c3f0bfd9b3054ef45f2d2 --- core/java/android/view/ViewRootImpl.java | 36 +++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'core/java/android/view/ViewRootImpl.java') diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 23faac6c0787..ebee198741d4 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2771,6 +2771,7 @@ public final class ViewRootImpl implements ViewParent, mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance); } } + final boolean wasReportNextDraw = mReportNextDraw; if (mFirst || windowShouldResize || viewVisibilityChanged || params != null || mForceNextWindowRelayout) { @@ -2817,6 +2818,16 @@ public final class ViewRootImpl implements ViewParent, final boolean dockedResizing = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED) != 0; final boolean dragResizing = freeformResizing || dockedResizing; + if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC) != 0) { + if (DEBUG_BLAST) { + Log.d(mTag, "Relayout called with blastSync"); + } + reportNextDraw(); + if (isHardwareEnabled()) { + mNextDrawUseBlastSync = true; + } + } + if (mSurfaceControl.isValid()) { updateOpacity(mWindowAttributes, dragResizing); } @@ -3035,7 +3046,16 @@ public final class ViewRootImpl implements ViewParent, } } - if (!mStopped || mReportNextDraw) { + // TODO: In the CL "ViewRootImpl: Fix issue with early draw report in + // seamless rotation". We moved processing of RELAYOUT_RES_BLAST_SYNC + // earlier in the function, potentially triggering a call to + // reportNextDraw(). That same CL changed this and the next reference + // to wasReportNextDraw, such that this logic would remain undisturbed + // (it continues to operate as if the code was never moved). This was + // done to achieve a more hermetic fix for S, but it's entirely + // possible that checking the most recent value is actually more + // correct here. + if (!mStopped || wasReportNextDraw) { boolean focusChangedDueToTouchMode = ensureTouchModeLocally( (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0); if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() @@ -3105,7 +3125,7 @@ public final class ViewRootImpl implements ViewParent, prepareSurfaces(); } - final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); + final boolean didLayout = layoutRequested && (!mStopped || wasReportNextDraw); boolean triggerGlobalLayoutListener = didLayout || mAttachInfo.mRecomputeGlobalAttributes; if (didLayout) { @@ -3261,21 +3281,10 @@ public final class ViewRootImpl implements ViewParent, mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes); - final boolean wasReportNextDraw = mReportNextDraw; - // Remember if we must report the next draw. if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { reportNextDraw(); } - if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC) != 0) { - if (DEBUG_BLAST) { - Log.d(mTag, "Relayout called with blastSync"); - } - reportNextDraw(); - if (isHardwareEnabled()) { - mNextDrawUseBlastSync = true; - } - } boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible; @@ -3286,7 +3295,6 @@ public final class ViewRootImpl implements ViewParent, } mPendingTransitions.clear(); } - performDraw(); } else { if (isViewVisible) { -- cgit v1.2.3