Merge "Re-enable quick scrub/switch from launcher" into ub-launcher3-master
diff --git a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
index 40246e2..f333b93 100644
--- a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
+++ b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
@@ -67,7 +67,6 @@
 
     private static final long MAX_SWIPE_DURATION = 200;
     private static final long MIN_SWIPE_DURATION = 80;
-    private static final int QUICK_SWITCH_SNAP_DURATION = 120;
 
     // Ideal velocity for a smooth transition
     private static final float PIXEL_PER_MS = 2f;
@@ -369,14 +368,8 @@
             ((TaskView) currentRecentsPage).animateIconToScale(1f);
         }
         if (mInteractionType == INTERACTION_QUICK_SWITCH) {
-            for (int i = mRecentsView.getFirstTaskIndex(); i < mRecentsView.getPageCount(); i++) {
-                TaskView taskView = (TaskView) mRecentsView.getPageAt(i);
-                if (taskView.getTask().key.id != mRunningTaskId) {
-                    mRecentsView.snapToPage(i, QUICK_SWITCH_SNAP_DURATION);
-                    taskView.postDelayed(() -> {taskView.launchTask(true);},
-                            QUICK_SWITCH_SNAP_DURATION);
-                    break;
-                }
+            if (mQuickScrubController != null) {
+                mQuickScrubController.onQuickSwitch();
             }
         } else if (mInteractionType == INTERACTION_QUICK_SCRUB) {
             if (mQuickScrubController != null) {
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index d1ce820..01c99d5 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -19,7 +19,6 @@
 import android.view.HapticFeedbackConstants;
 
 import com.android.launcher3.Alarm;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.OnAlarmListener;
 
 /**
@@ -30,26 +29,27 @@
  */
 public class QuickScrubController implements OnAlarmListener {
 
+    public static final int QUICK_SWITCH_START_DURATION = 133;
+    public static final int QUICK_SWITCH_SNAP_DURATION = 120;
+
     private static final int NUM_QUICK_SCRUB_SECTIONS = 5;
     private static final long AUTO_ADVANCE_DELAY = 500;
     private static final int QUICKSCRUB_SNAP_DURATION_PER_PAGE = 325;
     private static final int QUICKSCRUB_END_SNAP_DURATION_PER_PAGE = 60;
 
-    private Launcher mLauncher;
     private Alarm mAutoAdvanceAlarm;
     private RecentsView mRecentsView;
 
     private int mQuickScrubSection;
     private int mStartPage;
 
-    public QuickScrubController(Launcher launcher) {
-        mLauncher = launcher;
+    public QuickScrubController(RecentsView recentsView) {
+        mRecentsView = recentsView;
         mAutoAdvanceAlarm = new Alarm();
         mAutoAdvanceAlarm.setOnAlarmListener(this);
     }
 
     public void onQuickScrubStart(boolean startingFromHome) {
-        mRecentsView = mLauncher.getOverviewPanel();
         mStartPage = startingFromHome ? 0 : mRecentsView.getFirstTaskIndex();
         mQuickScrubSection = 0;
     }
@@ -92,6 +92,23 @@
         }
     }
 
+    public void onQuickSwitch() {
+        for (int i = mRecentsView.getFirstTaskIndex(); i < mRecentsView.getPageCount(); i++) {
+            TaskView taskView = (TaskView) mRecentsView.getPageAt(i);
+            if (taskView.getTask().key.id != mRecentsView.getRunningTaskId()) {
+                Runnable launchTaskRunnable = () -> taskView.launchTask(true);
+                if (mRecentsView.snapToPage(i, QUICK_SWITCH_SNAP_DURATION)) {
+                    // Snap to the new page then launch it
+                    mRecentsView.setNextPageSwitchRunnable(launchTaskRunnable);
+                } else {
+                    // No need to move page, just launch task directly
+                    launchTaskRunnable.run();
+                }
+                break;
+            }
+        }
+    }
+
     public void snapToPageForCurrentQuickScrubSection() {
         goToPageWithHaptic(mRecentsView.getFirstTaskIndex() + mQuickScrubSection);
     }
diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
index 343922c..5718869 100644
--- a/quickstep/src/com/android/quickstep/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/RecentsView.java
@@ -124,7 +124,7 @@
         setClipToOutline(true);
 
         mLauncher = Launcher.getLauncher(context);
-        mQuickScrubController = new QuickScrubController(mLauncher);
+        mQuickScrubController = new QuickScrubController(this);
         mModel = RecentsModel.getInstance(context);
 
         mScrollState.isRtl = mIsRtl;
@@ -431,6 +431,10 @@
         return getChildCount() - mFirstTaskIndex;
     }
 
+    public int getRunningTaskId() {
+        return mRunningTaskId;
+    }
+
     /**
      * Reloads the view if anything in recents changed.
      */
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 5e89644..0c5d961 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -44,6 +44,7 @@
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherState;
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.model.ModelPreload;
 import com.android.launcher3.R;
@@ -218,21 +219,27 @@
         if (!target.getWindowId().isFocused()) {
             return mNoOpTouchConsumer;
         }
-        return new LauncherTouchConsumer(target);
+        return new LauncherTouchConsumer(launcher, target);
     }
 
     private class LauncherTouchConsumer implements TouchConsumer {
 
+        private final Launcher mLauncher;
         private final View mTarget;
         private final int[] mLocationOnScreen = new int[2];
         private final PointF mDownPos = new PointF();
         private final int mTouchSlop;
+        private final QuickScrubController mQuickScrubController;
 
         private boolean mTrackingStarted = false;
 
-        LauncherTouchConsumer(View target) {
+        LauncherTouchConsumer(Launcher launcher, View target) {
+            mLauncher = launcher;
             mTarget = target;
             mTouchSlop = ViewConfiguration.get(mTarget.getContext()).getScaledTouchSlop();
+
+            mQuickScrubController = mLauncher.<RecentsView>getOverviewPanel()
+                    .getQuickScrubController();
         }
 
         @Override
@@ -282,6 +289,33 @@
             ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
             ev.setEdgeFlags(flags);
         }
+
+        @Override
+        public void updateTouchTracking(int interactionType) {
+            mMainThreadExecutor.execute(() -> {
+                if (TouchConsumer.isInteractionQuick(interactionType)) {
+                    Runnable onComplete = null;
+                    if (interactionType == INTERACTION_QUICK_SCRUB) {
+                        mQuickScrubController.onQuickScrubStart(true);
+                    } else if (interactionType == INTERACTION_QUICK_SWITCH) {
+                        onComplete = mQuickScrubController::onQuickSwitch;
+                    }
+                    mLauncher.getStateManager().goToState(LauncherState.OVERVIEW, true, 0,
+                            QuickScrubController.QUICK_SWITCH_START_DURATION, onComplete);
+                }
+            });
+        }
+
+        @Override
+        public void onQuickScrubEnd() {
+            mMainThreadExecutor.execute(mQuickScrubController::onQuickScrubEnd);
+        }
+
+        @Override
+        public void onQuickScrubProgress(float progress) {
+            mMainThreadExecutor.execute(() -> mQuickScrubController.onQuickScrubProgress(progress));
+        }
+
     }
 
     private void initBackgroundChoreographer() {
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 7247af4..5d0a6d1 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -18,6 +18,7 @@
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.quickstep.QuickScrubController.QUICK_SWITCH_START_DURATION;
 import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
 import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
 import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SWITCH;
@@ -105,8 +106,6 @@
 
     private static final long MAX_SWIPE_DURATION = 200;
     private static final long MIN_SWIPE_DURATION = 80;
-    private static final int QUICK_SWITCH_START_DURATION = 133;
-    private static final int QUICK_SWITCH_SNAP_DURATION = 120;
 
     private static final float MIN_PROGRESS_FOR_OVERVIEW = 0.5f;
 
@@ -161,7 +160,6 @@
     private boolean mGestureStarted;
 
     private @InteractionType int mInteractionType = INTERACTION_NORMAL;
-    private boolean mStartedQuickScrubFromHome;
     private boolean mDeferredQuickScrubEnd;
 
     private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper();
@@ -379,14 +377,10 @@
     }
 
     private void updateUiForQuickScrub() {
-        mStartedQuickScrubFromHome = mWasLauncherAlreadyVisible;
         mDeferredQuickScrubEnd = false;
         mQuickScrubController = mRecentsView.getQuickScrubController();
-        mQuickScrubController.onQuickScrubStart(mStartedQuickScrubFromHome);
+        mQuickScrubController.onQuickScrubStart(false);
         animateToProgress(1f, QUICK_SWITCH_START_DURATION);
-        if (mStartedQuickScrubFromHome) {
-            mLauncherLayoutListener.setVisibility(View.INVISIBLE);
-        }
     }
 
     @WorkerThread
@@ -431,10 +425,6 @@
 
     @WorkerThread
     private void updateFinalShift() {
-        if (mStartedQuickScrubFromHome) {
-            return;
-        }
-
         float shift = mCurrentShift.value;
 
         synchronized (mRecentsAnimationWrapper) {
@@ -642,19 +632,8 @@
         mRecentsAnimationWrapper.finish(true /* toHome */);
 
         if (mInteractionType == INTERACTION_QUICK_SWITCH) {
-            for (int i = mRecentsView.getFirstTaskIndex(); i < mRecentsView.getPageCount(); i++) {
-                TaskView taskView = (TaskView) mRecentsView.getPageAt(i);
-                if (taskView.getTask().key.id != mRunningTaskId) {
-                    Runnable launchTaskRunnable = () -> taskView.launchTask(true);
-                    if (mRecentsView.snapToPage(i, QUICK_SWITCH_SNAP_DURATION)) {
-                        // Snap to the new page then launch it
-                        mRecentsView.setNextPageSwitchRunnable(launchTaskRunnable);
-                    } else {
-                        // No need to move page, just launch task directly
-                        launchTaskRunnable.run();
-                    }
-                    break;
-                }
+            if (mQuickScrubController != null) {
+                mQuickScrubController.onQuickSwitch();
             }
         } else if (mInteractionType == INTERACTION_QUICK_SCRUB) {
             if (mQuickScrubController != null) {
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 137e4b1..6050d15 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -158,6 +158,11 @@
 
     private void goToState(LauncherState state, boolean animated, long delay,
             Runnable onCompleteRunnable) {
+        goToState(state, animated, delay, -1, onCompleteRunnable);
+    }
+
+    public void goToState(LauncherState state, boolean animated, long delay, long overrideDuration,
+            Runnable onCompleteRunnable) {
         if (mLauncher.isInState(state) && mConfig.mCurrentAnimation == null) {
             // Run any queued runnable
             if (onCompleteRunnable != null) {
@@ -189,6 +194,9 @@
         // Since state NORMAL can be reached from multiple states, just assume that the
         // transition plays in reverse and use the same duration as previous state.
         mConfig.duration = state == NORMAL ? mState.transitionDuration : state.transitionDuration;
+        if (overrideDuration > -1) {
+            mConfig.duration = overrideDuration;
+        }
 
         AnimatorSet animation = createAnimationToNewWorkspaceInternal(
                 state, new AnimatorSetBuilder(), onCompleteRunnable);