Merge "[Live Tile] Switch to screenshot when any task menu option is selected" into ub-launcher3-master
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index 43bf0ea..52475df 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -13,7 +13,8 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.quickstep.interaction.RootSandboxLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="?android:attr/colorBackground">
@@ -93,11 +94,11 @@
         style="@style/TextAppearance.GestureTutorial.Feedback"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_above="@id/gesture_tutorial_fragment_action_button"
+        android:layout_below="@id/gesture_tutorial_fragment_titles_container"
         android:layout_centerHorizontal="true"
         android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end"
         android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end"
-        android:layout_marginBottom="10dp"/>
+        android:layout_marginTop="40dp"/>
 
     <!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
          of elevation and shadow) which is replaced by ripple effect in android:foreground -->
@@ -126,4 +127,4 @@
         android:background="@null"
         android:foreground="?android:attr/selectableItemBackgroundBorderless"
         android:stateListAnimator="@null"/>
-</RelativeLayout>
\ No newline at end of file
+</com.android.quickstep.interaction.RootSandboxLayout>
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
index e4b348e..9489bac 100644
--- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
@@ -143,6 +143,10 @@
         return false;
     }
 
+    boolean onInterceptTouch(MotionEvent motionEvent) {
+        return isWithinTouchRegion((int) motionEvent.getX(), (int) motionEvent.getY());
+    }
+
     private boolean isWithinTouchRegion(int x, int y) {
         // Disallow if too far from the edge
         if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index f897ecc..d1b0a70 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -250,6 +250,12 @@
         return intercepted;
     }
 
+    boolean onInterceptTouch(MotionEvent event) {
+        return mAssistantLeftRegion.contains(event.getX(), event.getY())
+                || mAssistantRightRegion.contains(event.getX(), event.getY())
+                || event.getY() >= mDisplaySize.y - mBottomGestureHeight;
+    }
+
     protected void onMotionPauseDetected() {
         VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
     }
diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
new file mode 100644
index 0000000..db1afc2
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
@@ -0,0 +1,44 @@
+/*
+ * 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.quickstep.interaction;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.RelativeLayout;
+
+import androidx.fragment.app.FragmentManager;
+
+/** Root layout that TutorialFragment uses to intercept motion events. */
+public class RootSandboxLayout extends RelativeLayout {
+    public RootSandboxLayout(Context context) {
+        super(context);
+    }
+
+    public RootSandboxLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public RootSandboxLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent motionEvent) {
+        return ((TutorialFragment) FragmentManager.findFragment(this))
+                .onInterceptTouch(motionEvent);
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java b/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java
new file mode 100644
index 0000000..80ffe66
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java
@@ -0,0 +1,44 @@
+/*
+ * 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.quickstep.interaction;
+
+import android.content.Context;
+import android.view.View;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.graphics.LauncherPreviewRenderer;
+
+/** Renders a fake Launcher for use in the Sandbox. */
+class SandboxLauncherRenderer extends LauncherPreviewRenderer {
+    SandboxLauncherRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) {
+        super(context, idp, migrated);
+    }
+
+    @Override
+    public boolean shouldShowRealLauncherPreview() {
+        return false;
+    }
+
+    @Override
+    public boolean shouldShowQsb() {
+        return false;
+    }
+
+    @Override
+    public View.OnLongClickListener getWorkspaceChildOnLongClickListener() {
+        return null;
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 73f1f8c..db80342 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -47,6 +47,7 @@
     final TextView mTitleTextView;
     final TextView mSubtitleTextView;
     final TextView mFeedbackView;
+    final View mLauncherView;
     final ClipIconView mFakeIconView;
     final View mFakeTaskView;
     final View mRippleView;
@@ -68,6 +69,7 @@
         mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
         mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
         mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
+        mLauncherView = tutorialFragment.getLauncherView();
         mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view);
         mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view);
         mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
@@ -162,8 +164,10 @@
 
         if (isComplete()) {
             hideHandCoachingAnimation();
+            mLauncherView.setVisibility(View.INVISIBLE);
         } else {
             showHandCoachingAnimation();
+            mLauncherView.setVisibility(View.VISIBLE);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 9a8264d..c90ad94 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -31,6 +31,7 @@
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 
+import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.R;
 import com.android.quickstep.interaction.TutorialController.TutorialType;
 
@@ -45,6 +46,7 @@
     TutorialHandAnimation mHandCoachingAnimation;
     EdgeBackGestureHandler mEdgeBackGestureHandler;
     NavBarGestureHandler mNavBarGestureHandler;
+    private View mLauncherView;
 
     public static TutorialFragment newInstance(TutorialType tutorialType) {
         TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
@@ -114,8 +116,11 @@
             return insets;
         });
         mRootView.setOnTouchListener(this);
-        mHandCoachingAnimation = new TutorialHandAnimation(getContext(), mRootView,
-                getHandAnimationResId());
+        mHandCoachingAnimation =
+                new TutorialHandAnimation(getContext(), mRootView, getHandAnimationResId());
+        InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext());
+        mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView();
+        ((ViewGroup) mRootView).addView(mLauncherView, 0);
         return mRootView;
     }
 
@@ -133,11 +138,17 @@
 
     @Override
     public boolean onTouch(View view, MotionEvent motionEvent) {
-        // Note: Using logical or to ensure both functions get called.
+        // Note: Using logical-or to ensure both functions get called.
         return mEdgeBackGestureHandler.onTouch(view, motionEvent)
                 | mNavBarGestureHandler.onTouch(view, motionEvent);
     }
 
+    boolean onInterceptTouch(MotionEvent motionEvent) {
+        // Note: Using logical-or to ensure both functions get called.
+        return mEdgeBackGestureHandler.onInterceptTouch(motionEvent)
+                | mNavBarGestureHandler.onInterceptTouch(motionEvent);
+    }
+
     void onAttachedToWindow() {
         mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
     }
@@ -168,6 +179,10 @@
         return mRootView;
     }
 
+    View getLauncherView() {
+        return mLauncherView;
+    }
+
     TutorialHandAnimation getHandAnimation() {
         return mHandCoachingAnimation;
     }
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
index 4a298d3..1031c5b 100644
--- a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
+++ b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
@@ -18,8 +18,10 @@
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
 import static com.android.launcher3.anim.Interpolators.INSTANT;
+import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
@@ -110,7 +112,7 @@
         boolean isLayoutNaturalToLauncher = recentsView.getPagedOrientationHandler()
                 .isLayoutNaturalToLauncher();
         config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, isLayoutNaturalToLauncher
-                ? DEACCEL : FINAL_FRAME);
+                ? clampToProgress(FAST_OUT_SLOW_IN, 0, 0.75f) : FINAL_FRAME);
         config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME);
         config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
         config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT);
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/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 1cd201f..2809bd5 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -323,11 +323,8 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mTouchHelper != null
-                || (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) {
-            return true;
-        }
-        return false;
+        return mTouchHelper != null
+                || (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev));
     }
 
     public void enableHardwareLayer(boolean hasLayer) {
diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java
index ea887cc..d6302ce 100644
--- a/src/com/android/launcher3/WorkspaceLayoutManager.java
+++ b/src/com/android/launcher3/WorkspaceLayoutManager.java
@@ -130,12 +130,16 @@
         }
 
         child.setHapticFeedbackEnabled(false);
-        child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
+        child.setOnLongClickListener(getWorkspaceChildOnLongClickListener());
         if (child instanceof DropTarget) {
             onAddDropTarget((DropTarget) child);
         }
     }
 
+    default View.OnLongClickListener getWorkspaceChildOnLongClickListener() {
+        return ItemLongClickListener.INSTANCE_WORKSPACE;
+    }
+
     Hotseat getHotseat();
 
     CellLayout getScreenWithId(int screenId);
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index f01f90b..81d94ba 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;
         }
     }
 
@@ -334,7 +334,7 @@
     }
 
     // multiplier to support adapter item column count that is not mAppsPerRow.
-    private static final int SPAN_MULTIPLIER = 3;
+    public static final int SPAN_MULTIPLIER = 3;
 
     private final BaseDraggingActivity mLauncher;
     private final LayoutInflater mLayoutInflater;
@@ -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/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index cd84c96..effb3a4 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -513,8 +513,7 @@
         }
 
         // Setup search view
-        SearchUiManager searchUiManager =
-                mRootView.findViewById(R.id.search_container_all_apps);
+        SearchUiManager searchUiManager = mRootView.findViewById(R.id.search_container_all_apps);
         mRootView.findViewById(R.id.apps_view).setTranslationY(
                 mDp.heightPx - searchUiManager.getScrollRangeDelta(mInsets));
         ViewGroup searchView = (ViewGroup) searchUiManager;
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;