diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index e590739996839..076b33cc9d6a0 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -137,7 +137,10 @@ public class SurfaceView extends View { } break; case DRAW_FINISHED_MSG: { mDrawFinished = true; - invalidate(); + if (mAttachedToWindow) { + notifyDrawFinished(); + invalidate(); + } } break; } } @@ -188,9 +191,12 @@ public class SurfaceView extends View { private Translator mTranslator; private boolean mGlobalListenersAdded; + private boolean mAttachedToWindow; private int mSurfaceFlags = SurfaceControl.HIDDEN; + private int mPendingReportDraws; + public SurfaceView(Context context) { this(context, null); } @@ -227,6 +233,7 @@ public class SurfaceView extends View { mViewVisibility = getVisibility() == VISIBLE; mRequestedVisible = mViewVisibility && mWindowVisibility; + mAttachedToWindow = true; if (!mGlobalListenersAdded) { ViewTreeObserver observer = getViewTreeObserver(); observer.addOnScrollChangedListener(mScrollChangedListener); @@ -261,8 +268,17 @@ public class SurfaceView extends View { updateSurface(); } + void notifyDrawFinished() { + ViewRootImpl viewRoot = getViewRootImpl(); + if (viewRoot != null) { + viewRoot.pendingDrawFinished(); + } + mPendingReportDraws--; + } + @Override protected void onDetachedFromWindow() { + mAttachedToWindow = false; if (mGlobalListenersAdded) { ViewTreeObserver observer = getViewTreeObserver(); observer.removeOnScrollChangedListener(mScrollChangedListener); @@ -270,6 +286,10 @@ public class SurfaceView extends View { mGlobalListenersAdded = false; } + while (mPendingReportDraws > 0) { + notifyDrawFinished(); + } + mRequestedVisible = false; updateSurface(); @@ -618,6 +638,9 @@ public class SurfaceView extends View { if (callbacks == null) { callbacks = getSurfaceCallbacks(); } + + mPendingReportDraws++; + viewRoot.drawPending(); SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::onDrawFinished); sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 168178702ebf4..6d5037ab1fc5a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2703,8 +2703,40 @@ public final class ViewRootImpl implements ViewParent, } } - private void onDrawFinished() { + /** + * A count of the number of calls to pendingDrawFinished we + * require to notify the WM drawing is complete. + * + * This starts at 1, for the ViewRootImpl surface itself. + * Subsurfaces may debt the value with drawPending. + */ + int mDrawsNeededToReport = 1; + + /** + * Delay notifying WM of draw finished until + * a balanced call to pendingDrawFinished. + */ + void drawPending() { + mDrawsNeededToReport++; + } + + void pendingDrawFinished() { + if (mDrawsNeededToReport == 0) { + throw new RuntimeException("Unbalanced drawPending/pendingDrawFinished calls"); + } + mDrawsNeededToReport--; + if (mDrawsNeededToReport == 0) { + reportDrawFinished(); + } + } + + private void postDrawFinished() { + mHandler.sendEmptyMessage(MSG_DRAW_FINISHED); + } + + private void reportDrawFinished() { try { + mDrawsNeededToReport = 1; mWindowSession.finishDrawing(mWindow); } catch (RemoteException e) { // Have fun! @@ -2761,15 +2793,12 @@ public final class ViewRootImpl implements ViewParent, } if (mSurfaceHolder != null && mSurface.isValid()) { - SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::onDrawFinished); + SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::postDrawFinished); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks); } else { - try { - mWindowSession.finishDrawing(mWindow); - } catch (RemoteException e) { - } + pendingDrawFinished(); } } } @@ -3567,6 +3596,7 @@ public final class ViewRootImpl implements ViewParent, private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26; private final static int MSG_UPDATE_POINTER_ICON = 27; private final static int MSG_POINTER_CAPTURE_CHANGED = 28; + private final static int MSG_DRAW_FINISHED = 29; final class ViewRootHandler extends Handler { @Override @@ -3618,6 +3648,8 @@ public final class ViewRootImpl implements ViewParent, return "MSG_UPDATE_POINTER_ICON"; case MSG_POINTER_CAPTURE_CHANGED: return "MSG_POINTER_CAPTURE_CHANGED"; + case MSG_DRAW_FINISHED: + return "MSG_DRAW_FINISHED"; } return super.getMessageName(message); } @@ -3891,6 +3923,9 @@ public final class ViewRootImpl implements ViewParent, final boolean hasCapture = msg.arg1 != 0; handlePointerCaptureChanged(hasCapture); } break; + case MSG_DRAW_FINISHED: { + pendingDrawFinished(); + } break; } } }