Merge " Introduce feature education for AllApps Search"
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 8dab915..d95cc01 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -32,6 +32,7 @@
     <uses-permission android:name="android.permission.VIBRATE"/>
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
     <uses-permission android:name="${packageName}.permission.HOTSEAT_EDU" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
 
     <application android:backupAgent="com.android.launcher3.LauncherBackupAgent"
          android:fullBackupOnly="true"
diff --git a/quickstep/res/layout/search_result_icon_row.xml b/quickstep/res/layout/search_result_icon_row.xml
index 1393b87..2119fc3 100644
--- a/quickstep/res/layout/search_result_icon_row.xml
+++ b/quickstep/res/layout/search_result_icon_row.xml
@@ -45,14 +45,14 @@
 
         <TextView
             android:layout_width="wrap_content"
-            android:id="@+id/desc"
+            android:id="@+id/subtitle"
             android:maxLines="1"
             android:textColor="?android:attr/textColorTertiary"
             android:textSize="@dimen/search_hero_subtitle_size"
             android:layout_height="wrap_content" />
     </LinearLayout>
 
-    <com.android.launcher3.BubbleTextView
+    <com.android.launcher3.search.SearchResultIcon
         android:id="@+id/shortcut_0"
         style="@style/BaseIcon"
         android:layout_width="@dimen/deep_shortcut_icon_size"
@@ -63,7 +63,7 @@
         launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
         launcher:layoutHorizontal="false" />
 
-    <com.android.launcher3.BubbleTextView
+    <com.android.launcher3.search.SearchResultIcon
         android:id="@+id/shortcut_1"
         style="@style/BaseIcon"
         android:layout_width="@dimen/deep_shortcut_icon_size"
@@ -72,5 +72,4 @@
         android:textSize="@dimen/search_hero_inline_button_size"
         launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
         launcher:layoutHorizontal="false" />
-
 </com.android.launcher3.search.SearchResultIconRow>
\ No newline at end of file
diff --git a/quickstep/res/layout/search_result_play_item.xml b/quickstep/res/layout/search_result_play_item.xml
deleted file mode 100644
index ecd67b1..0000000
--- a/quickstep/res/layout/search_result_play_item.xml
+++ /dev/null
@@ -1,79 +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.search.SearchResultPlayItem xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:padding="4dp"
-    android:orientation="horizontal">
-    <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" />
-
-    <LinearLayout
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_gravity="start|center_vertical"
-        android:layout_weight="1"
-        android:orientation="vertical"
-        android:paddingTop="4dp"
-        android:paddingBottom="4dp"
-        android:paddingStart="8dp"
-        android:paddingEnd="8dp">
-
-        <TextView
-            android:id="@+id/title_view"
-            style="@style/TextHeadline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:maxLines="1"
-            android:ellipsize="end"
-            android:textAlignment="viewStart"
-            android:textColor="?android:attr/textColorPrimary"
-            android:textSize="16sp" />
-
-        <TextView
-            android:id="@+id/detail_0"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="?android:attr/textColorPrimary" />
-
-        <TextView
-            android:id="@+id/detail_1"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="?android:attr/textColorPrimary"
-            android:visibility="gone" />
-
-        <TextView
-            android:id="@+id/detail_2"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="?android:attr/textColorPrimary"
-            android:visibility="gone" />
-    </LinearLayout>
-    <Button
-        android:id="@+id/try_button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="start|center_vertical"
-        android:text="@string/search_action_try_now">
-    </Button>
-
-
-</com.android.launcher3.search.SearchResultPlayItem>
diff --git a/quickstep/res/layout/search_result_settings_row.xml b/quickstep/res/layout/search_result_settings_row.xml
deleted file mode 100644
index 33c9592..0000000
--- a/quickstep/res/layout/search_result_settings_row.xml
+++ /dev/null
@@ -1,60 +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.search.SearchSettingsRowView 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="horizontal"
-    android:gravity="center_vertical"
-    android:padding="@dimen/dynamic_grid_cell_padding_x"
-    android:textColor="?android:attr/textColorPrimary">
-
-    <View
-        android:layout_width="@dimen/search_settings_icon_size"
-        android:src="@drawable/ic_setting"
-        android:id="@+id/icon"
-        android:layout_height="@dimen/search_settings_icon_size" />
-
-    <LinearLayout
-        android:layout_width="0dp"
-        android:orientation="vertical"
-        android:paddingRight="@dimen/dynamic_grid_cell_padding_x"
-        android:paddingLeft="@dimen/dynamic_grid_cell_padding_x"
-        android:layout_height="wrap_content"
-        android:layout_weight="1">
-
-
-        <TextView
-            android:id="@+id/title"
-            style="@style/TextTitle"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/search_line_spacing"
-            android:maxLines="1"
-            android:textColor="?android:attr/textColorPrimary"
-            android:textSize="@dimen/search_hero_title_size" />
-
-        <TextView
-            android:id="@+id/breadcrumbs"
-            style="@style/TextTitle"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            android:textColor="?android:attr/textColorSecondary"
-            android:textSize="@dimen/search_hero_subtitle_size" />
-    </LinearLayout>
-</com.android.launcher3.search.SearchSettingsRowView>
\ No newline at end of file
diff --git a/quickstep/res/layout/search_result_slice.xml b/quickstep/res/layout/search_result_slice.xml
index f7dcfce..4f884ff 100644
--- a/quickstep/res/layout/search_result_slice.xml
+++ b/quickstep/res/layout/search_result_slice.xml
@@ -12,21 +12,21 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.launcher3.search.SearchResultSettingsSlice xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingHorizontal="@dimen/dynamic_grid_cell_padding_x"
+<com.android.launcher3.search.SearchResultIconSlice xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto"
+    android:padding="@dimen/dynamic_grid_edge_margin"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
     <FrameLayout
         android:layout_width="wrap_content"
-        android:paddingTop="@dimen/search_settings_icon_vertical_offset"
         android:layout_height="wrap_content">
 
-        <View
-            android:layout_width="@dimen/search_settings_icon_size"
-            android:src="@drawable/ic_setting"
+        <com.android.launcher3.search.SearchResultIcon
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:id="@+id/icon"
-            android:layout_height="@dimen/search_settings_icon_size" />
+            launcher:iconDisplay="hero_app" />
     </FrameLayout>
 
     <androidx.slice.widget.SliceView
@@ -36,5 +36,5 @@
         android:layout_marginStart="@dimen/dynamic_grid_cell_padding_x"
         android:layout_width="0dp" />
 
-</com.android.launcher3.search.SearchResultSettingsSlice>
+</com.android.launcher3.search.SearchResultIconSlice>
 
diff --git a/quickstep/res/layout/taskbar.xml b/quickstep/res/layout/taskbar.xml
new file mode 100644
index 0000000..5f1046d
--- /dev/null
+++ b/quickstep/res/layout/taskbar.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.taskbar.TaskbarContainerView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/taskbar_container"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <com.android.launcher3.taskbar.TaskbarView
+        android:id="@+id/taskbar_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@color/taskbar_background"/>
+
+</com.android.launcher3.taskbar.TaskbarContainerView>
\ No newline at end of file
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 449fe10..3bc8ddc 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -24,4 +24,7 @@
     <color name="all_apps_label_text_dark">#61FFFFFF</color>
     <color name="all_apps_prediction_row_separator">#3c000000</color>
     <color name="all_apps_prediction_row_separator_dark">#3cffffff</color>
+
+    <!-- Taskbar -->
+    <color name="taskbar_background">#101010</color>
 </resources>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 551f7b0..4272f50 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -119,4 +119,7 @@
 
     <!-- Minimum distance to swipe to trigger accessibility gesture -->
     <dimen name="accessibility_gesture_min_swipe_distance">80dp</dimen>
+
+    <!-- Taskbar -->
+    <dimen name="taskbar_size">48dp</dimen>
 </resources>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 3643d6d..2518f42 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -19,6 +19,7 @@
 import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
 import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_SIZE;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
 
@@ -29,8 +30,11 @@
 import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.view.LayoutInflater;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.WellbeingModel;
 import com.android.launcher3.popup.SystemShortcut;
@@ -39,7 +43,10 @@
 import com.android.launcher3.statehandlers.BackButtonAlphaHandler;
 import com.android.launcher3.statehandlers.DepthController;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
+import com.android.launcher3.taskbar.TaskbarContainerView;
+import com.android.launcher3.taskbar.TaskbarController;
 import com.android.launcher3.uioverrides.RecentsViewStateController;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.SysUINavigationMode;
@@ -53,7 +60,6 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.ActivityOptionsCompat;
-import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
 import java.util.stream.Stream;
@@ -75,6 +81,8 @@
 
     private OverviewActionsView mActionsView;
 
+    private @Nullable TaskbarController mTaskbarController;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -86,6 +94,11 @@
     @Override
     public void onDestroy() {
         SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
+
+        if (mTaskbarController != null) {
+            mTaskbarController.cleanup();
+        }
+
         super.onDestroy();
     }
 
@@ -190,6 +203,29 @@
         mActionsView = findViewById(R.id.overview_actions_view);
         ((RecentsView) getOverviewPanel()).init(mActionsView);
         mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
+
+        addTaskbarIfNecessary();
+    }
+
+    @Override
+    public void onDisplayInfoChanged(DisplayController.Info info, int flags) {
+        super.onDisplayInfoChanged(info, flags);
+        if ((flags & CHANGE_SIZE) != 0) {
+            addTaskbarIfNecessary();
+        }
+    }
+
+    private void addTaskbarIfNecessary() {
+        if (mTaskbarController != null) {
+            mTaskbarController.cleanup();
+            mTaskbarController = null;
+        }
+        if (FeatureFlags.ENABLE_TASKBAR.get() && mDeviceProfile.isTablet) {
+            TaskbarContainerView taskbarContainer = (TaskbarContainerView) LayoutInflater.from(this)
+                    .inflate(R.layout.taskbar, null, false);
+            mTaskbarController = new TaskbarController(this, taskbarContainer);
+            mTaskbarController.init();
+        }
     }
 
     public <T extends OverviewActionsView> T getActionsView() {
diff --git a/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java b/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
index 3343cf5..834a624 100644
--- a/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
+++ b/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
@@ -21,17 +21,16 @@
 import android.app.search.SearchTarget;
 import android.util.SparseIntArray;
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.app.search.LayoutType;
-import com.android.app.search.ResultType;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsGridAdapter;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
 import com.android.launcher3.config.FeatureFlags;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
 
 /**
  * Provides views for on-device search results
@@ -39,14 +38,12 @@
 public class DeviceSearchAdapterProvider extends SearchAdapterProvider {
 
     public static final int VIEW_TYPE_SEARCH_CORPUS_TITLE = 1 << 5;
-    public static final int VIEW_TYPE_SEARCH_ROW_WITH_BUTTON = 1 << 7;
-    public static final int VIEW_TYPE_SEARCH_ROW = 1 << 8;
-    public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 9;
-    public static final int VIEW_TYPE_SEARCH_ICON_ROW = 1 << 10;
+    public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 7;
+    public static final int VIEW_TYPE_SEARCH_ICON = (1 << 8) | VIEW_TYPE_ICON;
+    public static final int VIEW_TYPE_SEARCH_ICON_ROW = (1 << 9);
     public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11;
     public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12;
     public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13;
-    public static final int VIEW_TYPE_SEARCH_ICON = (1 << 14) | VIEW_TYPE_ICON;
     public static final int VIEW_TYPE_SEARCH_WIDGET_LIVE = 1 << 15;
     public static final int VIEW_TYPE_SEARCH_WIDGET_PREVIEW = 1 << 16;
 
@@ -58,13 +55,10 @@
         super(launcher);
         mAppsView = appsView;
 
-        mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_ICON, R.layout.search_result_icon);
         mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_CORPUS_TITLE, R.layout.search_section_title);
-        mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_ROW_WITH_BUTTON,
-                R.layout.search_result_play_item);
-        mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_ROW, R.layout.search_result_settings_row);
-        mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_SLICE, R.layout.search_result_slice);
+        mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_ICON, R.layout.search_result_icon);
         mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_ICON_ROW, R.layout.search_result_icon_row);
+        mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_SLICE, R.layout.search_result_slice);
         mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_PEOPLE, R.layout.search_result_people_item);
         mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_THUMBNAIL, R.layout.search_result_thumbnail);
         mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_SUGGEST, R.layout.search_result_suggest);
@@ -110,12 +104,9 @@
 
 
     @Override
-    public boolean onAdapterItemSelected(AllAppsGridAdapter.AdapterItem focusedItem) {
-        if (focusedItem instanceof SearchTargetHandler) {
-            SearchTargetLegacy searchTarget = ((SearchAdapterItem) focusedItem)
-                    .getSearchTargetLegacy();
-            SearchEventTracker.INSTANCE.get(mLauncher).quickSelect(searchTarget);
-            return true;
+    public boolean onAdapterItemSelected(AllAppsGridAdapter.AdapterItem adapterItem, View view) {
+        if (view instanceof SearchTargetHandler) {
+            return ((SearchTargetHandler) view).quickSelect();
         }
         return false;
     }
@@ -125,25 +116,20 @@
      * Returns -1 if viewType is not found
      */
     public int getViewTypeForSearchTarget(SearchTarget t) {
-        if (t.getLayoutType().equals(LayoutType.TEXT_HEADER)) {
-            return VIEW_TYPE_SEARCH_CORPUS_TITLE;
-        }
-        switch (t.getResultType()) {
-            case ResultType.APPLICATION:
-                if (t.getLayoutType().equals(LayoutType.ICON_SINGLE_VERTICAL_TEXT)) {
-                    return VIEW_TYPE_SEARCH_ICON;
-                }
-                break;
-            case ResultType.SETTING:
-                if (t.getLayoutType().equals(LayoutType.ICON_SLICE)) {
-                    return VIEW_TYPE_SEARCH_SLICE;
-                }
-                return VIEW_TYPE_SEARCH_ROW;
-            case ResultType.SHORTCUT:
+        switch (t.getLayoutType()) {
+            case LayoutType.TEXT_HEADER:
+                return VIEW_TYPE_SEARCH_CORPUS_TITLE;
+            case LayoutType.ICON_SINGLE_VERTICAL_TEXT:
+                return VIEW_TYPE_SEARCH_ICON;
+            case LayoutType.ICON_SLICE:
+                return VIEW_TYPE_SEARCH_SLICE;
+            case LayoutType.ICON_DOUBLE_HORIZONTAL_TEXT_BUTTON:
+            case LayoutType.ICON_DOUBLE_HORIZONTAL_TEXT:
+            case LayoutType.ICON_SINGLE_HORIZONTAL_TEXT:
                 return VIEW_TYPE_SEARCH_ICON_ROW;
-            case ResultType.PLAY:
-                return VIEW_TYPE_SEARCH_ROW_WITH_BUTTON;
+            default:
+                return -1;
+
         }
-        return -1;
     }
 }
diff --git a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
index 65ac3f9..01b1999 100644
--- a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
+++ b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
@@ -19,8 +19,6 @@
 import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_ICON;
 import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_ICON_ROW;
 import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_PEOPLE;
-import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_ROW;
-import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_ROW_WITH_BUTTON;
 import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_SLICE;
 import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_SUGGEST;
 import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_THUMBNAIL;
@@ -44,11 +42,11 @@
     private List<SearchTarget> mInlineItems = new ArrayList<>();
 
 
-    private static final int AVAILABLE_FOR_ACCESSIBILITY = VIEW_TYPE_SEARCH_ROW_WITH_BUTTON
-            | VIEW_TYPE_SEARCH_SLICE | VIEW_TYPE_SEARCH_ROW | VIEW_TYPE_SEARCH_PEOPLE
-            | VIEW_TYPE_SEARCH_THUMBNAIL | VIEW_TYPE_SEARCH_ICON_ROW | VIEW_TYPE_SEARCH_ICON
-            | VIEW_TYPE_SEARCH_WIDGET_PREVIEW | VIEW_TYPE_SEARCH_WIDGET_LIVE
-            | VIEW_TYPE_SEARCH_SUGGEST;
+    private static final int AVAILABLE_FOR_ACCESSIBILITY =
+            VIEW_TYPE_SEARCH_SLICE | VIEW_TYPE_SEARCH_PEOPLE | VIEW_TYPE_SEARCH_THUMBNAIL
+                    | VIEW_TYPE_SEARCH_ICON_ROW | VIEW_TYPE_SEARCH_ICON
+                    | VIEW_TYPE_SEARCH_WIDGET_PREVIEW | VIEW_TYPE_SEARCH_WIDGET_LIVE
+                    | VIEW_TYPE_SEARCH_SUGGEST;
 
     public SearchAdapterItem(SearchTargetLegacy searchTargetLegacy, int type) {
         mSearchTargetLegacy = searchTargetLegacy;
diff --git a/quickstep/src/com/android/launcher3/search/SearchEventTracker.java b/quickstep/src/com/android/launcher3/search/SearchEventTracker.java
deleted file mode 100644
index 90fe661..0000000
--- a/quickstep/src/com/android/launcher3/search/SearchEventTracker.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2017 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.search;
-
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
-import android.content.Context;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.systemui.plugins.AllAppsSearchPlugin;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
-
-import java.util.WeakHashMap;
-
-/**
- * A singleton class to track and report search events to search provider
- */
-public class SearchEventTracker {
-    @Nullable
-    private AllAppsSearchPlugin mPlugin;
-    private final WeakHashMap<SearchTargetLegacy, SearchTargetHandler>
-            mCallbacks = new WeakHashMap<>();
-
-    public static final MainThreadInitializedObject<SearchEventTracker> INSTANCE =
-            new MainThreadInitializedObject<>(SearchEventTracker::new);
-
-    private SearchEventTracker(Context context) {
-    }
-
-    /**
-     * Returns instance of SearchEventTracker
-     */
-    public static SearchEventTracker getInstance(Context context) {
-        return SearchEventTracker.INSTANCE.get(context);
-    }
-
-    /**
-     * Sets current connected plugin for event reporting
-     */
-    public void setPlugin(@Nullable AllAppsSearchPlugin plugin) {
-        mPlugin = plugin;
-    }
-
-    /**
-     * Sends SearchTargetEvent to search provider
-     */
-    public void notifySearchTargetEvent(SearchTargetEventLegacy searchTargetEvent) {
-        if (mPlugin != null) {
-            UI_HELPER_EXECUTOR.post(() -> mPlugin.notifySearchTargetEventLegacy(searchTargetEvent));
-        }
-    }
-
-    /**
-     * Registers a {@link SearchTargetHandler} to handle quick launch for specified SearchTarget.
-     */
-    public void registerWeakHandler(SearchTargetLegacy searchTarget,
-            SearchTargetHandler targetHandler) {
-        mCallbacks.put(searchTarget, targetHandler);
-    }
-
-    /**
-     * Handles quick select for SearchTarget
-     */
-    public void quickSelect(SearchTargetLegacy searchTarget) {
-        SearchTargetHandler searchTargetHandler = mCallbacks.get(searchTarget);
-        if (searchTargetHandler != null) {
-            searchTargetHandler.handleSelection(SearchTargetEventLegacy.QUICK_SELECT);
-        }
-    }
-
-    /**
-     * flushes all registered quick select handlers
-     */
-    public void clearHandlers() {
-        mCallbacks.clear();
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
index d5fe0e8..0b8d3cb 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
@@ -17,15 +17,16 @@
 
 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.app.search.SearchAction;
 import android.app.search.SearchTarget;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.view.View;
@@ -36,17 +37,14 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.allapps.AllAppsStore;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.model.data.RemoteActionItemInfo;
+import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.model.data.SearchActionItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.touch.ItemLongClickListener;
 import com.android.launcher3.util.ComponentKey;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
 
 import java.util.List;
 import java.util.function.Consumer;
@@ -58,22 +56,11 @@
         SearchTargetHandler, View.OnClickListener,
         View.OnLongClickListener {
 
-
-    public static final String TARGET_TYPE_APP = "app";
-    public static final String TARGET_TYPE_HERO_APP = "hero_app";
-    public static final String TARGET_TYPE_SHORTCUT = "shortcut";
-    public static final String TARGET_TYPE_REMOTE_ACTION = "remote_action";
-
-    public static final String REMOTE_ACTION_SHOULD_START = "should_start_for_result";
-    public static final String REMOTE_ACTION_TOKEN = "action_token";
-
-
-    private static final String[] LONG_PRESS_SUPPORTED_TYPES =
-            new String[]{TARGET_TYPE_APP, TARGET_TYPE_SHORTCUT, TARGET_TYPE_HERO_APP};
+    private static final String BUNDLE_EXTRA_SHOULD_START = "should_start";
+    private static final String BUNDLE_EXTRA_SHOULD_START_FOR_RESULT = "should_start_for_result";
 
     private final Launcher mLauncher;
 
-    private SearchTargetLegacy mSearchTarget;
     private Consumer<ItemInfoWithIcon> mOnItemInfoChanged;
 
     public SearchResultIcon(Context context) {
@@ -89,6 +76,8 @@
         mLauncher = Launcher.getLauncher(getContext());
     }
 
+    private boolean mLongPressSupported;
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
@@ -101,37 +90,6 @@
     }
 
     /**
-     * Applies search target with a ItemInfoWithIcon consumer to be called after itemInfo is
-     * constructed
-     */
-    public void applySearchTarget(SearchTargetLegacy searchTarget, Consumer<ItemInfoWithIcon> cb) {
-        mOnItemInfoChanged = cb;
-        applySearchTarget(searchTarget);
-    }
-
-    @Override
-    public void applySearchTarget(SearchTargetLegacy searchTarget) {
-        mSearchTarget = searchTarget;
-        SearchEventTracker.getInstance(getContext()).registerWeakHandler(mSearchTarget, this);
-        setVisibility(VISIBLE);
-        switch (searchTarget.getItemType()) {
-            case TARGET_TYPE_APP:
-            case TARGET_TYPE_HERO_APP:
-                prepareUsingApp(searchTarget.getComponentName(), searchTarget.getUserHandle());
-                break;
-            case TARGET_TYPE_SHORTCUT:
-                prepareUsingShortcutInfo(searchTarget.getShortcutInfos().get(0));
-                break;
-            case TARGET_TYPE_REMOTE_ACTION:
-                prepareUsingRemoteAction(searchTarget.getRemoteAction(),
-                        searchTarget.getExtras().getString(REMOTE_ACTION_TOKEN),
-                        searchTarget.getExtras().getBoolean(REMOTE_ACTION_SHOULD_START),
-                        searchTarget.getItemType().equals(TARGET_TYPE_REMOTE_ACTION));
-                break;
-        }
-    }
-
-    /**
      * Applies {@link SearchTarget} to view. registers a consumer after a corresponding
      * {@link ItemInfoWithIcon} is created
      */
@@ -147,13 +105,61 @@
             case ResultType.APPLICATION:
                 prepareUsingApp(new ComponentName(parentTarget.getPackageName(),
                         parentTarget.getExtras().getString("class")), parentTarget.getUserHandle());
+                mLongPressSupported = true;
                 break;
             case ResultType.SHORTCUT:
                 prepareUsingShortcutInfo(parentTarget.getShortcutInfo());
+                mLongPressSupported = true;
+                break;
+            default:
+                prepareUsingSearchAction(parentTarget);
+                mLongPressSupported = false;
                 break;
         }
     }
 
+    private void prepareUsingSearchAction(SearchTarget searchTarget) {
+        SearchAction searchAction = searchTarget.getSearchAction();
+        Bundle extras = searchAction.getExtras();
+        SearchActionItemInfo itemInfo = new SearchActionItemInfo(searchAction.getIcon(),
+                searchTarget.getPackageName(), searchTarget.getUserHandle(),
+                searchAction.getTitle());
+        itemInfo.setIntent(searchAction.getIntent());
+        itemInfo.setPendingIntent(searchAction.getPendingIntent());
+
+        //TODO: remove this after flags are introduced in SearchAction. Settings results require
+        // startActivityForResult
+        boolean isSettingsResult = searchTarget.getResultType() == ResultType.SETTING;
+        if ((extras != null && extras.getBoolean(BUNDLE_EXTRA_SHOULD_START_FOR_RESULT))
+                || isSettingsResult) {
+            itemInfo.setFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT);
+        } else if (extras != null && extras.getBoolean(BUNDLE_EXTRA_SHOULD_START)) {
+            itemInfo.setFlags(SearchActionItemInfo.FLAG_SHOULD_START);
+        }
+
+
+        notifyItemInfoChanged(itemInfo);
+        LauncherAppState appState = LauncherAppState.getInstance(mLauncher);
+        MODEL_EXECUTOR.post(() -> {
+            try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
+                Icon icon = searchTarget.getSearchAction().getIcon();
+                Drawable d;
+                if (icon == null) {
+                    PackageItemInfo pkgInfo = new PackageItemInfo(searchTarget.getPackageName());
+                    pkgInfo.user = searchTarget.getUserHandle();
+                    appState.getIconCache().getTitleAndIconForApp(pkgInfo, false);
+                    itemInfo.bitmap = pkgInfo.bitmap;
+                } else {
+                    d = itemInfo.getIcon().loadDrawable(getContext());
+                    itemInfo.bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
+                            Build.VERSION.SDK_INT);
+                }
+
+            }
+            MAIN_EXECUTOR.post(() -> applyFromSearchActionItemInfo(itemInfo));
+        });
+    }
+
     private void prepareUsingApp(ComponentName componentName, UserHandle userHandle) {
         AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
         AppInfo appInfo = appsStore.getApp(new ComponentKey(componentName, userHandle));
@@ -177,69 +183,26 @@
         });
     }
 
-    private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start,
-            boolean useIconToBadge) {
-        RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start);
-        notifyItemInfoChanged(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());
-                BitmapInfo bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
-                        Build.VERSION.SDK_INT);
-
-                if (useIconToBadge) {
-                    BitmapInfo placeholder = li.createIconBitmap(
-                            itemInfo.getRemoteAction().getTitle().toString().substring(0, 1),
-                            bitmap.color);
-                    itemInfo.bitmap = li.badgeBitmap(placeholder.icon, bitmap);
-                } else {
-                    itemInfo.bitmap = bitmap;
-                }
-            }
-            MAIN_EXECUTOR.post(() -> applyFromRemoteActionInfo(itemInfo));
-        });
-    }
-
     @Override
-    public void handleSelection(int eventType) {
-        mLauncher.getItemOnClickListener().onClick(this);
-        if (!FeatureFlags.USE_SEARCH_API.get()) {
-            reportEvent(eventType);
-        }
-    }
-
-    private void reportEvent(int eventType) {
-        SearchTargetEventLegacy.Builder b = new SearchTargetEventLegacy.Builder(mSearchTarget,
-                eventType);
-        if (mSearchTarget.getItemType().equals(TARGET_TYPE_SHORTCUT)) {
-            b.setShortcutPosition(0);
-        }
-        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(b.build());
-
+    public boolean quickSelect() {
+        //TODO: event reporting
+        this.performClick();
+        return true;
     }
 
     @Override
     public void onClick(View view) {
-        handleSelection(SearchTargetEventLegacy.SELECT);
+        //TODO: event reporting
+        mLauncher.getItemOnClickListener().onClick(this);
     }
 
     @Override
     public boolean onLongClick(View view) {
-        if (!supportsLongPress(mSearchTarget.getItemType())) {
+        //TODO: event reporting
+        if (!mLongPressSupported) {
             return false;
         }
-        reportEvent(SearchTargetEventLegacy.LONG_PRESS);
-        return ItemLongClickListener.INSTANCE_ALL_APPS.onLongClick(view);
-
-    }
-
-    private boolean supportsLongPress(String type) {
-        for (String t : LONG_PRESS_SUPPORTED_TYPES) {
-            if (t.equals(type)) return true;
-        }
-        return false;
+        return ItemLongClickListener.INSTANCE_ALL_APPS.onLongClick(this);
     }
 
     private void notifyItemInfoChanged(ItemInfoWithIcon itemInfoWithIcon) {
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java b/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
index 80d543a..4fb668e 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
@@ -19,56 +19,42 @@
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
 import android.app.search.SearchTarget;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ShortcutInfo;
-import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.Pair;
-import android.view.View;
-import android.view.ViewGroup;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
 
-import com.android.app.search.ResultType;
-import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.Consumer;
 
 /**
  * A full width representation of {@link SearchResultIcon} with a secondary label and inline
- * shortcuts
+ * SearchTargets
  */
-public class SearchResultIconRow extends LinearLayout implements
-        SearchTargetHandler, View.OnClickListener,
-        View.OnLongClickListener, Consumer<ItemInfoWithIcon> {
-    public static final int MAX_SHORTCUTS_COUNT = 2;
+public class SearchResultIconRow extends LinearLayout implements SearchTargetHandler {
 
+    public static final int MAX_INLINE_ITEMS = 2;
 
-    private final Launcher mLauncher;
+    protected final Launcher mLauncher;
     private final LauncherAppState mLauncherAppState;
     private SearchResultIcon mResultIcon;
+
     private TextView mTitleView;
-    private TextView mDescriptionView;
-    private BubbleTextView[] mShortcutViews = new BubbleTextView[2];
+    private TextView mSubTitleView;
+    private final SearchResultIcon[] mInlineIcons = new SearchResultIcon[MAX_INLINE_ITEMS];
 
-    private SearchTargetLegacy mSearchTarget;
     private PackageItemInfo mProviderInfo;
 
-
     public SearchResultIconRow(Context context) {
         this(context, null, 0);
     }
@@ -84,129 +70,87 @@
         mLauncherAppState = LauncherAppState.getInstance(getContext());
     }
 
+    protected int getIconSize() {
+        return mLauncher.getDeviceProfile().allAppsIconSizePx;
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        int iconSize = mLauncher.getDeviceProfile().allAppsIconSizePx;
+
+        int iconSize = getIconSize();
 
         mResultIcon = findViewById(R.id.icon);
         mTitleView = findViewById(R.id.title);
-        mDescriptionView = findViewById(R.id.desc);
-        mShortcutViews[0] = findViewById(R.id.shortcut_0);
-        mShortcutViews[1] = findViewById(R.id.shortcut_1);
+        mSubTitleView = findViewById(R.id.subtitle);
+        mSubTitleView.setVisibility(GONE);
         mResultIcon.getLayoutParams().height = iconSize;
         mResultIcon.getLayoutParams().width = iconSize;
         mResultIcon.setTextVisibility(false);
-        for (BubbleTextView bubbleTextView : mShortcutViews) {
-            ViewGroup.LayoutParams lp = bubbleTextView.getLayoutParams();
-            lp.width = iconSize;
-            bubbleTextView.setOnClickListener(view -> {
-                WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) bubbleTextView.getTag();
-                SearchTargetEventLegacy event = new SearchTargetEventLegacy.Builder(mSearchTarget,
-                        SearchTargetEventLegacy.CHILD_SELECT).setShortcutPosition(
-                        itemInfo.rank).build();
-                SearchEventTracker.getInstance(getContext()).notifySearchTargetEvent(event);
-                mLauncher.getItemOnClickListener().onClick(view);
-            });
+
+        mInlineIcons[0] = findViewById(R.id.shortcut_0);
+        mInlineIcons[1] = findViewById(R.id.shortcut_1);
+        for (SearchResultIcon inlineIcon : mInlineIcons) {
+            inlineIcon.getLayoutParams().width = getIconSize();
         }
-        setOnClickListener(this);
-        setOnLongClickListener(this);
+
+        setOnClickListener(mResultIcon);
+        setOnLongClickListener(mResultIcon);
     }
 
     @Override
     public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
-        mResultIcon.applySearchTarget(parentTarget, children, this);
-        if (parentTarget.getResultType() == ResultType.SHORTCUT) {
-            ShortcutInfo shortcutInfo = parentTarget.getShortcutInfo();
-            setProviderDetails(new ComponentName(shortcutInfo.getPackage(), ""),
-                    shortcutInfo.getUserHandle());
+        mResultIcon.applySearchTarget(parentTarget, children, this::onItemInfoCreated);
+        if (parentTarget.getShortcutInfo() != null) {
+            updateWithShortcutInfo(parentTarget.getShortcutInfo());
+        } else if (parentTarget.getSearchAction() != null) {
+            showSubtitleIfNeeded(parentTarget.getSearchAction().getSubtitle());
         }
+        showInlineItems(children);
     }
 
     @Override
-    public void applySearchTarget(SearchTargetLegacy searchTarget) {
-        mSearchTarget = searchTarget;
-        mResultIcon.applySearchTarget(searchTarget, this);
-        String itemType = searchTarget.getItemType();
-        boolean showDesc = itemType.equals(SearchResultIcon.TARGET_TYPE_SHORTCUT);
-        mDescriptionView.setVisibility(showDesc ? VISIBLE : GONE);
-
-        if (itemType.equals(SearchResultIcon.TARGET_TYPE_SHORTCUT)) {
-            ShortcutInfo shortcutInfo = searchTarget.getShortcutInfos().get(0);
-            setProviderDetails(new ComponentName(shortcutInfo.getPackage(), ""),
-                    shortcutInfo.getUserHandle());
-        } else if (itemType.equals(SearchResultIcon.TARGET_TYPE_HERO_APP)) {
-            showInlineShortcuts(mSearchTarget.getShortcutInfos());
-        } else if (itemType.equals(SearchResultIcon.TARGET_TYPE_REMOTE_ACTION)) {
-            CharSequence desc = mSearchTarget.getRemoteAction().getContentDescription();
-            if (!TextUtils.isEmpty(desc)) {
-                mDescriptionView.setVisibility(VISIBLE);
-                mDescriptionView.setText(desc);
-            }
-        }
-        if (!itemType.equals(SearchResultIcon.TARGET_TYPE_HERO_APP)) {
-            showInlineShortcuts(new ArrayList<>());
-        }
+    public boolean quickSelect() {
+        this.performClick();
+        return true;
     }
 
-    @Override
-    public void accept(ItemInfoWithIcon itemInfoWithIcon) {
-        mTitleView.setText(itemInfoWithIcon.title);
-    }
-
-    private void showInlineShortcuts(List<ShortcutInfo> infos) {
-        if (infos == null) return;
-        ArrayList<Pair<ShortcutInfo, ItemInfoWithIcon>> shortcuts = new ArrayList<>();
-        for (int i = 0; infos != null && i < infos.size() && i < MAX_SHORTCUTS_COUNT; i++) {
-            ShortcutInfo shortcutInfo = infos.get(i);
-            ItemInfoWithIcon si = new WorkspaceItemInfo(shortcutInfo, getContext());
-            si.rank = i;
-            shortcuts.add(new Pair<>(shortcutInfo, si));
-        }
-
-        for (int i = 0; i < mShortcutViews.length; i++) {
-            BubbleTextView shortcutView = mShortcutViews[i];
-            mShortcutViews[i].setVisibility(shortcuts.size() > i ? VISIBLE : GONE);
-            if (i < shortcuts.size()) {
-                Pair<ShortcutInfo, ItemInfoWithIcon> p = shortcuts.get(i);
-                //apply ItemInfo and prepare view
-                shortcutView.applyFromWorkspaceItem((WorkspaceItemInfo) p.second);
-                MODEL_EXECUTOR.execute(() -> {
-                    // load unbadged shortcut in background and update view when icon ready
-                    mLauncherAppState.getIconCache().getUnbadgedShortcutIcon(p.second, p.first);
-                    MAIN_EXECUTOR.post(() -> shortcutView.reapplyItemInfo(p.second));
-                });
-            }
-        }
-    }
-
-
-    private void setProviderDetails(ComponentName componentName, UserHandle userHandle) {
-        PackageItemInfo packageItemInfo = new PackageItemInfo(componentName.getPackageName());
-        if (mProviderInfo == packageItemInfo) return;
+    private void updateWithShortcutInfo(ShortcutInfo shortcutInfo) {
+        PackageItemInfo packageItemInfo = new PackageItemInfo(shortcutInfo.getPackage());
+        if (packageItemInfo.equals(mProviderInfo)) return;
         MODEL_EXECUTOR.post(() -> {
-            packageItemInfo.user = userHandle;
             mLauncherAppState.getIconCache().getTitleAndIconForApp(packageItemInfo, true);
             MAIN_EXECUTOR.post(() -> {
-                mDescriptionView.setText(packageItemInfo.title);
+                showSubtitleIfNeeded(packageItemInfo.title);
                 mProviderInfo = packageItemInfo;
             });
         });
     }
 
-    @Override
-    public void handleSelection(int eventType) {
-        mResultIcon.handleSelection(eventType);
+
+    protected void showSubtitleIfNeeded(CharSequence subTitle) {
+        if (!TextUtils.isEmpty(subTitle)) {
+            mSubTitleView.setText(subTitle);
+            mSubTitleView.setVisibility(VISIBLE);
+        } else {
+            mSubTitleView.setVisibility(GONE);
+        }
     }
 
-    @Override
-    public void onClick(View view) {
-        mResultIcon.performClick();
+
+    protected void showInlineItems(List<SearchTarget> children) {
+        for (int i = 0; i < MAX_INLINE_ITEMS; i++) {
+            if (i < children.size()) {
+                mInlineIcons[i].applySearchTarget(children.get(0), new ArrayList<>());
+                mInlineIcons[i].setVisibility(VISIBLE);
+            } else {
+                mInlineIcons[i].setVisibility(GONE);
+            }
+        }
     }
 
-    @Override
-    public boolean onLongClick(View view) {
-        mResultIcon.performLongClick();
-        return false;
+    protected void onItemInfoCreated(ItemInfoWithIcon info) {
+        setTag(info);
+        mTitleView.setText(info.title);
     }
 }
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultSettingsSlice.java b/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java
similarity index 69%
rename from quickstep/src/com/android/launcher3/search/SearchResultSettingsSlice.java
rename to quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java
index bf50b67..e6c952f 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultSettingsSlice.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java
@@ -15,12 +15,13 @@
  */
 package com.android.launcher3.search;
 
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
 import android.app.search.SearchTarget;
 import android.content.Context;
 import android.net.Uri;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.widget.LinearLayout;
 
 import androidx.annotation.NonNull;
@@ -32,40 +33,39 @@
 import androidx.slice.widget.SliceView;
 
 import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
+import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.systemui.plugins.shared.SearchTargetLegacy;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
  * A slice view wrapper with settings app icon at start
  */
-public class SearchResultSettingsSlice extends LinearLayout implements
+public class SearchResultIconSlice extends LinearLayout implements
         SearchTargetHandler, SliceView.OnSliceActionListener {
 
-
-    public static final String TARGET_TYPE_SLICE = "settings_slice";
-
     private static final String TAG = "SearchSliceController";
     private static final String URI_EXTRA_KEY = "slice_uri";
 
     private SliceView mSliceView;
-    private View mIcon;
+    private SearchResultIcon mIcon;
     private LiveData<Slice> mSliceLiveData;
     private SearchTargetLegacy mSearchTarget;
     private final Launcher mLauncher;
 
-    public SearchResultSettingsSlice(Context context) {
+    public SearchResultIconSlice(Context context) {
         this(context, null, 0);
     }
 
-    public SearchResultSettingsSlice(Context context,
+    public SearchResultIconSlice(Context context,
             @Nullable AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
-    public SearchResultSettingsSlice(Context context, @Nullable AttributeSet attrs,
+    public SearchResultIconSlice(Context context, @Nullable AttributeSet attrs,
             int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         mLauncher = Launcher.getLauncher(getContext());
@@ -76,24 +76,16 @@
         super.onFinishInflate();
         mSliceView = findViewById(R.id.slice);
         mIcon = findViewById(R.id.icon);
-        SearchSettingsRowView.applySettingsIcon(mLauncher, mIcon);
-    }
-
-    @Override
-    public void applySearchTarget(SearchTargetLegacy searchTarget) {
-        reset();
-        mSearchTarget = searchTarget;
-        try {
-            mSliceLiveData = mLauncher.getLiveSearchManager().getSliceForUri(getSliceUri());
-            mSliceLiveData.observe(mLauncher, mSliceView);
-        } catch (Exception ex) {
-            Log.e(TAG, "unable to bind slice", ex);
-        }
+        mIcon.setTextVisibility(false);
+        int iconSize = mLauncher.getDeviceProfile().iconSizePx;
+        mIcon.getLayoutParams().height = iconSize;
+        mIcon.getLayoutParams().width = iconSize;
     }
 
     @Override
     public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
         reset();
+        updateIcon(parentTarget, children);
         try {
             mSliceLiveData = mLauncher.getLiveSearchManager().getSliceForUri(
                     parentTarget.getSliceUri());
@@ -103,6 +95,20 @@
         }
     }
 
+    private void updateIcon(SearchTarget parentTarget, List<SearchTarget> children) {
+        if (children.size() == 1) {
+            mIcon.applySearchTarget(children.get(0), new ArrayList<>());
+        } else {
+            LauncherAppState appState = LauncherAppState.getInstance(getContext());
+            MODEL_EXECUTOR.post(() -> {
+                PackageItemInfo pkgItem = new PackageItemInfo(parentTarget.getPackageName());
+                pkgItem.user = parentTarget.getUserHandle();
+                appState.getIconCache().getTitleAndIconForApp(pkgItem, false);
+                mIcon.applyFromItemInfoWithIcon(pkgItem);
+            });
+        }
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -115,12 +121,6 @@
         reset();
     }
 
-    @Override
-    public void handleSelection(int eventType) {
-        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
-                new SearchTargetEventLegacy.Builder(mSearchTarget,
-                        SearchTargetEventLegacy.CHILD_SELECT).build());
-    }
 
     private void reset() {
         mSliceView.setOnSliceActionListener(null);
@@ -131,7 +131,7 @@
 
     @Override
     public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
-        handleSelection(SearchTargetEventLegacy.CHILD_SELECT);
+        //TODO: event reporting
     }
 
     private Uri getSliceUri() {
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java b/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java
index 8caa51c..f3355da 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java
@@ -44,7 +44,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.LauncherIcons;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
 import com.android.systemui.plugins.shared.SearchTargetLegacy;
 
 import java.util.ArrayList;
@@ -99,7 +98,6 @@
             button.getLayoutParams().width = mButtonSize;
             button.getLayoutParams().height = mButtonSize;
         }
-        setOnClickListener(v -> handleSelection(SearchTargetEventLegacy.SELECT));
     }
 
     @Override
@@ -137,7 +135,6 @@
                 button.setVisibility(GONE);
             }
         }
-        SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
     }
 
     /**
@@ -185,19 +182,6 @@
             launcher.startActivitySafely(b, intent, null);
             Bundle bundle = new Bundle();
             bundle.putBundle("provider", provider);
-            SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
-                    new SearchTargetEventLegacy.Builder(mSearchTarget,
-                            SearchTargetEventLegacy.CHILD_SELECT).setExtras(bundle).build());
         });
     }
-
-    @Override
-    public void handleSelection(int eventType) {
-        if (mIntent != null) {
-            Launcher launcher = Launcher.getLauncher(getContext());
-            launcher.startActivitySafely(this, mIntent, null);
-            SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
-                    new SearchTargetEventLegacy.Builder(mSearchTarget, eventType).build());
-        }
-    }
 }
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultPlayItem.java b/quickstep/src/com/android/launcher3/search/SearchResultPlayItem.java
deleted file mode 100644
index 840bde9..0000000
--- a/quickstep/src/com/android/launcher3/search/SearchResultPlayItem.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2015 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.search;
-
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
-import android.app.search.SearchAction;
-import android.app.search.SearchTarget;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.BitmapDrawable;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.icons.BitmapRenderer;
-import com.android.launcher3.util.Themes;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.List;
-
-/**
- * A View representing a PlayStore item.
- */
-public class SearchResultPlayItem extends LinearLayout implements
-        SearchTargetHandler {
-
-    public static final String TARGET_TYPE_PLAY = "play";
-
-    private static final int BITMAP_CROP_MASK_COLOR = 0xff424242;
-    final Paint mIconPaint = new Paint();
-    final Rect mTempRect = new Rect();
-    private final DeviceProfile mDeviceProfile;
-    private View mIconView;
-    private TextView mTitleView;
-    private TextView[] mDetailViews = new TextView[3];
-    private Button mPreviewButton;
-    private String mPackageName;
-    private Intent mIntent;
-    private Intent mSecondaryIntent;
-
-
-    public SearchResultPlayItem(Context context) {
-        this(context, null, 0);
-    }
-
-    public SearchResultPlayItem(Context context,
-            @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public SearchResultPlayItem(Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        mDeviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mIconView = findViewById(R.id.icon);
-        mTitleView = findViewById(R.id.title_view);
-        mPreviewButton = findViewById(R.id.try_button);
-        mPreviewButton.setOnClickListener(view -> launchIntent(mSecondaryIntent));
-        mDetailViews[0] = findViewById(R.id.detail_0);
-        mDetailViews[1] = findViewById(R.id.detail_1);
-        mDetailViews[2] = findViewById(R.id.detail_2);
-
-        ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
-        iconParams.height = mDeviceProfile.allAppsIconSizePx;
-        iconParams.width = mDeviceProfile.allAppsIconSizePx;
-        setOnClickListener(view -> launchIntent(mIntent));
-    }
-
-    private void showIfNecessary(TextView textView, @Nullable String string) {
-        if (string == null || string.isEmpty()) {
-            textView.setVisibility(GONE);
-        } else {
-            textView.setText(string);
-            textView.setVisibility(VISIBLE);
-        }
-    }
-
-    private void launchIntent(Intent intent) {
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        getContext().startActivity(intent);
-    }
-
-    @Override
-    public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
-        if (parentTarget.getPackageName().equals(mPackageName)) {
-            return;
-        }
-        mPackageName = parentTarget.getPackageName();
-        SearchAction action = parentTarget.getSearchAction();
-        mTitleView.setText(action.getTitle());
-        showIfNecessary(mDetailViews[0], action.getSubtitle().toString());
-        mIntent = action.getIntent();
-
-        mIconView.setBackgroundResource(R.drawable.ic_deepshortcut_placeholder);
-        loadIcon(action.getIcon().getUri().toString());
-
-        mSecondaryIntent = children.size() == 1 ? children.get(0).getSearchAction().getIntent()
-                : null;
-        mPreviewButton.setVisibility(mSecondaryIntent == null ? GONE : VISIBLE);
-    }
-
-    private void loadIcon(String iconUrl) {
-        UI_HELPER_EXECUTOR.execute(() -> {
-            try {
-                URL url = new URL(iconUrl);
-                URLConnection con = url.openConnection();
-                con.addRequestProperty("Cache-Control", "max-age: 0");
-                con.setUseCaches(true);
-                Bitmap bitmap = BitmapFactory.decodeStream(con.getInputStream());
-                BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), getRoundedBitmap(
-                        Bitmap.createScaledBitmap(bitmap, mDeviceProfile.allAppsIconSizePx,
-                                mDeviceProfile.allAppsIconSizePx, false)));
-                mIconView.post(() -> mIconView.setBackground(bitmapDrawable));
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        });
-    }
-
-    private Bitmap getRoundedBitmap(Bitmap bitmap) {
-        final int iconSize = bitmap.getWidth();
-        final float radius = Themes.getDialogCornerRadius(getContext());
-
-        Bitmap output = BitmapRenderer.createHardwareBitmap(iconSize, iconSize, (canvas) -> {
-            mTempRect.set(0, 0, iconSize, iconSize);
-            final RectF rectF = new RectF(mTempRect);
-
-            mIconPaint.setAntiAlias(true);
-            mIconPaint.reset();
-            canvas.drawARGB(0, 0, 0, 0);
-            mIconPaint.setColor(BITMAP_CROP_MASK_COLOR);
-            canvas.drawRoundRect(rectF, radius, radius, mIconPaint);
-
-            mIconPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
-            canvas.drawBitmap(bitmap, mTempRect, mTempRect, mIconPaint);
-        });
-        return output;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultWidget.java b/quickstep/src/com/android/launcher3/search/SearchResultWidget.java
index 4fe9229..c6bdb68 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultWidget.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultWidget.java
@@ -36,7 +36,6 @@
 import com.android.launcher3.dragndrop.DraggableView;
 import com.android.launcher3.touch.ItemLongClickListener;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
 import com.android.systemui.plugins.shared.SearchTargetLegacy;
 
 /**
@@ -82,7 +81,8 @@
 
         // detect tap event on widget container for search target event reporting
         mClickDetector = new GestureDetector(context,
-                new ClickListener(() -> handleSelection(SearchTargetEventLegacy.CHILD_SELECT)));
+                new ClickListener(() -> {
+                }));
 
         mLongPressHelper = new CheckLongPressHelper(this);
         mLongPressHelper.setLongPressTimeoutFactor(1);
@@ -139,12 +139,6 @@
     }
 
     @Override
-    public void handleSelection(int eventType) {
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
-                new SearchTargetEventLegacy.Builder(mSearchTarget, eventType).build());
-    }
-
-    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         mLongPressHelper.onTouchEvent(ev);
         mClickDetector.onTouchEvent(ev);
@@ -182,7 +176,6 @@
     @Override
     public boolean onLongClick(View view) {
         ItemLongClickListener.INSTANCE_ALL_APPS.onLongClick(view);
-        handleSelection(SearchTargetEventLegacy.LONG_PRESS);
         return false;
     }
 
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java b/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java
index 5effbe5..22f0b76 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java
@@ -39,7 +39,6 @@
 import com.android.launcher3.widget.PendingItemDragHelper;
 import com.android.launcher3.widget.WidgetCell;
 import com.android.launcher3.widget.WidgetImageView;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
 import com.android.systemui.plugins.shared.SearchTargetLegacy;
 
 /**
@@ -121,19 +120,11 @@
         new PendingItemDragHelper(mWidgetCell).startDrag(
                 imageView.getBitmapBounds(), imageView.getBitmap().getWidth(), imageView.getWidth(),
                 new Point(loc[0], loc[1]), mLauncher.getAppsView(), new DragOptions());
-        handleSelection(SearchTargetEventLegacy.LONG_PRESS);
         return true;
     }
 
     @Override
     public void onClick(View view) {
         mWidgetToast = BaseWidgetSheet.showWidgetToast(getContext(), mWidgetToast);
-        handleSelection(SearchTargetEventLegacy.SELECT);
-    }
-
-    @Override
-    public void handleSelection(int eventType) {
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
-                new SearchTargetEventLegacy.Builder(mSearchTarget, eventType).build());
     }
 }
diff --git a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
index ccc38db..e015122 100644
--- a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
+++ b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
@@ -22,8 +22,6 @@
 
 import androidx.annotation.Nullable;
 
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
-
 import java.util.List;
 
 /**
@@ -31,7 +29,6 @@
  */
 public class SearchSectionHeaderView extends TextView implements
         SearchTargetHandler {
-    public static final String TARGET_TYPE_SECTION_HEADER = "section_header";
 
     public SearchSectionHeaderView(Context context) {
         super(context);
@@ -47,17 +44,6 @@
     }
 
     @Override
-    public void applySearchTarget(SearchTargetLegacy searchTarget) {
-        String title = searchTarget.getExtras().getString("title");
-        if (title == null || !title.isEmpty()) {
-            setText(title);
-            setVisibility(VISIBLE);
-        } else {
-            setVisibility(INVISIBLE);
-        }
-    }
-
-    @Override
     public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
         setText(parentTarget.getSearchAction().getTitle());
         setVisibility(VISIBLE);
diff --git a/quickstep/src/com/android/launcher3/search/SearchSettingsRowView.java b/quickstep/src/com/android/launcher3/search/SearchSettingsRowView.java
deleted file mode 100644
index 6fc0046..0000000
--- a/quickstep/src/com/android/launcher3/search/SearchSettingsRowView.java
+++ /dev/null
@@ -1,161 +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.search;
-
-import static com.android.launcher3.FastBitmapDrawable.newIcon;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-
-import android.app.search.SearchAction;
-import android.app.search.SearchTarget;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-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.FastBitmapDrawable;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.R;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A row of clickable TextViews with a breadcrumb for settings search.
- */
-public class SearchSettingsRowView extends LinearLayout implements
-        View.OnClickListener, SearchTargetHandler {
-
-    public static final String TARGET_TYPE_SETTINGS_ROW = "settings_row";
-
-    private View mIconView;
-    private TextView mTitleView;
-    private TextView mBreadcrumbsView;
-    private Intent mIntent;
-    private SearchTargetLegacy mSearchTarget;
-
-
-    public SearchSettingsRowView(@NonNull Context context) {
-        this(context, null, 0);
-    }
-
-    public SearchSettingsRowView(@NonNull Context context,
-            @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public SearchSettingsRowView(@NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mIconView = findViewById(R.id.icon);
-        mTitleView = findViewById(R.id.title);
-        mBreadcrumbsView = findViewById(R.id.breadcrumbs);
-        setOnClickListener(this);
-        applySettingsIcon(Launcher.getLauncher(getContext()), mIconView);
-    }
-
-    @Override
-    public void applySearchTarget(SearchTargetLegacy searchTarget) {
-        mSearchTarget = searchTarget;
-        Bundle bundle = searchTarget.getExtras();
-        mIntent = bundle.getParcelable("intent");
-        showIfAvailable(mTitleView, bundle.getString("title"));
-        mIconView.setContentDescription(bundle.getString("title"));
-        ArrayList<String> breadcrumbs = bundle.getStringArrayList("breadcrumbs");
-        //TODO: implement RTL friendly breadcrumbs view
-        showIfAvailable(mBreadcrumbsView, breadcrumbs != null
-                ? String.join(" > ", breadcrumbs) : null);
-        SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
-    }
-
-    @Override
-    public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
-        SearchAction action = parentTarget.getSearchAction();
-        mIconView.setContentDescription(action.getTitle());
-        showIfAvailable(mTitleView, action.getTitle().toString());
-        showIfAvailable(mBreadcrumbsView, action.getSubtitle().toString());
-    }
-
-    private void showIfAvailable(TextView view, @Nullable String string) {
-        if (TextUtils.isEmpty(string)) {
-            view.setVisibility(GONE);
-        } else {
-            view.setVisibility(VISIBLE);
-            view.setText(string);
-        }
-    }
-
-    @Override
-    public void onClick(View view) {
-        handleSelection(SearchTargetEventLegacy.SELECT);
-    }
-
-    @Override
-    public void handleSelection(int eventType) {
-        if (mIntent == null) return;
-        // TODO: create ItemInfo object and then use it to call startActivityForResult for proper
-        //  WW logging
-        Launcher launcher = Launcher.getLauncher(getContext());
-        launcher.startActivityForResult(mIntent, 0);
-
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
-                new SearchTargetEventLegacy.Builder(mSearchTarget, eventType).build());
-    }
-
-    /**
-     * Requests settings app icon from {@link com.android.launcher3.icons.IconCache} and applies
-     * to to view
-     */
-    public static void applySettingsIcon(Launcher launcher, View view) {
-        LauncherAppState appState = LauncherAppState.getInstance(launcher);
-        MODEL_EXECUTOR.post(() -> {
-            PackageItemInfo packageItemInfo = new PackageItemInfo(getSettingsPackageName(launcher));
-            appState.getIconCache().getTitleAndIconForApp(packageItemInfo, false);
-            MAIN_EXECUTOR.post(() -> {
-                FastBitmapDrawable iconDrawable = newIcon(appState.getContext(), packageItemInfo);
-                view.setBackground(iconDrawable);
-            });
-        });
-    }
-
-    private static String getSettingsPackageName(Launcher launcher) {
-        Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
-        List<ResolveInfo> resolveInfos = launcher.getPackageManager().queryIntentActivities(intent,
-                PackageManager.MATCH_DEFAULT_ONLY);
-        if (resolveInfos.size() == 0) {
-            return "";
-        }
-        return resolveInfos.get(0).activityInfo.packageName;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
index e72578d..67502f6 100644
--- a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
+++ b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
@@ -29,7 +29,10 @@
 
     /**
      * Update view using values from {@link SearchTargetLegacy}
+     *
+     * @deprecated Use {@link SearchTargetHandler#applySearchTarget(SearchTarget, List)} instead
      */
+    @Deprecated
     default void applySearchTarget(SearchTargetLegacy searchTarget) {
     }
 
@@ -41,9 +44,10 @@
     }
 
     /**
-     * Handles selection of SearchTarget
+     * Handle IME quick select event. returns whether event was handled.
      */
-    default void handleSelection(int eventType) {
+    default boolean quickSelect() {
+        return false;
     }
 
 }
diff --git a/quickstep/src/com/android/launcher3/search/ThumbnailSearchResultView.java b/quickstep/src/com/android/launcher3/search/ThumbnailSearchResultView.java
index 44f7057..7108d63 100644
--- a/quickstep/src/com/android/launcher3/search/ThumbnailSearchResultView.java
+++ b/quickstep/src/com/android/launcher3/search/ThumbnailSearchResultView.java
@@ -16,27 +16,11 @@
 package com.android.launcher3.search;
 
 
-import static com.android.launcher3.search.SearchResultIcon.REMOTE_ACTION_SHOULD_START;
-import static com.android.launcher3.search.SearchResultIcon.REMOTE_ACTION_TOKEN;
-
+import android.app.search.SearchTarget;
 import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.net.Uri;
 import android.util.AttributeSet;
 
-import androidx.core.graphics.drawable.RoundedBitmapDrawable;
-import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
-
-import com.android.launcher3.Launcher;
-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.shared.SearchTargetEventLegacy;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
+import java.util.List;
 
 /**
  * A view representing a high confidence app search result that includes shortcuts
@@ -44,11 +28,6 @@
 public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView
         implements SearchTargetHandler {
 
-    public static final String TARGET_TYPE_SCREENSHOT = "screenshot";
-    public static final String TARGET_TYPE_SCREENSHOT_LEGACY = "screenshot_legacy";
-
-    private SearchTargetLegacy mSearchTarget;
-
     public ThumbnailSearchResultView(Context context) {
         super(context);
     }
@@ -62,53 +41,7 @@
     }
 
     @Override
-    public void handleSelection(int eventType) {
-        Launcher launcher = Launcher.getLauncher(getContext());
-        ItemInfo itemInfo = (ItemInfo) getTag();
-        if (itemInfo instanceof RemoteActionItemInfo) {
-            RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
-            ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
-        } else {
-            ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher);
-        }
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
-                new SearchTargetEventLegacy.Builder(mSearchTarget, eventType).build());
-    }
+    public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
 
-    @Override
-    public void applySearchTarget(SearchTargetLegacy target) {
-        mSearchTarget = target;
-        Bitmap bitmap;
-        if (target.getRemoteAction() != null) {
-            RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(target.getRemoteAction(),
-                    target.getExtras().getString(REMOTE_ACTION_TOKEN),
-                    target.getExtras().getBoolean(REMOTE_ACTION_SHOULD_START));
-            bitmap = ((BitmapDrawable) target.getRemoteAction().getIcon()
-                    .loadDrawable(getContext())).getBitmap();
-            // crop
-            if (bitmap.getWidth() < bitmap.getHeight()) {
-                bitmap = Bitmap.createBitmap(bitmap, 0,
-                        bitmap.getHeight() / 2 - bitmap.getWidth() / 2,
-                        bitmap.getWidth(), bitmap.getWidth());
-            } else {
-                bitmap = Bitmap.createBitmap(bitmap, bitmap.getWidth() / 2 - bitmap.getHeight() / 2,
-                        0,
-                        bitmap.getHeight(), bitmap.getHeight());
-            }
-            setTag(itemInfo);
-        } else {
-            bitmap = (Bitmap) target.getExtras().getParcelable("bitmap");
-            WorkspaceItemInfo itemInfo = new WorkspaceItemInfo();
-            itemInfo.intent = new Intent(Intent.ACTION_VIEW)
-                    .setData(Uri.parse(target.getExtras().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);
-        setOnClickListener(v -> handleSelection(SearchTargetEventLegacy.SELECT));
-        SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(target, this);
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarContainerView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarContainerView.java
new file mode 100644
index 0000000..0093e66
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarContainerView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.taskbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Top-level ViewGroup that hosts the TaskbarView as well as Views created by it such as Folder.
+ */
+public class TaskbarContainerView extends FrameLayout {
+    public TaskbarContainerView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public TaskbarContainerView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TaskbarContainerView(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public TaskbarContainerView(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java
new file mode 100644
index 0000000..7be1b92
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 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.taskbar;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
+import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
+
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.view.Gravity;
+import android.view.WindowManager;
+
+import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.R;
+import com.android.systemui.shared.system.WindowManagerWrapper;
+
+/**
+ * Interfaces with Launcher/WindowManager/SystemUI to determine what to show in TaskbarView.
+ */
+public class TaskbarController {
+
+    private static final String WINDOW_TITLE = "Taskbar";
+
+    private final TaskbarContainerView mTaskbarContainerView;
+    private final TaskbarView mTaskbarView;
+    private final BaseQuickstepLauncher mLauncher;
+    private final WindowManager mWindowManager;
+    // Layout width and height of the Taskbar in the default state.
+    private final Point mTaskbarSize;
+
+    private WindowManager.LayoutParams mWindowLayoutParams;
+
+    public TaskbarController(BaseQuickstepLauncher launcher,
+            TaskbarContainerView taskbarContainerView) {
+        mLauncher = launcher;
+        mTaskbarContainerView = taskbarContainerView;
+        mTaskbarView = mTaskbarContainerView.findViewById(R.id.taskbar_view);
+        mWindowManager = mLauncher.getWindowManager();
+        mTaskbarSize = new Point(MATCH_PARENT,
+                mLauncher.getResources().getDimensionPixelSize(R.dimen.taskbar_size));
+    }
+
+    /**
+     * Initializes the Taskbar, including adding it to the screen.
+     */
+    public void init() {
+        addToWindowManager();
+    }
+
+    /**
+     * Removes the Taskbar from the screen, and removes any obsolete listeners etc.
+     */
+    public void cleanup() {
+        removeFromWindowManager();
+    }
+
+    private void removeFromWindowManager() {
+        if (mTaskbarContainerView.isAttachedToWindow()) {
+            mWindowManager.removeViewImmediate(mTaskbarContainerView);
+        }
+    }
+
+    private void addToWindowManager() {
+        removeFromWindowManager();
+
+        final int gravity = Gravity.BOTTOM;
+
+        mWindowLayoutParams = new WindowManager.LayoutParams(
+                mTaskbarSize.x,
+                mTaskbarSize.y,
+                TYPE_APPLICATION_OVERLAY,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                PixelFormat.TRANSLUCENT);
+        mWindowLayoutParams.setTitle(WINDOW_TITLE);
+        mWindowLayoutParams.packageName = mLauncher.getPackageName();
+        mWindowLayoutParams.gravity = gravity;
+        mWindowLayoutParams.setFitInsetsTypes(0);
+        mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+        mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
+        WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance();
+        wmWrapper.setProvidesInsetsTypes(
+                mWindowLayoutParams,
+                new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT }
+        );
+
+        TaskbarContainerView.LayoutParams taskbarLayoutParams =
+                new TaskbarContainerView.LayoutParams(mTaskbarSize.x, mTaskbarSize.y);
+        taskbarLayoutParams.gravity = gravity;
+        mTaskbarView.setLayoutParams(taskbarLayoutParams);
+
+        mWindowManager.addView(mTaskbarContainerView, mWindowLayoutParams);
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
new file mode 100644
index 0000000..5df8d5f
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.taskbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps.
+ */
+public class TaskbarView extends LinearLayout {
+    public TaskbarView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public TaskbarView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TaskbarView(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public TaskbarView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 1f7cec5..196cae7 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -360,7 +360,7 @@
                     getString(R.string.all_apps_label),
                     getString(R.string.all_apps_label),
                     PendingIntent.getActivity(this, SYSTEM_ACTION_ID_ALL_APPS, intent,
-                            PendingIntent.FLAG_UPDATE_CURRENT));
+                            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));
             am.registerSystemAction(allAppsAction, SYSTEM_ACTION_ID_ALL_APPS);
         } else {
             am.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index f44f88b..22eb15a 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -72,7 +72,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.model.data.RemoteActionItemInfo;
+import com.android.launcher3.model.data.SearchActionItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.views.ActivityContext;
@@ -319,14 +319,14 @@
     }
 
     /**
-     * Apply label and tag using a {@link RemoteActionItemInfo}
+     * Apply label and tag using a {@link SearchActionItemInfo}
      */
-    public void applyFromRemoteActionInfo(RemoteActionItemInfo remoteActionItemInfo) {
-        applyIconAndLabel(remoteActionItemInfo);
-        setTag(remoteActionItemInfo);
+    public void applyFromSearchActionItemInfo(SearchActionItemInfo searchActionItemInfo) {
+        applyIconAndLabel(searchActionItemInfo);
+        setTag(searchActionItemInfo);
     }
 
-    private void applyIconAndLabel(ItemInfoWithIcon info) {
+    protected void applyIconAndLabel(ItemInfoWithIcon info) {
         FastBitmapDrawable iconDrawable = newIcon(getContext(), info);
         mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
 
@@ -595,7 +595,8 @@
         mLongPressHelper.cancelLongPress();
     }
 
-    /** Applies the loading progress value to the progress bar.
+    /**
+     * Applies the loading progress value to the progress bar.
      *
      * If this app is installing, the progress bar will be updated with the installation progress.
      * If this app is installed and downloading incrementally, the progress bar will be updated
@@ -609,7 +610,7 @@
                     != 0) {
                 updateProgressBarUi(progressLevel, progressLevel == 100);
             } else if (info.hasPromiseIconUi() || (info.runtimeStatusFlags
-                        & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
+                    & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
                 updateProgressBarUi(progressLevel, promiseStateChanged);
             }
         }
@@ -765,8 +766,8 @@
                 mActivity.invalidateParent(info);
             } else if (info instanceof PackageItemInfo) {
                 applyFromItemInfoWithIcon((PackageItemInfo) info);
-            } else if (info instanceof RemoteActionItemInfo) {
-                applyFromRemoteActionInfo((RemoteActionItemInfo) info);
+            } else if (info instanceof SearchActionItemInfo) {
+                applyFromSearchActionItemInfo((SearchActionItemInfo) info);
             }
 
             mDisableRelayout = false;
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index ff405ec..c707df0 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -115,7 +115,7 @@
     private void triggerLongPress() {
         if ((mView.getParent() != null)
                 && mView.hasWindowFocus()
-                && (!mView.isPressed() || mListener == null)
+                && (!mView.isPressed() || mListener != null)
                 && !mHasPerformedLongPress) {
             boolean handled;
             if (mListener != null) {
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 1d88e83..5fd9e01 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -202,7 +202,7 @@
                 DisplayController.getDefaultDisplay(context).getInfo(),
                 getPredefinedDeviceProfiles(context, gridName));
 
-        Info myInfo = new Info(display);
+        Info myInfo = new Info(context, display);
         DisplayOption myDisplayOption = invDistWeightedInterpolate(
                 myInfo, getPredefinedDeviceProfiles(context, gridName));
 
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 4d51d70..20f7c23 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -547,10 +547,15 @@
             return mLauncher.startActivitySafely(v, headerItem.getIntent(), headerItem);
         }
         AdapterItem focusedItem = getActiveRecyclerView().getApps().getFocusedChild();
-        if (mSearchAdapterProvider.onAdapterItemSelected(focusedItem)) {
-            return true;
+        if (focusedItem != null) {
+            View focusedView = getActiveRecyclerView().getLayoutManager()
+                    .findViewByPosition(focusedItem.position);
+            if (focusedView != null && mSearchAdapterProvider.onAdapterItemSelected(focusedItem,
+                    focusedView)) {
+                return true;
+            }
         }
-        if (focusedItem.appInfo != null) {
+        if (focusedItem != null && focusedItem.appInfo != null) {
             ItemInfo itemInfo = focusedItem.appInfo;
             return mLauncher.startActivitySafely(v, itemInfo.getIntent(), itemInfo);
         }
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 522f1d4..198c4b2 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -32,10 +32,8 @@
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.PackageManagerHelper;
-import com.android.systemui.plugins.AllAppsSearchPlugin;
 
 import java.util.ArrayList;
-import java.util.function.Consumer;
 
 /**
  * An interface to a search box that AllApps can command.
@@ -74,10 +72,7 @@
 
     @Override
     public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
-        if (mSearchAlgorithm instanceof PluginWrapper) {
-            ((PluginWrapper) mSearchAlgorithm).runOnPluginIfConnected(
-                    AllAppsSearchPlugin::startedSearchSession);
-        }
+        // Do nothing
     }
 
     @Override
@@ -174,16 +169,6 @@
     }
 
     /**
-     * A wrapper setup for running essential calls to plugin from search controller
-     */
-    public interface PluginWrapper {
-        /**
-         * executes call if plugin is connected
-         */
-        void runOnPluginIfConnected(Consumer<AllAppsSearchPlugin> plugin);
-    }
-
-    /**
      * Callback for getting search results.
      */
     public interface Callbacks {
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index e3c178b..330ec68 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.allapps.search;
 
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.launcher3.BaseDraggingActivity;
@@ -47,7 +48,7 @@
     }
 
     @Override
-    public boolean onAdapterItemSelected(AllAppsGridAdapter.AdapterItem focusedItem) {
+    public boolean onAdapterItemSelected(AllAppsGridAdapter.AdapterItem adapterItem, View view) {
         return false;
     }
 }
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 1c7247a..511de30 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -18,6 +18,7 @@
 
 
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.launcher3.BaseDraggingActivity;
@@ -61,5 +62,6 @@
      * handles selection event on search adapter item. Returns false if provider can not handle
      * event
      */
-    public abstract boolean onAdapterItemSelected(AllAppsGridAdapter.AdapterItem focusedItem);
+    public abstract boolean onAdapterItemSelected(AllAppsGridAdapter.AdapterItem adapterItem,
+            View view);
 }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 81174d8..1c5c222 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -214,6 +214,9 @@
             "ENABLE_APP_PREDICTIONS_WHILE_VISIBLE", true, "Allows app "
             + "predictions to be updated while they are visible to the user.");
 
+    public static final BooleanFlag ENABLE_TASKBAR = new DeviceFlag(
+            "ENABLE_TASKBAR", false, "Allows a system Taskbar to be shown on larger devices.");
+
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index 5e48a0f..d09bf81 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -104,8 +104,10 @@
     @WorkerThread
     private void addToQueue(PendingInstallShortcutInfo info) {
         ensureQueueLoaded();
-        mItems.add(info);
-        mStorage.write(mContext, mItems);
+        if (!mItems.contains(info)) {
+            mItems.add(info);
+            mStorage.write(mContext, mItems);
+        }
     }
 
     @WorkerThread
@@ -303,6 +305,33 @@
             }
             return null;
         }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof PendingInstallShortcutInfo) {
+                PendingInstallShortcutInfo other = (PendingInstallShortcutInfo) obj;
+
+                boolean userMatches = user.equals(other.user);
+                boolean itemTypeMatches = itemType == other.itemType;
+                boolean intentMatches = intent.toUri(0).equals(other.intent.toUri(0));
+                boolean shortcutInfoMatches = shortcutInfo == null
+                        ? other.shortcutInfo == null
+                        : other.shortcutInfo != null
+                            && shortcutInfo.getId().equals(other.shortcutInfo.getId())
+                            && shortcutInfo.getPackage().equals(other.shortcutInfo.getPackage());
+                boolean providerInfoMatches = providerInfo == null
+                        ? other.providerInfo == null
+                        : other.providerInfo != null
+                            && providerInfo.provider.equals(other.providerInfo.provider);
+
+                return userMatches
+                        && itemTypeMatches
+                        && intentMatches
+                        && shortcutInfoMatches
+                        && providerInfoMatches;
+            }
+            return false;
+        }
     }
 
     private static String getIntentPackage(Intent intent) {
diff --git a/src/com/android/launcher3/model/data/RemoteActionItemInfo.java b/src/com/android/launcher3/model/data/RemoteActionItemInfo.java
deleted file mode 100644
index d988bf9..0000000
--- a/src/com/android/launcher3/model/data/RemoteActionItemInfo.java
+++ /dev/null
@@ -1,68 +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.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;
-    }
-
-    public boolean isEscapeHatch() {
-        return mToken.contains("item_type:[ESCAPE_HATCH]");
-    }
-}
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
new file mode 100644
index 0000000..1831ffd
--- /dev/null
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 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.PendingIntent;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.Process;
+import android.os.UserHandle;
+
+/**
+ * Represents a SearchAction with in launcher
+ */
+public class SearchActionItemInfo extends ItemInfoWithIcon {
+
+    public static final int FLAG_SHOULD_START = 1 << 1;
+    public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2;
+
+    private final String mFallbackPackageName;
+
+    private int mFlags = 0;
+    private final Icon mIcon;
+
+    private Intent mIntent;
+
+    private PendingIntent mPendingIntent;
+
+    public SearchActionItemInfo(Icon icon, String packageName, UserHandle user,
+            CharSequence title) {
+        this.user = user == null ? Process.myUserHandle() : user;
+        this.title = title;
+        mFallbackPackageName = packageName;
+        mIcon = icon;
+    }
+
+    public SearchActionItemInfo(SearchActionItemInfo info) {
+        super(info);
+        mIcon = info.mIcon;
+        mFallbackPackageName = info.mFallbackPackageName;
+        mFlags = info.mFlags;
+        title = info.title;
+    }
+
+    public void setFlags(int flags) {
+        mFlags = flags;
+    }
+
+    public int getFlags() {
+        return mFlags;
+    }
+
+    @Override
+    public Intent getIntent() {
+        return mIntent;
+    }
+
+    /**
+     * Setter for mIntent with assertion for null value mPendingIntent
+     */
+    public void setIntent(Intent intent) {
+        if (mPendingIntent != null && intent != null) {
+            throw new RuntimeException(
+                    "SearchActionItemInfo can only have either an Intent or a PendingIntent");
+        }
+        mIntent = intent;
+    }
+
+    public PendingIntent getPendingIntent() {
+        return mPendingIntent;
+    }
+
+    /**
+     * Setter of mPendingIntent with assertion for null value mIntent
+     */
+    public void setPendingIntent(PendingIntent pendingIntent) {
+        if (mIntent != null && pendingIntent != null) {
+            throw new RuntimeException(
+                    "SearchActionItemInfo can only have either an Intent or a PendingIntent");
+        }
+        mPendingIntent = pendingIntent;
+    }
+
+
+    /**
+     * Returns if a flag is set on instance
+     */
+    public boolean hasFlag(int flag) {
+        return (mFlags & flag) == flag;
+    }
+
+    @Override
+    public ItemInfoWithIcon clone() {
+        return new SearchActionItemInfo(this);
+    }
+
+    public Icon getIcon() {
+        return mIcon;
+    }
+}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 4158735..d9483e5 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -51,7 +51,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.model.data.RemoteActionItemInfo;
+import com.android.launcher3.model.data.SearchActionItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.InstallSessionHelper;
 import com.android.launcher3.testing.TestLogging;
@@ -96,8 +96,8 @@
             if (v instanceof PendingAppWidgetHostView) {
                 onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
             }
-        } else if (tag instanceof RemoteActionItemInfo) {
-            onClickRemoteAction(launcher, (RemoteActionItemInfo) tag);
+        } else if (tag instanceof SearchActionItemInfo) {
+            onClickSearchAction(launcher, (SearchActionItemInfo) tag);
         }
     }
 
@@ -246,23 +246,31 @@
     }
 
     /**
-     * Event handler for a {@link android.app.RemoteAction} click
-     *
+     * Event handler for a {@link SearchActionItemInfo} 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);
+    public static void onClickSearchAction(Launcher launcher, SearchActionItemInfo itemInfo) {
+        if (itemInfo.getIntent() != null) {
+            if (itemInfo.hasFlag(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+                launcher.startActivityForResult(itemInfo.getIntent(), 0);
             } else {
-                pendingIntent.send();
+                launcher.startActivity(itemInfo.getIntent());
             }
-        } catch (PendingIntent.CanceledException | IntentSender.SendIntentException e) {
-            Toast.makeText(launcher,
-                    launcher.getResources().getText(R.string.shortcut_not_available),
-                    Toast.LENGTH_SHORT).show();
+        } else if (itemInfo.getPendingIntent() != null) {
+            try {
+                PendingIntent pendingIntent = itemInfo.getPendingIntent();
+                if (!itemInfo.hasFlag(SearchActionItemInfo.FLAG_SHOULD_START)) {
+                    pendingIntent.send();
+                } else if (itemInfo.hasFlag(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+                    launcher.startIntentSenderForResult(pendingIntent.getIntentSender(), 0, null, 0,
+                            0, 0);
+                } else {
+                    launcher.startIntentSender(pendingIntent.getIntentSender(), null, 0, 0, 0);
+                }
+            } catch (PendingIntent.CanceledException | IntentSender.SendIntentException e) {
+                Toast.makeText(launcher,
+                        launcher.getResources().getText(R.string.shortcut_not_available),
+                        Toast.LENGTH_SHORT).show();
+            }
         }
     }
 
@@ -272,7 +280,7 @@
         Intent intent;
         if (item instanceof ItemInfoWithIcon
                 && (((ItemInfoWithIcon) item).runtimeStatusFlags
-                    & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
+                & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
             ItemInfoWithIcon appInfo = (ItemInfoWithIcon) item;
             intent = new PackageManagerHelper(launcher)
                     .getMarketIntent(appInfo.getTargetComponent().getPackageName());
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 3ab736a..355c949 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -31,8 +31,6 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.launcher3.Utilities;
-
 import java.util.ArrayList;
 
 /**
@@ -159,13 +157,13 @@
         private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
         private DisplayController.Info mInfo;
 
-        private DisplayHolder(Context displayContext, Display display) {
+        private DisplayHolder(Context displayContext) {
             mDisplayContext = displayContext;
             // Note that the Display object must be obtained from DisplayManager which is
             // associated to the display context, so the Display is isolated from Activity and
             // Application to provide the actual state of device that excludes the additional
             // adjustment and override.
-            mInfo = new DisplayController.Info(display);
+            mInfo = new DisplayController.Info(mDisplayContext);
             mId = mInfo.id;
         }
 
@@ -182,31 +180,22 @@
         }
 
         protected void handleOnChange() {
-            Display display = Utilities.ATLEAST_R
-                    ? mDisplayContext.getDisplay()
-                    : mDisplayContext
-                        .getSystemService(DisplayManager.class)
-                        .getDisplay(mId);
-            if (display == null) {
-                return;
-            }
-
             Info oldInfo = mInfo;
-            Info newInfo = new Info(display);
+            Info info = new Info(mDisplayContext);
 
             int change = 0;
-            if (newInfo.hasDifferentSize(oldInfo)) {
+            if (info.hasDifferentSize(oldInfo)) {
                 change |= CHANGE_SIZE;
             }
-            if (newInfo.rotation != oldInfo.rotation) {
+            if (oldInfo.rotation != info.rotation) {
                 change |= CHANGE_ROTATION;
             }
-            if (newInfo.singleFrameMs != oldInfo.singleFrameMs) {
+            if (info.singleFrameMs != oldInfo.singleFrameMs) {
                 change |= CHANGE_FRAME_DELAY;
             }
 
             if (change != 0) {
-                mInfo = newInfo;
+                mInfo = info;
                 final int flags = change;
                 MAIN_EXECUTOR.execute(() -> notifyChange(flags));
             }
@@ -227,7 +216,7 @@
             // Use application context to create display context so that it can have its own
             // Resources.
             Context displayContext = context.getApplicationContext().createDisplayContext(display);
-            return new DisplayHolder(displayContext, display);
+            return new DisplayHolder(displayContext);
         }
     }
 
@@ -255,7 +244,12 @@
             this.metrics = metrics;
         }
 
-        public Info(Display display) {
+        private Info(Context context) {
+            this(context, context.getSystemService(DisplayManager.class)
+                    .getDisplay(DEFAULT_DISPLAY));
+        }
+
+        public Info(Context context, Display display) {
             id = display.getDisplayId();
             rotation = display.getRotation();
 
@@ -268,8 +262,7 @@
             display.getRealSize(realSize);
             display.getCurrentSizeRange(smallestSize, largestSize);
 
-            metrics = new DisplayMetrics();
-            display.getMetrics(metrics);
+            metrics = context.getResources().getDisplayMetrics();
         }
 
         private boolean hasDifferentSize(Info info) {
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index fab0bd4..4e82336 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -161,6 +161,11 @@
         float scaleY = rect.height() / minSize;
         float scale = Math.max(1f, Math.min(scaleX, scaleY));
 
+        if (Float.isNaN(scale)) {
+            // Views are no longer laid out, do not update.
+            return;
+        }
+
         update(rect, progress, shapeProgressStart, cornerRadius, isOpening, scale,
                 minSize, lp, isVerticalBarLayout, dp);