Merge "Add multi-task support to recents-animation task-appeared" into sc-v2-dev am: 35b8e2b997
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16184046 Change-Id: I57d186d78773bbd2bbb5c5095ff6a7110a8cdd04
This commit is contained in:
commit
c7e8bbf286
@ -217,7 +217,7 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) throws RemoteException {
|
||||
public void onTasksAppeared(RemoteAnimationTarget[] app) throws RemoteException {
|
||||
/* no-op */
|
||||
}
|
||||
};
|
||||
|
@ -63,5 +63,5 @@ oneway interface IRecentsAnimationRunner {
|
||||
* Called when the task of an activity that has been started while the recents animation
|
||||
* was running becomes ready for control.
|
||||
*/
|
||||
void onTaskAppeared(in RemoteAnimationTarget app) = 3;
|
||||
void onTasksAppeared(in RemoteAnimationTarget[] app) = 3;
|
||||
}
|
||||
|
@ -195,8 +195,13 @@ public class ActivityManagerWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) {
|
||||
animationHandler.onTaskAppeared(new RemoteAnimationTargetCompat(app));
|
||||
public void onTasksAppeared(RemoteAnimationTarget[] apps) {
|
||||
final RemoteAnimationTargetCompat[] compats =
|
||||
new RemoteAnimationTargetCompat[apps.length];
|
||||
for (int i = 0; i < apps.length; ++i) {
|
||||
compats[i] = new RemoteAnimationTargetCompat(apps[i]);
|
||||
}
|
||||
animationHandler.onTasksAppeared(compats);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -39,5 +39,5 @@ public interface RecentsAnimationListener {
|
||||
* Called when the task of an activity that has been started while the recents animation
|
||||
* was running becomes ready for control.
|
||||
*/
|
||||
void onTaskAppeared(RemoteAnimationTargetCompat app);
|
||||
void onTasksAppeared(RemoteAnimationTargetCompat[] app);
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.DataClass;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
@ -127,7 +128,7 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
mToken = transition;
|
||||
// This transition is for opening recents, so recents is on-top. We want to draw
|
||||
// the current going-away task on top of recents, though, so move it to front
|
||||
WindowContainerToken pausingTask = null;
|
||||
final ArrayList<WindowContainerToken> pausingTasks = new ArrayList<>();
|
||||
WindowContainerToken pipTask = null;
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
@ -138,7 +139,8 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
if (taskInfo == null) {
|
||||
continue;
|
||||
}
|
||||
pausingTask = taskInfo.token;
|
||||
// Add to front since we are iterating backwards.
|
||||
pausingTasks.add(0, taskInfo.token);
|
||||
if (taskInfo.pictureInPictureParams != null
|
||||
&& taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
|
||||
pipTask = taskInfo.token;
|
||||
@ -150,7 +152,7 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
t.setAlpha(wallpapers[i].leash.mSurfaceControl, 1);
|
||||
}
|
||||
t.apply();
|
||||
mRecentsSession.setup(controller, info, finishedCallback, pausingTask, pipTask,
|
||||
mRecentsSession.setup(controller, info, finishedCallback, pausingTasks, pipTask,
|
||||
leashMap, mToken);
|
||||
recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
|
||||
new Rect());
|
||||
@ -198,18 +200,18 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
|
||||
private RecentsAnimationControllerCompat mWrapped = null;
|
||||
private IRemoteTransitionFinishedCallback mFinishCB = null;
|
||||
private WindowContainerToken mPausingTask = null;
|
||||
private ArrayList<WindowContainerToken> mPausingTasks = null;
|
||||
private WindowContainerToken mPipTask = null;
|
||||
private TransitionInfo mInfo = null;
|
||||
private SurfaceControl mOpeningLeash = null;
|
||||
private ArrayList<SurfaceControl> mOpeningLeashes = null;
|
||||
private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
|
||||
private PictureInPictureSurfaceTransaction mPipTransaction = null;
|
||||
private IBinder mTransition = null;
|
||||
|
||||
void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
|
||||
IRemoteTransitionFinishedCallback finishCB, WindowContainerToken pausingTask,
|
||||
WindowContainerToken pipTask, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
|
||||
IBinder transition) {
|
||||
IRemoteTransitionFinishedCallback finishCB,
|
||||
ArrayList<WindowContainerToken> pausingTasks, WindowContainerToken pipTask,
|
||||
ArrayMap<SurfaceControl, SurfaceControl> leashMap, IBinder transition) {
|
||||
if (mInfo != null) {
|
||||
throw new IllegalStateException("Trying to run a new recents animation while"
|
||||
+ " recents is already active.");
|
||||
@ -217,7 +219,7 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
mWrapped = wrapped;
|
||||
mInfo = info;
|
||||
mFinishCB = finishCB;
|
||||
mPausingTask = pausingTask;
|
||||
mPausingTasks = pausingTasks;
|
||||
mPipTask = pipTask;
|
||||
mLeashMap = leashMap;
|
||||
mTransition = transition;
|
||||
@ -226,36 +228,57 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
@SuppressLint("NewApi")
|
||||
boolean merge(TransitionInfo info, SurfaceControl.Transaction t,
|
||||
RecentsAnimationListener recents) {
|
||||
TransitionInfo.Change openingTask = null;
|
||||
ArrayList<TransitionInfo.Change> openingTasks = null;
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) {
|
||||
if (change.getTaskInfo() != null) {
|
||||
if (openingTask != null) {
|
||||
Log.w(TAG, " Expecting to merge a task-open, but got >1 opening "
|
||||
+ "tasks");
|
||||
if (openingTasks == null) {
|
||||
openingTasks = new ArrayList<>();
|
||||
}
|
||||
openingTask = change;
|
||||
openingTasks.add(change);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (openingTask == null) return false;
|
||||
mOpeningLeash = openingTask.getLeash();
|
||||
if (openingTask.getContainer().equals(mPausingTask)) {
|
||||
// In this case, we are "returning" to the already running app, so just consume
|
||||
if (openingTasks == null) return false;
|
||||
int pauseMatches = 0;
|
||||
for (int i = 0; i < openingTasks.size(); ++i) {
|
||||
if (mPausingTasks.contains(openingTasks.get(i).getContainer())) {
|
||||
++pauseMatches;
|
||||
}
|
||||
if (openingTasks.get(i).getContainer().equals(mPausingTasks.get(i))) {
|
||||
// In this case, we are "returning" to an already running app, so just consume
|
||||
// the merge and do nothing.
|
||||
}
|
||||
}
|
||||
if (pauseMatches > 0) {
|
||||
if (pauseMatches != mPausingTasks.size()) {
|
||||
// We are not really "returning" properly... something went wrong.
|
||||
throw new IllegalStateException("\"Concelling\" a recents transitions by "
|
||||
+ "unpausing " + pauseMatches + " apps after pausing "
|
||||
+ mPausingTasks.size() + " apps.");
|
||||
}
|
||||
// In this case, we are "returning" to an already running app, so just consume
|
||||
// the merge and do nothing.
|
||||
return true;
|
||||
}
|
||||
// We are receiving a new opening task, so convert to onTaskAppeared.
|
||||
final int layer = mInfo.getChanges().size() * 3;
|
||||
final RemoteAnimationTargetCompat target = new RemoteAnimationTargetCompat(
|
||||
openingTask, layer, mInfo, t);
|
||||
mLeashMap.put(mOpeningLeash, target.leash.mSurfaceControl);
|
||||
t.reparent(target.leash.mSurfaceControl, mInfo.getRootLeash());
|
||||
t.setLayer(target.leash.mSurfaceControl, layer);
|
||||
t.hide(target.leash.mSurfaceControl);
|
||||
t.apply();
|
||||
recents.onTaskAppeared(target);
|
||||
mOpeningLeashes = new ArrayList<>();
|
||||
final RemoteAnimationTargetCompat[] targets =
|
||||
new RemoteAnimationTargetCompat[openingTasks.size()];
|
||||
for (int i = 0; i < openingTasks.size(); ++i) {
|
||||
mOpeningLeashes.add(openingTasks.get(i).getLeash());
|
||||
// We are receiving new opening tasks, so convert to onTasksAppeared.
|
||||
final RemoteAnimationTargetCompat target = new RemoteAnimationTargetCompat(
|
||||
openingTasks.get(i), layer, mInfo, t);
|
||||
mLeashMap.put(mOpeningLeashes.get(i), target.leash.mSurfaceControl);
|
||||
t.reparent(target.leash.mSurfaceControl, mInfo.getRootLeash());
|
||||
t.setLayer(target.leash.mSurfaceControl, layer);
|
||||
t.hide(target.leash.mSurfaceControl);
|
||||
t.apply();
|
||||
targets[i] = target;
|
||||
}
|
||||
recents.onTasksAppeared(targets);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -292,21 +315,26 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
}
|
||||
if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
|
||||
try {
|
||||
if (!toHome && mPausingTask != null && mOpeningLeash == null) {
|
||||
if (!toHome && mPausingTasks != null && mOpeningLeashes == null) {
|
||||
// The gesture went back to opening the app rather than continuing with
|
||||
// recents, so end the transition by moving the app back to the top (and also
|
||||
// re-showing it's task).
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.reorder(mPausingTask, true /* onTop */);
|
||||
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
t.show(mInfo.getChange(mPausingTask).getLeash());
|
||||
for (int i = mPausingTasks.size() - 1; i >= 0; ++i) {
|
||||
// reverse order so that index 0 ends up on top
|
||||
wct.reorder(mPausingTasks.get(i), true /* onTop */);
|
||||
t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
|
||||
}
|
||||
mFinishCB.onTransitionFinished(wct, t);
|
||||
} else {
|
||||
if (mOpeningLeash != null) {
|
||||
if (mOpeningLeashes != null) {
|
||||
// TODO: the launcher animation should handle this
|
||||
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
t.show(mOpeningLeash);
|
||||
t.setAlpha(mOpeningLeash, 1.f);
|
||||
for (int i = 0; i < mOpeningLeashes.size(); ++i) {
|
||||
t.show(mOpeningLeashes.get(i));
|
||||
t.setAlpha(mOpeningLeashes.get(i), 1.f);
|
||||
}
|
||||
t.apply();
|
||||
}
|
||||
if (mPipTask != null && mPipTransaction != null) {
|
||||
@ -339,9 +367,9 @@ public class RemoteTransitionCompat implements Parcelable {
|
||||
// Reset all members.
|
||||
mWrapped = null;
|
||||
mFinishCB = null;
|
||||
mPausingTask = null;
|
||||
mPausingTasks = null;
|
||||
mInfo = null;
|
||||
mOpeningLeash = null;
|
||||
mOpeningLeashes = null;
|
||||
mLeashMap = null;
|
||||
mTransition = null;
|
||||
}
|
||||
|
@ -934,6 +934,10 @@ public class AppTransitionController {
|
||||
voiceInteraction);
|
||||
applyAnimations(closingWcs, closingApps, transit, false /* visible */, animLp,
|
||||
voiceInteraction);
|
||||
final RecentsAnimationController rac = mService.getRecentsAnimationController();
|
||||
if (rac != null) {
|
||||
rac.sendTasksAppeared();
|
||||
}
|
||||
|
||||
for (int i = 0; i < openingApps.size(); ++i) {
|
||||
openingApps.valueAtUnchecked(i).mOverrideTaskTransition = false;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||
@ -163,6 +164,8 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
private boolean mNavigationBarAttachedToApp;
|
||||
private ActivityRecord mNavBarAttachedApp;
|
||||
|
||||
private final ArrayList<RemoteAnimationTarget> mPendingTaskAppears = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* An app transition listener to cancel the recents animation only after the app transition
|
||||
* starts or is canceled.
|
||||
@ -732,11 +735,19 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
return;
|
||||
}
|
||||
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "addTaskToTargets, target: %s", target);
|
||||
try {
|
||||
mRunner.onTaskAppeared(target);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to report task appeared", e);
|
||||
}
|
||||
mPendingTaskAppears.add(target);
|
||||
}
|
||||
}
|
||||
|
||||
void sendTasksAppeared() {
|
||||
if (mPendingTaskAppears.isEmpty() || mRunner == null) return;
|
||||
try {
|
||||
final RemoteAnimationTarget[] targets = mPendingTaskAppears.toArray(
|
||||
new RemoteAnimationTarget[0]);
|
||||
mRunner.onTasksAppeared(targets);
|
||||
mPendingTaskAppears.clear();
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to report task appeared", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,10 +755,15 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
OnAnimationFinishedCallback finishedCallback) {
|
||||
final SparseBooleanArray recentTaskIds =
|
||||
mService.mAtmService.getRecentTasks().getRecentTaskIds();
|
||||
// The target must be built off the root task (the leaf task surface would be cropped
|
||||
// within the root surface). However, recents only tracks leaf task ids, so we'll replace
|
||||
// the task-id with the leaf id.
|
||||
final Task leafTask = task.getTopLeafTask();
|
||||
int taskId = leafTask.mTaskId;
|
||||
TaskAnimationAdapter adapter = (TaskAnimationAdapter) addAnimation(task,
|
||||
!recentTaskIds.get(task.mTaskId), true /* hidden */, finishedCallback);
|
||||
mPendingNewTaskTargets.add(task.mTaskId);
|
||||
return adapter.createRemoteAnimationTarget();
|
||||
!recentTaskIds.get(taskId), true /* hidden */, finishedCallback);
|
||||
mPendingNewTaskTargets.add(taskId);
|
||||
return adapter.createRemoteAnimationTarget(taskId);
|
||||
}
|
||||
|
||||
void logRecentsAnimationStartTime(int durationMs) {
|
||||
@ -782,7 +798,8 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
|
||||
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
|
||||
final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
|
||||
final RemoteAnimationTarget target = taskAdapter.createRemoteAnimationTarget();
|
||||
final RemoteAnimationTarget target =
|
||||
taskAdapter.createRemoteAnimationTarget(INVALID_TASK_ID);
|
||||
if (target != null) {
|
||||
targets.add(target);
|
||||
} else {
|
||||
@ -995,6 +1012,8 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
removeAnimation(taskAdapter);
|
||||
taskAdapter.onCleanup();
|
||||
}
|
||||
// Should already be empty, but clean-up pending task-appears in-case they weren't sent.
|
||||
mPendingTaskAppears.clear();
|
||||
|
||||
for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) {
|
||||
final WallpaperAnimationAdapter wallpaperAdapter = mPendingWallpaperAnimations.get(i);
|
||||
@ -1224,7 +1243,14 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
mLocalBounds.offsetTo(tmpPos.x, tmpPos.y);
|
||||
}
|
||||
|
||||
RemoteAnimationTarget createRemoteAnimationTarget() {
|
||||
/**
|
||||
* @param overrideTaskId overrides the target's taskId. It may differ from mTaskId and thus
|
||||
* can differ from taskInfo. This mismatch is needed, however, in
|
||||
* some cases where we are animating root tasks but need need leaf
|
||||
* ids for identification. If this is INVALID (-1), then mTaskId
|
||||
* will be used.
|
||||
*/
|
||||
RemoteAnimationTarget createRemoteAnimationTarget(int overrideTaskId) {
|
||||
final ActivityRecord topApp = mTask.getTopVisibleActivity();
|
||||
final WindowState mainWindow = topApp != null
|
||||
? topApp.findMainWindow()
|
||||
@ -1238,7 +1264,10 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
final int mode = topApp.getActivityType() == mTargetActivityType
|
||||
? MODE_OPENING
|
||||
: MODE_CLOSING;
|
||||
mTarget = new RemoteAnimationTarget(mTask.mTaskId, mode, mCapturedLeash,
|
||||
if (overrideTaskId < 0) {
|
||||
overrideTaskId = mTask.mTaskId;
|
||||
}
|
||||
mTarget = new RemoteAnimationTarget(overrideTaskId, mode, mCapturedLeash,
|
||||
!topApp.fillsParent(), new Rect(),
|
||||
insets, mTask.getPrefixOrderIndex(), new Point(mBounds.left, mBounds.top),
|
||||
mLocalBounds, mBounds, mTask.getWindowConfiguration(),
|
||||
|
@ -2380,6 +2380,16 @@ class Task extends TaskFragment {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return the top-most leaf-task under this one, or this task if it is a leaf. */
|
||||
public Task getTopLeafTask() {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final Task child = mChildren.get(i).asTask();
|
||||
if (child == null) continue;
|
||||
return child.getTopLeafTask();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
int getDescendantTaskCount() {
|
||||
final int[] currentCount = {0};
|
||||
final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
|
||||
|
Loading…
x
Reference in New Issue
Block a user