Handle AppSearch in plugin

+ Use AppSearchPipeline as a fallback if plugin times out

Bug: 166058597
Test: Manual
Change-Id: I96a38e412fd08f47475d2bc37bff34b86538ea12
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 55d5de7..06bb263 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -79,7 +79,7 @@
     private static final int DISPLAY_FOLDER = 2;
     private static final int DISPLAY_HERO_APP = 5;
 
-    private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed};
+    private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
 
     private final PointF mTranslationForReorderBounce = new PointF(0, 0);
     private final PointF mTranslationForReorderPreview = new PointF(0, 0);
@@ -280,7 +280,10 @@
         applyDotState(info, false /* animate */);
     }
 
-    public void applyFromPackageItemInfo(PackageItemInfo info) {
+    /**
+     * Apply label and tag using a generic {@link ItemInfoWithIcon}
+     */
+    public void applyFromItemInfoWithIcon(ItemInfoWithIcon info) {
         applyIconAndLabel(info);
         // We don't need to check the info since it's not a WorkspaceItemInfo
         super.setTag(info);
@@ -407,12 +410,14 @@
 
     /**
      * Draws the notification dot in the top right corner of the icon bounds.
+     *
      * @param canvas The canvas to draw to.
      */
     protected void drawDotIfNecessary(Canvas canvas) {
         if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) {
             getIconBounds(mDotParams.iconBounds);
-            Utilities.scaleRectAboutCenter(mDotParams.iconBounds, IconShape.getNormalizationScale());
+            Utilities.scaleRectAboutCenter(mDotParams.iconBounds,
+                    IconShape.getNormalizationScale());
             final int scrollX = getScrollX();
             final int scrollY = getScrollY();
             canvas.translate(scrollX, scrollY);
@@ -507,6 +512,7 @@
 
     /**
      * Creates an animator to fade the text in or out.
+     *
      * @param fadeIn Whether the text should fade in or fade out.
      */
     public ObjectAnimator createTextAlphaAnimator(boolean fadeIn) {
@@ -663,7 +669,7 @@
                 applyFromWorkspaceItem((WorkspaceItemInfo) info);
                 mActivity.invalidateParent(info);
             } else if (info instanceof PackageItemInfo) {
-                applyFromPackageItemInfo((PackageItemInfo) info);
+                applyFromItemInfoWithIcon((PackageItemInfo) info);
             }
 
             mDisableRelayout = false;
@@ -761,7 +767,8 @@
     public SafeCloseable prepareDrawDragView() {
         resetIconScale();
         setForceHideDot(true);
-        return () -> { };
+        return () -> {
+        };
     }
 
     private void resetIconScale() {
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
index 6e9a7da..dc9c155 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
@@ -15,26 +15,15 @@
  */
 package com.android.launcher3.allapps.search;
 
-import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS;
-import static com.android.launcher3.allapps.AllAppsGridAdapter.VIEW_TYPE_SEARCH_HERO_APP;
-
 import android.content.Context;
-import android.content.pm.ShortcutInfo;
-
-import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.allapps.AllAppsGridAdapter;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.allapps.AllAppsSectionDecorator.SectionDecorationHandler;
-import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.AllAppsList;
 import com.android.launcher3.model.BaseModelUpdateTask;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.popup.PopupPopulator;
-import com.android.launcher3.shortcuts.ShortcutRequest;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -46,65 +35,29 @@
 public class AppsSearchPipeline implements SearchPipeline {
 
     private static final int MAX_RESULTS_COUNT = 5;
-    private static final int MAX_HERO_SECTION_COUNT = 2;
-    private static final int MAX_SHORTCUTS_COUNT = 2;
 
     private final SearchSectionInfo mSearchSectionInfo;
     private final LauncherAppState mLauncherAppState;
-    private final boolean mHeroSectionSupported;
 
     public AppsSearchPipeline(Context context, LauncherAppState launcherAppState) {
-        this(context, launcherAppState, true);
-    }
-
-    public AppsSearchPipeline(Context context, LauncherAppState launcherAppState,
-            boolean supportsHeroView) {
         mLauncherAppState = launcherAppState;
         mSearchSectionInfo = new SearchSectionInfo();
         mSearchSectionInfo.setDecorationHandler(
                 new SectionDecorationHandler(context, true));
-        mHeroSectionSupported = supportsHeroView;
     }
 
     @Override
-    @WorkerThread
     public void performSearch(String query, Consumer<ArrayList<AdapterItem>> callback) {
         mLauncherAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
             @Override
             public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
                 List<AppInfo> matchingResults = getTitleMatchResult(apps.data, query);
-                if (mHeroSectionSupported && matchingResults.size() <= MAX_HERO_SECTION_COUNT) {
-                    callback.accept(getHeroAdapterItems(app.getContext(), matchingResults));
-                } else {
-                    callback.accept(getAdapterItems(matchingResults));
-                }
+                callback.accept(getAdapterItems(matchingResults));
             }
         });
     }
 
     /**
-     * Returns MAX_SHORTCUTS_COUNT shortcuts from local cache
-     * TODO: Shortcuts should be ranked based on relevancy
-     */
-    private ArrayList<WorkspaceItemInfo> getShortcutInfos(Context context, AppInfo appInfo) {
-        List<ShortcutInfo> shortcuts = new ShortcutRequest(context, appInfo.user)
-                .withContainer(appInfo.getTargetComponent())
-                .query(ShortcutRequest.PUBLISHED);
-        shortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts, null);
-        IconCache cache = LauncherAppState.getInstance(context).getIconCache();
-        ArrayList<WorkspaceItemInfo> shortcutItems = new ArrayList<>();
-        for (int i = 0; i < shortcuts.size() && i < MAX_SHORTCUTS_COUNT; i++) {
-            final ShortcutInfo shortcut = shortcuts.get(i);
-            final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, context);
-            cache.getUnbadgedShortcutIcon(si, shortcut);
-            si.rank = i;
-            si.container = CONTAINER_SHORTCUTS;
-            shortcutItems.add(si);
-        }
-        return shortcutItems;
-    }
-
-    /**
      * Filters {@link AppInfo}s matching specified query
      */
     public static ArrayList<AppInfo> getTitleMatchResult(List<AppInfo> apps, String query) {
@@ -122,21 +75,6 @@
         return result;
     }
 
-    private ArrayList<AdapterItem> getHeroAdapterItems(Context context, List<AppInfo> apps) {
-        ArrayList<AdapterItem> adapterItems = new ArrayList<>();
-        for (int i = 0; i < apps.size(); i++) {
-            //hero app
-            AppInfo appInfo = apps.get(i);
-            ArrayList<WorkspaceItemInfo> shortcuts = getShortcutInfos(context, appInfo);
-            AdapterItem adapterItem = new AllAppsGridAdapter.AdapterItemWithPayload(shortcuts,
-                    VIEW_TYPE_SEARCH_HERO_APP);
-            adapterItem.appInfo = appInfo;
-            adapterItem.searchSectionInfo = mSearchSectionInfo;
-            adapterItems.add(adapterItem);
-        }
-        return adapterItems;
-    }
-
     private ArrayList<AdapterItem> getAdapterItems(List<AppInfo> matchingApps) {
         ArrayList<AdapterItem> items = new ArrayList<>();
         for (int i = 0; i < matchingApps.size() && i < MAX_RESULTS_COUNT; i++) {
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index d757f78..5ed7de5 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -33,7 +33,7 @@
 
     public DefaultAppSearchAlgorithm(Context context, LauncherAppState launcherAppState) {
         mResultHandler = new Handler();
-        mAppsSearchPipeline = new AppsSearchPipeline(context, launcherAppState, false);
+        mAppsSearchPipeline = new AppsSearchPipeline(context, launcherAppState);
     }
 
     @Override
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index eb5d106..2695e66 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -305,7 +305,7 @@
      *
      * @return the corresponding AppInfo or null
      */
-    private @Nullable AppInfo findAppInfo(@NonNull ComponentName componentName,
+    public @Nullable AppInfo findAppInfo(@NonNull ComponentName componentName,
                                           @NonNull UserHandle user) {
         for (AppInfo info: data) {
             if (componentName.equals(info.componentName) && user.equals(info.user)) {
diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java
index 7b2df80..761ef0d 100644
--- a/src/com/android/launcher3/views/HeroSearchResultView.java
+++ b/src/com/android/launcher3/views/HeroSearchResultView.java
@@ -37,6 +37,7 @@
 import com.android.launcher3.graphics.DragPreviewProvider;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
 import com.android.launcher3.touch.ItemLongClickListener;
@@ -47,8 +48,9 @@
  * A view representing a high confidence app search result that includes shortcuts
  */
 public class HeroSearchResultView extends LinearLayout implements DragSource,
-        AllAppsSearchBarController.PayloadResultHandler<List<WorkspaceItemInfo>> {
+        AllAppsSearchBarController.PayloadResultHandler<List<ItemInfoWithIcon>> {
 
+    public static final int MAX_SHORTCUTS_COUNT = 2;
     BubbleTextView mBubbleTextView;
     View mIconView;
     BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2];
@@ -97,15 +99,15 @@
      * Apply {@link ItemInfo} for appIcon and shortcut Icons
      */
     @Override
-    public void applyAdapterInfo(AdapterItemWithPayload<List<WorkspaceItemInfo>> adapterItem) {
+    public void applyAdapterInfo(AdapterItemWithPayload<List<ItemInfoWithIcon>> adapterItem) {
         mBubbleTextView.applyFromApplicationInfo(adapterItem.appInfo);
         mIconView.setBackground(mBubbleTextView.getIcon());
         mIconView.setTag(adapterItem.appInfo);
-        List<WorkspaceItemInfo> shorcutInfos = adapterItem.getPayload();
+        List<ItemInfoWithIcon> shorcutInfos = adapterItem.getPayload();
         for (int i = 0; i < mDeepShortcutTextViews.length; i++) {
             mDeepShortcutTextViews[i].setVisibility(shorcutInfos.size() > i ? VISIBLE : GONE);
             if (i < shorcutInfos.size()) {
-                mDeepShortcutTextViews[i].applyFromWorkspaceItem(shorcutInfos.get(i));
+                mDeepShortcutTextViews[i].applyFromItemInfoWithIcon(shorcutInfos.get(i));
             }
         }
     }
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
index a45521d..5bf9690 100644
--- a/src/com/android/launcher3/widget/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -23,9 +23,12 @@
 import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 
-import com.android.launcher3.icons.IconCache;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+
 import com.android.launcher3.R;
 import com.android.launcher3.WidgetPreviewLoader;
+import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.util.LabelComparator;
 
@@ -34,9 +37,6 @@
 import java.util.Comparator;
 import java.util.List;
 
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-
 /**
  * List view adapter for the widget tray.
  *
@@ -128,7 +128,7 @@
         int childCount = row.getChildCount();
 
         if (expectedChildCount > childCount) {
-            for (int i = childCount ; i < expectedChildCount; i++) {
+            for (int i = childCount; i < expectedChildCount; i++) {
                 if ((i & 1) == 1) {
                     // Add a divider for odd index
                     mLayoutInflater.inflate(R.layout.widget_list_divider, row);
@@ -144,24 +144,24 @@
                 }
             }
         } else if (expectedChildCount < childCount) {
-            for (int i = expectedChildCount ; i < childCount; i++) {
+            for (int i = expectedChildCount; i < childCount; i++) {
                 row.getChildAt(i).setVisibility(View.GONE);
             }
         }
 
         // Bind the views in the application info section.
-        holder.title.applyFromPackageItemInfo(entry.pkgItem);
+        holder.title.applyFromItemInfoWithIcon(entry.pkgItem);
 
         // Bind the view in the widget horizontal tray region.
-        for (int i=0; i < infoList.size(); i++) {
-            WidgetCell widget = (WidgetCell) row.getChildAt(2*i);
+        for (int i = 0; i < infoList.size(); i++) {
+            WidgetCell widget = (WidgetCell) row.getChildAt(2 * i);
             widget.applyFromCellItem(infoList.get(i), mWidgetPreviewLoader);
             widget.setApplyBitmapDeferred(mApplyBitmapDeferred);
             widget.ensurePreview();
             widget.setVisibility(View.VISIBLE);
 
             if (i > 0) {
-                row.getChildAt(2*i - 1).setVisibility(View.VISIBLE);
+                row.getChildAt(2 * i - 1).setVisibility(View.VISIBLE);
             }
         }
     }
@@ -185,7 +185,7 @@
     @Override
     public void onViewRecycled(WidgetsRowViewHolder holder) {
         int total = holder.cellContainer.getChildCount();
-        for (int i = 0; i < total; i+=2) {
+        for (int i = 0; i < total; i += 2) {
             WidgetCell widget = (WidgetCell) holder.cellContainer.getChildAt(i);
             widget.clear();
         }