Merge "Remove consumeNextDraw and replace with SurfaceSyncer" into tm-dev

This commit is contained in:
Chavi Weingarten
2022-03-25 22:08:17 +00:00
committed by Android (Google) Code Review
2 changed files with 16 additions and 86 deletions

View File

@@ -228,7 +228,6 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
/** /**
* The top of a view hierarchy, implementing the needed protocol between View * 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 long mRtLastAttemptedDrawFrameNum = 0;
private Consumer<SurfaceControl.Transaction> mBLASTDrawConsumer;
private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks; private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks;
private long mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; private long mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS;
@@ -3492,36 +3489,24 @@ public final class ViewRootImpl implements ViewParent,
} }
private void createSyncIfNeeded() { private void createSyncIfNeeded() {
// Started a sync already. // Started a sync already or there's nothing needing to sync
if (mLastSyncId != -1) { if (mLastSyncId != -1 || !mReportNextDraw) {
return; return;
} }
Consumer<Transaction> syncConsumer = null;
final int seqId = mSyncSeqId; final int seqId = mSyncSeqId;
if (mBLASTDrawConsumer != null) {
syncConsumer = mBLASTDrawConsumer;
mBLASTDrawConsumer = null;
} else if (mReportNextDraw) {
syncConsumer = transaction -> {
mSurfaceChangedTransaction.merge(transaction);
reportDrawFinished(seqId);
};
}
if (syncConsumer != null) {
final Consumer<Transaction> capturedSyncConsumer = syncConsumer;
mLastSyncId = mSurfaceSyncer.setupSync(transaction -> { mLastSyncId = mSurfaceSyncer.setupSync(transaction -> {
// Callback will be invoked on executor thread so post to main thread. // Callback will be invoked on executor thread so post to main thread.
mHandler.postAtFrontOfQueue(() -> capturedSyncConsumer.accept(transaction)); mHandler.postAtFrontOfQueue(() -> {
mSurfaceChangedTransaction.merge(transaction);
reportDrawFinished(seqId);
});
}); });
if (DEBUG_BLAST) { if (DEBUG_BLAST) {
Log.d(mTag, "Setup new sync id=" + mLastSyncId); Log.d(mTag, "Setup new sync id=" + mLastSyncId);
} }
mSurfaceSyncer.addToSync(mLastSyncId, mSyncTarget); mSurfaceSyncer.addToSync(mLastSyncId, mSyncTarget);
} }
}
private void notifyContentCatpureEvents() { private void notifyContentCatpureEvents() {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents"); Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
@@ -10774,37 +10759,6 @@ public final class ViewRootImpl implements ViewParent,
showControl, transformationApplied, callback); 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<SurfaceControl.Transaction> consume) {
if (mBLASTDrawConsumer != null) {
return false;
}
mBLASTDrawConsumer = consume;
return true;
}
boolean wasRelayoutRequested() { boolean wasRelayoutRequested() {
return mRelayoutRequested; return mRelayoutRequested;
} }

View File

@@ -1,15 +1,15 @@
package com.android.systemui.animation package com.android.systemui.animation
import android.app.ActivityManager import android.app.ActivityManager
import android.view.SurfaceControl
import android.view.View import android.view.View
import android.view.ViewRootImpl import android.window.SurfaceSyncer
/** A util class to synchronize 2 view roots. */ /** A util class to synchronize 2 view roots. */
// TODO(b/200284684): Remove this class. // TODO(b/200284684): Remove this class.
object ViewRootSync { object ViewRootSync {
// TODO(b/217621394): Remove special handling for low-RAM devices after animation sync is fixed // TODO(b/217621394): Remove special handling for low-RAM devices after animation sync is fixed
private val forceDisableSynchronization = ActivityManager.isLowRamDeviceStatic() 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]. * Synchronize the next draw between the view roots of [view] and [otherView], then run [then].
@@ -33,35 +33,11 @@ object ViewRootSync {
return return
} }
// Consume the next frames of both view roots to make sure the ghost view is drawn at surfaceSyncer = SurfaceSyncer().apply {
// exactly the same time as when the touch surface is made invisible. val syncId = setupSync(Runnable { then() })
var remainingTransactions = 0 addToSync(syncId, view)
val mergedTransactions = SurfaceControl.Transaction() addToSync(syncId, otherView)
markSyncReady(syncId)
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()
} }
} }