summaryrefslogtreecommitdiff
path: root/core/java/android/view/ViewRootImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/view/ViewRootImpl.java')
-rw-r--r--core/java/android/view/ViewRootImpl.java197
1 files changed, 119 insertions, 78 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index af496dcea8e3..1fdbf0e204da 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED;
+import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND;
import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -1392,11 +1394,20 @@ public final class ViewRootImpl implements ViewParent,
*/
public void registerRtFrameCallback(@NonNull FrameDrawingCallback callback) {
if (mAttachInfo.mThreadedRenderer != null) {
- mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frame -> {
- try {
- callback.onFrameDraw(frame);
- } catch (Exception e) {
- Log.e(TAG, "Exception while executing onFrameDraw", e);
+ mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
+ @Override
+ public void onFrameDraw(long frame) {
+ }
+
+ @Override
+ public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult,
+ long frame) {
+ try {
+ return callback.onFrameDraw(syncResult, frame);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while executing onFrameDraw", e);
+ }
+ return null;
}
});
}
@@ -4020,36 +4031,49 @@ public final class ViewRootImpl implements ViewParent,
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
}
- private boolean addFrameCompleteCallbackIfNeeded(boolean useBlastSync,
- boolean reportNextDraw) {
+ private void addFrameCommitCallbackIfNeeded() {
if (!isHardwareEnabled()) {
- return false;
+ return;
}
- if (!useBlastSync && !reportNextDraw) {
- return false;
+ ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
+ .captureFrameCommitCallbacks();
+ final boolean needFrameCommitCallback =
+ (commitCallbacks != null && commitCallbacks.size() > 0);
+ if (!needFrameCommitCallback) {
+ return;
}
- if (DEBUG_BLAST) {
- Log.d(mTag, "Creating frameCompleteCallback");
+ if (DEBUG_DRAW) {
+ Log.d(mTag, "Creating frameCommitCallback"
+ + " commitCallbacks size=" + commitCallbacks.size());
}
+ mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> {
+ if (DEBUG_DRAW) {
+ Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer);
+ }
- final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
- mBLASTDrawConsumer = null;
+ mHandler.postAtFrontOfQueue(() -> {
+ for (int i = 0; i < commitCallbacks.size(); i++) {
+ commitCallbacks.get(i).run();
+ }
+ });
+ });
+ }
- mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> {
- long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum();
+ private HardwareRenderer.FrameCommitCallback createFrameCommitCallbackForSync(
+ boolean useBlastSync, boolean reportNextDraw, Consumer<Transaction> blastSyncConsumer) {
+ return didProduceBuffer -> {
if (DEBUG_BLAST) {
- Log.d(mTag, "Received frameCompleteCallback "
- + " lastAcquiredFrameNum=" + frameNr
- + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum);
+ Log.d(mTag, "Received frameCommittedCallback "
+ + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum
+ + " didProduceBuffer=" + didProduceBuffer);
}
- boolean frameWasNotDrawn = frameNr != mRtLastAttemptedDrawFrameNum;
// 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.
- if (frameWasNotDrawn) {
+ if (!didProduceBuffer) {
mBlastBufferQueue.setSyncTransaction(null);
// Apply 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
@@ -4059,6 +4083,11 @@ public final class ViewRootImpl implements ViewParent,
Transaction tmpTransaction = new Transaction();
tmpTransaction.merge(mRtBLASTSyncTransaction);
+ // 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 (useBlastSync) {
mSurfaceChangedTransaction.merge(tmpTransaction);
@@ -4071,85 +4100,92 @@ public final class ViewRootImpl implements ViewParent,
pendingDrawFinished();
}
});
- });
- return true;
+ };
}
- private void addFrameCommitCallbackIfNeeded() {
+ @Nullable
+ private FrameDrawingCallback createFrameDrawingCallbackIfNeeded(boolean useBlastSync,
+ boolean reportNextDraw) {
if (!isHardwareEnabled()) {
- return;
- }
-
- ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
- .captureFrameCommitCallbacks();
- final boolean needFrameCommitCallback =
- (commitCallbacks != null && commitCallbacks.size() > 0);
- if (!needFrameCommitCallback) {
- return;
- }
-
- if (DEBUG_DRAW) {
- Log.d(mTag, "Creating frameCommitCallback"
- + " commitCallbacks size=" + commitCallbacks.size());
+ return null;
}
- mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> {
- if (DEBUG_DRAW) {
- Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer);
- }
-
- mHandler.postAtFrontOfQueue(() -> {
- for (int i = 0; i < commitCallbacks.size(); i++) {
- commitCallbacks.get(i).run();
- }
- });
- });
- }
-
- private void addFrameCallbackIfNeeded(boolean useBlastSync) {
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
- if (!useBlastSync && !needsCallbackForBlur) {
- return;
+ if (!useBlastSync && !needsCallbackForBlur && !reportNextDraw) {
+ return null;
}
+ final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
+ mBLASTDrawConsumer = null;
+
if (DEBUG_BLAST) {
Log.d(mTag, "Creating frameDrawingCallback"
+ " nextDrawUseBlastSync=" + useBlastSync
- + " hasBlurUpdates=" + hasBlurUpdates);
+ + " reportNextDraw=" + reportNextDraw
+ + " hasBlurUpdates=" + hasBlurUpdates
+ + " hasBlastSyncConsumer=" + (blastSyncConsumer != null));
}
+
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
needsCallbackForBlur ? mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;
// The callback will run on the render thread.
- HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> {
- if (DEBUG_BLAST) {
- Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "."
- + " Creating transactionCompleteCallback=" + useBlastSync);
+ return new FrameDrawingCallback() {
+ @Override
+ public void onFrameDraw(long frame) {
}
- mRtLastAttemptedDrawFrameNum = frame;
+ @Override
+ public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
+ if (DEBUG_BLAST) {
+ Log.d(mTag,
+ "Received frameDrawingCallback syncResult=" + syncResult + " frameNum="
+ + frame + ".");
+ }
- if (needsCallbackForBlur) {
- mBlurRegionAggregator
- .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
- }
+ mRtLastAttemptedDrawFrameNum = frame;
- if (mBlastBufferQueue == null) {
- return;
- }
+ if (needsCallbackForBlur) {
+ mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame,
+ blurRegionsForFrame, hasBlurUpdates);
+ }
- 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 that.
+ if (mBlastBufferQueue == null) {
+ return null;
+ }
- // We don't need to synchronize mRtBLASTSyncTransaction here since it's not
- // being modified and only sent to BlastBufferQueue.
- mBlastBufferQueue.setSyncTransaction(mRtBLASTSyncTransaction);
+ if (!useBlastSync && !reportNextDraw) {
+ 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());
+ }
+ 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.setSyncTransaction(mRtBLASTSyncTransaction);
+ }
+
+ return createFrameCommitCallbackForSync(useBlastSync, reportNextDraw,
+ blastSyncConsumer);
}
};
- registerRtFrameCallback(frameDrawingCallback);
}
private void performDraw(boolean useBlastSync) {
@@ -4165,15 +4201,20 @@ public final class ViewRootImpl implements ViewParent,
mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
- addFrameCallbackIfNeeded(useBlastSync);
+ FrameDrawingCallback frameDrawingCallback = createFrameDrawingCallbackIfNeeded(useBlastSync,
+ mReportNextDraw);
+ if (frameDrawingCallback != null) {
+ mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frameDrawingCallback);
+ }
addFrameCommitCallbackIfNeeded();
- boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(useBlastSync, mReportNextDraw);
+ boolean usingAsyncReport = isHardwareEnabled() && (useBlastSync || mReportNextDraw);
try {
boolean canUseAsync = draw(fullRedrawNeeded);
if (usingAsyncReport && !canUseAsync) {
- mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
+ mAttachInfo.mThreadedRenderer.setFrameCallback(null);
usingAsyncReport = false;
+ mAttachInfo.mThreadedRenderer.unregisterRtFrameCallback(frameDrawingCallback);
}
} finally {
mIsDrawing = false;