Loading core/java/android/view/SurfaceView.java +57 −43 Original line number Diff line number Diff line Loading @@ -420,8 +420,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final boolean useBLAST = viewRoot.useBLAST(); viewRoot.registerRtFrameCallback(frame -> { try { final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() : new SurfaceControl.Transaction(); synchronized (mSurfaceControlLock) { if (!parent.isValid()) { if (DEBUG) { Loading @@ -443,16 +441,22 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha RT: set alpha=" + alpha); } if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { viewRoot.getBLASTSyncTransaction() .setAlpha(mSurfaceControl, alpha); } } else { Transaction t = new SurfaceControl.Transaction(); t.setAlpha(mSurfaceControl, alpha); if (!useBLAST) { t.deferTransactionUntil(mSurfaceControl, viewRoot.getRenderSurfaceControl(), frame); t.apply(); } } // It's possible that mSurfaceControl is released in the UI thread before // the transaction completes. If that happens, an exception is thrown, which // must be caught immediately. t.apply(); } catch (Exception e) { Log.e(TAG, System.identityHashCode(this) + "updateSurfaceAlpha RT: Exception during surface transaction", e); Loading Loading @@ -793,23 +797,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final boolean useBLAST = viewRoot.useBLAST(); viewRoot.registerRtFrameCallback(frame -> { try { final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() : new SurfaceControl.Transaction(); synchronized (mSurfaceControlLock) { if (!parent.isValid() || mSurfaceControl == null) { return; } if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { updateRelativeZ(viewRoot.getBLASTSyncTransaction()); } } else { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); updateRelativeZ(t); if (!useBLAST) { t.deferTransactionUntil(mSurfaceControl, viewRoot.getRenderSurfaceControl(), frame); t.apply(); } } // It's possible that mSurfaceControl is released in the UI thread before // the transaction completes. If that happens, an exception is thrown, which // must be caught immediately. t.apply(); } catch (Exception e) { Log.e(TAG, System.identityHashCode(this) + "setZOrderOnTop RT: Exception during surface transaction", e); Loading Loading @@ -1252,7 +1259,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t, Rect position, long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); if (frameNumber > 0 && viewRoot != null && !viewRoot.isDrawingToBLASTTransaction()) { if (frameNumber > 0 && viewRoot != null && !viewRoot.useBLAST()) { t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(), frameNumber); } Loading @@ -1277,19 +1284,23 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall return mRTLastReportedPosition; } private void setParentSpaceRectangle(Rect position, long frameNumber) { private void setParentSpaceRectangle(Transaction t, Rect position, long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); final boolean useBLAST = viewRoot.isDrawingToBLASTTransaction(); final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() : mRtTransaction; applySurfaceTransforms(mSurfaceControl, t, position, frameNumber); applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber); } applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber); private void setParentSpaceRectangle(Rect position, long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); final boolean useBLAST = viewRoot.useBLAST(); if (!useBLAST) { t.apply(); if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { setParentSpaceRectangle(viewRoot.getBLASTSyncTransaction(), position, frameNumber); } } else { setParentSpaceRectangle(mRtTransaction, position, frameNumber); mRtTransaction.apply(); } } Loading Loading @@ -1337,10 +1348,20 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } private void releaseSurfaces(Transaction t) { if (mRtReleaseSurfaces) { mRtReleaseSurfaces = false; t.remove(mSurfaceControl); t.remove(mBackgroundControl); mSurfaceControl = null; mBackgroundControl = null; } } @Override public void positionLost(long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); boolean useBLAST = viewRoot != null && viewRoot.isDrawingToBLASTTransaction(); boolean useBLAST = viewRoot != null && viewRoot.useBLAST(); if (DEBUG) { Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d", System.identityHashCode(this), frameNumber)); Loading @@ -1351,38 +1372,31 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall return; } final SurfaceControl.Transaction t = useBLAST ? (viewRoot != null ? viewRoot.getBLASTSyncTransaction() : mRtTransaction) : mRtTransaction; /** * positionLost can be called while UI thread is un-paused so we * need to hold the lock here. */ synchronized (mSurfaceControlLock) { if (frameNumber > 0 && viewRoot != null && !useBLAST) { if (viewRoot.mSurface.isValid()) { if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { viewRoot.getBLASTSyncTransaction().hide(mSurfaceControl); releaseSurfaces(viewRoot.getBLASTSyncTransaction()); } } else { if (frameNumber > 0 && viewRoot != null && viewRoot.mSurface.isValid()) { mRtTransaction.deferTransactionUntil(mSurfaceControl, viewRoot.getRenderSurfaceControl(), frameNumber); } } t.hide(mSurfaceControl); if (mRtReleaseSurfaces) { mRtReleaseSurfaces = false; mRtTransaction.remove(mSurfaceControl); mRtTransaction.remove(mBackgroundControl); mSurfaceControl = null; mBackgroundControl = null; mRtTransaction.hide(mSurfaceControl); releaseSurfaces(mRtTransaction); // If we aren't using BLAST, we apply the transaction locally, otherwise we let // the ViewRoot apply it for us. // If the ViewRoot is null, we behave as if we aren't using BLAST so we need to // apply the transaction. mRtTransaction.apply(); } mRtHandlingPositionUpdates = false; } // If we aren't using BLAST, we apply the transaction locally, otherise we let the ViewRoot apply it for us. // If the ViewRoot is null, we behave as if we aren't using BLAST so we need to apply the transaction. if (!useBLAST || viewRoot == null) { mRtTransaction.apply(); } } }; Loading core/java/android/view/ViewRootImpl.java +44 −43 Original line number Diff line number Diff line Loading @@ -654,26 +654,25 @@ public final class ViewRootImpl implements ViewParent, int localChanges; } // If set, ViewRootImpl will call BLASTBufferQueue::setNextTransaction with // mRtBLASTSyncTransaction, prior to invoking draw. This provides a way // to redirect the buffers in to transactions. // 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; // Set when calling setNextTransaction, we can't just reuse mNextDrawUseBLASTSyncTransaction // because, imagine this scenario: // 1. First draw is using BLAST, mNextDrawUseBLAST = true // 2. We call perform draw and are waiting on the callback // 3. After the first perform draw but before the first callback and the // second perform draw, a second draw sets mNextDrawUseBLAST = true (it already was) // 4. At this point the callback fires and we set mNextDrawUseBLAST = false; // 5. We get to performDraw and fail to sync as we intended because mNextDrawUseBLAST // is now false. // This is why we use a two-step latch with the two booleans, one consumed from // performDraw and one consumed from finishBLASTSync() private boolean mNextReportConsumeBLAST; // Be very careful with the threading here. This is used from the render thread while // the UI thread is paused and then applied and cleared from the UI thread right after // draw returns. private SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction(); // 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. 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 Loading Loading @@ -3783,26 +3782,29 @@ public final class ViewRootImpl implements ViewParent, commitCallbacks.get(i).run(); } } });}); }); }); } } try { if (mNextDrawUseBLASTSyncTransaction) { // TODO(b/149747443) // We aren't prepared to handle overlapping use of mRtBLASTSyncTransaction // so if we are BLAST syncing we make sure the previous draw has // totally finished. if (mAttachInfo.mThreadedRenderer != null) { mAttachInfo.mThreadedRenderer.pause(); } mNextReportConsumeBLAST = true; mNextDrawUseBLASTSyncTransaction = false; // 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. registerRtFrameCallback(frame -> { mRtNextFrameReportedConsumeWithBlast = true; if (mBlastBufferQueue != null) { // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } }); mNextDrawUseBLASTSyncTransaction = false; } boolean canUseAsync = draw(fullRedrawNeeded); if (usingAsyncReport && !canUseAsync) { Loading Loading @@ -9757,9 +9759,12 @@ public final class ViewRootImpl implements ViewParent, private void finishBLASTSync(boolean apply) { mSendNextFrameToWm = false; if (mNextReportConsumeBLAST) { mNextReportConsumeBLAST = false; 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 { Loading @@ -9772,6 +9777,10 @@ public final class ViewRootImpl implements ViewParent, return mRtBLASTSyncTransaction; } Object getBlastTransactionLock() { return mRtBLASTSyncTransaction; } /** * @hide */ Loading Loading @@ -9799,12 +9808,4 @@ public final class ViewRootImpl implements ViewParent, boolean useBLAST() { return mUseBLASTAdapter && !mForceDisableBLAST; } /** * Returns true if we are about to or currently processing a draw directed * in to a BLAST transaction. */ boolean isDrawingToBLASTTransaction() { return mNextReportConsumeBLAST; } } Loading
core/java/android/view/SurfaceView.java +57 −43 Original line number Diff line number Diff line Loading @@ -420,8 +420,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final boolean useBLAST = viewRoot.useBLAST(); viewRoot.registerRtFrameCallback(frame -> { try { final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() : new SurfaceControl.Transaction(); synchronized (mSurfaceControlLock) { if (!parent.isValid()) { if (DEBUG) { Loading @@ -443,16 +441,22 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha RT: set alpha=" + alpha); } if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { viewRoot.getBLASTSyncTransaction() .setAlpha(mSurfaceControl, alpha); } } else { Transaction t = new SurfaceControl.Transaction(); t.setAlpha(mSurfaceControl, alpha); if (!useBLAST) { t.deferTransactionUntil(mSurfaceControl, viewRoot.getRenderSurfaceControl(), frame); t.apply(); } } // It's possible that mSurfaceControl is released in the UI thread before // the transaction completes. If that happens, an exception is thrown, which // must be caught immediately. t.apply(); } catch (Exception e) { Log.e(TAG, System.identityHashCode(this) + "updateSurfaceAlpha RT: Exception during surface transaction", e); Loading Loading @@ -793,23 +797,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final boolean useBLAST = viewRoot.useBLAST(); viewRoot.registerRtFrameCallback(frame -> { try { final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() : new SurfaceControl.Transaction(); synchronized (mSurfaceControlLock) { if (!parent.isValid() || mSurfaceControl == null) { return; } if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { updateRelativeZ(viewRoot.getBLASTSyncTransaction()); } } else { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); updateRelativeZ(t); if (!useBLAST) { t.deferTransactionUntil(mSurfaceControl, viewRoot.getRenderSurfaceControl(), frame); t.apply(); } } // It's possible that mSurfaceControl is released in the UI thread before // the transaction completes. If that happens, an exception is thrown, which // must be caught immediately. t.apply(); } catch (Exception e) { Log.e(TAG, System.identityHashCode(this) + "setZOrderOnTop RT: Exception during surface transaction", e); Loading Loading @@ -1252,7 +1259,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t, Rect position, long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); if (frameNumber > 0 && viewRoot != null && !viewRoot.isDrawingToBLASTTransaction()) { if (frameNumber > 0 && viewRoot != null && !viewRoot.useBLAST()) { t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(), frameNumber); } Loading @@ -1277,19 +1284,23 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall return mRTLastReportedPosition; } private void setParentSpaceRectangle(Rect position, long frameNumber) { private void setParentSpaceRectangle(Transaction t, Rect position, long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); final boolean useBLAST = viewRoot.isDrawingToBLASTTransaction(); final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() : mRtTransaction; applySurfaceTransforms(mSurfaceControl, t, position, frameNumber); applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber); } applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber); private void setParentSpaceRectangle(Rect position, long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); final boolean useBLAST = viewRoot.useBLAST(); if (!useBLAST) { t.apply(); if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { setParentSpaceRectangle(viewRoot.getBLASTSyncTransaction(), position, frameNumber); } } else { setParentSpaceRectangle(mRtTransaction, position, frameNumber); mRtTransaction.apply(); } } Loading Loading @@ -1337,10 +1348,20 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } private void releaseSurfaces(Transaction t) { if (mRtReleaseSurfaces) { mRtReleaseSurfaces = false; t.remove(mSurfaceControl); t.remove(mBackgroundControl); mSurfaceControl = null; mBackgroundControl = null; } } @Override public void positionLost(long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); boolean useBLAST = viewRoot != null && viewRoot.isDrawingToBLASTTransaction(); boolean useBLAST = viewRoot != null && viewRoot.useBLAST(); if (DEBUG) { Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d", System.identityHashCode(this), frameNumber)); Loading @@ -1351,38 +1372,31 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall return; } final SurfaceControl.Transaction t = useBLAST ? (viewRoot != null ? viewRoot.getBLASTSyncTransaction() : mRtTransaction) : mRtTransaction; /** * positionLost can be called while UI thread is un-paused so we * need to hold the lock here. */ synchronized (mSurfaceControlLock) { if (frameNumber > 0 && viewRoot != null && !useBLAST) { if (viewRoot.mSurface.isValid()) { if (useBLAST) { synchronized (viewRoot.getBlastTransactionLock()) { viewRoot.getBLASTSyncTransaction().hide(mSurfaceControl); releaseSurfaces(viewRoot.getBLASTSyncTransaction()); } } else { if (frameNumber > 0 && viewRoot != null && viewRoot.mSurface.isValid()) { mRtTransaction.deferTransactionUntil(mSurfaceControl, viewRoot.getRenderSurfaceControl(), frameNumber); } } t.hide(mSurfaceControl); if (mRtReleaseSurfaces) { mRtReleaseSurfaces = false; mRtTransaction.remove(mSurfaceControl); mRtTransaction.remove(mBackgroundControl); mSurfaceControl = null; mBackgroundControl = null; mRtTransaction.hide(mSurfaceControl); releaseSurfaces(mRtTransaction); // If we aren't using BLAST, we apply the transaction locally, otherwise we let // the ViewRoot apply it for us. // If the ViewRoot is null, we behave as if we aren't using BLAST so we need to // apply the transaction. mRtTransaction.apply(); } mRtHandlingPositionUpdates = false; } // If we aren't using BLAST, we apply the transaction locally, otherise we let the ViewRoot apply it for us. // If the ViewRoot is null, we behave as if we aren't using BLAST so we need to apply the transaction. if (!useBLAST || viewRoot == null) { mRtTransaction.apply(); } } }; Loading
core/java/android/view/ViewRootImpl.java +44 −43 Original line number Diff line number Diff line Loading @@ -654,26 +654,25 @@ public final class ViewRootImpl implements ViewParent, int localChanges; } // If set, ViewRootImpl will call BLASTBufferQueue::setNextTransaction with // mRtBLASTSyncTransaction, prior to invoking draw. This provides a way // to redirect the buffers in to transactions. // 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; // Set when calling setNextTransaction, we can't just reuse mNextDrawUseBLASTSyncTransaction // because, imagine this scenario: // 1. First draw is using BLAST, mNextDrawUseBLAST = true // 2. We call perform draw and are waiting on the callback // 3. After the first perform draw but before the first callback and the // second perform draw, a second draw sets mNextDrawUseBLAST = true (it already was) // 4. At this point the callback fires and we set mNextDrawUseBLAST = false; // 5. We get to performDraw and fail to sync as we intended because mNextDrawUseBLAST // is now false. // This is why we use a two-step latch with the two booleans, one consumed from // performDraw and one consumed from finishBLASTSync() private boolean mNextReportConsumeBLAST; // Be very careful with the threading here. This is used from the render thread while // the UI thread is paused and then applied and cleared from the UI thread right after // draw returns. private SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction(); // 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. 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 Loading Loading @@ -3783,26 +3782,29 @@ public final class ViewRootImpl implements ViewParent, commitCallbacks.get(i).run(); } } });}); }); }); } } try { if (mNextDrawUseBLASTSyncTransaction) { // TODO(b/149747443) // We aren't prepared to handle overlapping use of mRtBLASTSyncTransaction // so if we are BLAST syncing we make sure the previous draw has // totally finished. if (mAttachInfo.mThreadedRenderer != null) { mAttachInfo.mThreadedRenderer.pause(); } mNextReportConsumeBLAST = true; mNextDrawUseBLASTSyncTransaction = false; // 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. registerRtFrameCallback(frame -> { mRtNextFrameReportedConsumeWithBlast = true; if (mBlastBufferQueue != null) { // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } }); mNextDrawUseBLASTSyncTransaction = false; } boolean canUseAsync = draw(fullRedrawNeeded); if (usingAsyncReport && !canUseAsync) { Loading Loading @@ -9757,9 +9759,12 @@ public final class ViewRootImpl implements ViewParent, private void finishBLASTSync(boolean apply) { mSendNextFrameToWm = false; if (mNextReportConsumeBLAST) { mNextReportConsumeBLAST = false; 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 { Loading @@ -9772,6 +9777,10 @@ public final class ViewRootImpl implements ViewParent, return mRtBLASTSyncTransaction; } Object getBlastTransactionLock() { return mRtBLASTSyncTransaction; } /** * @hide */ Loading Loading @@ -9799,12 +9808,4 @@ public final class ViewRootImpl implements ViewParent, boolean useBLAST() { return mUseBLASTAdapter && !mForceDisableBLAST; } /** * Returns true if we are about to or currently processing a draw directed * in to a BLAST transaction. */ boolean isDrawingToBLASTTransaction() { return mNextReportConsumeBLAST; } }