From cc9fe8032359eb311e751c97949f8da9c9e0c22a Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 27 Apr 2020 22:42:47 -0500 Subject: [PATCH] Cleanup quick switch logic - Remove mFinishingRecentsAnimationTaskId and related logic; track mLastStartedTaskId and mLastAppearedTaskTarget instead. - Don't finish controller if new gesture is in progress, only finish it when the last started task appears (and invalidate the handler at that point). - Remove onTaskAppeared() from GestureState, handle it directly in BaseSwipeHandler. - When the end target animation finishes, possibly change the end target from LAST_TASK to NEW_TASK or vice versa, depending on the last appeared task. Bug: 154814771 Bug: 154727089 Bug: 155609695 Bug: 154812078 Change-Id: I38669515d064a131361359087f502783d875ddde --- .../android/quickstep/BaseSwipeUpHandler.java | 34 ++++++++-- .../quickstep/FallbackSwipeHandler.java | 20 +++--- .../quickstep/LauncherSwipeHandler.java | 63 ++++++++----------- .../quickstep/TouchInteractionService.java | 32 ++++------ .../android/quickstep/views/RecentsView.java | 10 ++- .../com/android/quickstep/GestureState.java | 62 ++++++------------ .../quickstep/RecentsAnimationCallbacks.java | 2 +- .../quickstep/TaskAnimationManager.java | 23 +++++++ 8 files changed, 127 insertions(+), 119 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index 313ae44902..f797f17302 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -120,7 +120,7 @@ public abstract class BaseSwipeUpHandler resultCallback) { + protected void startNewTask(Consumer resultCallback) { // Launch the task user scrolled to (mRecentsView.getNextPage()). if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { // We finish recents animation inside launchTask() when live tile is enabled. @@ -210,18 +210,17 @@ public abstract class BaseSwipeUpHandler { resultCallback.accept(success); if (!success) { mActivityInterface.onLaunchTaskFailed(); nextTask.notifyTaskLaunchFailed(TAG); - } else { - mActivityInterface.onLaunchTaskSuccess(); + mRecentsAnimationController.finish(true /* toRecents */, null); } }, MAIN_EXECUTOR.getHandler()); } - mStateCallback.setStateOnUiThread(successStateFlag); } mCanceled = false; } @@ -241,6 +240,7 @@ public abstract class BaseSwipeUpHandler {}); + startNewTask(success -> { }); break; } } @@ -416,7 +407,7 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler= 0 && taskToLaunch != runningTaskIndex) @@ -494,6 +485,11 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler | STATE_RECENTS_SCROLLING_FINISHED, this::onSettledOnEndTarget); - mGestureState.runOnceAtState(STATE_TASK_APPEARED_DURING_SWITCH, this::onTaskAppeared); - mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, this::invalidateHandler); mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED, this::invalidateHandlerWithLauncher); @@ -771,20 +768,16 @@ public class LauncherSwipeHandler } } - private void onTaskAppeared() { - RemoteAnimationTargetCompat app = mGestureState.getAnimationTarget(); - if (mRecentsAnimationController != null && app != null) { - - // TODO(b/152480470): Update Task target animation after onTaskAppeared holistically. - /* android.util.Log.d("LauncherSwipeHandler", "onTaskAppeared"); - - final boolean result = mRecentsAnimationController.removeTaskTarget(app); - mGestureState.setAnimationTarget(null); - android.util.Log.d("LauncherSwipeHandler", "removeTask, result=" + result); */ - - mRecentsAnimationController.finish(false /* toRecents */, - null /* onFinishComplete */); + @Override + protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) { + if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) { + return false; } + if (appearedTaskTarget.taskId == mLastStartedTaskId) { + reset(); + return true; + } + return false; } private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling, @@ -1031,12 +1024,22 @@ public class LauncherSwipeHandler // skip doing any future work here for the current gesture. return; } - if (target == NEW_TASK && mRecentsView != null - && mRecentsView.getNextPage() == mRecentsView.getRunningTaskIndex()) { - // 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); + if (mRecentsView != null) { + int taskToLaunch = mRecentsView.getNextPage(); + int runningTask = getLastAppearedTaskIndex(); + if (target == NEW_TASK && taskToLaunch == runningTask) { + // 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) { + // 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? + mGestureState.setEndTarget(NEW_TASK); + } } mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); } @@ -1160,8 +1163,9 @@ public class LauncherSwipeHandler @UiThread private void startNewTaskInternal() { - startNewTask(STATE_HANDLER_INVALIDATED, success -> { + startNewTask(success -> { if (!success) { + reset(); // We couldn't launch the task, so take user to overview so they can // decide what to do instead of staying in this broken state. endLauncherTransitionController(); @@ -1186,19 +1190,6 @@ public class LauncherSwipeHandler .getAnimationPlayer().isStarted()) { mLauncherTransitionController.getAnimationPlayer().cancel(); } - - if (mFinishingRecentsAnimationForNewTaskId != -1) { - // If we are canceling mid-starting a new task, switch to the screenshot since the - // recents animation has finished - switchToScreenshot(); - TaskView newRunningTaskView = mRecentsView.getTaskView( - mFinishingRecentsAnimationForNewTaskId); - int newRunningTaskId = newRunningTaskView != null - ? newRunningTaskView.getTask().key.id - : -1; - mRecentsView.setCurrentTask(newRunningTaskId); - mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId); - } } private void invalidateHandler() { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index ce7a141bae..8eb15cf449 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -30,8 +30,6 @@ import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYS import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED; import android.annotation.TargetApi; -import android.app.ActivityManager; -import android.app.ActivityManager.RunningTaskInfo; import android.app.PendingIntent; import android.app.RemoteAction; import android.app.Service; @@ -518,8 +516,12 @@ public class TouchInteractionService extends Service implements PluginListener mAM.getRunningTask(false /* filterOnlyVisibleRecents */))); + if (mTaskAnimationManager.isRecentsAnimationRunning()) { + gestureState.updateRunningTask(mGestureState.getRunningTask()); + } else { + gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0", + () -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */))); + } return gestureState; } @@ -637,14 +639,7 @@ public class TouchInteractionService extends Service implements PluginListener 0) { - // If the finish animation was interrupted, then continue using the other activity input - // consumer but with the next task as the running task - RunningTaskInfo info = new ActivityManager.RunningTaskInfo(); - info.id = previousGestureState.getFinishingRecentsAnimationTaskId(); - gestureState.updateRunningTask(info); - return createOtherActivityInputConsumer(previousGestureState, gestureState, event); - } else if (gestureState.getRunningTask() == null) { + if (gestureState.getRunningTask() == null) { return mResetGestureInputConsumer; } else if (previousGestureState.isRunningAnimationToLauncher() || gestureState.getActivityInterface().isResumed() @@ -658,25 +653,22 @@ public class TouchInteractionService extends Service implements PluginListener extends PagedView impl } public int getRunningTaskIndex() { - TaskView tv = getRunningTaskView(); + return getTaskIndexForId(mRunningTaskId); + } + + /** + * Get the index of the task view whose id matches {@param taskId}. + * @return -1 if there is no task view for the task id, else the index of the task view. + */ + public int getTaskIndexForId(int taskId) { + TaskView tv = getTaskView(taskId); return tv == null ? -1 : indexOfChild(tv); } diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java index 544f420811..f06e1a6afc 100644 --- a/quickstep/src/com/android/quickstep/GestureState.java +++ b/quickstep/src/com/android/quickstep/GestureState.java @@ -15,6 +15,7 @@ */ 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; @@ -110,10 +111,6 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL public static final int STATE_RECENTS_SCROLLING_FINISHED = getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED"); - // Called when the new task appeared from quick switching. - public static final int STATE_TASK_APPEARED_DURING_SWITCH = - getFlagForIndex("STATE_TASK_APPEARED_DURING_SWITCH"); - // Needed to interact with the current activity private final Intent mHomeIntent; private final Intent mOverviewIntent; @@ -123,9 +120,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL private ActivityManager.RunningTaskInfo mRunningTask; private GestureEndTarget mEndTarget; - private RemoteAnimationTargetCompat mAnimationTarget; - // TODO: This can be removed once we stop finishing the animation when starting a new task - private int mFinishingRecentsAnimationTaskId = -1; + private RemoteAnimationTargetCompat mLastAppearedTaskTarget; public GestureState(OverviewComponentObserver componentObserver, int gestureId) { mHomeIntent = componentObserver.getHomeIntent(); @@ -143,7 +138,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL mGestureId = other.mGestureId; mRunningTask = other.mRunningTask; mEndTarget = other.mEndTarget; - mFinishingRecentsAnimationTaskId = other.mFinishingRecentsAnimationTaskId; + mLastAppearedTaskTarget = other.mLastAppearedTaskTarget; } public GestureState() { @@ -225,6 +220,20 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL mRunningTask = runningTask; } + /** + * Updates the last task that appeared during this gesture. + */ + public void updateLastAppearedTaskTarget(RemoteAnimationTargetCompat lastAppearedTaskTarget) { + mLastAppearedTaskTarget = lastAppearedTaskTarget; + } + + /** + * @return The id of the task that appeared during this gesture. + */ + public int getLastAppearedTaskId() { + return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1; + } + /** * @return the end target for this gesture (if known). */ @@ -232,14 +241,6 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL return mEndTarget; } - public void setAnimationTarget(RemoteAnimationTargetCompat target) { - mAnimationTarget = target; - } - - public RemoteAnimationTargetCompat getAnimationTarget() { - return mAnimationTarget; - } - /** * Sets the end target of this gesture and immediately notifies the state changes. */ @@ -259,30 +260,9 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL } } - /** - * @return the id for the task that was about to be launched following the finish of the recents - * animation. Only defined between when the finish-recents call was made and the launch - * activity call is made. - */ - public int getFinishingRecentsAnimationTaskId() { - return mFinishingRecentsAnimationTaskId; - } - - /** - * Sets the id for the task will be launched after the recents animation is finished. Once the - * animation has finished then the id will be reset to -1. - */ - public void setFinishingRecentsAnimationTaskId(int taskId) { - mFinishingRecentsAnimationTaskId = taskId; - mStateCallback.runOnceAtState(STATE_RECENTS_ANIMATION_FINISHED, () -> { - mFinishingRecentsAnimationTaskId = -1; - }); - } - /** * @return whether the current gesture is still running a recents animation to a state in the * Launcher or Recents activity. - * Updates the running task for the gesture to be the given {@param runningTask}. */ public boolean isRunningAnimationToLauncher() { return isRecentsAnimationRunning() && mEndTarget != null && mEndTarget.isLauncher; @@ -314,18 +294,12 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED); } - @Override - public void onTaskAppeared(RemoteAnimationTargetCompat app) { - mAnimationTarget = app; - mStateCallback.setState(STATE_TASK_APPEARED_DURING_SWITCH); - } - public void dump(PrintWriter pw) { pw.println("GestureState:"); pw.println(" gestureID=" + mGestureId); pw.println(" runningTask=" + mRunningTask); pw.println(" endTarget=" + mEndTarget); - pw.println(" finishingRecentsAnimationTaskId=" + mFinishingRecentsAnimationTaskId); + pw.println(" lastAppearedTaskTarget=" + mLastAppearedTaskTarget); pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning()); } } diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index 103ea4ea23..a21c7140de 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -159,6 +159,6 @@ public class RecentsAnimationCallbacks implements /** * Callback made when a task started from the recents is ready for an app transition. */ - default void onTaskAppeared(RemoteAnimationTargetCompat app) {} + default void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {} } } diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 21e8c92494..cad51f4cc6 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -18,6 +18,7 @@ package com.android.quickstep; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED; +import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED; import android.content.Intent; import android.util.Log; @@ -28,6 +29,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener { @@ -36,6 +38,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn private RecentsAnimationTargets mTargets; // Temporary until we can hook into gesture state events private GestureState mLastGestureState; + private RemoteAnimationTargetCompat mLastAppearedTaskTarget; /** * Preloads the recents animation. @@ -79,6 +82,8 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn } mController = controller; mTargets = targets; + mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId()); + mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); } @Override @@ -96,6 +101,20 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn public void onRecentsAnimationFinished(RecentsAnimationController controller) { cleanUpRecentsAnimation(null /* canceledThumbnail */); } + + @Override + public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) { + if (mController != null) { + if (mLastAppearedTaskTarget == null + || appearedTaskTarget.taskId != mLastAppearedTaskTarget.taskId) { + if (mLastAppearedTaskTarget != null) { + mController.removeTaskTarget(mLastAppearedTaskTarget); + } + mLastAppearedTaskTarget = appearedTaskTarget; + mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); + } + } + } }); mCallbacks.addListener(gestureState); mCallbacks.addListener(listener); @@ -112,6 +131,9 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mCallbacks.removeListener(mLastGestureState); mLastGestureState = gestureState; mCallbacks.addListener(gestureState); + gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED + | STATE_RECENTS_ANIMATION_STARTED); + gestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); return mCallbacks; } @@ -171,6 +193,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mCallbacks = null; mTargets = null; mLastGestureState = null; + mLastAppearedTaskTarget = null; } public void dump() {