Remove consumeNextDraw and replace with SurfaceSyncer
Replace the usage of consumeNextDraw with the SurfaceSyncer since it's safer and integrated with VRI in a cleaner way. Test: Internet Dialog in Notification Shade Bug: 200284684 Change-Id: Ia837086040329c5fd3b8bb5b0adb0fddb339f3f9
This commit is contained in:
@@ -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;
|
||||||
@@ -3493,36 +3490,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");
|
||||||
@@ -10775,37 +10760,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user