diff options
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 35 | ||||
| -rw-r--r-- | core/java/android/window/SurfaceSyncer.java | 31 | ||||
| -rw-r--r-- | packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt | 6 |
3 files changed, 54 insertions, 18 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ac381756d516..7dc4f22000b8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -817,12 +817,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; @@ -4250,7 +4245,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; @@ -4410,7 +4405,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; @@ -4547,6 +4542,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 @@ -10870,9 +10868,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); } 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 35b4166675ed..76de7b503451 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt @@ -1,14 +1,11 @@ package com.android.systemui.animation -import android.app.ActivityManager import android.view.View 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 /** @@ -23,8 +20,7 @@ object ViewRootSync { otherView: View, then: () -> Unit ) { - if (forceDisableSynchronization || - !view.isAttachedToWindow || view.viewRootImpl == null || + if (!view.isAttachedToWindow || view.viewRootImpl == null || !otherView.isAttachedToWindow || otherView.viewRootImpl == null || view.viewRootImpl == otherView.viewRootImpl) { // No need to synchronize if either the touch surface or dialog view is not attached |