From cb2b925a50198e3dd04ea636fb4e95df1cb1d4c3 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Thu, 27 Mar 2025 14:21:51 -0700 Subject: [PATCH] Reland "Reduce calls to surface reparenting and set relative layer" Surface reparenting was happening on every frame since we call applyDepthAndBlur on each frame during animation. Instead we can do it only when base surface is set. mBlurSurface should always be parented to mBaseSurface so no point in calling it again and again. Relative layer changes only when we either draw above or recents. While drawing above recents, mBaseSurface relative layer should be used. mBaseSurfaceOverride otherwise. No point to call this during animation. Added perfetto traces comparison home->all apps, alongwith all other generic overview scenarios which possibly could have caused jank is added here: https://drive.google.com/drive/folders/146K_4WLaOGQcZ1gsuhCFlOCzfZ-mJBw8?resourcekey=0-r1-NnNtYGH88d8DGEvnXZg&usp=sharing Bug: 404647629 Test: Manual. Enter overview from Desktop tile / home. Flag: com.android.launcher3.enable_overview_background_wallpaper_blur Change-Id: I567d6b8615685e5c50ef7b7b15787fa56cb2da79 --- .../quickstep/util/BaseDepthController.java | 186 +++++++++++------- 1 file changed, 116 insertions(+), 70 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/BaseDepthController.java b/quickstep/src/com/android/quickstep/util/BaseDepthController.java index 89f1e33d6e..80b31b5b96 100644 --- a/quickstep/src/com/android/quickstep/util/BaseDepthController.java +++ b/quickstep/src/com/android/quickstep/util/BaseDepthController.java @@ -122,13 +122,6 @@ public class BaseDepthController { new MultiPropertyFactory<>(this, DEPTH, DEPTH_INDEX_COUNT, Float::max); stateDepth = depthProperty.get(DEPTH_INDEX_STATE_TRANSITION); widgetDepth = depthProperty.get(DEPTH_INDEX_WIDGET); - if (enableOverviewBackgroundWallpaperBlur()) { - mBlurSurface = new SurfaceControl.Builder() - .setName("Overview Blur") - .setHidden(false) - .build(); - } - } protected void setCrossWindowBlursEnabled(boolean isEnabled) { @@ -150,75 +143,74 @@ public class BaseDepthController { protected void onInvalidSurface() { } protected void applyDepthAndBlur() { - float depth = mDepth; - IBinder windowToken = mLauncher.getRootView().getWindowToken(); - if (windowToken != null) { + applyDepthAndBlur(createTransaction()); + } + + protected void applyDepthAndBlur(SurfaceControl.Transaction transaction) { + try (transaction) { + float depth = mDepth; + IBinder windowToken = mLauncher.getRootView().getWindowToken(); + if (windowToken != null) { + if (enableScalingRevealHomeAnimation()) { + mWallpaperManager.setWallpaperZoomOut(windowToken, depth); + } else { + // The API's full zoom-out is three times larger than the zoom-out we apply + // to the + // icons. To keep the two consistent throughout the animation while keeping + // Launcher's concept of full depth unchanged, we divide the depth by 3 here. + mWallpaperManager.setWallpaperZoomOut(windowToken, depth / 3); + } + } + + if (!BlurUtils.supportsBlursOnWindows()) { + return; + } + if (mBaseSurface == null) { + Log.d(TAG, "mSurface is null and mCurrentBlur is: " + mCurrentBlur); + return; + } + if (!mBaseSurface.isValid()) { + Log.d(TAG, "mSurface is not valid"); + mWaitingOnSurfaceValidity = true; + onInvalidSurface(); + return; + } + mWaitingOnSurfaceValidity = false; + boolean hasOpaqueBg = mLauncher.getScrimView().isFullyOpaque(); + boolean isSurfaceOpaque = !mHasContentBehindLauncher && hasOpaqueBg && !mPauseBlurs; + + float blurAmount; if (enableScalingRevealHomeAnimation()) { - mWallpaperManager.setWallpaperZoomOut(windowToken, depth); + blurAmount = mapDepthToBlur(depth); } else { - // The API's full zoom-out is three times larger than the zoom-out we apply to the - // icons. To keep the two consistent throughout the animation while keeping - // Launcher's concept of full depth unchanged, we divide the depth by 3 here. - mWallpaperManager.setWallpaperZoomOut(windowToken, depth / 3); + blurAmount = depth; } - } + mCurrentBlur = !mCrossWindowBlursEnabled || hasOpaqueBg || mPauseBlurs + ? 0 : (int) (blurAmount * mMaxBlurRadius); - if (!BlurUtils.supportsBlursOnWindows()) { - return; - } - if (mBaseSurface == null) { - Log.d(TAG, "mSurface is null and mCurrentBlur is: " + mCurrentBlur); - return; - } - if (!mBaseSurface.isValid()) { - Log.d(TAG, "mSurface is not valid"); - mWaitingOnSurfaceValidity = true; - onInvalidSurface(); - return; - } - mWaitingOnSurfaceValidity = false; - boolean hasOpaqueBg = mLauncher.getScrimView().isFullyOpaque(); - boolean isSurfaceOpaque = !mHasContentBehindLauncher && hasOpaqueBg && !mPauseBlurs; + SurfaceControl blurSurface = + enableOverviewBackgroundWallpaperBlur() && mBlurSurface != null ? mBlurSurface + : mBaseSurface; - float blurAmount; - if (enableScalingRevealHomeAnimation()) { - blurAmount = mapDepthToBlur(depth); - } else { - blurAmount = depth; - } - mCurrentBlur = !mCrossWindowBlursEnabled || hasOpaqueBg || mPauseBlurs - ? 0 : (int) (blurAmount * mMaxBlurRadius); + transaction.setBackgroundBlurRadius(blurSurface, mCurrentBlur) + .setOpaque(blurSurface, isSurfaceOpaque); - SurfaceControl.Transaction transaction = new SurfaceControl.Transaction(); - if (enableOverviewBackgroundWallpaperBlur() && mBlurSurface != null) { - // Reparent to launcher for full screen blur. - transaction.setBackgroundBlurRadius(mBlurSurface, mCurrentBlur) - .reparent(mBlurSurface, mBaseSurface); - // Set mBlurSurface to be 1 layer behind mBaseSurface or mBaseSurfaceOverride. - if (mBaseSurfaceOverride != null && mBaseSurfaceOverride.isValid()) { - transaction.setRelativeLayer(mBlurSurface, mBaseSurfaceOverride, -1); - } else { - transaction.setRelativeLayer(mBlurSurface, mBaseSurface, -1); + // Set early wake-up flags when we know we're executing an expensive operation, this way + // SurfaceFlinger will adjust its internal offsets to avoid jank. + boolean wantsEarlyWakeUp = depth > 0 && depth < 1; + if (wantsEarlyWakeUp && !mInEarlyWakeUp) { + transaction.setEarlyWakeupStart(); + mInEarlyWakeUp = true; + } else if (!wantsEarlyWakeUp && mInEarlyWakeUp) { + transaction.setEarlyWakeupEnd(); + mInEarlyWakeUp = false; } - } else { - transaction.setBackgroundBlurRadius(mBaseSurface, mCurrentBlur); - } - transaction.setOpaque(mBaseSurface, isSurfaceOpaque); - // Set early wake-up flags when we know we're executing an expensive operation, this way - // SurfaceFlinger will adjust its internal offsets to avoid jank. - boolean wantsEarlyWakeUp = depth > 0 && depth < 1; - if (wantsEarlyWakeUp && !mInEarlyWakeUp) { - transaction.setEarlyWakeupStart(); - mInEarlyWakeUp = true; - } else if (!wantsEarlyWakeUp && mInEarlyWakeUp) { - transaction.setEarlyWakeupEnd(); - mInEarlyWakeUp = false; - } - AttachedSurfaceControl rootSurfaceControl = - mLauncher.getRootView().getRootSurfaceControl(); - if (rootSurfaceControl != null) { - rootSurfaceControl.applyTransactionOnDraw(transaction); + AttachedSurfaceControl rootSurfaceControl = + mLauncher.getRootView().getRootSurfaceControl(); + if (rootSurfaceControl != null) { + rootSurfaceControl.applyTransactionOnDraw(transaction); + } } } @@ -244,7 +236,10 @@ public class BaseDepthController { */ public void setBaseSurfaceOverride(@Nullable SurfaceControl baseSurfaceOverride) { this.mBaseSurfaceOverride = baseSurfaceOverride; - applyDepthAndBlur(); + SurfaceControl.Transaction transaction = createTransaction(); + Log.d(TAG, "setBaseSurfaceOverride: applying blur behind leash " + baseSurfaceOverride); + updateBlurSurfaceOrder(transaction); + applyDepthAndBlur(transaction); } /** @@ -255,7 +250,54 @@ public class BaseDepthController { mBaseSurface = baseSurface; Log.d(TAG, "setSurface:\n\tmWaitingOnSurfaceValidity: " + mWaitingOnSurfaceValidity + "\n\tmBaseSurface: " + mBaseSurface); - applyDepthAndBlur(); + if (enableOverviewBackgroundWallpaperBlur()) { + SurfaceControl.Transaction transaction = createTransaction(); + if (mBaseSurface != null) { + if (mBlurSurface == null) { + mBlurSurface = new SurfaceControl.Builder() + .setName("Overview Blur") + .setHidden(false) + .build(); + Log.d(TAG, + "setBaseSurface: creating Overview Blur surface " + mBlurSurface); + } + updateBlurSurfaceParent(transaction); + updateBlurSurfaceOrder(transaction); + applyDepthAndBlur(transaction); + } else { + if (mBlurSurface != null) { + Log.d(TAG, "setBaseSurface: removing base surface " + mBlurSurface); + transaction.remove(mBlurSurface); + mBlurSurface = null; + } + } + } else { + applyDepthAndBlur(); + } + } + } + + private void updateBlurSurfaceOrder(SurfaceControl.Transaction transaction) { + SurfaceControl baseSurface = null; + if (mBaseSurfaceOverride != null && mBaseSurfaceOverride.isValid()) { + Log.d(TAG, "updateBlurSurfaceOrder: relayering to leash " + mBaseSurfaceOverride); + baseSurface = mBaseSurfaceOverride; + } else if (mBaseSurface != null && mBaseSurface.isValid()) { + Log.d(TAG, "updateBlurSurfaceOrder: relayering to base " + mBaseSurface); + baseSurface = mBaseSurface; + } + if (baseSurface != null && mBlurSurface != null) { + // Set mBlurSurface to be 1 layer behind mBaseSurface or mBaseSurfaceOverride. + transaction.setRelativeLayer(mBlurSurface, baseSurface, -1); + } + } + + private void updateBlurSurfaceParent(SurfaceControl.Transaction transaction) { + if (mBlurSurface != null) { + // Reparent to launcher for full screen blur. + Log.d(TAG, + "updateBlurSurfaceParent: reparenting " + mBlurSurface + " to " + mBaseSurface); + transaction.reparent(mBlurSurface, mBaseSurface); } } @@ -266,4 +308,8 @@ public class BaseDepthController { private static float mapDepthToBlur(float depth) { return Math.min(3 * depth, 1f); } + + private SurfaceControl.Transaction createTransaction() { + return new SurfaceControl.Transaction(); + } }