diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java index 62cc0bb90a..0dac388493 100644 --- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java +++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java @@ -26,6 +26,7 @@ import android.os.SystemProperties; import android.util.Log; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.Launcher; @@ -39,6 +40,7 @@ import com.android.wm.shell.desktopmode.IDesktopTaskListener; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.Executor; /** * Controls the visibility of the workspace and the resumed / paused state when desktop mode @@ -57,7 +59,7 @@ public class DesktopVisibilityController { private boolean mGestureInProgress; @Nullable - private IDesktopTaskListener mDesktopTaskListener; + private DesktopTaskListenerImpl mDesktopTaskListener; public DesktopVisibilityController(Launcher launcher) { mLauncher = launcher; @@ -67,24 +69,7 @@ public class DesktopVisibilityController { * Register a listener with System UI to receive updates about desktop tasks state */ public void registerSystemUiListener() { - mDesktopTaskListener = new IDesktopTaskListener.Stub() { - @Override - public void onTasksVisibilityChanged(int displayId, int visibleTasksCount) { - MAIN_EXECUTOR.execute(() -> { - if (displayId == mLauncher.getDisplayId()) { - if (DEBUG) { - Log.d(TAG, "desktop visible tasks count changed=" + visibleTasksCount); - } - setVisibleDesktopTasksCount(visibleTasksCount); - } - }); - } - - @Override - public void onStashedChanged(int displayId, boolean stashed) { - Log.w(TAG, "IDesktopTaskListener: onStashedChanged is deprecated"); - } - }; + mDesktopTaskListener = new DesktopTaskListenerImpl(this, mLauncher.getDisplayId()); SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(mDesktopTaskListener); } @@ -93,6 +78,7 @@ public class DesktopVisibilityController { */ public void unregisterSystemUiListener() { SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(null); + mDesktopTaskListener.release(); mDesktopTaskListener = null; } @@ -356,4 +342,43 @@ public class DesktopVisibilityController { */ void onDesktopVisibilityChanged(boolean visible); } + + /** + * Wrapper for the IDesktopTaskListener stub to prevent lingering references to the launcher + * activity via the controller. + */ + private static class DesktopTaskListenerImpl extends IDesktopTaskListener.Stub { + + private DesktopVisibilityController mController; + private final int mDisplayId; + + DesktopTaskListenerImpl(@NonNull DesktopVisibilityController controller, int displayId) { + mController = controller; + mDisplayId = displayId; + } + + /** + * Clears any references to the controller. + */ + void release() { + mController = null; + } + + @Override + public void onTasksVisibilityChanged(int displayId, int visibleTasksCount) { + MAIN_EXECUTOR.execute(() -> { + if (mController != null && displayId == mDisplayId) { + if (DEBUG) { + Log.d(TAG, "desktop visible tasks count changed=" + visibleTasksCount); + } + mController.setVisibleDesktopTasksCount(visibleTasksCount); + } + }); + } + + @Override + public void onStashedChanged(int displayId, boolean stashed) { + Log.w(TAG, "IDesktopTaskListener: onStashedChanged is deprecated"); + } + } } diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index d906bb3fd3..5e6f7e94ff 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -961,7 +961,7 @@ public class SplitSelectStateController { private final int mSplitPlaceholderSize; private final int mSplitPlaceholderInset; private ActivityManager.RunningTaskInfo mTaskInfo; - private ISplitSelectListener mSplitSelectListener; + private DesktopSplitSelectListenerImpl mSplitSelectListener; private Drawable mAppIcon; public SplitFromDesktopController(QuickstepLauncher launcher, @@ -972,21 +972,14 @@ public class SplitSelectStateController { R.dimen.split_placeholder_size); mSplitPlaceholderInset = mLauncher.getResources().getDimensionPixelSize( R.dimen.split_placeholder_inset); - mSplitSelectListener = new ISplitSelectListener.Stub() { - @Override - public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo, - int splitPosition, Rect taskBounds) { - MAIN_EXECUTOR.execute(() -> enterSplitSelect(taskInfo, splitPosition, - taskBounds)); - return true; - } - }; + mSplitSelectListener = new DesktopSplitSelectListenerImpl(this); SystemUiProxy.INSTANCE.get(mLauncher).registerSplitSelectListener(mSplitSelectListener); } void onDestroy() { SystemUiProxy.INSTANCE.get(mLauncher).unregisterSplitSelectListener( mSplitSelectListener); + mSplitSelectListener.release(); mSplitSelectListener = null; } @@ -1079,4 +1072,35 @@ public class SplitSelectStateController { } } } + + /** + * Wrapper for the ISplitSelectListener stub to prevent lingering references to the launcher + * activity via the controller. + */ + private static class DesktopSplitSelectListenerImpl extends ISplitSelectListener.Stub { + + private SplitFromDesktopController mController; + + DesktopSplitSelectListenerImpl(@NonNull SplitFromDesktopController controller) { + mController = controller; + } + + /** + * Clears any references to the controller. + */ + void release() { + mController = null; + } + + @Override + public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo, + int splitPosition, Rect taskBounds) { + MAIN_EXECUTOR.execute(() -> { + if (mController != null) { + mController.enterSplitSelect(taskInfo, splitPosition, taskBounds); + } + }); + return true; + } + } }