Loading core/java/android/view/ViewRootImpl.java +46 −100 Original line number Diff line number Diff line Loading @@ -698,34 +698,33 @@ public final class ViewRootImpl implements ViewParent, int localChanges; } // If set, ViewRootImpl will request a callback from HWRender when it's ready to render the next // frame. This will allow VRI to call BLASTBufferQueue::setNextTransaction with // mRtBLASTSyncTransaction, so the next frame submitted will be added to the // mRtBLASTSyncTransaction instead of getting applied. private boolean mNextDrawUseBLASTSyncTransaction; // This is used to signal if the mRtBLASTSyncTransaction should be applied/merged. When true, // it indicates mRtBLASTSyncTransaction was sent to BLASTBufferQueue::setNextTransaction. // Therefore, in onFrameComplete, if mRtNextFrameReportConsumeWithBlast is true, that means // mRtBLASTSyncTransaction now contains the next buffer frame to be applied. private boolean mRtNextFrameReportedConsumeWithBlast; // Be very careful with the threading here. This is used from a thread pool generated by the // render thread. Therefore, it needs to be locked when updating from the thread pool since // multiple threads can be accessing it. It does not need to be locked when applied or merged // since that can only happen from the frame complete callback after the other callbacks have // been invoked. /** * This is only used when the UI thread is paused due to {@link #mNextDrawUseBlastSync} being * set. Specifically, it's only used when calling * {@link BLASTBufferQueue#setNextTransaction(Transaction)} and then merged with * {@link #mSurfaceChangedTransaction}. It doesn't need to be thread safe since it's only * accessed when the UI thread is paused. */ private final SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction(); // Keeps track of whether the WM requested us to use BLAST Sync when calling relayout. // We use this to make sure we don't send the WM transactions from an internal BLAST sync // (e.g. SurfaceView) private boolean mSendNextFrameToWm = false; /** * Keeps track of whether the WM requested to use BLAST Sync when calling relayout. When set, * we pause the UI thread to ensure we don't get overlapping requests. We then send a * transaction to {@link BLASTBufferQueue#setNextTransaction(Transaction)}, which is then sent * back to WM to synchronize. * * This flag is set to false only after the synchronized transaction that contains the buffer * has been sent to SurfaceFlinger. */ private boolean mNextDrawUseBlastSync = false; // Keeps track of whether a traverse was triggered while the UI thread was paused. This can // occur when the client is waiting on another process to submit the transaction that contains // the buffer. The UI thread needs to wait on the callback before it can submit another buffer. /** * Keeps track of whether a traverse was triggered while the UI thread was paused. This can * occur when the client is waiting on another process to submit the transaction that * contains the buffer. The UI thread needs to wait on the callback before it can submit * another buffer. */ private boolean mRequestedTraverseWhilePaused = false; private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks; Loading Loading @@ -1533,7 +1532,7 @@ public final class ViewRootImpl implements ViewParent, mForceNextWindowRelayout = forceNextWindowRelayout; mPendingAlwaysConsumeSystemBars = args.argi2 != 0; if (msg == MSG_RESIZED_REPORT && !mSendNextFrameToWm) { if (msg == MSG_RESIZED_REPORT && !mNextDrawUseBlastSync) { reportNextDraw(); } Loading Loading @@ -2424,7 +2423,7 @@ public final class ViewRootImpl implements ViewParent, // // When the callback is invoked, it will trigger a traversal request if // mRequestedTraverseWhilePaused is set so there's no need to attempt a retry here. if (mSendNextFrameToWm) { if (mNextDrawUseBlastSync) { if (DEBUG_BLAST) { Log.w(mTag, "Can't perform draw while waiting for a transaction complete"); } Loading Loading @@ -3176,8 +3175,7 @@ public final class ViewRootImpl implements ViewParent, Log.d(mTag, "Relayout called with blastSync"); } reportNextDraw(); setUseBLASTSyncTransaction(); mSendNextFrameToWm = true; mNextDrawUseBlastSync = true; } boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible; Loading Loading @@ -3871,14 +3869,16 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_BLAST) { Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr); } // Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by // the render thread and mSurfaceChangedTransaction can only be accessed by the UI // thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged // with mSurfaceChangedTransaction without synchronization issues. final Transaction t = new Transaction(); finishBLASTSyncOnRT(!mSendNextFrameToWm, t); handler.postAtFrontOfQueue(() -> { mSurfaceChangedTransaction.merge(t); if (mNextDrawUseBlastSync) { // We don't need to synchronize mRtBLASTSyncTransaction here since we're // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync // is only true when the UI thread is paused. Therefore, no one should be // modifying this object until the next vsync. mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction); } if (reportNextDraw) { // TODO: Use the frame number pendingDrawFinished(); Loading @@ -3900,12 +3900,12 @@ public final class ViewRootImpl implements ViewParent, ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction || mReportNextDraw mNextDrawUseBlastSync || mReportNextDraw || (commitCallbacks != null && commitCallbacks.size() > 0); if (needFrameCompleteCallback) { if (DEBUG_BLAST) { Log.d(mTag, "Creating frameCompleteCallback" + " mNextDrawUseBLASTSyncTransaction=" + mNextDrawUseBLASTSyncTransaction + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync + " mReportNextDraw=" + mReportNextDraw + " commitCallbacks size=" + (commitCallbacks == null ? 0 : commitCallbacks.size())); Loading @@ -3919,17 +3919,14 @@ public final class ViewRootImpl implements ViewParent, } private void addFrameCallbackIfNeeded() { boolean nextDrawUseBlastSync = mNextDrawUseBLASTSyncTransaction; boolean nextDrawUseBlastSync = mNextDrawUseBlastSync; boolean hasBlur = mBlurRegionAggregator.hasRegions(); boolean reportNextDraw = mReportNextDraw; boolean addTransactionComplete = mSendNextFrameToWm; if (!nextDrawUseBlastSync && !reportNextDraw && !hasBlur) { return; } mNextDrawUseBLASTSyncTransaction = false; if (DEBUG_BLAST) { Log.d(mTag, "Creating frameDrawingCallback" + " nextDrawUseBlastSync=" + nextDrawUseBlastSync Loading @@ -3941,7 +3938,7 @@ public final class ViewRootImpl implements ViewParent, HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> { if (DEBUG_BLAST) { Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "." + " Creating transactionCompleteCallback=" + addTransactionComplete); + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync); } if (hasBlur) { Loading @@ -3956,29 +3953,17 @@ public final class ViewRootImpl implements ViewParent, // 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. // // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the // next frame completed should be reported with the blast sync transaction. mRtNextFrameReportedConsumeWithBlast = true; // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } else if (reportNextDraw) { // If we need to report next draw, wait for adapter to flush its shadow queue // by processing previously queued buffers so that we can submit the // transaction a timely manner. mBlastBufferQueue.flushShadowQueue(); } if (addTransactionComplete) { mBlastBufferQueue.setTransactionCompleteCallback(frame, frameNumber -> { if (DEBUG_BLAST) { Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame); } mHandler.postAtFrontOfQueue(() -> { mSendNextFrameToWm = false; mNextDrawUseBlastSync = false; if (DEBUG_BLAST) { Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused + " due to a previous skipped traversal."); Loading @@ -3989,6 +3974,11 @@ public final class ViewRootImpl implements ViewParent, } }); }); } else if (reportNextDraw) { // If we need to report next draw, wait for adapter to flush its shadow queue // by processing previously queued buffers so that we can submit the // transaction a timely manner. mBlastBufferQueue.flushShadowQueue(); } }; registerRtFrameCallback(frameDrawingCallback); Loading @@ -4002,7 +3992,7 @@ public final class ViewRootImpl implements ViewParent, } final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw || mNextDrawUseBLASTSyncTransaction; mFullRedrawNeeded || mReportNextDraw || mNextDrawUseBlastSync; mFullRedrawNeeded = false; mIsDrawing = true; Loading Loading @@ -10025,42 +10015,6 @@ public final class ViewRootImpl implements ViewParent, } } void setUseBLASTSyncTransaction() { mNextDrawUseBLASTSyncTransaction = true; } /** * This should only be called from the render thread. */ private void finishBLASTSyncOnRT(boolean apply, Transaction t) { // This is safe to modify on the render thread since the only other place it's modified // is on the UI thread when the render thread is paused. if (mRtNextFrameReportedConsumeWithBlast) { mRtNextFrameReportedConsumeWithBlast = false; // We don't need to synchronize mRtBLASTSyncTransaction here we're guaranteed that this // is called after all onFrameDraw and after callbacks to PositionUpdateListener. // Therefore, no one should be modifying this object until the next vsync. if (apply) { mRtBLASTSyncTransaction.apply(); } else { t.merge(mRtBLASTSyncTransaction); } // There's potential for the frame callback to get called even if nothing was drawn. // When that occurs, we remove the transaction sent to BBQ since the draw we were // waiting on will not happen. We can apply the transaction here but it will not contain // a buffer since nothing new was drawn. // // This is mainly for the case when the SurfaceView has changed and wants to synchronize // with the main window. If the main window doesn't need to draw anything, we can just // apply the transaction without the new buffer from the main window. if (mBlastBufferQueue != null) { mBlastBufferQueue.setNextTransaction(null); } } } /** * Sends a list of blur regions to SurfaceFlinger, tagged with a frame. * Loading Loading @@ -10091,14 +10045,6 @@ public final class ViewRootImpl implements ViewParent, return mBlurRegionAggregator.createBackgroundBlurDrawable(mContext); } SurfaceControl.Transaction getBLASTSyncTransaction() { return mRtBLASTSyncTransaction; } Object getBlastTransactionLock() { return mRtBLASTSyncTransaction; } @Override public void onDescendantUnbufferedRequested() { mUnbufferedInputSource = mView.mUnbufferedInputSource; Loading Loading
core/java/android/view/ViewRootImpl.java +46 −100 Original line number Diff line number Diff line Loading @@ -698,34 +698,33 @@ public final class ViewRootImpl implements ViewParent, int localChanges; } // If set, ViewRootImpl will request a callback from HWRender when it's ready to render the next // frame. This will allow VRI to call BLASTBufferQueue::setNextTransaction with // mRtBLASTSyncTransaction, so the next frame submitted will be added to the // mRtBLASTSyncTransaction instead of getting applied. private boolean mNextDrawUseBLASTSyncTransaction; // This is used to signal if the mRtBLASTSyncTransaction should be applied/merged. When true, // it indicates mRtBLASTSyncTransaction was sent to BLASTBufferQueue::setNextTransaction. // Therefore, in onFrameComplete, if mRtNextFrameReportConsumeWithBlast is true, that means // mRtBLASTSyncTransaction now contains the next buffer frame to be applied. private boolean mRtNextFrameReportedConsumeWithBlast; // Be very careful with the threading here. This is used from a thread pool generated by the // render thread. Therefore, it needs to be locked when updating from the thread pool since // multiple threads can be accessing it. It does not need to be locked when applied or merged // since that can only happen from the frame complete callback after the other callbacks have // been invoked. /** * This is only used when the UI thread is paused due to {@link #mNextDrawUseBlastSync} being * set. Specifically, it's only used when calling * {@link BLASTBufferQueue#setNextTransaction(Transaction)} and then merged with * {@link #mSurfaceChangedTransaction}. It doesn't need to be thread safe since it's only * accessed when the UI thread is paused. */ private final SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction(); // Keeps track of whether the WM requested us to use BLAST Sync when calling relayout. // We use this to make sure we don't send the WM transactions from an internal BLAST sync // (e.g. SurfaceView) private boolean mSendNextFrameToWm = false; /** * Keeps track of whether the WM requested to use BLAST Sync when calling relayout. When set, * we pause the UI thread to ensure we don't get overlapping requests. We then send a * transaction to {@link BLASTBufferQueue#setNextTransaction(Transaction)}, which is then sent * back to WM to synchronize. * * This flag is set to false only after the synchronized transaction that contains the buffer * has been sent to SurfaceFlinger. */ private boolean mNextDrawUseBlastSync = false; // Keeps track of whether a traverse was triggered while the UI thread was paused. This can // occur when the client is waiting on another process to submit the transaction that contains // the buffer. The UI thread needs to wait on the callback before it can submit another buffer. /** * Keeps track of whether a traverse was triggered while the UI thread was paused. This can * occur when the client is waiting on another process to submit the transaction that * contains the buffer. The UI thread needs to wait on the callback before it can submit * another buffer. */ private boolean mRequestedTraverseWhilePaused = false; private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks; Loading Loading @@ -1533,7 +1532,7 @@ public final class ViewRootImpl implements ViewParent, mForceNextWindowRelayout = forceNextWindowRelayout; mPendingAlwaysConsumeSystemBars = args.argi2 != 0; if (msg == MSG_RESIZED_REPORT && !mSendNextFrameToWm) { if (msg == MSG_RESIZED_REPORT && !mNextDrawUseBlastSync) { reportNextDraw(); } Loading Loading @@ -2424,7 +2423,7 @@ public final class ViewRootImpl implements ViewParent, // // When the callback is invoked, it will trigger a traversal request if // mRequestedTraverseWhilePaused is set so there's no need to attempt a retry here. if (mSendNextFrameToWm) { if (mNextDrawUseBlastSync) { if (DEBUG_BLAST) { Log.w(mTag, "Can't perform draw while waiting for a transaction complete"); } Loading Loading @@ -3176,8 +3175,7 @@ public final class ViewRootImpl implements ViewParent, Log.d(mTag, "Relayout called with blastSync"); } reportNextDraw(); setUseBLASTSyncTransaction(); mSendNextFrameToWm = true; mNextDrawUseBlastSync = true; } boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible; Loading Loading @@ -3871,14 +3869,16 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_BLAST) { Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr); } // Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by // the render thread and mSurfaceChangedTransaction can only be accessed by the UI // thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged // with mSurfaceChangedTransaction without synchronization issues. final Transaction t = new Transaction(); finishBLASTSyncOnRT(!mSendNextFrameToWm, t); handler.postAtFrontOfQueue(() -> { mSurfaceChangedTransaction.merge(t); if (mNextDrawUseBlastSync) { // We don't need to synchronize mRtBLASTSyncTransaction here since we're // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync // is only true when the UI thread is paused. Therefore, no one should be // modifying this object until the next vsync. mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction); } if (reportNextDraw) { // TODO: Use the frame number pendingDrawFinished(); Loading @@ -3900,12 +3900,12 @@ public final class ViewRootImpl implements ViewParent, ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction || mReportNextDraw mNextDrawUseBlastSync || mReportNextDraw || (commitCallbacks != null && commitCallbacks.size() > 0); if (needFrameCompleteCallback) { if (DEBUG_BLAST) { Log.d(mTag, "Creating frameCompleteCallback" + " mNextDrawUseBLASTSyncTransaction=" + mNextDrawUseBLASTSyncTransaction + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync + " mReportNextDraw=" + mReportNextDraw + " commitCallbacks size=" + (commitCallbacks == null ? 0 : commitCallbacks.size())); Loading @@ -3919,17 +3919,14 @@ public final class ViewRootImpl implements ViewParent, } private void addFrameCallbackIfNeeded() { boolean nextDrawUseBlastSync = mNextDrawUseBLASTSyncTransaction; boolean nextDrawUseBlastSync = mNextDrawUseBlastSync; boolean hasBlur = mBlurRegionAggregator.hasRegions(); boolean reportNextDraw = mReportNextDraw; boolean addTransactionComplete = mSendNextFrameToWm; if (!nextDrawUseBlastSync && !reportNextDraw && !hasBlur) { return; } mNextDrawUseBLASTSyncTransaction = false; if (DEBUG_BLAST) { Log.d(mTag, "Creating frameDrawingCallback" + " nextDrawUseBlastSync=" + nextDrawUseBlastSync Loading @@ -3941,7 +3938,7 @@ public final class ViewRootImpl implements ViewParent, HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> { if (DEBUG_BLAST) { Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "." + " Creating transactionCompleteCallback=" + addTransactionComplete); + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync); } if (hasBlur) { Loading @@ -3956,29 +3953,17 @@ public final class ViewRootImpl implements ViewParent, // 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. // // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the // next frame completed should be reported with the blast sync transaction. mRtNextFrameReportedConsumeWithBlast = true; // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } else if (reportNextDraw) { // If we need to report next draw, wait for adapter to flush its shadow queue // by processing previously queued buffers so that we can submit the // transaction a timely manner. mBlastBufferQueue.flushShadowQueue(); } if (addTransactionComplete) { mBlastBufferQueue.setTransactionCompleteCallback(frame, frameNumber -> { if (DEBUG_BLAST) { Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame); } mHandler.postAtFrontOfQueue(() -> { mSendNextFrameToWm = false; mNextDrawUseBlastSync = false; if (DEBUG_BLAST) { Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused + " due to a previous skipped traversal."); Loading @@ -3989,6 +3974,11 @@ public final class ViewRootImpl implements ViewParent, } }); }); } else if (reportNextDraw) { // If we need to report next draw, wait for adapter to flush its shadow queue // by processing previously queued buffers so that we can submit the // transaction a timely manner. mBlastBufferQueue.flushShadowQueue(); } }; registerRtFrameCallback(frameDrawingCallback); Loading @@ -4002,7 +3992,7 @@ public final class ViewRootImpl implements ViewParent, } final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw || mNextDrawUseBLASTSyncTransaction; mFullRedrawNeeded || mReportNextDraw || mNextDrawUseBlastSync; mFullRedrawNeeded = false; mIsDrawing = true; Loading Loading @@ -10025,42 +10015,6 @@ public final class ViewRootImpl implements ViewParent, } } void setUseBLASTSyncTransaction() { mNextDrawUseBLASTSyncTransaction = true; } /** * This should only be called from the render thread. */ private void finishBLASTSyncOnRT(boolean apply, Transaction t) { // This is safe to modify on the render thread since the only other place it's modified // is on the UI thread when the render thread is paused. if (mRtNextFrameReportedConsumeWithBlast) { mRtNextFrameReportedConsumeWithBlast = false; // We don't need to synchronize mRtBLASTSyncTransaction here we're guaranteed that this // is called after all onFrameDraw and after callbacks to PositionUpdateListener. // Therefore, no one should be modifying this object until the next vsync. if (apply) { mRtBLASTSyncTransaction.apply(); } else { t.merge(mRtBLASTSyncTransaction); } // There's potential for the frame callback to get called even if nothing was drawn. // When that occurs, we remove the transaction sent to BBQ since the draw we were // waiting on will not happen. We can apply the transaction here but it will not contain // a buffer since nothing new was drawn. // // This is mainly for the case when the SurfaceView has changed and wants to synchronize // with the main window. If the main window doesn't need to draw anything, we can just // apply the transaction without the new buffer from the main window. if (mBlastBufferQueue != null) { mBlastBufferQueue.setNextTransaction(null); } } } /** * Sends a list of blur regions to SurfaceFlinger, tagged with a frame. * Loading Loading @@ -10091,14 +10045,6 @@ public final class ViewRootImpl implements ViewParent, return mBlurRegionAggregator.createBackgroundBlurDrawable(mContext); } SurfaceControl.Transaction getBLASTSyncTransaction() { return mRtBLASTSyncTransaction; } Object getBlastTransactionLock() { return mRtBLASTSyncTransaction; } @Override public void onDescendantUnbufferedRequested() { mUnbufferedInputSource = mView.mUnbufferedInputSource; Loading