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
This commit is contained in:
committed by
Andy Wickham
parent
af7ff56792
commit
e16edc943f
@@ -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<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 @@ 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<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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user