diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 80ee57791c..2e31ef239e 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -127,13 +127,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag private RemoteAnimationProvider mRemoteAnimationProvider; - private final AnimatorListenerAdapter mReapplyStateListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mLauncher.getStateManager().reapplyState(); - } - }; - private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { @@ -260,7 +253,13 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag launcherAnim.setDuration(RECENTS_LAUNCH_DURATION); // Make sure recents gets fixed up by resetting task alphas and scales, etc. - windowAnimEndListener = mReapplyStateListener; + windowAnimEndListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLauncher.getStateManager().moveToRestState(); + mLauncher.getStateManager().reapplyState(); + } + }; } else { AnimatorPlaybackController controller = mLauncher.getStateManager() diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java index 28b06fb2d6..abb479dea7 100644 --- a/quickstep/src/com/android/quickstep/QuickScrubController.java +++ b/quickstep/src/com/android/quickstep/QuickScrubController.java @@ -63,6 +63,7 @@ public class QuickScrubController implements OnAlarmListener { private final BaseActivity mActivity; private boolean mInQuickScrub; + private boolean mWaitingForTaskLaunch; private int mQuickScrubSection; private boolean mStartedFromHome; private boolean mFinishedTransitionToQuickScrub; @@ -79,11 +80,11 @@ public class QuickScrubController implements OnAlarmListener { } public void onQuickScrubStart(boolean startingFromHome, ActivityControlHelper controlHelper) { + prepareQuickScrub(TAG); mInQuickScrub = true; mStartedFromHome = startingFromHome; mQuickScrubSection = 0; mFinishedTransitionToQuickScrub = false; - mOnFinishedTransitionToQuickScrubRunnable = null; mActivityControlHelper = controlHelper; snapToNextTaskIfAvailable(); @@ -99,11 +100,17 @@ public class QuickScrubController implements OnAlarmListener { Runnable launchTaskRunnable = () -> { TaskView taskView = mRecentsView.getPageAt(page); if (taskView != null) { + mWaitingForTaskLaunch = true; taskView.launchTask(true, (result) -> { if (!result) { taskView.notifyTaskLaunchFailed(TAG); breakOutOfQuickScrub(); + } else { + mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(Touch.DRAGDROP, + LauncherLogProto.Action.Direction.NONE, page, + TaskUtils.getComponentKeyForTask(taskView.getTask().key)); } + mWaitingForTaskLaunch = false; }, taskView.getHandler()); } else { breakOutOfQuickScrub(); @@ -123,9 +130,19 @@ public class QuickScrubController implements OnAlarmListener { mOnFinishedTransitionToQuickScrubRunnable = launchTaskRunnable; } } - mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(Touch.DRAGDROP, - LauncherLogProto.Action.Direction.NONE, page, - TaskUtils.getComponentKeyForTask(mRecentsView.getPageAt(page).getTask().key)); + } + + /** + * Initializes the UI for quick scrub, returns true if success. + */ + public boolean prepareQuickScrub(String tag) { + if (mWaitingForTaskLaunch || mInQuickScrub) { + Log.d(tag, "Waiting for last scrub to finish, will skip this interaction"); + return false; + } + mOnFinishedTransitionToQuickScrubRunnable = null; + mRecentsView.setNextPageSwitchRunnable(null); + return true; } /** @@ -166,9 +183,11 @@ public class QuickScrubController implements OnAlarmListener { public void onFinishedTransitionToQuickScrub() { mFinishedTransitionToQuickScrub = true; - if (mOnFinishedTransitionToQuickScrubRunnable != null) { - mOnFinishedTransitionToQuickScrubRunnable.run(); - mOnFinishedTransitionToQuickScrubRunnable = null; + Runnable action = mOnFinishedTransitionToQuickScrubRunnable; + // Clear the runnable before executing it, to prevent potential recursion. + mOnFinishedTransitionToQuickScrubRunnable = null; + if (action != null) { + action.run(); } } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index bd05b6d7bf..541369d508 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -349,12 +349,20 @@ public class TouchInteractionService extends Service { return; } if (interactionType == INTERACTION_QUICK_SCRUB) { + if (!mQuickScrubController.prepareQuickScrub(TAG)) { + mInvalidated = true; + return; + } OverviewCallbacks.get(mActivity).closeAllWindows(); ActivityManagerWrapper.getInstance() .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); mStartPending = true; Runnable action = () -> { + if (!mQuickScrubController.prepareQuickScrub(TAG)) { + mInvalidated = true; + return; + } mActivityHelper.onQuickInteractionStart(mActivity, null, true); mQuickScrubController.onQuickScrubProgress(mLastProgress); mStartPending = false; @@ -384,7 +392,7 @@ public class TouchInteractionService extends Service { @Override public void onQuickScrubProgress(float progress) { mLastProgress = progress; - if (mInvalidated || mEndPending) { + if (mInvalidated || mStartPending) { return; } mQuickScrubController.onQuickScrubProgress(progress); diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 807dae8bcd..84b2176488 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -109,6 +109,8 @@ public class WindowTransformSwipeHandler { private static final int STATE_CAPTURE_SCREENSHOT = 1 << 14; private static final int STATE_SCREENSHOT_CAPTURED = 1 << 15; + private static final int STATE_RESUME_LAST_TASK = 1 << 16; + private static final int LAUNCHER_UI_STATES = STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED; @@ -139,6 +141,7 @@ public class WindowTransformSwipeHandler { "STATE_QUICK_SCRUB_END", "STATE_CAPTURE_SCREENSHOT", "STATE_SCREENSHOT_CAPTURED", + "STATE_RESUME_LAST_TASK", }; public static final long MAX_SWIPE_DURATION = 350; @@ -187,6 +190,7 @@ public class WindowTransformSwipeHandler { private boolean mGestureStarted; private int mLogAction = Touch.SWIPE; private float mCurrentQuickScrubProgress; + private boolean mQuickScrubBlocked; private @InteractionType int mInteractionType = INTERACTION_NORMAL; @@ -239,9 +243,12 @@ public class WindowTransformSwipeHandler { mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED, this::sendRemoteAnimationsToAnimationFactory); - mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED - | STATE_SCALED_CONTROLLER_APP, + + mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_APP, + this::resumeLastTaskForQuickstep); + mStateCallback.addCallback(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED, this::resumeLastTask); + mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED | STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_CAPTURE_SCREENSHOT, @@ -258,9 +265,6 @@ public class WindowTransformSwipeHandler { | STATE_GESTURE_COMPLETED, this::setupLauncherUiAfterSwipeUpAnimation); - mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_APP, - this::reset); - mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler); mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED, this::invalidateHandlerWithLauncher); @@ -656,10 +660,16 @@ public class WindowTransformSwipeHandler { anim.start(); } + @UiThread + private void resumeLastTaskForQuickstep() { + setStateOnUiThread(STATE_RESUME_LAST_TASK); + doLogGesture(false /* toLauncher */); + reset(); + } + @UiThread private void resumeLastTask() { mRecentsAnimationWrapper.finish(false /* toHome */, null); - doLogGesture(false /* toLauncher */); } public void reset() { @@ -760,6 +770,11 @@ public class WindowTransformSwipeHandler { } private void onQuickScrubStart() { + if (!mQuickScrubController.prepareQuickScrub(TAG)) { + mQuickScrubBlocked = true; + setStateOnUiThread(STATE_RESUME_LAST_TASK | STATE_HANDLER_INVALIDATED); + return; + } if (mLauncherTransitionController != null) { mLauncherTransitionController.getAnimationPlayer().end(); mLauncherTransitionController = null; @@ -793,12 +808,16 @@ public class WindowTransformSwipeHandler { } private void onFinishedTransitionToQuickScrub() { + if (mQuickScrubBlocked) { + return; + } mQuickScrubController.onFinishedTransitionToQuickScrub(); } public void onQuickScrubProgress(float progress) { mCurrentQuickScrubProgress = progress; - if (Looper.myLooper() != Looper.getMainLooper() || mQuickScrubController == null) { + if (Looper.myLooper() != Looper.getMainLooper() || mQuickScrubController == null + || mQuickScrubBlocked) { return; } mQuickScrubController.onQuickScrubProgress(progress); @@ -809,6 +828,9 @@ public class WindowTransformSwipeHandler { } private void switchToFinalAppAfterQuickScrub() { + if (mQuickScrubBlocked) { + return; + } mQuickScrubController.onQuickScrubEnd(); // Normally this is handled in reset(), but since we are still scrubbing after the