summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/SurfaceControlViewHost.java2
-rw-r--r--core/java/android/view/SurfaceView.java145
-rw-r--r--core/java/android/view/ViewRootImpl.java409
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java3
4 files changed, 244 insertions, 315 deletions
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index a13579d0acad..406281d4cade 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -401,7 +401,7 @@ public class SurfaceControlViewHost {
public void relayout(WindowManager.LayoutParams attrs,
WindowlessWindowManager.ResizeCompleteCallback callback) {
mViewRoot.setLayoutParams(attrs, false);
- mViewRoot.setReportNextDraw();
+ mViewRoot.setReportNextDraw(true /* syncBuffer */);
mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), callback);
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 413855639d09..c04b0964a7a4 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -50,6 +50,7 @@ import android.view.accessibility.IAccessibilityEmbeddedConnection;
import com.android.internal.view.SurfaceCallbackHelper;
import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
@@ -203,8 +204,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
private int mSurfaceFlags = SurfaceControl.HIDDEN;
- private int mPendingReportDraws;
-
/**
* Transaction that should be used from the render thread. This transaction is only thread safe
* with other calls directly from the render thread.
@@ -212,11 +211,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
private final SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction();
/**
- * Used on the main thread to set the transaction that will be synced with the main window.
- */
- private final Transaction mSyncTransaction = new Transaction();
-
- /**
* Transaction that should be used whe
* {@link HardwareRenderer.FrameDrawingCallback#onFrameDraw} is invoked. All
* frame callbacks can use the same transaction since they will be thread safe
@@ -391,31 +385,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
}
- private void performDrawFinished(@Nullable Transaction t) {
- if (t != null) {
- mSyncTransaction.merge(t);
- }
-
- if (mPendingReportDraws > 0) {
- mDrawFinished = true;
- if (mAttachedToWindow) {
- mParent.requestTransparentRegion(SurfaceView.this);
- notifyDrawFinished();
- invalidate();
- }
- } else {
- Log.e(TAG, System.identityHashCode(this) + "finished drawing"
- + " but no pending report draw (extra call"
- + " to draw completion runnable?)");
- }
- }
-
- void notifyDrawFinished() {
- ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot != null) {
- viewRoot.pendingDrawFinished(mSyncTransaction);
+ private void performDrawFinished() {
+ mDrawFinished = true;
+ if (mAttachedToWindow) {
+ mParent.requestTransparentRegion(SurfaceView.this);
+ invalidate();
}
- mPendingReportDraws--;
}
@Override
@@ -438,10 +413,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mGlobalListenersAdded = false;
}
- while (mPendingReportDraws > 0) {
- notifyDrawFinished();
- }
-
mRequestedVisible = false;
updateSurface();
@@ -993,10 +964,17 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
return;
}
- final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
- translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
final boolean redrawNeeded = sizeChanged || creating || hintChanged
|| (mVisible && !mDrawFinished);
+ final TransactionCallback transactionCallback =
+ redrawNeeded ? new TransactionCallback() : null;
+ if (redrawNeeded && viewRoot.wasRelayoutRequested() && viewRoot.isInSync()) {
+ mBlastBufferQueue.syncNextTransaction(
+ false /* acquireSingleBuffer */,
+ transactionCallback::onTransactionReady);
+ }
+ final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
+ translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
try {
SurfaceHolder.Callback[] callbacks = null;
@@ -1015,9 +993,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mIsCreating = true;
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "visibleChanged -- surfaceCreated");
- if (callbacks == null) {
- callbacks = getSurfaceCallbacks();
- }
+ callbacks = getSurfaceCallbacks();
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceCreated(mSurfaceHolder);
}
@@ -1035,32 +1011,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
}
if (redrawNeeded) {
- if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
- + "surfaceRedrawNeeded");
- if (callbacks == null) {
- callbacks = getSurfaceCallbacks();
- }
-
- final boolean wasRelayoutRequested = viewRoot.wasRelayoutRequested();
- if (wasRelayoutRequested && (mBlastBufferQueue != null)) {
- mBlastBufferQueue.syncNextTransaction(
- false /* acquireSingleBuffer */,
- this::onDrawFinished);
- }
- mPendingReportDraws++;
- viewRoot.drawPending();
- SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() -> {
- if (mBlastBufferQueue != null) {
- mBlastBufferQueue.stopContinuousSyncTransaction();
- }
- // If relayout was requested, then a callback from BBQ will
- // be invoked with the sync transaction. onDrawFinished will be
- // called in there
- if (!wasRelayoutRequested) {
- onDrawFinished(null);
- }
- });
- sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
+ redrawNeeded(callbacks, transactionCallback);
}
}
} finally {
@@ -1079,6 +1030,64 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
}
+ private void redrawNeeded(SurfaceHolder.Callback[] callbacks,
+ @Nullable TransactionCallback transactionCallback) {
+ if (DEBUG) {
+ Log.i(TAG, System.identityHashCode(this) + " surfaceRedrawNeeded");
+ }
+ final SurfaceHolder.Callback[] capturedCallbacks =
+ callbacks == null ? getSurfaceCallbacks() : callbacks;
+
+ ViewRootImpl viewRoot = getViewRootImpl();
+ boolean isVriSync = viewRoot.addToSync(syncBufferCallback ->
+ redrawNeededAsync(capturedCallbacks, () -> {
+ if (mBlastBufferQueue != null) {
+ mBlastBufferQueue.stopContinuousSyncTransaction();
+ }
+
+ Transaction t = null;
+ if (transactionCallback != null && mBlastBufferQueue != null) {
+ t = transactionCallback.waitForTransaction();
+ }
+ // If relayout was requested, then a callback from BBQ will
+ // be invoked with the sync transaction. onDrawFinished will be
+ // called in there
+ syncBufferCallback.onBufferReady(t);
+ onDrawFinished();
+ }));
+
+ // If isVriSync, then everything was setup in the addToSync.
+ if (isVriSync) {
+ return;
+ }
+
+ redrawNeededAsync(capturedCallbacks, this::onDrawFinished);
+ }
+
+ private void redrawNeededAsync(SurfaceHolder.Callback[] callbacks,
+ Runnable callbacksCollected) {
+ SurfaceCallbackHelper sch = new SurfaceCallbackHelper(callbacksCollected);
+ sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
+ }
+
+ private static class TransactionCallback {
+ private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+ private Transaction mTransaction;
+
+ Transaction waitForTransaction() {
+ try {
+ mCountDownLatch.await();
+ } catch (InterruptedException e) {
+ }
+ return mTransaction;
+ }
+
+ void onTransactionReady(Transaction t) {
+ mTransaction = t;
+ mCountDownLatch.countDown();
+ }
+ }
+
/**
* Copy the Surface from the SurfaceControl or the blast adapter.
*
@@ -1189,13 +1198,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat);
}
- private void onDrawFinished(@Nullable Transaction t) {
+ private void onDrawFinished() {
if (DEBUG) {
Log.i(TAG, System.identityHashCode(this) + " "
+ "finishedDrawing");
}
- runOnUiThread(() -> performDrawFinished(t));
+ runOnUiThread(this::performDrawFinished);
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2613c1a2992f..5133b2e18266 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -587,11 +587,13 @@ public final class ViewRootImpl implements ViewParent,
boolean mReportNextDraw;
+
/**
- * Set whether the draw should use blast sync. This is in case the draw is canceled,
- * but will be rescheduled. We still want the next draw to be sync.
+ * Set whether the draw should send the buffer to system server. When set to true, VRI will
+ * create a sync transaction with BBQ and send the resulting buffer to system server. If false,
+ * VRI will not try to sync a buffer in BBQ, but still report when a draw occurred.
*/
- boolean mNextDrawUseBlastSync;
+ private boolean mSyncBuffer = false;
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
@@ -812,6 +814,10 @@ public final class ViewRootImpl implements ViewParent,
return mHandwritingInitiator;
}
+ private final SurfaceSyncer mSurfaceSyncer = new SurfaceSyncer();
+ private int mLastSyncId = -1;
+ private SurfaceSyncer.SyncBufferCallback mSyncBufferCallback;
+
/**
* Keeps track of the last frame number that was attempted to draw. Should only be accessed on
* the RenderThread.
@@ -2899,8 +2905,6 @@ public final class ViewRootImpl implements ViewParent,
mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance);
}
}
- final boolean wasReportNextDraw = mReportNextDraw;
- boolean useBlastSync = mNextDrawUseBlastSync;
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|| mForceNextWindowRelayout) {
@@ -2939,9 +2943,7 @@ public final class ViewRootImpl implements ViewParent,
Log.d(mTag, "Relayout called with blastSync");
}
reportNextDraw();
- if (isHardwareEnabled()) {
- useBlastSync = true;
- }
+ mSyncBuffer = true;
}
final boolean surfaceControlChanged =
@@ -3177,7 +3179,7 @@ public final class ViewRootImpl implements ViewParent,
// 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) {
+ if (!mStopped || mReportNextDraw) {
if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()
|| dispatchApplyInsets || updatedConfiguration) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width,
@@ -3246,7 +3248,7 @@ public final class ViewRootImpl implements ViewParent,
prepareSurfaces();
}
- final boolean didLayout = layoutRequested && (!mStopped || wasReportNextDraw);
+ final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
boolean triggerGlobalLayoutListener = didLayout
|| mAttachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
@@ -3439,51 +3441,37 @@ public final class ViewRootImpl implements ViewParent,
mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes);
- // Remember if we must report the next draw.
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
reportNextDraw();
}
- boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
- if (mBLASTDrawConsumer != null) {
- useBlastSync = true;
+ boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw();
+ if (!cancelAndRedraw) {
+ createSyncIfNeeded();
}
- if (!cancelDraw) {
+ if (!isViewVisible) {
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
for (int i = 0; i < mPendingTransitions.size(); ++i) {
- mPendingTransitions.get(i).startChangingAnimations();
+ mPendingTransitions.get(i).endChangingAnimations();
}
mPendingTransitions.clear();
}
- performDraw(useBlastSync);
- mNextDrawUseBlastSync = false;
- } else {
- if (isViewVisible) {
- // Try again
- mNextDrawUseBlastSync = useBlastSync;
- scheduleTraversals();
- } else {
- if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
- for (int i = 0; i < mPendingTransitions.size(); ++i) {
- mPendingTransitions.get(i).endChangingAnimations();
- }
- mPendingTransitions.clear();
- }
-
- // We may never draw since it's not visible. Report back that we're finished
- // drawing.
- if (!wasReportNextDraw && mReportNextDraw) {
- mReportNextDraw = false;
- pendingDrawFinished();
- }
- // Make sure the consumer is not waiting if the view root was just made invisible.
- if (mBLASTDrawConsumer != null) {
- mBLASTDrawConsumer.accept(null);
- mBLASTDrawConsumer = null;
+ if (mSyncBufferCallback != null) {
+ mSyncBufferCallback.onBufferReady(null);
+ }
+ } else if (cancelAndRedraw) {
+ // Try again
+ scheduleTraversals();
+ } else {
+ if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
+ for (int i = 0; i < mPendingTransitions.size(); ++i) {
+ mPendingTransitions.get(i).startChangingAnimations();
}
+ mPendingTransitions.clear();
}
+ performDraw();
}
if (mAttachInfo.mContentCaptureEvents != null) {
@@ -3492,6 +3480,46 @@ public final class ViewRootImpl implements ViewParent,
mIsInTraversal = false;
mRelayoutRequested = false;
+
+ if (!cancelAndRedraw) {
+ mReportNextDraw = false;
+ mSyncBufferCallback = null;
+ mSyncBuffer = false;
+ if (mLastSyncId != -1) {
+ mSurfaceSyncer.markSyncReady(mLastSyncId);
+ mLastSyncId = -1;
+ }
+ }
+ }
+
+ private void createSyncIfNeeded() {
+ // Started a sync already.
+ if (mLastSyncId != -1) {
+ return;
+ }
+
+ Consumer<Transaction> syncConsumer = null;
+ if (mBLASTDrawConsumer != null) {
+ syncConsumer = mBLASTDrawConsumer;
+ mBLASTDrawConsumer = null;
+ } else if (mReportNextDraw) {
+ syncConsumer = transaction -> {
+ mSurfaceChangedTransaction.merge(transaction);
+ reportDrawFinished();
+ };
+ }
+
+ if (syncConsumer != null) {
+ final Consumer<Transaction> capturedSyncConsumer = syncConsumer;
+ mLastSyncId = mSurfaceSyncer.setupSync(transaction -> {
+ // Callback will be invoked on executor thread so post to main thread.
+ mHandler.postAtFrontOfQueue(() -> capturedSyncConsumer.accept(transaction));
+ });
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "Setup new sync id=" + mLastSyncId);
+ }
+ mSurfaceSyncer.addToSync(mLastSyncId, mSyncTarget);
+ }
}
private void notifyContentCatpureEvents() {
@@ -4105,54 +4133,10 @@ public final class ViewRootImpl implements ViewParent,
}
}
- /**
- * A count of the number of calls to pendingDrawFinished we
- * require to notify the WM drawing is complete.
- */
- int mDrawsNeededToReport = 0;
-
- /**
- * Delay notifying WM of draw finished until
- * a balanced call to pendingDrawFinished.
- */
- void drawPending() {
- mDrawsNeededToReport++;
- }
-
- void pendingDrawFinished(Transaction t) {
- if (mDrawsNeededToReport == 0) {
- throw new RuntimeException("Unbalanced drawPending/pendingDrawFinished calls");
- }
-
- if (t != null) {
- if (DEBUG_BLAST) {
- Log.d(mTag, "Merging transaction into main window transaction");
- }
- mSurfaceChangedTransaction.merge(t);
- }
-
- mDrawsNeededToReport--;
- if (mDrawsNeededToReport == 0) {
- reportDrawFinished();
- } else if (DEBUG_BLAST) {
- Log.d(mTag, "pendingDrawFinished. Waiting on draw reported mDrawsNeededToReport="
- + mDrawsNeededToReport);
- }
- }
-
- void pendingDrawFinished() {
- pendingDrawFinished(null);
- }
-
- private void postDrawFinished() {
- mHandler.sendEmptyMessage(MSG_DRAW_FINISHED);
- }
-
private void reportDrawFinished() {
if (DEBUG_BLAST) {
- Log.d(mTag, "reportDrawFinished");
+ Log.d(mTag, "reportDrawFinished " + Debug.getCallers(5));
}
- mDrawsNeededToReport = 0;
try {
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
@@ -4171,6 +4155,19 @@ public final class ViewRootImpl implements ViewParent,
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
}
+ boolean addToSync(SurfaceSyncer.SyncTarget syncable) {
+ if (mLastSyncId == -1) {
+ return false;
+ }
+ mSurfaceSyncer.addToSync(mLastSyncId, syncable);
+ return true;
+ }
+
+
+ public boolean isInSync() {
+ return mLastSyncId != -1;
+ }
+
private void addFrameCommitCallbackIfNeeded() {
if (!isHardwareEnabled()) {
return;
@@ -4201,188 +4198,81 @@ public final class ViewRootImpl implements ViewParent,
});
}
- private HardwareRenderer.FrameCommitCallback createFrameCommitCallbackForSync(
- boolean useBlastSync, boolean reportNextDraw, Consumer<Transaction> blastSyncConsumer) {
- return didProduceBuffer -> {
- if (DEBUG_BLAST) {
- Log.d(mTag, "Received frameCommittedCallback "
- + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum
- + " didProduceBuffer=" + didProduceBuffer);
- }
-
- // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next
- // draw attempt. The next transaction and transaction complete callback were only set
- // for the current draw attempt.
- final Transaction pendingTransactions;
- if (!didProduceBuffer) {
- mBlastBufferQueue.syncNextTransaction(null);
- // Get the transactions that were sent to mergeWithNextTransaction since the
- // frame didn't draw on this vsync. It's possible the frame will draw later, but
- // it's better to not be sync than to block on a frame that may never come.
- pendingTransactions = mBlastBufferQueue.gatherPendingTransactions(
- mRtLastAttemptedDrawFrameNum);
- if (!useBlastSync && !reportNextDraw) {
- pendingTransactions.apply();
- }
- } else {
- pendingTransactions = null;
- }
- // Post at front of queue so the buffer can be processed immediately and allow RT
- // to continue processing new buffers. If RT tries to process buffers before the sync
- // buffer is applied, the new buffers will not get acquired and could result in a
- // deadlock. UI thread would wait on RT, but RT would be blocked waiting for a free
- // buffer.
- mHandler.postAtFrontOfQueue(() -> {
- if (!didProduceBuffer && useBlastSync) {
- mSurfaceChangedTransaction.merge(pendingTransactions);
- if (blastSyncConsumer != null) {
- blastSyncConsumer.accept(mSurfaceChangedTransaction);
- }
- }
-
- // This is to ensure pendingDrawFinished is only called exactly one time per draw
- // attempt when reportNextDraw is true. Since, we sometimes create a sync
- // transaction callback, the callback will handle calling pendingDrawFinished.
- // However, there are cases where the transaction callback may not be called.
- // 1. If useBlastSync is false, then we know that a sync transaction callback was
- // not created so we won't invoke pendingDrawFinished there.
- // 2. If the draw didn't produce a frame, didProduceBuffer == false, then we know
- // the sync transaction callback will not be invoked even if one was set up.
- if (reportNextDraw && (!didProduceBuffer || !useBlastSync)) {
- pendingDrawFinished();
- }
- });
-
- };
- }
-
@Nullable
- private FrameDrawingCallback createFrameDrawingCallbackIfNeeded(boolean useBlastSync,
- boolean reportNextDraw) {
+ private void registerFrameDrawingCallbackForBlur() {
if (!isHardwareEnabled()) {
- return null;
+ return;
}
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
- if (!useBlastSync && !needsCallbackForBlur && !reportNextDraw && !mHasPendingTransactions) {
- return null;
- }
-
- final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
- mBLASTDrawConsumer = null;
-
- if (DEBUG_BLAST) {
- Log.d(mTag, "Creating frameDrawingCallback"
- + " nextDrawUseBlastSync=" + useBlastSync
- + " reportNextDraw=" + reportNextDraw
- + " hasBlurUpdates=" + hasBlurUpdates
- + " hasBlastSyncConsumer=" + (blastSyncConsumer != null)
- + " mHasPendingTransactions=" + mHasPendingTransactions);
+ if (!needsCallbackForBlur) {
+ return;
}
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
- needsCallbackForBlur ? mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;
- final boolean hasPendingTransactions = mHasPendingTransactions;
- mHasPendingTransactions = false;
-
+ mBlurRegionAggregator.getBlurRegionsCopyForRT();
// The callback will run on the render thread.
- return new FrameDrawingCallback() {
- @Override
- public void onFrameDraw(long frame) {
- }
+ registerRtFrameCallback((frame) -> mBlurRegionAggregator
+ .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates));
+ }
+ private void registerCallbackForPendingTransactions() {
+ registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
- if (DEBUG_BLAST) {
- Log.d(mTag,
- "Received frameDrawingCallback syncResult=" + syncResult + " frameNum="
- + frame + ".");
- }
-
- mRtLastAttemptedDrawFrameNum = frame;
-
- if (needsCallbackForBlur) {
- mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame,
- blurRegionsForFrame, hasBlurUpdates);
- }
-
- if (mBlastBufferQueue == null) {
- return null;
- }
-
- if (!useBlastSync && !reportNextDraw && !hasPendingTransactions) {
- return null;
- }
-
- // If the syncResults are SYNC_LOST_SURFACE_REWARD_IF_FOUND or
- // SYNC_CONTEXT_IS_STOPPED it means nothing will draw. There's no need to set up
- // any blast sync or commit callback, and the code should directly call
- // pendingDrawFinished.
if ((syncResult
& (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
- if (reportNextDraw) {
- mHandler.postAtFrontOfQueue(() -> pendingDrawFinished());
- }
+ mBlastBufferQueue.applyPendingTransactions(frame);
return null;
}
- if (DEBUG_BLAST) {
- Log.d(mTag, "Setting up sync and frameCommitCallback");
- }
-
- if (useBlastSync) {
- // Frame callbacks will always occur after submitting draw requests and before
- // the draw actually occurs. This will ensure that we set the next transaction
- // for the frame that's about to get drawn and not on a previous frame.
- mBlastBufferQueue.syncNextTransaction(
- t -> {
- mHandler.postAtFrontOfQueue(() -> {
- mSurfaceChangedTransaction.merge(t);
- if (blastSyncConsumer != null) {
- blastSyncConsumer.accept(mSurfaceChangedTransaction);
- }
+ return didProduceBuffer -> {
+ if (!didProduceBuffer) {
+ mBlastBufferQueue.applyPendingTransactions(frame);
+ }
+ };
- if (reportNextDraw) {
- pendingDrawFinished();
- }
- });
- });
- }
+ }
- return createFrameCommitCallbackForSync(useBlastSync, reportNextDraw,
- blastSyncConsumer);
+ @Override
+ public void onFrameDraw(long frame) {
}
- };
+ });
}
- private void performDraw(boolean useBlastSync) {
+ private void performDraw() {
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
return;
} else if (mView == null) {
return;
}
- final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw || useBlastSync;
+ final boolean fullRedrawNeeded = mFullRedrawNeeded || mSyncBufferCallback != null;
mFullRedrawNeeded = false;
mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
- FrameDrawingCallback frameDrawingCallback = createFrameDrawingCallbackIfNeeded(useBlastSync,
- mReportNextDraw);
- if (frameDrawingCallback != null) {
- mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frameDrawingCallback);
- }
+ registerFrameDrawingCallbackForBlur();
addFrameCommitCallbackIfNeeded();
- boolean usingAsyncReport = isHardwareEnabled() && (useBlastSync || mReportNextDraw);
+
+ boolean usingAsyncReport = isHardwareEnabled() && mSyncBufferCallback != null;
+ if (usingAsyncReport) {
+ registerCallbacksForSync(mSyncBuffer, mSyncBufferCallback);
+ } else if (mHasPendingTransactions) {
+ // These callbacks are only needed if there's no sync involved and there were calls to
+ // applyTransactionOnDraw. These callbacks check if the draw failed for any reason and
+ // apply those transactions directly so they don't get stuck forever.
+ registerCallbackForPendingTransactions();
+ }
+ mHasPendingTransactions = false;
try {
boolean canUseAsync = draw(fullRedrawNeeded);
if (usingAsyncReport && !canUseAsync) {
mAttachInfo.mThreadedRenderer.setFrameCallback(null);
usingAsyncReport = false;
- mAttachInfo.mThreadedRenderer.unregisterRtFrameCallback(frameDrawingCallback);
}
} finally {
mIsDrawing = false;
@@ -4400,7 +4290,6 @@ public final class ViewRootImpl implements ViewParent,
}
if (mReportNextDraw) {
- mReportNextDraw = false;
// if we're using multi-thread renderer, wait for the window frame draws
if (mWindowDrawCountDown != null) {
@@ -4421,7 +4310,11 @@ public final class ViewRootImpl implements ViewParent,
}
if (mSurfaceHolder != null && mSurface.isValid()) {
- SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::postDrawFinished);
+ final SurfaceSyncer.SyncBufferCallback syncBufferCallback = mSyncBufferCallback;
+ SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() ->
+ mHandler.post(() -> syncBufferCallback.onBufferReady(null)));
+ mSyncBufferCallback = null;
+
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
@@ -4429,9 +4322,11 @@ public final class ViewRootImpl implements ViewParent,
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.fence();
}
- pendingDrawFinished();
}
}
+ if (mSyncBufferCallback != null && !usingAsyncReport) {
+ mSyncBufferCallback.onBufferReady(null);
+ }
if (mPerformContentCapture) {
performContentCaptureInitialReport();
}
@@ -5440,7 +5335,6 @@ public final class ViewRootImpl implements ViewParent,
private static final int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
private static final int MSG_UPDATE_POINTER_ICON = 27;
private static final int MSG_POINTER_CAPTURE_CHANGED = 28;
- private static final int MSG_DRAW_FINISHED = 29;
private static final int MSG_INSETS_CHANGED = 30;
private static final int MSG_INSETS_CONTROL_CHANGED = 31;
private static final int MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED = 32;
@@ -5503,8 +5397,6 @@ 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";
case MSG_INSETS_CHANGED:
return "MSG_INSETS_CHANGED";
case MSG_INSETS_CONTROL_CHANGED:
@@ -5735,9 +5627,6 @@ public final class ViewRootImpl implements ViewParent,
final boolean hasCapture = msg.arg1 != 0;
handlePointerCaptureChanged(hasCapture);
} break;
- case MSG_DRAW_FINISHED: {
- pendingDrawFinished();
- } break;
case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: {
systemGestureExclusionChanged();
} break;
@@ -9942,8 +9831,8 @@ public final class ViewRootImpl implements ViewParent,
}
private void reportNextDraw() {
- if (mReportNextDraw == false) {
- drawPending();
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "reportNextDraw " + Debug.getCallers(5));
}
mReportNextDraw = true;
}
@@ -9954,9 +9843,14 @@ public final class ViewRootImpl implements ViewParent,
* This method is only supposed to be used to speed up the interaction from SystemUI and window
* manager when waiting for the first frame to be drawn when turning on the screen. DO NOT USE
* unless you fully understand this interaction.
+ *
+ * @param syncBuffer If true, the transaction that contains the buffer from the draw should be
+ * sent to system to be synced. If false, VRI will not try to sync the buffer,
+ * but only report back that a buffer was drawn.
* @hide
*/
- public void setReportNextDraw() {
+ public void setReportNextDraw(boolean syncBuffer) {
+ mSyncBuffer = syncBuffer;
reportNextDraw();
invalidate();
}
@@ -10982,14 +10876,15 @@ public final class ViewRootImpl implements ViewParent,
return mWindowSession;
}
- private void registerCallbacksForSync(
+ private void registerCallbacksForSync(boolean syncBuffer,
final SurfaceSyncer.SyncBufferCallback syncBufferCallback) {
if (!isHardwareEnabled()) {
- // TODO: correctly handle when hardware disabled
- syncBufferCallback.onBufferReady(null);
return;
}
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "registerCallbacksForSync syncBuffer=" + syncBuffer);
+ }
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public void onFrameDraw(long frame) {
@@ -11018,7 +10913,9 @@ public final class ViewRootImpl implements ViewParent,
Log.d(mTag, "Setting up sync and frameCommitCallback");
}
- mBlastBufferQueue.syncNextTransaction(t -> syncBufferCallback.onBufferReady(t));
+ if (syncBuffer) {
+ mBlastBufferQueue.syncNextTransaction(syncBufferCallback::onBufferReady);
+ }
return didProduceBuffer -> {
if (DEBUG_BLAST) {
@@ -11032,18 +10929,40 @@ public final class ViewRootImpl implements ViewParent,
// were only set for the current draw attempt.
if (!didProduceBuffer) {
mBlastBufferQueue.syncNextTransaction(null);
+
// Gather the transactions that were sent to mergeWithNextTransaction
// since the frame didn't draw on this vsync. It's possible the frame will
// draw later, but it's better to not be sync than to block on a frame that
// may never come.
syncBufferCallback.onBufferReady(
mBlastBufferQueue.gatherPendingTransactions(frame));
+ return;
+ }
+
+ // If we didn't request to sync a buffer, then we won't get the
+ // syncNextTransaction callback. Instead, just report back to the Syncer so it
+ // knows that this sync request is complete.
+ if (!syncBuffer) {
+ syncBufferCallback.onBufferReady(null);
}
};
}
});
}
- public final SurfaceSyncer.SyncTarget mSyncTarget =
- syncBufferCallback -> registerCallbacksForSync(syncBufferCallback);
+ public final SurfaceSyncer.SyncTarget mSyncTarget = this::readyToSync;
+
+ private void readyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) {
+ if (mSyncBufferCallback != null) {
+ Log.d(mTag, "Already set sync for the next draw.");
+ mSyncBufferCallback.onBufferReady(null);
+ }
+ if (DEBUG_BLAST) {
+ Log.d(mTag, "Setting syncFrameCallback");
+ }
+ mSyncBufferCallback = syncBufferCallback;
+ if (!mIsInTraversal && !mTraversalScheduled) {
+ scheduleTraversals();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d36bb72e4d3b..758609a541e2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2373,7 +2373,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
// the next draw from here, so we don't have to wait for window manager to signal
// this to our ViewRootImpl.
- mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
+ mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw(
+ false /* syncBuffer */);
mScreenOnCoordinator.setWakeAndUnlocking(false);
}