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() {
registerRtFrameCallback(new FrameDrawingCallback() {
@Override
@@ -4253,7 +4233,6 @@ public final class ViewRootImpl implements ViewParent,
mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
registerFrameDrawingCallbackForBlur();
addFrameCommitCallbackIfNeeded();
boolean usingAsyncReport = isHardwareEnabled() && mSyncBufferCallback != null;

View File

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

View File

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