Thumbnail/Suggest view type support remote action

Bug: 169330678


Change-Id: I629d3e6b1622bf71e0174eb2489e976ef98875ad
diff --git a/res/layout/search_result_suggest.xml b/res/layout/search_result_suggest.xml
new file mode 100644
index 0000000..c5d96f0
--- /dev/null
+++ b/res/layout/search_result_suggest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.launcher3.views.SearchResultSuggestRow xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextHeadline"
+    android:id="@+id/section_title"
+    android:background="?android:attr/selectableItemBackground"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:gravity="center_vertical"
+    android:padding="4dp"
+    android:minHeight="48dp"
+    android:textColor="?android:attr/textColorPrimary"
+    android:textSize="14sp">
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/TextTitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="8dp"
+        android:layout_marginBottom="4dp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textSize="14sp" />
+
+</com.android.launcher3.views.SearchResultSuggestRow>
\ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 81d94ba..8bc8e53 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -98,6 +98,8 @@
 
     public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12;
 
+    public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13;
+
     // Common view type masks
     public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
     public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
@@ -189,7 +191,8 @@
                     || viewType == VIEW_TYPE_SEARCH_ROW
                     || viewType == VIEW_TYPE_SEARCH_PEOPLE
                     || viewType == VIEW_TYPE_SEARCH_THUMBNAIL
-                    || viewType == VIEW_TYPE_SEARCH_ICON_ROW;
+                    || viewType == VIEW_TYPE_SEARCH_ICON_ROW
+                    || viewType == VIEW_TYPE_SEARCH_SUGGEST;
         }
     }
 
@@ -467,6 +470,9 @@
             case VIEW_TYPE_SEARCH_THUMBNAIL:
                 return new ViewHolder(mLayoutInflater.inflate(
                         R.layout.search_result_thumbnail, parent, false));
+            case VIEW_TYPE_SEARCH_SUGGEST:
+                return new ViewHolder(mLayoutInflater.inflate(
+                        R.layout.search_result_suggest, parent, false));
             default:
                 throw new RuntimeException("Unexpected view type");
         }
@@ -554,6 +560,7 @@
             case VIEW_TYPE_SEARCH_ICON_ROW:
             case VIEW_TYPE_SEARCH_PEOPLE:
             case VIEW_TYPE_SEARCH_THUMBNAIL:
+            case VIEW_TYPE_SEARCH_SUGGEST:
                 AdapterItemWithPayload item =
                         (AdapterItemWithPayload) mApps.getAdapterItems().get(position);
                 PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView;
diff --git a/src/com/android/launcher3/views/SearchResultSuggestRow.java b/src/com/android/launcher3/views/SearchResultSuggestRow.java
new file mode 100644
index 0000000..b5abbcc
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchResultSuggestRow.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.views;
+
+import static com.android.systemui.plugins.shared.SearchTarget.ItemType.SUGGEST;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.RemoteActionItemInfo;
+import com.android.launcher3.touch.ItemClickHandler;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
+
+/**
+ * A view representing a fallback search suggestion row.
+ */
+public class SearchResultSuggestRow extends LinearLayout implements
+        View.OnClickListener, AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
+
+    private final Object[] mTargetInfo = createTargetInfo();
+    private AllAppsSearchPlugin mPlugin;
+    private AdapterItemWithPayload<SearchTarget> mAdapterItem;
+    private TextView mTitle;
+
+
+    public SearchResultSuggestRow(@NonNull Context context) {
+        super(context);
+    }
+
+    public SearchResultSuggestRow(@NonNull Context context,
+            @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public SearchResultSuggestRow(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTitle = findViewById(R.id.title);
+        setOnClickListener(this);
+    }
+    @Override
+    public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
+        mAdapterItem = adapterItemWithPayload;
+        SearchTarget payload = adapterItemWithPayload.getPayload();
+        mPlugin = adapterItemWithPayload.getPlugin();
+
+        if (payload.mRemoteAction != null) {
+            RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(payload.mRemoteAction,
+                    payload.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
+                    payload.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START));
+            setTag(itemInfo);
+        }
+        showIfAvailable(mTitle, payload.mRemoteAction.getTitle().toString());
+        setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
+        adapterItemWithPayload.setSelectionHandler(this::handleSelection);
+    }
+
+    @Override
+    public Object[] getTargetInfo() {
+        return mTargetInfo;
+    }
+
+    private void handleSelection(int eventType) {
+        ItemInfo itemInfo = (ItemInfo) getTag();
+        Launcher launcher = Launcher.getLauncher(getContext());
+        if (itemInfo instanceof  RemoteActionItemInfo) return;
+
+        RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
+        ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
+        SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SUGGEST, eventType);
+        searchTargetEvent.bundle = new Bundle();
+        searchTargetEvent.remoteAction = remoteItemInfo.getRemoteAction();
+        searchTargetEvent.bundle.putBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START,
+                remoteItemInfo.shouldStartInLauncher());
+        searchTargetEvent.bundle.putString(SearchTarget.REMOTE_ACTION_TOKEN,
+                remoteItemInfo.getToken());
+
+        if (mPlugin != null) {
+            mPlugin.notifySearchTargetEvent(searchTargetEvent);
+        }
+    }
+
+    @Override
+    public void onClick(View view) {
+        handleSelection(SearchTargetEvent.SELECT);
+    }
+
+    private void showIfAvailable(TextView view, @Nullable String string) {
+        System.out.println("Plugin suggest string:" + string);
+        if (TextUtils.isEmpty(string)) {
+            view.setVisibility(GONE);
+        } else {
+            System.out.println("Plugin suggest string:" + string);
+            view.setVisibility(VISIBLE);
+            view.setText(string);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/views/ThumbnailSearchResultView.java b/src/com/android/launcher3/views/ThumbnailSearchResultView.java
index 1d58a06..bbc4773 100644
--- a/src/com/android/launcher3/views/ThumbnailSearchResultView.java
+++ b/src/com/android/launcher3/views/ThumbnailSearchResultView.java
@@ -18,8 +18,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
-import android.os.Bundle;
 import android.util.AttributeSet;
 
 import androidx.core.graphics.drawable.RoundedBitmapDrawable;
@@ -28,6 +28,10 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
 import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.RemoteActionItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.util.Themes;
 import com.android.systemui.plugins.AllAppsSearchPlugin;
 import com.android.systemui.plugins.shared.SearchTarget;
@@ -37,10 +41,9 @@
  * A view representing a high confidence app search result that includes shortcuts
  */
 public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView
-        implements AllAppsSearchBarController.PayloadResultHandler<Bundle> {
+        implements AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
 
     private final Object[] mTargetInfo = createTargetInfo();
-    Intent mIntent;
     AllAppsSearchPlugin mPlugin;
     int mPosition;
 
@@ -58,26 +61,48 @@
 
     private void handleSelection(int eventType) {
         Launcher launcher = Launcher.getLauncher(getContext());
-        launcher.startActivitySafely(this, mIntent, null);
-
-        SearchTargetEvent event = getSearchTargetEvent(
-                SearchTarget.ItemType.SCREENSHOT, eventType);
+        ItemInfo itemInfo = (ItemInfo) getTag();
+        if (itemInfo instanceof RemoteActionItemInfo) {
+            RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
+            ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
+        } else {
+            ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher);
+        }
         if (mPlugin != null) {
+            SearchTargetEvent event = getSearchTargetEvent(
+                    SearchTarget.ItemType.SCREENSHOT, eventType);
             mPlugin.notifySearchTargetEvent(event);
         }
     }
 
     @Override
-    public void applyAdapterInfo(AdapterItemWithPayload<Bundle> adapterItem) {
+    public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItem) {
+        Launcher launcher = Launcher.getLauncher(getContext());
         mPosition = adapterItem.position;
-        RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null,
-                (Bitmap) adapterItem.getPayload().getParcelable("bitmap"));
+
+        SearchTarget target = adapterItem.getPayload();
+        Bitmap bitmap;
+        if (target.mRemoteAction != null) {
+            RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(target.mRemoteAction,
+                    target.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
+                    target.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START));
+            ItemClickHandler.onClickRemoteAction(launcher, itemInfo);
+            bitmap = ((BitmapDrawable) target.mRemoteAction.getIcon()
+                    .loadDrawable(getContext())).getBitmap();
+            setTag(itemInfo);
+        } else {
+            bitmap = (Bitmap) target.bundle.getParcelable("bitmap");
+            WorkspaceItemInfo itemInfo = new WorkspaceItemInfo();
+            itemInfo.intent = new Intent(Intent.ACTION_VIEW)
+                    .setData(Uri.parse(target.bundle.getString("uri")))
+                    .setType("image/*")
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            setTag(itemInfo);
+        }
+        RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, bitmap);
         drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext()));
         setImageDrawable(drawable);
-        mIntent = new Intent(Intent.ACTION_VIEW)
-                .setData(Uri.parse(adapterItem.getPayload().getString("uri")))
-                .setType("image/*")
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
         mPlugin = adapterItem.getPlugin();
         adapterItem.setSelectionHandler(this::handleSelection);
     }
diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
index 9d9ccba..3780b20 100644
--- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
+++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
@@ -80,7 +80,12 @@
          * N number of 1x1 ratio thumbnail is rendered.
          * (current N = 3)
          */
-        THUMBNAIL(8);
+        THUMBNAIL(8),
+
+        /**
+         * Fallback search icon and relevant text is rendered.
+         */
+        SUGGEST(9);
 
         private final int mId;
 
@@ -102,7 +107,8 @@
         SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT),
         PEOPLE(6, "People", ViewType.PEOPLE),
         SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL),
-        REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT);
+        REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT),
+        SUGGEST(9, "Fallback Search", ViewType.SUGGEST);
 
         private final int mId;