diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a3e6945617315..5023075b3bd07 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -228,7 +228,6 @@ import java.util.List; import java.util.Objects; import java.util.Queue; import java.util.concurrent.CountDownLatch; -import java.util.function.Consumer; /** * The top of a view hierarchy, implementing the needed protocol between View @@ -827,8 +826,6 @@ public final class ViewRootImpl implements ViewParent, */ private long mRtLastAttemptedDrawFrameNum = 0; - private Consumer mBLASTDrawConsumer; - private HashSet mRootScrollCaptureCallbacks; private long mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; @@ -3493,35 +3490,23 @@ public final class ViewRootImpl implements ViewParent, } private void createSyncIfNeeded() { - // Started a sync already. - if (mLastSyncId != -1) { + // Started a sync already or there's nothing needing to sync + if (mLastSyncId != -1 || !mReportNextDraw) { return; } - Consumer syncConsumer = null; final int seqId = mSyncSeqId; - - if (mBLASTDrawConsumer != null) { - syncConsumer = mBLASTDrawConsumer; - mBLASTDrawConsumer = null; - } else if (mReportNextDraw) { - syncConsumer = transaction -> { + mLastSyncId = mSurfaceSyncer.setupSync(transaction -> { + // Callback will be invoked on executor thread so post to main thread. + mHandler.postAtFrontOfQueue(() -> { mSurfaceChangedTransaction.merge(transaction); reportDrawFinished(seqId); - }; - } - - if (syncConsumer != null) { - final Consumer 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); + }); + if (DEBUG_BLAST) { + Log.d(mTag, "Setup new sync id=" + mLastSyncId); } + mSurfaceSyncer.addToSync(mLastSyncId, mSyncTarget); } private void notifyContentCatpureEvents() { @@ -10775,37 +10760,6 @@ public final class ViewRootImpl implements ViewParent, showControl, transformationApplied, callback); } - /** - * Redirect the next draw of this ViewRoot (from the UI thread perspective) - * to the passed in consumer. This can be used to create P2P synchronization - * between ViewRoot's however it comes with many caveats. - * - * 1. You MUST consume the transaction, by either applying it immediately or - * merging it in to another transaction. The threading model doesn't - * allow you to hold in the passed transaction. - * 2. If you merge it in to another transaction, this ViewRootImpl will be - * paused until you finally apply that transaction and it receives - * the callback from SF. If you lose track of the transaction you will - * ANR the app. - * 3. Only one person can consume the transaction at a time, if you already - * have a pending consumer for this frame, the function will return false - * 4. Someone else may have requested to consume the next frame, in which case - * this function will return false and you will not receive a callback. - * 5. This function does not trigger drawing so even if it returns true you - * may not receive a callback unless there is some other UI thread work - * to trigger drawing. If it returns true, and a draw occurs, the callback - * will be called (Though again watch out for the null transaction case!) - * 6. This function must be called on the UI thread. The consumer will likewise - * be called on the UI thread. - */ - public boolean consumeNextDraw(Consumer consume) { - if (mBLASTDrawConsumer != null) { - return false; - } - mBLASTDrawConsumer = consume; - return true; - } - boolean wasRelayoutRequested() { return mRelayoutRequested; } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt index 5b3e45c9704dc..35b4166675edf 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt @@ -1,15 +1,15 @@ package com.android.systemui.animation import android.app.ActivityManager -import android.view.SurfaceControl import android.view.View -import android.view.ViewRootImpl +import android.window.SurfaceSyncer /** A util class to synchronize 2 view roots. */ // TODO(b/200284684): Remove this class. object ViewRootSync { // TODO(b/217621394): Remove special handling for low-RAM devices after animation sync is fixed private val forceDisableSynchronization = ActivityManager.isLowRamDeviceStatic() + private var surfaceSyncer: SurfaceSyncer? = null /** * Synchronize the next draw between the view roots of [view] and [otherView], then run [then]. @@ -33,35 +33,11 @@ object ViewRootSync { return } - // Consume the next frames of both view roots to make sure the ghost view is drawn at - // exactly the same time as when the touch surface is made invisible. - var remainingTransactions = 0 - val mergedTransactions = SurfaceControl.Transaction() - - fun onTransaction(transaction: SurfaceControl.Transaction?) { - remainingTransactions-- - transaction?.let { mergedTransactions.merge(it) } - - if (remainingTransactions == 0) { - mergedTransactions.apply() - then() - } - } - - fun consumeNextDraw(viewRootImpl: ViewRootImpl) { - if (viewRootImpl.consumeNextDraw(::onTransaction)) { - remainingTransactions++ - - // Make sure we trigger a traversal. - viewRootImpl.view.invalidate() - } - } - - consumeNextDraw(view.viewRootImpl) - consumeNextDraw(otherView.viewRootImpl) - - if (remainingTransactions == 0) { - then() + surfaceSyncer = SurfaceSyncer().apply { + val syncId = setupSync(Runnable { then() }) + addToSync(syncId, view) + addToSync(syncId, otherView) + markSyncReady(syncId) } }