Account for tasks over splitscreen in RemoteTargetGluer

* Previously we defaulted to 2 handles, but we didn't take into
account the posibility of having assistant showing a translucent
task on top of 2 apps. Or other tasks such as Home controls.
* We can scale down the number of handles we have from
initialization (as done in assignTargetsForSplitscreen), but it's
a bit harder to scale up. This is a separate, larger problem in
that the handles are created and needed before onAnimationStart(),
so Launcher doesn't know exactly how many handles are needed to be
created for the recents animation, that's determined by the actual
onAnimationStart() call itself.
* There's a small known bug only in the split case where one of
the tasks shows up over the assistant task, but can live with that
to minimize changes. (peanutbutter@ to clarify?)

Demo: https://drive.google.com/file/d/1hqipfdym_rRXFsAW932es7UdxTx66Zu4/view?usp=drive_link&resourcekey=0-Ri_Kl0xCNN3E81StTh4vxw

As you can see, Assistant translucent overlay seems to work well,
but there are still some glitches with Home controls. Specifically,
there is a flicker, sometimes followed by a black screen, when
returning to the split tasks with Home controls open on top. The
flicker also happens with Assistant, but I haven't seen the black
screen for that case yet. In any case, the crash is avoided, so...
progress? (Also these flickers/black screen happen for Home controls
even without splitscreen).

Original change by peanutbutter@: ag/24830632

Test: Tested assistant result tasks with fullscreen and splitscreen,
and by itself. Seems to animate fine. Also tested with Home controls,
which animates fine and avoids the crash, but still has some issues
when re-opening the tasks as described above.
Flag: NA
Bug: 321328009

Change-Id: I0aa04a6a14cf723b34431855483662039c96e553
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 98d0ece..2e70703 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -20,11 +20,13 @@
 import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.wm.shell.util.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;
 
+import android.app.WindowConfiguration;
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.Log;
 import android.view.RemoteAnimationTarget;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.util.SplitConfigurationOptions;
@@ -35,6 +37,8 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Glues together the necessary components to animate a remote target using a
@@ -43,7 +47,9 @@
 public class RemoteTargetGluer {
     private static final String TAG = "RemoteTargetGluer";
 
-    private static final int DEFAULT_NUM_HANDLES = 2;
+    // This is the default number of handles to create when we don't know how many tasks are running
+    // (e.g. if we're in split screen). Allocate extra for potential tasks overlaid, like volume.
+    private static final int DEFAULT_NUM_HANDLES = 4;
 
     private RemoteTargetHandle[] mRemoteTargetHandles;
     private SplitConfigurationOptions.SplitBounds mSplitBounds;
@@ -107,7 +113,7 @@
         for (int i = 0; i < mRemoteTargetHandles.length; i++) {
             RemoteAnimationTarget primaryTaskTarget = targets.apps[i];
             mRemoteTargetHandles[i].mTransformParams.setTargetSet(
-                    createRemoteAnimationTargetsForTarget(targets, null));
+                    createRemoteAnimationTargetsForTarget(targets, Collections.emptyList()));
             mRemoteTargetHandles[i].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
         }
         return mRemoteTargetHandles;
@@ -177,18 +183,42 @@
             RemoteAnimationTarget topLeftTarget = targets.findTask(mSplitBounds.leftTopTaskId);
             RemoteAnimationTarget bottomRightTarget = targets.findTask(
                     mSplitBounds.rightBottomTaskId);
+            List<RemoteAnimationTarget> overlayTargets = Arrays.stream(targets.apps).filter(
+                    target -> target.windowConfiguration.getWindowingMode()
+                            != WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW).toList();
 
             // remoteTargetHandle[0] denotes topLeft task, so we pass in the bottomRight to exclude,
             // vice versa
             mRemoteTargetHandles[0].mTransformParams.setTargetSet(
-                    createRemoteAnimationTargetsForTarget(targets, bottomRightTarget));
-            mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(topLeftTarget,
-                    mSplitBounds);
+                    createRemoteAnimationTargetsForTarget(targets,
+                            Collections.singletonList(bottomRightTarget)));
+            mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(topLeftTarget, mSplitBounds);
 
             mRemoteTargetHandles[1].mTransformParams.setTargetSet(
-                    createRemoteAnimationTargetsForTarget(targets, topLeftTarget));
-            mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(bottomRightTarget,
-                    mSplitBounds);
+                    createRemoteAnimationTargetsForTarget(targets,
+                            Collections.singletonList(topLeftTarget)));
+            mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(bottomRightTarget, mSplitBounds);
+
+            // Set the remaining overlay tasks to be their own TaskViewSimulator as fullscreen tasks
+            if (!overlayTargets.isEmpty()) {
+                ArrayList<RemoteAnimationTarget> targetsToExclude = new ArrayList<>();
+                targetsToExclude.add(topLeftTarget);
+                targetsToExclude.add(bottomRightTarget);
+                // Start i at 2 to account for top/left and bottom/right split handles already made
+                for (int i = 2; i < targets.apps.length; i++) {
+                    if (i >= mRemoteTargetHandles.length) {
+                        Log.e(TAG, String.format("Attempting to animate an untracked target"
+                                + " (%d handles allocated, but %d want to animate)",
+                                mRemoteTargetHandles.length, targets.apps.length));
+                        break;
+                    }
+                    mRemoteTargetHandles[i].mTransformParams.setTargetSet(
+                            createRemoteAnimationTargetsForTarget(targets, targetsToExclude));
+                    mRemoteTargetHandles[i].mTaskViewSimulator.setPreview(
+                            overlayTargets.get(i - 2));
+                }
+
+            }
         }
         return mRemoteTargetHandles;
     }
@@ -214,32 +244,38 @@
     /**
      * Ensures that we aren't excluding ancillary targets such as home/recents
      *
-     * @param targetToExclude Will be excluded from the resulting return value.
-     *                        Pass in {@code null} to not exclude anything
+     * @param targetsToExclude Will be excluded from the resulting return value.
+     *                        Pass in an empty list to not exclude anything
      * @return RemoteAnimationTargets where all the app targets from the passed in
-     *         {@param targets} are included except {@param targetToExclude}
+     *         {@code targets} are included except {@code targetsToExclude}
      */
     private RemoteAnimationTargets createRemoteAnimationTargetsForTarget(
-            RemoteAnimationTargets targets,
-            RemoteAnimationTarget targetToExclude) {
-        ArrayList<RemoteAnimationTarget> targetsWithoutExcluded = new ArrayList<>();
+            @NonNull RemoteAnimationTargets targets,
+            @NonNull List<RemoteAnimationTarget> targetsToExclude) {
+        ArrayList<RemoteAnimationTarget> targetsToInclude = new ArrayList<>();
 
         for (RemoteAnimationTarget targetCompat : targets.unfilteredApps) {
-            if (targetCompat == targetToExclude) {
+            boolean skipTarget = false;
+            for (RemoteAnimationTarget excludingTarget : targetsToExclude) {
+                if (targetCompat == excludingTarget) {
+                    skipTarget = true;
+                    break;
+                }
+                if (excludingTarget != null
+                        && excludingTarget.taskInfo != null
+                        && targetCompat.taskInfo != null
+                        && excludingTarget.taskInfo.parentTaskId == targetCompat.taskInfo.taskId) {
+                    // Also exclude corresponding parent task
+                    skipTarget = true;
+                }
+            }
+            if (skipTarget) {
                 continue;
             }
-            if (targetToExclude != null
-                    && targetToExclude.taskInfo != null
-                    && targetCompat.taskInfo != null
-                    && targetToExclude.taskInfo.parentTaskId == targetCompat.taskInfo.taskId) {
-                // Also exclude corresponding parent task
-                continue;
-            }
-
-            targetsWithoutExcluded.add(targetCompat);
+            targetsToInclude.add(targetCompat);
         }
-        final RemoteAnimationTarget[] filteredApps = targetsWithoutExcluded.toArray(
-                new RemoteAnimationTarget[targetsWithoutExcluded.size()]);
+        final RemoteAnimationTarget[] filteredApps = targetsToInclude.toArray(
+                new RemoteAnimationTarget[0]);
         return new RemoteAnimationTargets(
                 filteredApps, targets.wallpapers, targets.nonApps, targets.targetMode);
     }