Cancel recents animation to app when new task is launched while gesturing
- A bit of a degenerate case, but if a new task is received while
the user is swiping up (but not yet released), none of the usual
signals will finish the recents animation (it's not considered
being in overview so we don't launch it, it's not a quickswitch
since we haven't launched any new tasks ourselves). As a result,
nothing happens (we don't finish the animation, and the new task
is never shown to the user as a result).
Bug: 271188120
Test: Start a gesture, in parallel run:
adb shell am start -n com.android.settings/.Settings
Change-Id: I5215ee87f761c837db9f764bd5d8135e55fa0a21
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index edd8823..9795670 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -62,6 +62,7 @@
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.content.Context;
import android.content.Intent;
@@ -2079,13 +2080,16 @@
if (!mCanceled) {
TaskView nextTask = mRecentsView.getNextPageTaskView();
if (nextTask != null) {
- int taskId = nextTask.getTask().key.id;
+ Task.TaskKey nextTaskKey = nextTask.getTask().key;
+ int taskId = nextTaskKey.id;
mGestureState.updateLastStartedTaskId(taskId);
boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
.contains(taskId);
if (!hasTaskPreviouslyAppeared) {
ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
}
+ ActiveGestureLog.INSTANCE.addLog("Launching task: id=" + taskId
+ + " pkg=" + nextTaskKey.getPackageName());
nextTask.launchTask(success -> {
resultCallback.accept(success);
if (success) {
@@ -2154,7 +2158,18 @@
@Override
public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) {
if (mRecentsAnimationController != null) {
- if (handleTaskAppeared(appearedTaskTargets)) {
+ boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTargets).anyMatch(
+ targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId());
+ if (!mStateCallback.hasStates(STATE_GESTURE_COMPLETED) && !hasStartedTaskBefore) {
+ // This is a special case, if a task is started mid-gesture that wasn't a part of a
+ // previous quickswitch task launch, then cancel the animation back to the app
+ RemoteAnimationTarget appearedTaskTarget = appearedTaskTargets[0];
+ TaskInfo taskInfo = appearedTaskTarget.taskInfo;
+ ActiveGestureLog.INSTANCE.addLog("Unexpected task appeared"
+ + " id=" + taskInfo.taskId
+ + " pkg=" + taskInfo.baseIntent.getComponent().getPackageName());
+ finishRecentsAnimationOnTasksAppeared();
+ } else if (handleTaskAppeared(appearedTaskTargets)) {
Optional<RemoteAnimationTarget> taskTargetOptional =
Arrays.stream(appearedTaskTargets)
.filter(targetCompat ->
@@ -2202,7 +2217,7 @@
if (mRecentsAnimationController != null) {
mRecentsAnimationController.finish(false /* toRecents */, null /* onFinishComplete */);
}
- ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
+ ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimationOnTasksAppeared");
}
/**