diff options
author | 2025-03-20 15:53:33 -0700 | |
---|---|---|
committer | 2025-03-21 13:40:17 -0700 | |
commit | 8c7805b67a1e71e21ea29ab6b2a18a67614c4941 (patch) | |
tree | 535a457b1651d63e65de0d6352cfc70b148e9b32 /quickstep/src | |
parent | 4b40d05ebb683e3ab963c25367779eac21ff864d (diff) |
[Memory Leak] Avoid spamming DragLayer's run queue
Avoid adding duplicated ViewTreeObserver#addOnDrawListener from DepthController
Fix: 405158421
Flag: NONE - released code
Test: manual - presubmit
Change-Id: Ib59c130667c5c0a012de3205d11c8de1d6de3903
Diffstat (limited to 'quickstep/src')
-rw-r--r-- | quickstep/src/com/android/launcher3/statehandlers/DepthController.java | 90 |
1 files changed, 57 insertions, 33 deletions
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java index 360210b010..d9808308e8 100644 --- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java +++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java @@ -30,6 +30,8 @@ import android.view.View; import android.view.ViewRootImpl; import android.view.ViewTreeObserver; +import androidx.annotation.VisibleForTesting; + import com.android.launcher3.BaseActivity; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; @@ -46,8 +48,8 @@ import java.util.function.Consumer; */ public class DepthController extends BaseDepthController implements StateHandler<LauncherState>, BaseActivity.MultiWindowModeChangedListener { - - private final ViewTreeObserver.OnDrawListener mOnDrawListener = this::onLauncherDraw; + @VisibleForTesting + final ViewTreeObserver.OnDrawListener mOnDrawListener = this::onLauncherDraw; private final Consumer<Boolean> mCrossWindowBlurListener = this::setCrossWindowBlursEnabled; @@ -58,6 +60,10 @@ public class DepthController extends BaseDepthController implements StateHandler private View.OnAttachStateChangeListener mOnAttachListener; + // Ensure {@link mOnDrawListener} is added only once to avoid spamming DragLayer's mRunQueue + // via {@link View#post(Runnable)} + private boolean mIsOnDrawListenerAdded = false; + public DepthController(Launcher l) { super(l); } @@ -66,33 +72,37 @@ public class DepthController extends BaseDepthController implements StateHandler View view = mLauncher.getDragLayer(); ViewRootImpl viewRootImpl = view.getViewRootImpl(); setBaseSurface(viewRootImpl != null ? viewRootImpl.getSurfaceControl() : null); - view.post(() -> view.getViewTreeObserver().removeOnDrawListener(mOnDrawListener)); + view.post(this::removeOnDrawListener); } private void ensureDependencies() { - if (mLauncher.getRootView() != null && mOnAttachListener == null) { - View rootView = mLauncher.getRootView(); - mOnAttachListener = new View.OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View view) { - UI_HELPER_EXECUTOR.execute(() -> - CrossWindowBlurListeners.getInstance().addListener( - mLauncher.getMainExecutor(), mCrossWindowBlurListener)); - mLauncher.getScrimView().addOpaquenessListener(mOpaquenessListener); - - // To handle the case where window token is invalid during last setDepth call. - applyDepthAndBlur(); - } - - @Override - public void onViewDetachedFromWindow(View view) { - removeSecondaryListeners(); - } - }; - rootView.addOnAttachStateChangeListener(mOnAttachListener); - if (rootView.isAttachedToWindow()) { - mOnAttachListener.onViewAttachedToWindow(rootView); + View rootView = mLauncher.getRootView(); + if (rootView == null) { + return; + } + if (mOnAttachListener != null) { + return; + } + mOnAttachListener = new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View view) { + UI_HELPER_EXECUTOR.execute(() -> + CrossWindowBlurListeners.getInstance().addListener( + mLauncher.getMainExecutor(), mCrossWindowBlurListener)); + mLauncher.getScrimView().addOpaquenessListener(mOpaquenessListener); + + // To handle the case where window token is invalid during last setDepth call. + applyDepthAndBlur(); + } + + @Override + public void onViewDetachedFromWindow(View view) { + removeSecondaryListeners(); } + }; + rootView.addOnAttachStateChangeListener(mOnAttachListener); + if (rootView.isAttachedToWindow()) { + mOnAttachListener.onViewAttachedToWindow(rootView); } } @@ -109,11 +119,9 @@ public class DepthController extends BaseDepthController implements StateHandler } private void removeSecondaryListeners() { - if (mCrossWindowBlurListener != null) { - UI_HELPER_EXECUTOR.execute(() -> - CrossWindowBlurListeners.getInstance() - .removeListener(mCrossWindowBlurListener)); - } + UI_HELPER_EXECUTOR.execute(() -> + CrossWindowBlurListeners.getInstance() + .removeListener(mCrossWindowBlurListener)); if (mOpaquenessListener != null) { mLauncher.getScrimView().removeOpaquenessListener(mOpaquenessListener); } @@ -124,9 +132,9 @@ public class DepthController extends BaseDepthController implements StateHandler */ public void setActivityStarted(boolean isStarted) { if (isStarted) { - mLauncher.getDragLayer().getViewTreeObserver().addOnDrawListener(mOnDrawListener); + addOnDrawListener(); } else { - mLauncher.getDragLayer().getViewTreeObserver().removeOnDrawListener(mOnDrawListener); + removeOnDrawListener(); setBaseSurface(null); } } @@ -139,7 +147,7 @@ public class DepthController extends BaseDepthController implements StateHandler stateDepth.setValue(toState.getDepth(mLauncher)); if (toState == LauncherState.BACKGROUND_APP) { - mLauncher.getDragLayer().getViewTreeObserver().addOnDrawListener(mOnDrawListener); + addOnDrawListener(); } } @@ -165,7 +173,23 @@ public class DepthController extends BaseDepthController implements StateHandler @Override protected void onInvalidSurface() { // Lets wait for surface to become valid again + addOnDrawListener(); + } + + private void addOnDrawListener() { + if (mIsOnDrawListenerAdded) { + return; + } mLauncher.getDragLayer().getViewTreeObserver().addOnDrawListener(mOnDrawListener); + mIsOnDrawListenerAdded = true; + } + + private void removeOnDrawListener() { + if (!mIsOnDrawListenerAdded) { + return; + } + mLauncher.getDragLayer().getViewTreeObserver().removeOnDrawListener(mOnDrawListener); + mIsOnDrawListenerAdded = false; } @Override |