From b24efa44949d1c06ea8900182c8e5d2bc0e76aaa Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 5 Apr 2023 05:36:32 +0000 Subject: [PATCH] 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 --- .../android/quickstep/AbsSwipeUpHandler.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index edd88230be..97956701ab 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -62,6 +62,7 @@ import android.animation.ValueAnimator; 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 @@ public abstract class AbsSwipeUpHandler, 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 @@ public abstract class AbsSwipeUpHandler, @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 taskTargetOptional = Arrays.stream(appearedTaskTargets) .filter(targetCompat -> @@ -2202,7 +2217,7 @@ public abstract class AbsSwipeUpHandler, if (mRecentsAnimationController != null) { mRecentsAnimationController.finish(false /* toRecents */, null /* onFinishComplete */); } - ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); + ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimationOnTasksAppeared"); } /**