Merge "Fix missing position updates to blur regions" into tm-dev

This commit is contained in:
Galia Peycheva
2022-05-04 16:09:27 +00:00
committed by Android (Google) Code Review
3 changed files with 78 additions and 58 deletions

View File

@@ -4196,26 +4196,6 @@ public final class ViewRootImpl implements ViewParent,
}); });
} }
@Nullable
private void registerFrameDrawingCallbackForBlur() {
if (!isHardwareEnabled()) {
return;
}
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
if (!needsCallbackForBlur) {
return;
}
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
mBlurRegionAggregator.getBlurRegionsCopyForRT();
// The callback will run on the render thread.
registerRtFrameCallback((frame) -> mBlurRegionAggregator
.dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates));
}
private void registerCallbackForPendingTransactions() { private void registerCallbackForPendingTransactions() {
registerRtFrameCallback(new FrameDrawingCallback() { registerRtFrameCallback(new FrameDrawingCallback() {
@Override @Override
@@ -4253,7 +4233,6 @@ public final class ViewRootImpl implements ViewParent,
mIsDrawing = true; mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
registerFrameDrawingCallbackForBlur();
addFrameCommitCallbackIfNeeded(); addFrameCommitCallbackIfNeeded();
boolean usingAsyncReport = isHardwareEnabled() && mSyncBufferCallback != null; boolean usingAsyncReport = isHardwareEnabled() && mSyncBufferCallback != null;

View File

@@ -36,6 +36,7 @@ import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import android.util.LongSparseArray; import android.util.LongSparseArray;
import android.view.ViewRootImpl; import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
@@ -232,9 +233,12 @@ public final class BackgroundBlurDrawable extends Drawable {
private final ArraySet<BackgroundBlurDrawable> mDrawables = new ArraySet(); private final ArraySet<BackgroundBlurDrawable> mDrawables = new ArraySet();
@GuardedBy("mRtLock") @GuardedBy("mRtLock")
private final LongSparseArray<ArraySet<Runnable>> mFrameRtUpdates = new LongSparseArray(); private final LongSparseArray<ArraySet<Runnable>> mFrameRtUpdates = new LongSparseArray();
private long mLastFrameNumber = 0;
private BlurRegion[] mLastFrameBlurRegions = null;
private final ViewRootImpl mViewRoot; private final ViewRootImpl mViewRoot;
private BlurRegion[] mTmpBlurRegionsForFrame = new BlurRegion[0]; private BlurRegion[] mTmpBlurRegionsForFrame = new BlurRegion[0];
private boolean mHasUiUpdates; private boolean mHasUiUpdates;
private ViewTreeObserver.OnPreDrawListener mOnPreDrawListener;
public Aggregator(ViewRootImpl viewRoot) { public Aggregator(ViewRootImpl viewRoot) {
mViewRoot = viewRoot; mViewRoot = viewRoot;
@@ -277,6 +281,38 @@ public final class BackgroundBlurDrawable extends Drawable {
Log.d(TAG, "Remove " + drawable); Log.d(TAG, "Remove " + drawable);
} }
} }
if (mOnPreDrawListener == null && mViewRoot.getView() != null
&& hasRegions()) {
registerPreDrawListener();
}
}
private void registerPreDrawListener() {
mOnPreDrawListener = () -> {
final boolean hasUiUpdates = hasUpdates();
if (hasUiUpdates || hasRegions()) {
final BlurRegion[] blurRegionsForNextFrame = getBlurRegionsCopyForRT();
mViewRoot.registerRtFrameCallback(frame -> {
synchronized (mRtLock) {
mLastFrameNumber = frame;
mLastFrameBlurRegions = blurRegionsForNextFrame;
handleDispatchBlurTransactionLocked(
frame, blurRegionsForNextFrame, hasUiUpdates);
}
});
}
if (!hasRegions() && mViewRoot.getView() != null) {
mViewRoot.getView().getViewTreeObserver()
.removeOnPreDrawListener(mOnPreDrawListener);
mOnPreDrawListener = null;
}
return true;
};
mViewRoot.getView().getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);
} }
// Called from a thread pool // Called from a thread pool
@@ -290,7 +326,14 @@ public final class BackgroundBlurDrawable extends Drawable {
mFrameRtUpdates.put(frameNumber, frameRtUpdates); mFrameRtUpdates.put(frameNumber, frameRtUpdates);
} }
frameRtUpdates.add(update); frameRtUpdates.add(update);
if (mLastFrameNumber == frameNumber) {
// The transaction for this frame has already been sent, so we have to manually
// trigger sending a transaction here in order to apply this position update
handleDispatchBlurTransactionLocked(frameNumber, mLastFrameBlurRegions, true);
}
} }
} }
/** /**
@@ -329,29 +372,27 @@ public final class BackgroundBlurDrawable extends Drawable {
/** /**
* Called on RenderThread. * Called on RenderThread.
* *
* @return all blur regions if there are any ui or position updates for this frame, * @return true if it is necessary to send an update to Sf this frame
* null otherwise
*/ */
@GuardedBy("mRtLock")
@VisibleForTesting @VisibleForTesting
public float[][] getBlurRegionsToDispatchToSf(long frameNumber, public float[][] getBlurRegionsForFrameLocked(long frameNumber,
BlurRegion[] blurRegionsForFrame, boolean hasUiUpdatesForFrame) { BlurRegion[] blurRegionsForFrame, boolean forceUpdate) {
synchronized (mRtLock) { if (!forceUpdate && (mFrameRtUpdates.size() == 0
if (!hasUiUpdatesForFrame && (mFrameRtUpdates.size() == 0 || mFrameRtUpdates.keyAt(0) > frameNumber)) {
|| mFrameRtUpdates.keyAt(0) > frameNumber)) { return null;
return null; }
}
// mFrameRtUpdates holds position updates coming from a thread pool span from // mFrameRtUpdates holds position updates coming from a thread pool span from
// RenderThread. At this point, all position updates for frame frameNumber should // RenderThread. At this point, all position updates for frame frameNumber should
// have been added to mFrameRtUpdates. // have been added to mFrameRtUpdates.
// Here, we apply all updates for frames <= frameNumber in case some previous update // Here, we apply all updates for frames <= frameNumber in case some previous update
// has been missed. This also protects mFrameRtUpdates from memory leaks. // has been missed. This also protects mFrameRtUpdates from memory leaks.
while (mFrameRtUpdates.size() != 0 && mFrameRtUpdates.keyAt(0) <= frameNumber) { while (mFrameRtUpdates.size() != 0 && mFrameRtUpdates.keyAt(0) <= frameNumber) {
final ArraySet<Runnable> frameUpdates = mFrameRtUpdates.valueAt(0); final ArraySet<Runnable> frameUpdates = mFrameRtUpdates.valueAt(0);
mFrameRtUpdates.removeAt(0); mFrameRtUpdates.removeAt(0);
for (int i = 0; i < frameUpdates.size(); i++) { for (int i = 0; i < frameUpdates.size(); i++) {
frameUpdates.valueAt(i).run(); frameUpdates.valueAt(i).run();
}
} }
} }
@@ -370,13 +411,13 @@ public final class BackgroundBlurDrawable extends Drawable {
} }
/** /**
* Called on RenderThread in FrameDrawingCallback. * Dispatch all blur regions if there are any ui or position updates for that frame.
* Dispatch all blur regions if there are any ui or position updates.
*/ */
public void dispatchBlurTransactionIfNeeded(long frameNumber, @GuardedBy("mRtLock")
BlurRegion[] blurRegionsForFrame, boolean hasUiUpdatesForFrame) { private void handleDispatchBlurTransactionLocked(long frameNumber, BlurRegion[] blurRegions,
final float[][] blurRegionsArray = getBlurRegionsToDispatchToSf(frameNumber, boolean forceUpdate) {
blurRegionsForFrame, hasUiUpdatesForFrame); float[][] blurRegionsArray =
getBlurRegionsForFrameLocked(frameNumber, blurRegions, forceUpdate);
if (blurRegionsArray != null) { if (blurRegionsArray != null) {
mViewRoot.dispatchBlurRegions(blurRegionsArray, frameNumber); mViewRoot.dispatchBlurRegions(blurRegionsArray, frameNumber);
} }

View File

@@ -65,7 +65,7 @@ public class BlurAggregatorTest {
drawable.setBlurRadius(TEST_BLUR_RADIUS); drawable.setBlurRadius(TEST_BLUR_RADIUS);
final boolean hasUpdates = mAggregator.hasUpdates(); final boolean hasUpdates = mAggregator.hasUpdates();
final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT(); final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
mAggregator.getBlurRegionsToDispatchToSf(TEST_FRAME_NUMBER, blurRegions, hasUpdates); mAggregator.getBlurRegionsForFrameLocked(TEST_FRAME_NUMBER, blurRegions, hasUpdates);
return drawable; return drawable;
} }
@@ -154,7 +154,7 @@ public class BlurAggregatorTest {
assertEquals(1, blurRegions.length); assertEquals(1, blurRegions.length);
mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4); mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
mAggregator.getBlurRegionsToDispatchToSf(TEST_FRAME_NUMBER, blurRegions, mAggregator.getBlurRegionsForFrameLocked(TEST_FRAME_NUMBER, blurRegions,
mAggregator.hasUpdates()); mAggregator.hasUpdates());
assertEquals(1, blurRegions[0].rect.left); assertEquals(1, blurRegions[0].rect.left);
assertEquals(2, blurRegions[0].rect.top); assertEquals(2, blurRegions[0].rect.top);
@@ -169,7 +169,7 @@ public class BlurAggregatorTest {
final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT(); final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
assertEquals(1, blurRegions.length); assertEquals(1, blurRegions.length);
float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( float[][] blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER, blurRegions, hasUpdates); TEST_FRAME_NUMBER, blurRegions, hasUpdates);
assertNull(blurRegionsForSf); assertNull(blurRegionsForSf);
} }
@@ -182,7 +182,7 @@ public class BlurAggregatorTest {
final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT(); final BlurRegion[] blurRegions = mAggregator.getBlurRegionsCopyForRT();
assertEquals(1, blurRegions.length); assertEquals(1, blurRegions.length);
float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( float[][] blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER, blurRegions, hasUpdates); TEST_FRAME_NUMBER, blurRegions, hasUpdates);
assertNotNull(blurRegionsForSf); assertNotNull(blurRegionsForSf);
assertEquals(1, blurRegionsForSf.length); assertEquals(1, blurRegionsForSf.length);
@@ -197,7 +197,7 @@ public class BlurAggregatorTest {
assertEquals(1, blurRegions.length); assertEquals(1, blurRegions.length);
mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4); mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( float[][] blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER, blurRegions, hasUpdates); TEST_FRAME_NUMBER, blurRegions, hasUpdates);
assertNotNull(blurRegionsForSf); assertNotNull(blurRegionsForSf);
assertEquals(1, blurRegionsForSf.length); assertEquals(1, blurRegionsForSf.length);
@@ -216,7 +216,7 @@ public class BlurAggregatorTest {
assertEquals(1, blurRegions.length); assertEquals(1, blurRegions.length);
mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4); mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( float[][] blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER + 1, blurRegions, hasUpdates); TEST_FRAME_NUMBER + 1, blurRegions, hasUpdates);
assertNotNull(blurRegionsForSf); assertNotNull(blurRegionsForSf);
assertEquals(1, blurRegionsForSf.length); assertEquals(1, blurRegionsForSf.length);
@@ -237,19 +237,19 @@ public class BlurAggregatorTest {
assertEquals(2, blurRegions.length); assertEquals(2, blurRegions.length);
// Check that an update in one of the drawables triggers a dispatch of all blur regions // Check that an update in one of the drawables triggers a dispatch of all blur regions
float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( float[][] blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER, blurRegions, hasUpdates); TEST_FRAME_NUMBER, blurRegions, hasUpdates);
assertNotNull(blurRegionsForSf); assertNotNull(blurRegionsForSf);
assertEquals(2, blurRegionsForSf.length); assertEquals(2, blurRegionsForSf.length);
// Check that the Aggregator deleted all position updates for frame TEST_FRAME_NUMBER // Check that the Aggregator deleted all position updates for frame TEST_FRAME_NUMBER
blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER, blurRegions, /* hasUiUpdates= */ false); TEST_FRAME_NUMBER, blurRegions, /* hasUiUpdates= */ false);
assertNull(blurRegionsForSf); assertNull(blurRegionsForSf);
// Check that a position update triggers a dispatch of all blur regions // Check that a position update triggers a dispatch of all blur regions
drawable2.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4); drawable2.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER + 1, blurRegions, hasUpdates); TEST_FRAME_NUMBER + 1, blurRegions, hasUpdates);
assertNotNull(blurRegionsForSf); assertNotNull(blurRegionsForSf);
assertEquals(2, blurRegionsForSf.length); assertEquals(2, blurRegionsForSf.length);
@@ -292,7 +292,7 @@ public class BlurAggregatorTest {
mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4); mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER, 1, 2, 3, 4);
mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER + 1, 5, 6, 7, 8); mDrawable.mPositionUpdateListener.positionChanged(TEST_FRAME_NUMBER + 1, 5, 6, 7, 8);
final float[][] blurRegionsForSf = mAggregator.getBlurRegionsToDispatchToSf( final float[][] blurRegionsForSf = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER, blurRegions, /* hasUiUpdates= */ false); TEST_FRAME_NUMBER, blurRegions, /* hasUiUpdates= */ false);
assertNotNull(blurRegionsForSf); assertNotNull(blurRegionsForSf);
assertEquals(1, blurRegionsForSf.length); assertEquals(1, blurRegionsForSf.length);
@@ -303,7 +303,7 @@ public class BlurAggregatorTest {
assertEquals(3f, blurRegionsForSf[0][4]); assertEquals(3f, blurRegionsForSf[0][4]);
assertEquals(4f, blurRegionsForSf[0][5]); assertEquals(4f, blurRegionsForSf[0][5]);
final float[][] blurRegionsForSfForNextFrame = mAggregator.getBlurRegionsToDispatchToSf( final float[][] blurRegionsForSfForNextFrame = mAggregator.getBlurRegionsForFrameLocked(
TEST_FRAME_NUMBER + 1, blurRegions, /* hasUiUpdates= */ false); TEST_FRAME_NUMBER + 1, blurRegions, /* hasUiUpdates= */ false);
assertNotNull(blurRegionsForSfForNextFrame); assertNotNull(blurRegionsForSfForNextFrame);
assertEquals(1, blurRegionsForSfForNextFrame.length); assertEquals(1, blurRegionsForSfForNextFrame.length);