Fix issue with Shell listeners being unbound if SysUI is restarted

- If SysUI is restarted (ie. during dev or a crash), the components
  registering the shell listeners may not be aware of this, and
  listener callbacks will not be re-registered.  Currently all the
  listeners are managed correctly (bound & later unbound) so we can
  just keep the active listener references to re-register if this
  happens.

Bug: 207142749
Test: Kill SysUI, start some apps and ensure Launcher still shows them
      in recents
Change-Id: Iba3b11ee972caf8f0b482942d38c3a7359211180
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index c5f4a53..097850f 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -36,6 +36,7 @@
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
 import com.android.wm.shell.util.StagedSplitBounds;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.function.Consumer;
@@ -219,6 +220,26 @@
         return newTasks;
     }
 
+    public void dump(String prefix, PrintWriter writer) {
+        writer.println(prefix + "RecentTasksList:");
+        writer.println(prefix + "  mChangeId=" + mChangeId);
+        writer.println(prefix + "  mResultsUi=[id=" + mResultsUi.mRequestId + ", tasks=");
+        for (GroupTask task : mResultsUi) {
+            writer.println(prefix + "    t1=" + task.task1.key.id
+                    + " t2=" + (task.hasMultipleTasks() ? task.task2.key.id : "-1"));
+        }
+        writer.println(prefix + "  ]");
+        int currentUserId = Process.myUserHandle().getIdentifier();
+        ArrayList<GroupedRecentTaskInfo> rawTasks =
+                mSysUiProxy.getRecentTasks(Integer.MAX_VALUE, currentUserId);
+        writer.println(prefix + "  rawTasks=[");
+        for (GroupedRecentTaskInfo task : rawTasks) {
+            writer.println(prefix + "    t1=" + task.mTaskInfo1.taskId
+                    + " t2=" + (task.mTaskInfo2 != null ? task.mTaskInfo2.taskId : "-1"));
+        }
+        writer.println(prefix + "  ]");
+    }
+
     private static class TaskLoadResult extends ArrayList<GroupTask> {
 
         final int mRequestId;
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index e539a8c..5d77a6e 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -43,6 +43,7 @@
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
@@ -220,6 +221,11 @@
         mThumbnailChangeListeners.remove(listener);
     }
 
+    public void dump(String prefix, PrintWriter writer) {
+        writer.println(prefix + "RecentsModel:");
+        mTaskList.dump("  ", writer);
+    }
+
     /**
      * Listener for receiving various task properties changes
      */
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 68b7558..c8abd14 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -83,14 +83,16 @@
         MAIN_EXECUTOR.execute(() -> clearProxy());
     };
 
-    // Save the listeners passed into the proxy since when set/register these listeners,
-    // setProxy may not have been called, eg. OverviewProxyService is not connected yet.
-    private IPipAnimationListener mPendingPipAnimationListener;
-    private ISplitScreenListener mPendingSplitScreenListener;
-    private IStartingWindowListener mPendingStartingWindowListener;
-    private ISmartspaceCallback mPendingSmartspaceCallback;
-    private IRecentTasksListener mPendingRecentTasksListener;
-    private final ArrayList<RemoteTransitionCompat> mPendingRemoteTransitions = new ArrayList<>();
+    // Save the listeners passed into the proxy since OverviewProxyService may not have been bound
+    // yet, and we'll need to set/register these listeners with SysUI when they do.  Note that it is
+    // up to the caller to clear the listeners to prevent leaks as these can be held indefinitely
+    // in case SysUI needs to rebind.
+    private IPipAnimationListener mPipAnimationListener;
+    private ISplitScreenListener mSplitScreenListener;
+    private IStartingWindowListener mStartingWindowListener;
+    private ISmartspaceCallback mSmartspaceCallback;
+    private IRecentTasksListener mRecentTasksListener;
+    private final ArrayList<RemoteTransitionCompat> mRemoteTransitions = new ArrayList<>();
 
     // Used to dedupe calls to SystemUI
     private int mLastShelfHeight;
@@ -167,29 +169,23 @@
         mRecentTasks = recentTasks;
         linkToDeath();
         // re-attach the listeners once missing due to setProxy has not been initialized yet.
-        if (mPendingPipAnimationListener != null && mPip != null) {
-            setPinnedStackAnimationListener(mPendingPipAnimationListener);
-            mPendingPipAnimationListener = null;
+        if (mPipAnimationListener != null && mPip != null) {
+            setPinnedStackAnimationListener(mPipAnimationListener);
         }
-        if (mPendingSplitScreenListener != null && mSplitScreen != null) {
-            registerSplitScreenListener(mPendingSplitScreenListener);
-            mPendingSplitScreenListener = null;
+        if (mSplitScreenListener != null && mSplitScreen != null) {
+            registerSplitScreenListener(mSplitScreenListener);
         }
-        if (mPendingStartingWindowListener != null && mStartingWindow != null) {
-            setStartingWindowListener(mPendingStartingWindowListener);
-            mPendingStartingWindowListener = null;
+        if (mStartingWindowListener != null && mStartingWindow != null) {
+            setStartingWindowListener(mStartingWindowListener);
         }
-        if (mPendingSmartspaceCallback != null && mSmartspaceTransitionController != null) {
-            setSmartspaceCallback(mPendingSmartspaceCallback);
-            mPendingSmartspaceCallback = null;
+        if (mSmartspaceCallback != null && mSmartspaceTransitionController != null) {
+            setSmartspaceCallback(mSmartspaceCallback);
         }
-        for (int i = mPendingRemoteTransitions.size() - 1; i >= 0; --i) {
-            registerRemoteTransition(mPendingRemoteTransitions.get(i));
+        for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) {
+            registerRemoteTransition(mRemoteTransitions.get(i));
         }
-        mPendingRemoteTransitions.clear();
-        if (mPendingRecentTasksListener != null && mRecentTasks != null) {
-            registerRecentTasksListener(mPendingRecentTasksListener);
-            mPendingRecentTasksListener = null;
+        if (mRecentTasksListener != null && mRecentTasks != null) {
+            registerRecentTasksListener(mRecentTasksListener);
         }
 
         if (mPendingSetNavButtonAlpha != null) {
@@ -513,9 +509,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call setPinnedStackAnimationListener", e);
             }
-        } else {
-            mPendingPipAnimationListener = listener;
         }
+        mPipAnimationListener = listener;
     }
 
     public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
@@ -553,9 +548,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call registerSplitScreenListener");
             }
-        } else {
-            mPendingSplitScreenListener = listener;
         }
+        mSplitScreenListener = listener;
     }
 
     public void unregisterSplitScreenListener(ISplitScreenListener listener) {
@@ -566,7 +560,7 @@
                 Log.w(TAG, "Failed call unregisterSplitScreenListener");
             }
         }
-        mPendingSplitScreenListener = null;
+        mSplitScreenListener = null;
     }
 
     /** Start multiple tasks in split-screen simultaneously. */
@@ -687,9 +681,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call registerRemoteTransition");
             }
-        } else {
-            mPendingRemoteTransitions.add(remoteTransition);
         }
+        mRemoteTransitions.add(remoteTransition);
     }
 
     public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) {
@@ -700,7 +693,7 @@
                 Log.w(TAG, "Failed call registerRemoteTransition");
             }
         }
-        mPendingRemoteTransitions.remove(remoteTransition);
+        mRemoteTransitions.remove(remoteTransition);
     }
 
     //
@@ -717,9 +710,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call setStartingWindowListener", e);
             }
-        } else {
-            mPendingStartingWindowListener = listener;
         }
+        mStartingWindowListener = listener;
     }
 
     //
@@ -733,9 +725,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call setStartingWindowListener", e);
             }
-        } else {
-            mPendingSmartspaceCallback = callback;
         }
+        mSmartspaceCallback = callback;
     }
 
     //
@@ -749,9 +740,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call registerRecentTasksListener", e);
             }
-        } else {
-            mPendingRecentTasksListener = listener;
         }
+        mRecentTasksListener = listener;
     }
 
     public void unregisterRecentTasksListener(IRecentTasksListener listener) {
@@ -762,7 +752,7 @@
                 Log.w(TAG, "Failed call unregisterRecentTasksListener");
             }
         }
-        mPendingRecentTasksListener = null;
+        mRecentTasksListener = null;
     }
 
     public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index bda5a30..30dce61 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -976,6 +976,7 @@
             pw.println("  resumed=" + resumed);
             pw.println("  mConsumer=" + mConsumer.getName());
             ActiveGestureLog.INSTANCE.dump("", pw);
+            RecentsModel.INSTANCE.get(this).dump("", pw);
             pw.println("ProtoTrace:");
             pw.println("  file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
         }