diff options
3 files changed, 78 insertions, 58 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 335cd2799c01..42b5691b239e 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -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; diff --git a/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java index 402d7fed90c5..4e1ecc281df3 100644 --- a/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java +++ b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java @@ -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); } diff --git a/core/tests/coretests/src/android/view/BlurAggregatorTest.java b/core/tests/coretests/src/android/view/BlurAggregatorTest.java index b01f2755efdd..ded925e50a6a 100644 --- a/core/tests/coretests/src/android/view/BlurAggregatorTest.java +++ b/core/tests/coretests/src/android/view/BlurAggregatorTest.java @@ -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); |