diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java index 98d0ece5a0..2e70703b61 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.util.SplitScreenUtils.convertShellSplitBound 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 com.android.wm.shell.util.SplitBounds; 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 @@ import java.util.Arrays; 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 @@ public class RemoteTargetGluer { 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 @@ public class RemoteTargetGluer { RemoteAnimationTarget topLeftTarget = targets.findTask(mSplitBounds.leftTopTaskId); RemoteAnimationTarget bottomRightTarget = targets.findTask( mSplitBounds.rightBottomTaskId); + List 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 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 @@ public class RemoteTargetGluer { /** * 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 targetsWithoutExcluded = new ArrayList<>(); + @NonNull RemoteAnimationTargets targets, + @NonNull List targetsToExclude) { + ArrayList 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); }