Restart running task if another task was started but not appeared
If we just finish the controller to resume the running task like we normally would, the delayed task will appear on top when it's ready. Instead, we need to start the original task in this case. - Move mLastStartedTaskId to GestureState, shared between swipe handlers when continuing the gesture. - Update logic to change LAST_TASK to NEW_TASK if a task was started (but not appeared) during the same gesture; likewise, only change NEW_TASK to LAST_TASK if no task was started. - Finish the controller when successfully starting the task that already appeared, since we won't get onTaskAppeared(). Bug: 156132424 Change-Id: I1e9af297840745ab3d5e90214425f10a2616d90a
This commit is contained in:
@@ -40,6 +40,7 @@ import android.util.Pair;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
@@ -128,7 +129,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
protected MultiStateCallback mStateCallback;
|
||||
|
||||
protected boolean mCanceled;
|
||||
protected int mLastStartedTaskId = -1;
|
||||
|
||||
private boolean mRecentsViewScrollLinked = false;
|
||||
|
||||
@@ -218,11 +218,16 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
if (nextTask != null) {
|
||||
mLastStartedTaskId = taskId;
|
||||
mGestureState.updateLastStartedTaskId(taskId);
|
||||
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
|
||||
success -> {
|
||||
resultCallback.accept(success);
|
||||
if (!success) {
|
||||
if (success) {
|
||||
if (mRecentsView.indexOfChild(nextTask)
|
||||
== getLastAppearedTaskIndex()) {
|
||||
onRestartLastAppearedTask();
|
||||
}
|
||||
} else {
|
||||
mActivityInterface.onLaunchTaskFailed();
|
||||
nextTask.notifyTaskLaunchFailed(TAG);
|
||||
mRecentsAnimationController.finish(true /* toRecents */, null);
|
||||
@@ -235,6 +240,19 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we successfully startNewTask() on the task that was previously running. Normally
|
||||
* we call resumeLastTask() when returning to the previously running task, but this handles a
|
||||
* specific edge case: if we switch from A to B, and back to A before B appears, we need to
|
||||
* start A again to ensure it stays on top.
|
||||
*/
|
||||
@CallSuper
|
||||
protected void onRestartLastAppearedTask() {
|
||||
// Finish the controller here, since we won't get onTaskAppeared() for a task that already
|
||||
// appeared.
|
||||
mRecentsAnimationController.finish(false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@param action} if the recents animation has already started, or queues it to
|
||||
* be run when it is next started.
|
||||
@@ -331,6 +349,14 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
: mRecentsView.getRunningTaskIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether we are continuing a gesture that already landed on a new task,
|
||||
* but before that task appeared.
|
||||
*/
|
||||
protected boolean hasStartedNewTask() {
|
||||
return mGestureState.getLastStartedTaskId() != -1;
|
||||
}
|
||||
|
||||
protected void initTransitionEndpoints(DeviceProfile dp) {
|
||||
mDp = dp;
|
||||
|
||||
|
||||
@@ -725,7 +725,8 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
|
||||
return false;
|
||||
}
|
||||
if (appearedTaskTarget.taskId == mLastStartedTaskId) {
|
||||
if (mGestureState.getEndTarget() == NEW_TASK
|
||||
&& appearedTaskTarget.taskId == mGestureState.getLastStartedTaskId()) {
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
@@ -1016,17 +1017,19 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
if (mRecentsView != null) {
|
||||
int taskToLaunch = mRecentsView.getNextPage();
|
||||
int runningTask = getLastAppearedTaskIndex();
|
||||
if (target == NEW_TASK && taskToLaunch == runningTask) {
|
||||
boolean hasStartedNewTask = hasStartedNewTask();
|
||||
if (target == NEW_TASK && taskToLaunch == runningTask
|
||||
&& !hasStartedNewTask) {
|
||||
// We are about to launch the current running task, so use LAST_TASK
|
||||
// state instead of NEW_TASK. This could happen, for example, if our
|
||||
// scroll is aborted after we determined the target to be NEW_TASK.
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
} else if (target == LAST_TASK && taskToLaunch != runningTask) {
|
||||
} else if (target == LAST_TASK && hasStartedNewTask) {
|
||||
// We are about to re-launch the previously running task, but we can't
|
||||
// just finish the controller like we normally would because that would
|
||||
// instead resume the last task that appeared. As a workaround, launch
|
||||
// the task as if it were a new task.
|
||||
// TODO: is this expected?
|
||||
// instead resume the last task that appeared, and not ensure that this
|
||||
// task is restored to the top. To address this, re-launch the task as
|
||||
// if it were a new task.
|
||||
mGestureState.setEndTarget(NEW_TASK);
|
||||
}
|
||||
}
|
||||
@@ -1164,6 +1167,12 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestartLastAppearedTask() {
|
||||
super.onRestartLastAppearedTask();
|
||||
reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
@@ -518,6 +518,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
ActiveGestureLog.INSTANCE.generateAndSetLogId());
|
||||
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
|
||||
gestureState.updateRunningTask(mGestureState.getRunningTask());
|
||||
gestureState.updateLastStartedTaskId(mGestureState.getLastStartedTaskId());
|
||||
} else {
|
||||
gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||
() -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
@@ -121,6 +120,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
private ActivityManager.RunningTaskInfo mRunningTask;
|
||||
private GestureEndTarget mEndTarget;
|
||||
private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
|
||||
private int mLastStartedTaskId = -1;
|
||||
|
||||
public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
|
||||
mHomeIntent = componentObserver.getHomeIntent();
|
||||
@@ -139,6 +139,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
mRunningTask = other.mRunningTask;
|
||||
mEndTarget = other.mEndTarget;
|
||||
mLastAppearedTaskTarget = other.mLastAppearedTaskTarget;
|
||||
mLastStartedTaskId = other.mLastStartedTaskId;
|
||||
}
|
||||
|
||||
public GestureState() {
|
||||
@@ -234,6 +235,21 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last task that we started via startActivityFromRecents() during this gesture.
|
||||
*/
|
||||
public void updateLastStartedTaskId(int lastStartedTaskId) {
|
||||
mLastStartedTaskId = lastStartedTaskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The id of the task that was most recently started during this gesture, or -1 if
|
||||
* no task has been started yet (i.e. we haven't settled on a new task).
|
||||
*/
|
||||
public int getLastStartedTaskId() {
|
||||
return mLastStartedTaskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the end target for this gesture (if known).
|
||||
*/
|
||||
@@ -300,6 +316,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
pw.println(" runningTask=" + mRunningTask);
|
||||
pw.println(" endTarget=" + mEndTarget);
|
||||
pw.println(" lastAppearedTaskTarget=" + mLastAppearedTaskTarget);
|
||||
pw.println(" lastStartedTaskId=" + mLastStartedTaskId);
|
||||
pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user