summaryrefslogtreecommitdiff
path: root/quickstep/src
diff options
context:
space:
mode:
author Fengjiang Li <fengjial@google.com> 2025-03-20 15:53:33 -0700
committer Fengjiang Li <fengjial@google.com> 2025-03-21 13:40:17 -0700
commit8c7805b67a1e71e21ea29ab6b2a18a67614c4941 (patch)
tree535a457b1651d63e65de0d6352cfc70b148e9b32 /quickstep/src
parent4b40d05ebb683e3ab963c25367779eac21ff864d (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.java90
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