Support Remote actions

Bug: 168846477
Test: Manual
Change-Id: I7b9dc96bc7a8ccb25ccb4b7135880768256f1ef3
diff --git a/res/layout/search_result_icon_row.xml b/res/layout/search_result_icon_row.xml
new file mode 100644
index 0000000..5ecc0c2
--- /dev/null
+++ b/res/layout/search_result_icon_row.xml
@@ -0,0 +1,31 @@
+<?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.SearchResultIconRow xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto"
+    style="@style/BaseIcon"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
+    android:gravity="start|center_vertical"
+    android:textAlignment="viewStart"
+    android:textColor="?android:attr/textColorPrimary"
+    android:textSize="16sp"
+    android:padding="@dimen/dynamic_grid_edge_margin"
+    launcher:iconDisplay="hero_app"
+    launcher:layoutHorizontal="true"
+    >
+
+</com.android.launcher3.views.SearchResultIconRow>
\ No newline at end of file
diff --git a/res/layout/search_result_shortcut.xml b/res/layout/search_result_shortcut.xml
deleted file mode 100644
index c350c97..0000000
--- a/res/layout/search_result_shortcut.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?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.SearchResultShortcut xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="horizontal"
-    android:gravity="center_vertical"
-    android:padding="@dimen/dynamic_grid_edge_margin">
-
-    <com.android.launcher3.BubbleTextView
-        android:id="@+id/bubble_text"
-        style="@style/BaseIcon"
-        android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
-        android:gravity="start|center_vertical"
-        android:textAlignment="viewStart"
-        android:textColor="?android:attr/textColorPrimary"
-        android:textSize="16sp"
-        android:layout_height="wrap_content"
-        launcher:iconDisplay="hero_app"
-        launcher:layoutHorizontal="true" />
-
-    <View
-        android:id="@+id/icon"
-        android:layout_width="@dimen/deep_shortcut_icon_size"
-        android:layout_height="@dimen/deep_shortcut_icon_size"
-        android:layout_gravity="start|center_vertical"
-        android:background="@drawable/ic_deepshortcut_placeholder" />
-
-</com.android.launcher3.views.SearchResultShortcut>
\ No newline at end of file
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index fd04081..1e5a9e4 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -65,6 +65,7 @@
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.model.data.PromiseAppInfo;
+import com.android.launcher3.model.data.RemoteActionItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.views.ActivityContext;
@@ -300,6 +301,14 @@
         verifyHighRes();
     }
 
+    /**
+     * Apply label and tag using a {@link RemoteActionItemInfo}
+     */
+    public void applyFromRemoteActionInfo(RemoteActionItemInfo remoteActionItemInfo) {
+        applyIconAndLabel(remoteActionItemInfo);
+        setTag(remoteActionItemInfo);
+    }
+
     private void applyIconAndLabel(ItemInfoWithIcon info) {
         FastBitmapDrawable iconDrawable = newIcon(getContext(), info);
         mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
@@ -681,6 +690,8 @@
                 mActivity.invalidateParent(info);
             } else if (info instanceof PackageItemInfo) {
                 applyFromItemInfoWithIcon((PackageItemInfo) info);
+            } else if (info instanceof RemoteActionItemInfo) {
+                applyFromRemoteActionInfo((RemoteActionItemInfo) info);
             }
 
             mDisableRelayout = false;
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index f01f90b..2779ba7 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -92,7 +92,7 @@
 
     public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 9;
 
-    public static final int VIEW_TYPE_SEARCH_SHORTCUT = 1 << 10;
+    public static final int VIEW_TYPE_SEARCH_ICON_ROW = 1 << 10;
 
     public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11;
 
@@ -189,7 +189,7 @@
                     || viewType == VIEW_TYPE_SEARCH_ROW
                     || viewType == VIEW_TYPE_SEARCH_PEOPLE
                     || viewType == VIEW_TYPE_SEARCH_THUMBNAIL
-                    || viewType == VIEW_TYPE_SEARCH_SHORTCUT;
+                    || viewType == VIEW_TYPE_SEARCH_ICON_ROW;
         }
     }
 
@@ -458,9 +458,9 @@
             case VIEW_TYPE_SEARCH_SLICE:
                 return new ViewHolder(mLayoutInflater.inflate(
                         R.layout.search_result_slice, parent, false));
-            case VIEW_TYPE_SEARCH_SHORTCUT:
+            case VIEW_TYPE_SEARCH_ICON_ROW:
                 return new ViewHolder(mLayoutInflater.inflate(
-                        R.layout.search_result_shortcut, parent, false));
+                        R.layout.search_result_icon_row, parent, false));
             case VIEW_TYPE_SEARCH_PEOPLE:
                 return new ViewHolder(mLayoutInflater.inflate(
                         R.layout.search_result_people_item, parent, false));
@@ -551,7 +551,7 @@
             case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
             case VIEW_TYPE_SEARCH_HERO_APP:
             case VIEW_TYPE_SEARCH_ROW:
-            case VIEW_TYPE_SEARCH_SHORTCUT:
+            case VIEW_TYPE_SEARCH_ICON_ROW:
             case VIEW_TYPE_SEARCH_PEOPLE:
             case VIEW_TYPE_SEARCH_THUMBNAIL:
                 AdapterItemWithPayload item =
@@ -571,8 +571,8 @@
         if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
         if (holder.itemView instanceof BubbleTextView) {
             BubbleTextView icon = (BubbleTextView) holder.itemView;
-            icon.setOnClickListener(mOnIconClickListener);
-            icon.setOnLongClickListener(mOnIconLongClickListener);
+            icon.setOnClickListener(null);
+            icon.setOnLongClickListener(null);
         } else if (holder.itemView instanceof SliceView) {
             SliceView sliceView = (SliceView) holder.itemView;
             sliceView.setOnSliceActionListener(null);
diff --git a/src/com/android/launcher3/model/data/RemoteActionItemInfo.java b/src/com/android/launcher3/model/data/RemoteActionItemInfo.java
new file mode 100644
index 0000000..81f7f3a
--- /dev/null
+++ b/src/com/android/launcher3/model/data/RemoteActionItemInfo.java
@@ -0,0 +1,64 @@
+/*
+ * 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.model.data;
+
+import android.app.RemoteAction;
+import android.os.Process;
+
+/**
+ * Represents a launchable {@link RemoteAction}
+ */
+public class RemoteActionItemInfo extends ItemInfoWithIcon {
+
+    private final RemoteAction mRemoteAction;
+    private final String mToken;
+    private final boolean mShouldStart;
+
+    public RemoteActionItemInfo(RemoteAction remoteAction, String token, boolean shouldStart) {
+        mShouldStart = shouldStart;
+        mToken = token;
+        mRemoteAction = remoteAction;
+        title = remoteAction.getTitle();
+        user = Process.myUserHandle();
+    }
+
+    public RemoteActionItemInfo(RemoteActionItemInfo info) {
+        super(info);
+        this.mShouldStart = info.mShouldStart;
+        this.mRemoteAction = info.mRemoteAction;
+        this.mToken = info.mToken;
+    }
+
+    @Override
+    public ItemInfoWithIcon clone() {
+        return new RemoteActionItemInfo(this);
+    }
+
+    public RemoteAction getRemoteAction() {
+        return mRemoteAction;
+    }
+
+    public String getToken() {
+        return mToken;
+    }
+
+    /**
+     * Getter method for mShouldStart
+     */
+    public boolean shouldStartInLauncher() {
+        return mShouldStart;
+    }
+}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 61d6f7d..d56391d 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -25,7 +25,9 @@
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
 
 import android.app.AlertDialog;
+import android.app.PendingIntent;
 import android.content.Intent;
+import android.content.IntentSender;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.os.Process;
@@ -49,6 +51,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.PromiseAppInfo;
+import com.android.launcher3.model.data.RemoteActionItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.InstallSessionHelper;
 import com.android.launcher3.testing.TestLogging;
@@ -236,6 +239,27 @@
         startAppShortcutOrInfoActivity(v, shortcut, launcher);
     }
 
+    /**
+     * Event handler for a {@link android.app.RemoteAction} click
+     *
+     */
+    public static void onClickRemoteAction(Launcher launcher,
+            RemoteActionItemInfo remoteActionInfo) {
+        try {
+            PendingIntent pendingIntent = remoteActionInfo.getRemoteAction().getActionIntent();
+            if (remoteActionInfo.shouldStartInLauncher()) {
+                launcher.startIntentSenderForResult(pendingIntent.getIntentSender(), 0, null, 0, 0,
+                        0);
+            } else {
+                pendingIntent.send();
+            }
+        } catch (PendingIntent.CanceledException | IntentSender.SendIntentException e) {
+            Toast.makeText(launcher,
+                    launcher.getResources().getText(R.string.shortcut_not_available),
+                    Toast.LENGTH_SHORT).show();
+        }
+    }
+
     private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
         TestLogging.recordEvent(
                 TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity");
diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java
index 94b9ca1..dd322d9 100644
--- a/src/com/android/launcher3/views/HeroSearchResultView.java
+++ b/src/com/android/launcher3/views/HeroSearchResultView.java
@@ -138,7 +138,7 @@
             if (i < shortcutDetails.size()) {
                 Pair<ShortcutInfo, ItemInfoWithIcon> p = shortcutDetails.get(i);
                 //apply ItemInfo and prepare view
-                shortcutView.applyFromItemInfoWithIcon(p.second);
+                shortcutView.applyFromWorkspaceItem((WorkspaceItemInfo) p.second);
                 MODEL_EXECUTOR.execute(() -> {
                     // load unbadged shortcut in background and update view when icon ready
                     appState.getIconCache().getUnbadgedShortcutIcon(p.second, p.first);
diff --git a/src/com/android/launcher3/views/SearchResultIconRow.java b/src/com/android/launcher3/views/SearchResultIconRow.java
new file mode 100644
index 0000000..57c85cf
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchResultIconRow.java
@@ -0,0 +1,154 @@
+/*
+ * 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.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.app.RemoteAction;
+import android.content.Context;
+import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.AttributeSet;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.launcher3.icons.LauncherIcons;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.launcher3.model.data.RemoteActionItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+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 stand alone shortcut search result
+ */
+public class SearchResultIconRow extends DoubleShadowBubbleTextView implements
+        AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
+
+    private final Object[] mTargetInfo = createTargetInfo();
+    private ShortcutInfo mShortcutInfo;
+    private AllAppsSearchPlugin mPlugin;
+    private AdapterItemWithPayload<SearchTarget> mAdapterItem;
+
+
+    public SearchResultIconRow(@NonNull Context context) {
+        super(context);
+    }
+
+    public SearchResultIconRow(@NonNull Context context,
+            @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public SearchResultIconRow(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
+        if (mAdapterItem != null) {
+            mAdapterItem.setSelectionHandler(null);
+        }
+        mAdapterItem = adapterItemWithPayload;
+        SearchTarget payload = adapterItemWithPayload.getPayload();
+        mPlugin = adapterItemWithPayload.getPlugin();
+
+        if (payload.mRemoteAction != null) {
+            prepareUsingRemoteAction(payload.mRemoteAction,
+                    payload.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
+                    payload.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START));
+        } else {
+            prepareUsingShortcutInfo(payload.shortcuts.get(0));
+        }
+        setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
+        adapterItemWithPayload.setSelectionHandler(this::handleSelection);
+    }
+
+    private void prepareUsingShortcutInfo(ShortcutInfo shortcutInfo) {
+        mShortcutInfo = shortcutInfo;
+        WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext());
+        applyFromWorkspaceItem(workspaceItemInfo);
+        LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
+        MODEL_EXECUTOR.execute(() -> {
+            launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo);
+            reapplyItemInfoAsync(workspaceItemInfo);
+        });
+    }
+
+    private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start) {
+        RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start);
+
+        applyFromRemoteActionInfo(itemInfo);
+        UI_HELPER_EXECUTOR.post(() -> {
+            // If the Drawable from the remote action is not AdaptiveBitmap, styling will not work.
+            try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
+                Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext());
+                itemInfo.bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
+                        Build.VERSION.SDK_INT);
+                reapplyItemInfoAsync(itemInfo);
+            }
+        });
+
+    }
+
+    void reapplyItemInfoAsync(ItemInfoWithIcon itemInfoWithIcon) {
+        MAIN_EXECUTOR.post(() -> reapplyItemInfo(itemInfoWithIcon));
+    }
+
+    @Override
+    public Object[] getTargetInfo() {
+        return mTargetInfo;
+    }
+
+    private void handleSelection(int eventType) {
+        ItemInfo itemInfo = (ItemInfo) getTag();
+        Launcher launcher = Launcher.getLauncher(getContext());
+        final SearchTargetEvent searchTargetEvent;
+        if (itemInfo instanceof WorkspaceItemInfo) {
+            ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher);
+            searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.SHORTCUT,
+                    eventType);
+            searchTargetEvent.shortcut = mShortcutInfo;
+        } else {
+            RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
+            ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
+            searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.REMOTE_ACTION,
+                    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);
+        }
+    }
+}
diff --git a/src/com/android/launcher3/views/SearchResultShortcut.java b/src/com/android/launcher3/views/SearchResultShortcut.java
deleted file mode 100644
index a409f08..0000000
--- a/src/com/android/launcher3/views/SearchResultShortcut.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.launcher3.util.Executors.MODEL_EXECUTOR;
-
-import android.content.Context;
-import android.content.pm.ShortcutInfo;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsGridAdapter;
-import com.android.launcher3.allapps.search.AllAppsSearchBarController;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-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 stand alone shortcut search result
- */
-public class SearchResultShortcut extends FrameLayout implements
-        AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
-
-    private BubbleTextView mBubbleTextView;
-    private View mIconView;
-    private ShortcutInfo mShortcutInfo;
-    private AllAppsSearchPlugin mPlugin;
-    private final Object[] mTargetInfo = createTargetInfo();
-
-
-    public SearchResultShortcut(@NonNull Context context) {
-        super(context);
-    }
-
-    public SearchResultShortcut(@NonNull Context context,
-            @Nullable AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public SearchResultShortcut(@NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        Launcher launcher = Launcher.getLauncher(getContext());
-        DeviceProfile grid = launcher.getDeviceProfile();
-        mIconView = findViewById(R.id.icon);
-        ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
-        iconParams.height = grid.allAppsIconSizePx;
-        iconParams.width = grid.allAppsIconSizePx;
-        mBubbleTextView = findViewById(R.id.bubble_text);
-        setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
-    }
-
-    @Override
-    public void applyAdapterInfo(
-            AllAppsGridAdapter.AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
-        SearchTarget payload = adapterItemWithPayload.getPayload();
-        mPlugin = adapterItemWithPayload.getPlugin();
-        mShortcutInfo = payload.shortcuts.get(0);
-        WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext());
-        mBubbleTextView.applyFromWorkspaceItem(workspaceItemInfo);
-        mIconView.setBackground(mBubbleTextView.getIcon());
-        LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
-        MODEL_EXECUTOR.execute(() -> {
-            launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo);
-            mBubbleTextView.applyFromWorkspaceItem(workspaceItemInfo);
-            mIconView.setBackground(mBubbleTextView.getIcon());
-        });
-        adapterItemWithPayload.setSelectionHandler(this::handleSelection);
-    }
-
-    @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
-    private void handleSelection(int eventType) {
-        WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) mBubbleTextView.getTag();
-        ItemClickHandler.onClickAppShortcut(this, itemInfo, Launcher.getLauncher(getContext()));
-
-        SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.SHORTCUT,
-                eventType);
-        searchTargetEvent.shortcut = mShortcutInfo;
-        if (mPlugin != null) {
-            mPlugin.notifySearchTargetEvent(searchTargetEvent);
-        }
-    }
-}
diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
index fb8dd72..9d9ccba 100644
--- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
+++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.plugins.shared;
 
+import android.app.RemoteAction;
 import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
 
@@ -25,6 +26,14 @@
  */
 public class SearchTarget implements Comparable<SearchTarget> {
 
+
+    /**
+     * A bundle key for boolean value of whether remote action should be started in launcher or not
+     */
+    public static final String REMOTE_ACTION_SHOULD_START = "should_start_for_result";
+    public static final String REMOTE_ACTION_TOKEN = "action_token";
+
+
     public enum ViewType {
 
         /**
@@ -74,6 +83,7 @@
         THUMBNAIL(8);
 
         private final int mId;
+
         ViewType(int id) {
             mId = id;
         }
@@ -91,7 +101,8 @@
         APP_HERO(4, "", ViewType.HERO),
         SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT),
         PEOPLE(6, "People", ViewType.PEOPLE),
-        SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL);
+        SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL),
+        REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT);
 
         private final int mId;
 
@@ -123,12 +134,12 @@
     public Bundle bundle;
     public float score;
     public String mSessionId;
+    public RemoteAction mRemoteAction;
 
     /**
      * Constructor to create the search target. Bundle is currently temporary to hold
      * search target primitives that cannot be expressed as java primitive objects
      * or AOSP native objects.
-     *
      */
     public SearchTarget(ItemType itemType, List<ShortcutInfo> shortcuts,
             Bundle bundle, float score, String sessionId) {
diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
index 00a78de..5016abc 100644
--- a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
+++ b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.plugins.shared;
 
+import android.app.RemoteAction;
 import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
 
@@ -29,6 +30,7 @@
 
     public SearchTarget.ItemType type;
     public ShortcutInfo shortcut;
+    public RemoteAction remoteAction;
     public int eventType;
     public Bundle bundle;
     public int index;