Making long-press of AllApps to jump directly to search.

Bug: 22210146
Change-Id: Iacf28416d6e31233a68e3b41576a8860b4b72b88
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index ff4c93a..17fdeb1 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -123,9 +123,10 @@
         allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
         allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
         if (mLauncher != null) {
-            allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
             mLauncher.setAllAppsButton(allAppsButton);
+            allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
             allAppsButton.setOnClickListener(mLauncher);
+            allAppsButton.setOnLongClickListener(mLauncher);
             allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
         }
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 55b8f03..339d5a3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -990,7 +990,7 @@
             // view after launching an app, as they may be depending on the UI to be static to
             // switch to another app, otherwise, if it was
             showAppsView(false /* animated */, false /* resetListToTop */,
-                    !launchedFromApp /* updatePredictedApps */);
+                    !launchedFromApp /* updatePredictedApps */, false /* focusSearchBar */);
         } else if (mOnResumeState == State.WIDGETS) {
             showWidgetsView(false, false);
         }
@@ -2543,12 +2543,17 @@
      */
     protected void onClickAllAppsButton(View v) {
         if (LOGD) Log.d(TAG, "onClickAllAppsButton");
-        if (isAppsViewVisible()) {
-            showWorkspace(true);
-        } else {
-            // Try and refresh the set of predicted apps before we enter launcher
+        if (!isAppsViewVisible()) {
             showAppsView(true /* animated */, false /* resetListToTop */,
-                    true /* updatePredictedApps */);
+                    true /* updatePredictedApps */, false /* focusSearchBar */);
+        }
+    }
+
+    protected void onLongClickAllAppsButton(View v) {
+        if (LOGD) Log.d(TAG, "onLongClickAllAppsButton");
+        if (!isAppsViewVisible()) {
+            showAppsView(true /* animated */, false /* resetListToTop */,
+                    true /* updatePredictedApps */, true /* focusSearchBar */);
         }
     }
 
@@ -3125,6 +3130,11 @@
         if (isWorkspaceLocked()) return false;
         if (mState != State.WORKSPACE) return false;
 
+        if (v == mAllAppsButton) {
+            onLongClickAllAppsButton(v);
+            return true;
+        }
+
         if (v instanceof Workspace) {
             if (!mWorkspace.isInOverviewMode()) {
                 if (!mWorkspace.isTouchActive()) {
@@ -3317,14 +3327,15 @@
     /**
      * Shows the apps view.
      */
-    void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps) {
+    void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps,
+            boolean focusSearchBar) {
         if (resetListToTop) {
             mAppsView.scrollToTop();
         }
         if (updatePredictedApps) {
             tryAndUpdatePredictedApps();
         }
-        showAppsOrWidgets(animated, State.APPS);
+        showAppsOrWidgets(State.APPS, animated, focusSearchBar);
     }
 
     /**
@@ -3335,7 +3346,7 @@
         if (resetPageToZero) {
             mWidgetsView.scrollToTop();
         }
-        showAppsOrWidgets(animated, State.WIDGETS);
+        showAppsOrWidgets(State.WIDGETS, animated, false);
 
         mWidgetsView.post(new Runnable() {
             @Override
@@ -3352,7 +3363,7 @@
      */
     // TODO: calling method should use the return value so that when {@code false} is returned
     // the workspace transition doesn't fall into invalid state.
-    private boolean showAppsOrWidgets(boolean animated, State toState) {
+    private boolean showAppsOrWidgets(State toState, boolean animated, boolean focusSearchBar) {
         if (mState != State.WORKSPACE &&  mState != State.APPS_SPRING_LOADED &&
                 mState != State.WIDGETS_SPRING_LOADED) {
             return false;
@@ -3362,7 +3373,7 @@
         }
 
         if (toState == State.APPS) {
-            mStateTransitionAnimation.startAnimationToAllApps(mState, animated);
+            mStateTransitionAnimation.startAnimationToAllApps(animated, focusSearchBar);
         } else {
             mStateTransitionAnimation.startAnimationToWidgets(animated);
         }
@@ -3432,7 +3443,7 @@
     void exitSpringLoadedDragMode() {
         if (mState == State.APPS_SPRING_LOADED) {
             showAppsView(true /* animated */, false /* resetListToTop */,
-                    false /* updatePredictedApps */);
+                    false /* updatePredictedApps */, false /* focusSearchBar */);
         } else if (mState == State.WIDGETS_SPRING_LOADED) {
             showWidgetsView(true, false);
         }
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index e94a2ac..0ea9d8b 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -91,7 +91,6 @@
      */
     static abstract class PrivateTransitionCallbacks {
         void onRevealViewVisible(View revealView, View contentView, View allAppsButtonView) {}
-        void onAnimationComplete(View revealView, View contentView, View allAppsButtonView) {}
         float getMaterialRevealViewFinalAlpha(View revealView) {
             return 0;
         }
@@ -108,6 +107,7 @@
                 View allAppsButtonView) {
             return null;
         }
+        void onTransitionComplete() {}
     }
 
     public static final String TAG = "LauncherStateTransitionAnimation";
@@ -128,8 +128,12 @@
 
     /**
      * Starts an animation to the apps view.
+     *
+     * @param startSearchAfterTransition Immediately starts app search after the transition to
+     *                                   All Apps is completed.
      */
-    public void startAnimationToAllApps(final Launcher.State fromState, final boolean animated) {
+    public void startAnimationToAllApps(final boolean animated,
+            final boolean startSearchAfterTransition) {
         final AllAppsContainerView toView = mLauncher.getAppsView();
         PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
             private int[] mAllAppsToPanelDelta;
@@ -171,10 +175,17 @@
                     }
                 };
             }
+            @Override
+            void onTransitionComplete() {
+                if (startSearchAfterTransition) {
+                    toView.startAppsSearch();
+                }
+            }
         };
         // Only animate the search bar if animating from spring loaded mode back to all apps
         startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, toView, toView.getContentView(),
-                toView.getRevealView(), toView.getSearchBarView(), animated, true, cb);
+                toView.getRevealView(), toView.getSearchBarView(), animated,
+                true /* hideSearchBar */, cb);
     }
 
     /**
@@ -348,7 +359,6 @@
 
                     // Hide the reveal view
                     revealView.setVisibility(View.INVISIBLE);
-                    pCb.onAnimationComplete(revealView, contentView, allAppsButtonView);
 
                     // Disable all necessary layers
                     for (View v : layerViews.keySet()) {
@@ -363,6 +373,7 @@
 
                     // This can hold unnecessary references to views.
                     mStateAnimation = null;
+                    pCb.onTransitionComplete();
                 }
 
             });
@@ -428,6 +439,7 @@
             dispatchOnLauncherTransitionPrepare(toView, animated, false);
             dispatchOnLauncherTransitionStart(toView, animated, false);
             dispatchOnLauncherTransitionEnd(toView, animated, false);
+            pCb.onTransitionComplete();
         }
     }
 
@@ -682,9 +694,6 @@
                         onCompleteRunnable.run();
                     }
 
-                    // Animation complete callback
-                    pCb.onAnimationComplete(revealView, contentView, allAppsButtonView);
-
                     // Disable all necessary layers
                     for (View v : layerViews.keySet()) {
                         if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
@@ -704,6 +713,7 @@
 
                     // This can hold unnecessary references to views.
                     mStateAnimation = null;
+                    pCb.onTransitionComplete();
                 }
             });
 
@@ -739,6 +749,7 @@
             dispatchOnLauncherTransitionPrepare(toView, animated, true);
             dispatchOnLauncherTransitionStart(toView, animated, true);
             dispatchOnLauncherTransitionEnd(toView, animated, true);
+            pCb.onTransitionComplete();
 
             // Run any queued runnables
             if (onCompleteRunnable != null) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 47bbf15..67d5728 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -284,6 +284,15 @@
         return new DefaultAppSearchController(getContext(), this, mAppsRecyclerView);
     }
 
+    /**
+     * Focuses the search field and begins an app search.
+     */
+    public void startAppsSearch() {
+        if (mSearchBarController != null) {
+            mSearchBarController.focusSearchField();
+        }
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();