diff options
| author | chaviw <chaviw@google.com> | 2022-03-24 17:38:48 -0500 |
|---|---|---|
| committer | chaviw <chaviw@google.com> | 2022-03-28 09:41:25 -0500 |
| commit | 7b7dabc218523195d181393383ee28dd285457a4 (patch) | |
| tree | b5774a129002bef7a94883872783fbdaa05ea181 /core/java/android | |
| parent | d8ea5df38154bfed206cebe288eba385b76e89a4 (diff) | |
Force draw during a blast sync and disable rt animations
When ViewRootImpl is going to draw a frame due to a blast sync request,
we call forceDrawNextFrame to ensure we get a draw this vsync, even if
RT animation rendered a frame. This will ensure that we aren't required
to reschedule a draw either in rt thread or ui thread since we'll get a
frame back as long as there's an available buffer.
We also disable rt animations if a sync set has started with Syncer and
then re-enable when the sync set is complete. This ensures we don't
continue to acquire buffers for a render thread scheduled animation
during a UI animation since we want the UI request to get the buffer.
Test: Open internet dialog from notification shade on 60hz device
Fixes: 217621394
Bug: 200284684
Change-Id: Ic1534d21b0ee2ad82f20ff34df4cbbbad87557fd
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 35 | ||||
| -rw-r--r-- | core/java/android/window/SurfaceSyncer.java | 31 |
2 files changed, 53 insertions, 13 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 0df8a0bded48..9a25be804002 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -816,12 +816,7 @@ public final class ViewRootImpl implements ViewParent, private final SurfaceSyncer mSurfaceSyncer = new SurfaceSyncer(); private int mLastSyncId = -1; private SurfaceSyncer.SyncBufferCallback mSyncBufferCallback; - - /** - * Keeps track of the last frame number that was attempted to draw. Should only be accessed on - * the RenderThread. - */ - private long mRtLastAttemptedDrawFrameNum = 0; + private int mNumSyncsInProgress = 0; private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks; @@ -4249,7 +4244,7 @@ public final class ViewRootImpl implements ViewParent, mHasPendingTransactions = false; try { - boolean canUseAsync = draw(fullRedrawNeeded); + boolean canUseAsync = draw(fullRedrawNeeded, usingAsyncReport && mSyncBuffer); if (usingAsyncReport && !canUseAsync) { mAttachInfo.mThreadedRenderer.setFrameCallback(null); usingAsyncReport = false; @@ -4409,7 +4404,7 @@ public final class ViewRootImpl implements ViewParent, } } - private boolean draw(boolean fullRedrawNeeded) { + private boolean draw(boolean fullRedrawNeeded, boolean forceDraw) { Surface surface = mSurface; if (!surface.isValid()) { return false; @@ -4546,6 +4541,9 @@ public final class ViewRootImpl implements ViewParent, useAsyncReport = true; + if (forceDraw) { + mAttachInfo.mThreadedRenderer.forceDrawNextFrame(); + } mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this); } else { // If we get here with a disabled & requested hardware renderer, something went @@ -10864,9 +10862,28 @@ public final class ViewRootImpl implements ViewParent, }); } - public final SurfaceSyncer.SyncTarget mSyncTarget = this::readyToSync; + public final SurfaceSyncer.SyncTarget mSyncTarget = new SurfaceSyncer.SyncTarget() { + @Override + public void onReadyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) { + readyToSync(syncBufferCallback); + } + + @Override + public void onSyncComplete() { + mHandler.postAtFrontOfQueue(() -> { + if (--mNumSyncsInProgress == 0 && mAttachInfo.mThreadedRenderer != null) { + HardwareRenderer.setRtAnimationsEnabled(true); + } + }); + } + }; private void readyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) { + mNumSyncsInProgress++; + if (mAttachInfo.mThreadedRenderer != null) { + HardwareRenderer.setRtAnimationsEnabled(false); + } + if (mSyncBufferCallback != null) { Log.d(mTag, "Already set sync for the next draw."); mSyncBufferCallback.onBufferReady(null); diff --git a/core/java/android/window/SurfaceSyncer.java b/core/java/android/window/SurfaceSyncer.java index 0c32219f79a0..0e011bb0d0b3 100644 --- a/core/java/android/window/SurfaceSyncer.java +++ b/core/java/android/window/SurfaceSyncer.java @@ -21,15 +21,16 @@ import android.annotation.Nullable; import android.annotation.UiThread; import android.os.Handler; import android.os.Looper; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.view.SurfaceControl.Transaction; import android.view.SurfaceView; import android.view.View; +import android.view.ViewRootImpl; import com.android.internal.annotations.GuardedBy; -import java.util.HashSet; import java.util.Set; import java.util.function.Consumer; import java.util.function.Supplier; @@ -99,7 +100,9 @@ public class SurfaceSyncer { Handler handler = new Handler(Looper.myLooper()); return setupSync(transaction -> { transaction.apply(); - handler.post(onComplete); + if (onComplete != null) { + handler.post(onComplete); + } }); } @@ -171,7 +174,11 @@ public class SurfaceSyncer { */ @UiThread public boolean addToSync(int syncId, @NonNull View view) { - return addToSync(syncId, view.getViewRootImpl().mSyncTarget); + ViewRootImpl viewRoot = view.getViewRootImpl(); + if (viewRoot == null) { + return false; + } + return addToSync(syncId, viewRoot.mSyncTarget); } /** @@ -232,9 +239,17 @@ public class SurfaceSyncer { * and {@link SyncBufferCallback#onBufferReady(Transaction)} in order for this Syncable * to be marked as complete. * + * Always invoked on the thread that initiated the call to + * {@link #addToSync(int, SyncTarget)} + * * @param syncBufferCallback A SyncBufferCallback that the caller must invoke onBufferReady */ void onReadyToSync(SyncBufferCallback syncBufferCallback); + + /** + * There's no guarantee about the thread this callback is invoked on. + */ + default void onSyncComplete() {} } /** @@ -260,11 +275,13 @@ public class SurfaceSyncer { private final Object mLock = new Object(); @GuardedBy("mLock") - private final Set<Integer> mPendingSyncs = new HashSet<>(); + private final Set<Integer> mPendingSyncs = new ArraySet<>(); @GuardedBy("mLock") private final Transaction mTransaction = sTransactionFactory.get(); @GuardedBy("mLock") private boolean mSyncReady; + @GuardedBy("mLock") + private final Set<SyncTarget> mSyncTargets = new ArraySet<>(); private final int mSyncId; private final Consumer<Transaction> mSyncRequestCompleteCallback; @@ -290,6 +307,7 @@ public class SurfaceSyncer { synchronized (mLock) { mPendingSyncs.add(syncBufferCallback.hashCode()); + mSyncTargets.add(syncTarget); } syncTarget.onReadyToSync(syncBufferCallback); } @@ -314,6 +332,11 @@ public class SurfaceSyncer { if (DEBUG) { Log.d(TAG, "Successfully finished sync id=" + mSyncId); } + + for (SyncTarget syncTarget : mSyncTargets) { + syncTarget.onSyncComplete(); + } + mSyncTargets.clear(); mSyncRequestCompleteCallback.accept(mTransaction); } |
