Loading core/java/android/view/ViewRootImpl.java +26 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading core/java/android/window/SurfaceSyncer.java +27 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -99,7 +100,9 @@ public class SurfaceSyncer { Handler handler = new Handler(Looper.myLooper()); return setupSync(transaction -> { transaction.apply(); if (onComplete != null) { handler.post(onComplete); } }); } Loading Loading @@ -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); } /** Loading Loading @@ -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() {} } /** Loading @@ -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; Loading @@ -290,6 +307,7 @@ public class SurfaceSyncer { synchronized (mLock) { mPendingSyncs.add(syncBufferCallback.hashCode()); mSyncTargets.add(syncTarget); } syncTarget.onReadyToSync(syncBufferCallback); } Loading @@ -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); } Loading packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt +1 −5 Original line number Diff line number Diff line 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 /** Loading @@ -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 Loading Loading
core/java/android/view/ViewRootImpl.java +26 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading
core/java/android/window/SurfaceSyncer.java +27 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -99,7 +100,9 @@ public class SurfaceSyncer { Handler handler = new Handler(Looper.myLooper()); return setupSync(transaction -> { transaction.apply(); if (onComplete != null) { handler.post(onComplete); } }); } Loading Loading @@ -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); } /** Loading Loading @@ -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() {} } /** Loading @@ -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; Loading @@ -290,6 +307,7 @@ public class SurfaceSyncer { synchronized (mLock) { mPendingSyncs.add(syncBufferCallback.hashCode()); mSyncTargets.add(syncTarget); } syncTarget.onReadyToSync(syncBufferCallback); } Loading @@ -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); } Loading
packages/SystemUI/animation/src/com/android/systemui/animation/ViewRootSync.kt +1 −5 Original line number Diff line number Diff line 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 /** Loading @@ -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 Loading