Merge "Fix memory leak of Launcher activityfrom QuickstepTransitionManager and LauncherBackAnimationController" into main
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index c6c4dde..f8ea932 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -159,6 +159,7 @@
 import com.android.wm.shell.startingsurface.IStartingWindowListener;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -225,7 +226,8 @@
     private final float mClosingWindowTransY;
     private final float mMaxShadowRadius;
 
-    private final StartingWindowListener mStartingWindowListener = new StartingWindowListener();
+    private final StartingWindowListener mStartingWindowListener =
+            new StartingWindowListener(this);
 
     private DeviceProfile mDeviceProfile;
 
@@ -278,7 +280,6 @@
                 }
             };
 
-            mStartingWindowListener.setTransitionManager(this);
             SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
                     mStartingWindowListener);
         }
@@ -310,8 +311,8 @@
         mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);
         ItemInfo tag = (ItemInfo) v.getTag();
         if (tag != null && tag.shouldUseBackgroundAnimation()) {
-            ContainerAnimationRunner containerAnimationRunner =
-                    ContainerAnimationRunner.from(v, mStartingWindowListener, onEndCallback);
+            ContainerAnimationRunner containerAnimationRunner = ContainerAnimationRunner.from(
+                            v, mLauncher, mStartingWindowListener, onEndCallback);
             if (containerAnimationRunner != null) {
                 mAppLaunchRunner = containerAnimationRunner;
             }
@@ -1152,7 +1153,6 @@
     public void onActivityDestroyed() {
         unregisterRemoteAnimations();
         unregisterRemoteTransitions();
-        mStartingWindowListener.setTransitionManager(null);
         SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
     }
 
@@ -1775,8 +1775,8 @@
         }
 
         @Nullable
-        private static ContainerAnimationRunner from(
-                View v, StartingWindowListener startingWindowListener, RunnableList onEndCallback) {
+        private static ContainerAnimationRunner from(View v, Launcher launcher,
+                StartingWindowListener startingWindowListener, RunnableList onEndCallback) {
             View viewToUse = findViewWithBackground(v);
             if (viewToUse == null) {
                 viewToUse = v;
@@ -1801,8 +1801,13 @@
                         }
                     };
 
-            ActivityLaunchAnimator.Callback callback = task -> ColorUtils.setAlphaComponent(
-                    startingWindowListener.getBackgroundColor(), 255);
+            ActivityLaunchAnimator.Callback callback = task -> {
+                final int backgroundColor =
+                        startingWindowListener.mBackgroundColor == Color.TRANSPARENT
+                                ? launcher.getScrimView().getBackgroundColor()
+                                : startingWindowListener.mBackgroundColor;
+                return ColorUtils.setAlphaComponent(backgroundColor, 255);
+            };
 
             ActivityLaunchAnimator.Listener listener = new ActivityLaunchAnimator.Listener() {
                 @Override
@@ -1912,25 +1917,22 @@
         }
     }
 
-    private class StartingWindowListener extends IStartingWindowListener.Stub {
-        private QuickstepTransitionManager mTransitionManager;
+    private static class StartingWindowListener extends IStartingWindowListener.Stub {
+        private final WeakReference<QuickstepTransitionManager> mTransitionManagerRef;
         private int mBackgroundColor;
 
-        public void setTransitionManager(QuickstepTransitionManager transitionManager) {
-            mTransitionManager = transitionManager;
+        private StartingWindowListener(QuickstepTransitionManager transitionManager) {
+            mTransitionManagerRef = new WeakReference<>(transitionManager);
         }
 
         @Override
         public void onTaskLaunching(int taskId, int supportedType, int color) {
-            mTransitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
+            QuickstepTransitionManager transitionManager = mTransitionManagerRef.get();
+            if (transitionManager != null) {
+                transitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
+            }
             mBackgroundColor = color;
         }
-
-        public int getBackgroundColor() {
-            return mBackgroundColor == Color.TRANSPARENT
-                    ? mLauncher.getScrimView().getBackgroundColor()
-                    : mBackgroundColor;
-        }
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index f1660ee..857c831 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -58,6 +58,8 @@
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.systemui.shared.system.QuickStepContract;
 
+import java.lang.ref.WeakReference;
+
 /**
  * Controls the animation of swiping back and returning to launcher.
  *
@@ -105,7 +107,7 @@
     private boolean mAnimatorSetInProgress = false;
     private float mBackProgress = 0;
     private boolean mBackInProgress = false;
-    private IOnBackInvokedCallback mBackCallback;
+    private OnBackInvokedCallbackStub mBackCallback;
     private IRemoteAnimationFinishedCallback mAnimationFinishedCallback;
     private BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
     private SurfaceControl mScrimLayer;
@@ -137,65 +139,104 @@
      * @param handler Handler to the thread to run the animations on.
      */
     public void registerBackCallbacks(Handler handler) {
-        mBackCallback = new IOnBackInvokedCallback.Stub() {
-            @Override
-            public void onBackCancelled() {
-                handler.post(() -> {
+        mBackCallback = new OnBackInvokedCallbackStub(handler, mProgressAnimator, this);
+        SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(mBackCallback,
+                new RemoteAnimationRunnerStub(this));
+    }
+
+    private static class OnBackInvokedCallbackStub extends IOnBackInvokedCallback.Stub {
+        private Handler mHandler;
+        private BackProgressAnimator mProgressAnimator;
+        // LauncherBackAnimationController has strong reference to Launcher activity, the binder
+        // callback should not hold strong reference to it to avoid memory leak.
+        private WeakReference<LauncherBackAnimationController> mControllerRef;
+
+        private OnBackInvokedCallbackStub(
+                Handler handler,
+                BackProgressAnimator progressAnimator,
+                LauncherBackAnimationController controller) {
+            mHandler = handler;
+            mProgressAnimator = progressAnimator;
+            mControllerRef = new WeakReference<>(controller);
+        }
+
+        @Override
+        public void onBackCancelled() {
+            mHandler.post(() -> {
+                LauncherBackAnimationController controller = mControllerRef.get();
+                if (controller != null) {
                     mProgressAnimator.onBackCancelled(
-                            LauncherBackAnimationController.this::resetPositionAnimated);
-                });
-            }
-
-            @Override
-            public void onBackInvoked() {
-                handler.post(() -> {
-                    startTransition();
-                    mProgressAnimator.reset();
-                });
-            }
-
-            @Override
-            public void onBackProgressed(BackMotionEvent backEvent) {
-                handler.post(() -> {
-                    mProgressAnimator.onBackProgressed(backEvent);
-                });
-            }
-
-            @Override
-            public void onBackStarted(BackMotionEvent backEvent) {
-                handler.post(() -> {
-                    startBack(backEvent);
-                    mProgressAnimator.onBackStarted(backEvent, event -> {
-                        mBackProgress = event.getProgress();
-                        // TODO: Update once the interpolation curve spec is finalized.
-                        mBackProgress =
-                                1 - (1 - mBackProgress) * (1 - mBackProgress) * (1
-                                        - mBackProgress);
-                        updateBackProgress(mBackProgress, event);
-                    });
-                });
-            }
-        };
-
-        final IRemoteAnimationRunner runner = new IRemoteAnimationRunner.Stub() {
-            @Override
-            public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
-                    RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
-                    IRemoteAnimationFinishedCallback finishedCallback) {
-                for (final RemoteAnimationTarget target : apps) {
-                    if (MODE_CLOSING == target.mode) {
-                        mBackTarget = target;
-                        break;
-                    }
+                            controller::resetPositionAnimated);
                 }
-                mAnimationFinishedCallback = finishedCallback;
+            });
+        }
+
+        @Override
+        public void onBackInvoked() {
+            mHandler.post(() -> {
+                LauncherBackAnimationController controller = mControllerRef.get();
+                if (controller != null) {
+                    controller.startTransition();
+                }
+                mProgressAnimator.reset();
+            });
+        }
+
+        @Override
+        public void onBackProgressed(BackMotionEvent backMotionEvent) {
+            mHandler.post(() -> {
+                mProgressAnimator.onBackProgressed(backMotionEvent);
+            });
+        }
+
+        @Override
+        public void onBackStarted(BackMotionEvent backEvent) {
+            mHandler.post(() -> {
+                LauncherBackAnimationController controller = mControllerRef.get();
+                if (controller != null) {
+                    controller.startBack(backEvent);
+                    mProgressAnimator.onBackStarted(backEvent, event -> {
+                        float backProgress = event.getProgress();
+                        // TODO: Update once the interpolation curve spec is finalized.
+                        controller.mBackProgress =
+                                1 - (1 - backProgress) * (1 - backProgress) * (1
+                                        - backProgress);
+                        controller.updateBackProgress(controller.mBackProgress, event);
+                    });
+                }
+            });
+        }
+    }
+
+    private static class RemoteAnimationRunnerStub extends IRemoteAnimationRunner.Stub {
+
+        // LauncherBackAnimationController has strong reference to Launcher activity, the binder
+        // callback should not hold strong reference to it to avoid memory leak.
+        private WeakReference<LauncherBackAnimationController> mControllerRef;
+
+        private RemoteAnimationRunnerStub(LauncherBackAnimationController controller) {
+            mControllerRef = new WeakReference<>(controller);
+        }
+
+        @Override
+        public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
+                RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+                IRemoteAnimationFinishedCallback finishedCallback) {
+            LauncherBackAnimationController controller = mControllerRef.get();
+            if (controller == null) {
+                return;
             }
+            for (final RemoteAnimationTarget target : apps) {
+                if (MODE_CLOSING == target.mode) {
+                    controller.mBackTarget = target;
+                    break;
+                }
+            }
+            controller.mAnimationFinishedCallback = finishedCallback;
+        }
 
-            @Override
-            public void onAnimationCancelled() {}
-        };
-
-        SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(mBackCallback, runner);
+        @Override
+        public void onAnimationCancelled() {}
     }
 
     private void resetPositionAnimated() {