summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorchaviw <chaviw@google.com>2022-03-24 17:38:48 -0500
committerchaviw <chaviw@google.com>2022-03-28 09:41:25 -0500
commit7b7dabc218523195d181393383ee28dd285457a4 (patch)
treeb5774a129002bef7a94883872783fbdaa05ea181 /core/java/android
parentd8ea5df38154bfed206cebe288eba385b76e89a4 (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.java35
-rw-r--r--core/java/android/window/SurfaceSyncer.java31
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);
}