diff options
| author | 2017-03-27 15:46:27 -0700 | |
|---|---|---|
| committer | 2017-03-28 12:39:33 -0700 | |
| commit | 8508bb2f10f8da49fff402d04ee81b2fba15ad19 (patch) | |
| tree | 993765e1381f1fe680e36f0ca5042e35ef3e5c71 | |
| parent | 78f5c26fa6687a03858b7eec8c991950a4837af6 (diff) | |
SurfaceView: Make surfaceRedrawNeededAsync work with WM bypass.
Prior to SurfaceView bypassing the WM, the WM would see that
the app had multiple windows and wait for them all
to finish drawing before beginning any animation, or similar operations.
Now that SurfaceView is invisible to the WM we have to replicate this
two-way latching in ViewRootImpl.
Bug: 36492285
Test: Launch Chrome over and over.
Change-Id: Ie72c2d394f1bb0eb8551e6f63bb1c19a5df43afd
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 25 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 47 |
2 files changed, 65 insertions, 7 deletions
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index e59073999683..076b33cc9d6a 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 168178702ebf..6d5037ab1fc5 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; } } } |