Search query method should support multiple consumers

Bug: 170488559
Change-Id: I64bef9523d3c3950c4ca3a4b9ce1d506d1672200
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 8c059d5..2450787 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -178,16 +178,46 @@
     /**
      * Sets results list for search
      */
-    public boolean setSearchResults(ArrayList<AdapterItem> f) {
-        if (f == null || mSearchResults != f) {
-            boolean same = mSearchResults != null && mSearchResults.equals(f);
-            mSearchResults = f;
+    public boolean setSearchResults(ArrayList<AdapterItem> results) {
+        if (results == null || mSearchResults != results) {
+            boolean same = mSearchResults != null && mSearchResults.equals(results);
+            mSearchResults = results;
             onAppsUpdated();
             return !same;
         }
         return false;
     }
 
+    public boolean appendSearchResults(ArrayList<AdapterItem> results) {
+        if (mSearchResults != null && results != null && results.size() > 0) {
+            updateSearchAdapterItems(results, mSearchResults.size());
+            refreshRecyclerView();
+            return true;
+        }
+        return false;
+    }
+
+    void updateSearchAdapterItems(ArrayList<AdapterItem> list, int offset) {
+        SearchSectionInfo lastSection = null;
+        for (int i = 0; i < list.size(); i++) {
+            AdapterItem adapterItem = list.get(i);
+            adapterItem.position = offset + i;
+            mAdapterItems.add(adapterItem);
+            if (adapterItem.searchSectionInfo != lastSection) {
+                if (adapterItem.searchSectionInfo != null) {
+                    adapterItem.searchSectionInfo.setPosStart(adapterItem.position);
+                }
+                if (lastSection != null) {
+                    lastSection.setPosEnd(adapterItem.position - 1);
+                }
+                lastSection = adapterItem.searchSectionInfo;
+            }
+            if (adapterItem.isCountedForAccessibility()) {
+                mAccessibilityResultsCount++;
+            }
+        }
+    }
+
     /**
      * Updates internals when the set of apps are updated.
      */
@@ -294,28 +324,7 @@
             }
             appSection.setPosEnd(mApps.isEmpty() ? appSection.getPosStart() : position - 1);
         } else {
-            List<AppInfo> appInfos = new ArrayList<>();
-            SearchSectionInfo lastSection = null;
-            for (int i = 0; i < mSearchResults.size(); i++) {
-                AdapterItem adapterItem = mSearchResults.get(i);
-                adapterItem.position = i;
-                mAdapterItems.add(adapterItem);
-                if (adapterItem.searchSectionInfo != lastSection) {
-                    if (adapterItem.searchSectionInfo != null) {
-                        adapterItem.searchSectionInfo.setPosStart(i);
-                    }
-                    if (lastSection != null) {
-                        lastSection.setPosEnd(i - 1);
-                    }
-                    lastSection = adapterItem.searchSectionInfo;
-                }
-                if (AllAppsGridAdapter.isIconViewType(adapterItem.viewType)) {
-                    appInfos.add(adapterItem.appInfo);
-                }
-                if (adapterItem.isCountedForAccessibility()) {
-                    mAccessibilityResultsCount++;
-                }
-            }
+            updateSearchAdapterItems(mSearchResults, 0);
             if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
                 // Append the search market item
                 if (hasNoFilteredResults()) {
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 9e6ca34..bc5a5f2 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -30,7 +30,7 @@
 import com.android.launcher3.ExtendedEditText;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.systemui.plugins.AllAppsSearchPlugin;
@@ -194,9 +194,16 @@
         /**
          * Called when the search from primary source is complete.
          *
-         * @param items sorted list of search result adapter items.
+         * @param items sorted list of search result adapter items
          */
-        void onSearchResult(String query, ArrayList<AllAppsGridAdapter.AdapterItem> items);
+        void onSearchResult(String query, ArrayList<AdapterItem> items);
+
+        /**
+         * Called when the search from secondary source is complete.
+         *
+         * @param items sorted list of search result adapter items
+         */
+        void onAppendSearchResult(String query, ArrayList<AdapterItem> items);
 
         /**
          * Called when the search results should be cleared.
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 7518521..000ccbb 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -42,7 +42,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.allapps.AlphabeticalAppsList;
 import com.android.launcher3.allapps.SearchUiManager;
@@ -173,7 +173,7 @@
     }
 
     @Override
-    public void onSearchResult(String query, ArrayList<AllAppsGridAdapter.AdapterItem> items) {
+    public void onSearchResult(String query, ArrayList<AdapterItem> items) {
         if (items != null) {
             mApps.setSearchResults(items);
             notifyResultChanged();
@@ -182,6 +182,14 @@
     }
 
     @Override
+    public void onAppendSearchResult(String query, ArrayList<AdapterItem> items) {
+        if (items != null) {
+            mApps.appendSearchResults(items);
+            notifyResultChanged();
+        }
+    }
+
+    @Override
     public void clearSearchResult() {
         if (mApps.setSearchResults(null)) {
             notifyResultChanged();
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
index dc9c155..84688e1 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.allapps.search;
 
 import android.content.Context;
+import android.os.CancellationSignal;
 
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
@@ -47,11 +48,12 @@
     }
 
     @Override
-    public void performSearch(String query, Consumer<ArrayList<AdapterItem>> callback) {
+    public void query(String input, Consumer<ArrayList<AdapterItem>> callback,
+            CancellationSignal cancellationSignal) {
         mLauncherAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
             @Override
             public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
-                List<AppInfo> matchingResults = getTitleMatchResult(apps.data, query);
+                List<AppInfo> matchingResults = getTitleMatchResult(apps.data, input);
                 callback.accept(getAdapterItems(matchingResults));
             }
         });
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index 5ed7de5..3bddace 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -46,8 +46,10 @@
     @Override
     public void doSearch(final String query,
             final AllAppsSearchBarController.Callbacks callback) {
-        mAppsSearchPipeline.performSearch(query,
-                results -> mResultHandler.post(() -> callback.onSearchResult(query, results)));
+        mAppsSearchPipeline.query(query,
+                results -> mResultHandler.post(
+                        () -> callback.onSearchResult(query, results)),
+                null);
     }
 
     public static boolean matches(AppInfo info, String query, StringMatcher matcher) {
diff --git a/src/com/android/launcher3/allapps/search/SearchPipeline.java b/src/com/android/launcher3/allapps/search/SearchPipeline.java
index 545f0e3..3516a41 100644
--- a/src/com/android/launcher3/allapps/search/SearchPipeline.java
+++ b/src/com/android/launcher3/allapps/search/SearchPipeline.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.allapps.search;
 
+import android.os.CancellationSignal;
+
 import com.android.launcher3.allapps.AllAppsGridAdapter;
 
 import java.util.ArrayList;
@@ -23,10 +25,13 @@
 /**
  * An interface for handling search within pipeline
  */
+// Remove when System Service API is added.
 public interface SearchPipeline {
 
     /**
      * Perform query
      */
-    void performSearch(String query, Consumer<ArrayList<AllAppsGridAdapter.AdapterItem>> cb);
+    void query(String input,
+            Consumer<ArrayList<AllAppsGridAdapter.AdapterItem>> callback,
+            CancellationSignal cancellationSignal);
 }
diff --git a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
index aa3ab8f..5cc238d 100644
--- a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
+++ b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
@@ -17,6 +17,8 @@
 package com.android.systemui.plugins;
 
 import android.app.Activity;
+import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.view.View;
 
 import com.android.systemui.plugins.annotations.ProvidesInterface;
@@ -32,7 +34,7 @@
 @ProvidesInterface(action = AllAppsSearchPlugin.ACTION, version = AllAppsSearchPlugin.VERSION)
 public interface AllAppsSearchPlugin extends Plugin {
     String ACTION = "com.android.systemui.action.PLUGIN_ALL_APPS_SEARCH_ACTIONS";
-    int VERSION = 7;
+    int VERSION = 8;
 
     void setup(Activity activity, View view);
 
@@ -49,10 +51,21 @@
     void onWindowVisibilityChanged(int visibility);
 
     /**
-     * Send signal when user starts typing, perform search, when search ends
+     * Send signal when user starts typing, perform search, notify search target
+     * event when search ends.
      */
     void startedSearchSession();
-    void performSearch(String query, Consumer<List<SearchTarget>> results);
+
+    /**
+     * Main function that triggers search.
+     *
+     * @param input string that has been typed by a user
+     * @param inputArgs extra info that may be relevant for the input query
+     * @param results contains the result that will be rendered in all apps search surface
+     * @param cancellationSignal {@link CancellationSignal} can be used to share status of current
+     */
+    void query(String input, Bundle inputArgs, Consumer<List<SearchTarget>> results,
+            CancellationSignal cancellationSignal);
 
     /**
      * Send over search target interaction events to Plugin