Merge "Add the ability to specify a list of tutorial steps in the gesture sandbox tutorial intent." into ub-launcher3-master
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 97e3786..a47a500 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -30,6 +30,7 @@
     with some minor changed based on the derivative app.
     -->
 
+    <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
     <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index df1833d..54a753c 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -802,33 +802,31 @@
     }
 
     private void addCujInstrumentation(Animator anim, int cuj, String transition) {
-        if (Trace.isEnabled()) {
-            anim.addListener(new AnimationSuccessListener() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    Trace.beginAsyncSection(transition, 0);
-                    InteractionJankMonitorWrapper.begin(cuj);
-                    super.onAnimationStart(animation);
-                }
+        anim.addListener(new AnimationSuccessListener() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                Trace.beginAsyncSection(transition, 0);
+                InteractionJankMonitorWrapper.begin(cuj);
+                super.onAnimationStart(animation);
+            }
 
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    super.onAnimationCancel(animation);
-                    InteractionJankMonitorWrapper.cancel(cuj);
-                }
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                super.onAnimationCancel(animation);
+                InteractionJankMonitorWrapper.cancel(cuj);
+            }
 
-                @Override
-                public void onAnimationSuccess(Animator animator) {
-                    InteractionJankMonitorWrapper.end(cuj);
-                }
+            @Override
+            public void onAnimationSuccess(Animator animator) {
+                InteractionJankMonitorWrapper.end(cuj);
+            }
 
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    super.onAnimationEnd(animation);
-                    Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
-                }
-            });
-        }
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
+            }
+        });
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index 65e89cf..dd0ed8f 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -21,12 +21,14 @@
 import android.app.ActivityManager.TaskDescription;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.SparseArray;
 import android.view.accessibility.AccessibilityManager;
 
@@ -34,6 +36,7 @@
 
 import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.IconProvider;
 import com.android.launcher3.icons.LauncherIcons;
@@ -42,7 +45,6 @@
 import com.android.quickstep.util.TaskKeyLruCache;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.shared.system.TaskDescriptionCompat;
 
@@ -163,9 +165,8 @@
                         key.getComponent(), key.userId);
             }
             if (activityInfo != null) {
-                entry.contentDescription = ActivityManagerWrapper.getInstance()
-                        .getBadgedContentDescription(activityInfo, task.key.userId,
-                                task.taskDescription);
+                entry.contentDescription = getBadgedContentDescription(
+                        activityInfo, task.key.userId, task.taskDescription);
             }
         }
 
@@ -173,6 +174,21 @@
         return entry;
     }
 
+    private String getBadgedContentDescription(ActivityInfo info, int userId, TaskDescription td) {
+        PackageManager pm = mContext.getPackageManager();
+        String taskLabel = td == null ? null : Utilities.trim(td.getLabel());
+        if (TextUtils.isEmpty(taskLabel)) {
+            taskLabel = Utilities.trim(info.loadLabel(pm));
+        }
+
+        String applicationLabel = Utilities.trim(info.applicationInfo.loadLabel(pm));
+        String badgedApplicationLabel = userId != UserHandle.myUserId()
+                ? pm.getUserBadgedLabel(applicationLabel, UserHandle.of(userId)).toString()
+                : applicationLabel;
+        return applicationLabel.equals(taskLabel)
+                ? badgedApplicationLabel : badgedApplicationLabel + " " + taskLabel;
+    }
+
     @WorkerThread
     private Drawable getDefaultIcon(int userId) {
         synchronized (mDefaultIcons) {
diff --git a/res/layout/all_apps_icon.xml b/res/layout/all_apps_icon.xml
index 79fb612..069954c 100644
--- a/res/layout/all_apps_icon.xml
+++ b/res/layout/all_apps_icon.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- 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.
@@ -13,16 +12,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.launcher3.BubbleTextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res-auto"
-    style="@style/BaseIcon"
+    style="@style/BaseIcon.AllApps"
     android:id="@+id/icon"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:stateListAnimator="@animator/all_apps_fastscroll_icon_anim"
     launcher:iconDisplay="all_apps"
-    launcher:centerVertically="true"
-    android:paddingLeft="@dimen/dynamic_grid_cell_padding_x"
-    android:paddingRight="@dimen/dynamic_grid_cell_padding_x" />
+    launcher:centerVertically="true" />
 
diff --git a/res/layout/search_result_icon.xml b/res/layout/search_result_icon.xml
new file mode 100644
index 0000000..3c1dd49
--- /dev/null
+++ b/res/layout/search_result_icon.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<com.android.launcher3.views.SearchResultIcon xmlns:launcher="http://schemas.android.com/apk/res-auto"
+    style="@style/BaseIcon.AllApps"
+    launcher:iconDisplay="all_apps"
+    launcher:centerVertically="true" />
+
diff --git a/res/values/styles.xml b/res/values/styles.xml
index fd3d873..067cf7f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -223,6 +223,16 @@
         <item name="android:lines">1</item>
     </style>
 
+    <!-- Base theme for AllApps BubbleTextViews -->
+    <style name="BaseIcon.AllApps" parent="BaseIcon">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:stateListAnimator">@animator/all_apps_fastscroll_icon_anim</item>
+        <item name="android:paddingLeft">@dimen/dynamic_grid_cell_padding_x</item>
+        <item name="android:paddingRight">@dimen/dynamic_grid_cell_padding_x</item>
+    </style>
+
+
     <!-- Icon displayed on the workspace -->
     <style name="BaseIcon.Workspace" >
         <item name="android:shadowRadius">2.0</item>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 817d028..6245637 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -17,6 +17,7 @@
 package com.android.launcher3;
 
 import static com.android.launcher3.FastBitmapDrawable.newIcon;
+import static com.android.launcher3.graphics.IconShape.getShape;
 import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
 
@@ -27,15 +28,18 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.graphics.BlurMaskFilter;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.Path;
 import android.graphics.PointF;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Process;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
 import android.util.Property;
@@ -50,6 +54,8 @@
 
 import com.android.launcher3.Launcher.OnResumeCallback;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
+import com.android.launcher3.allapps.AllAppsSectionDecorator;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.dragndrop.DraggableView;
 import com.android.launcher3.folder.FolderIcon;
@@ -60,6 +66,7 @@
 import com.android.launcher3.icons.DotRenderer;
 import com.android.launcher3.icons.IconCache.IconLoadRequest;
 import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
+import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -79,7 +86,7 @@
  * too aggressive.
  */
 public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback,
-        IconLabelDotView, DraggableView, Reorderable {
+        IconLabelDotView, DraggableView, Reorderable, AllAppsSectionDecorator.SelfDecoratingView {
 
     private static final int DISPLAY_WORKSPACE = 0;
     private static final int DISPLAY_ALL_APPS = 1;
@@ -87,6 +94,8 @@
     private static final int DISPLAY_HERO_APP = 5;
 
     private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
+    private static final float HIGHLIGHT_SCALE = 1.16f;
+
 
     private final PointF mTranslationForReorderBounce = new PointF(0, 0);
     private final PointF mTranslationForReorderPreview = new PointF(0, 0);
@@ -95,6 +104,11 @@
 
     private float mScaleForReorderBounce = 1f;
 
+    protected final Paint mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    private final Path mHighlightPath = new Path();
+    protected int mHighlightColor = Color.TRANSPARENT;
+    private final BlurMaskFilter mHighlightShadowFilter;
+
     private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
             = new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
         @Override
@@ -208,6 +222,11 @@
         setEllipsize(TruncateAt.END);
         setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
         setTextAlpha(1f);
+
+        int shadowSize = context.getResources().getDimensionPixelSize(
+                R.dimen.blur_size_click_shadow);
+        mHighlightShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.INNER);
+
     }
 
     @Override
@@ -421,8 +440,38 @@
 
     @Override
     public void onDraw(Canvas canvas) {
+        if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mHighlightColor != Color.TRANSPARENT) {
+            int count = canvas.save();
+            drawFocusHighlight(canvas);
+            canvas.restoreToCount(count);
+        }
         super.onDraw(canvas);
-        drawDotIfNecessary(canvas);
+    }
+
+    protected void drawFocusHighlight(Canvas canvas) {
+        boolean isBadged = getTag() instanceof ItemInfo && !Process.myUserHandle().equals(
+                ((ItemInfo) getTag()).user);
+        float insetScale = (HIGHLIGHT_SCALE - 1) / 2;
+        canvas.translate(-getIconSize() * insetScale, -insetScale * getIconSize());
+        float outlineSize = getIconSize() * HIGHLIGHT_SCALE;
+        mHighlightPath.reset();
+        mHighlightPaint.reset();
+        getIconBounds(mDotParams.iconBounds);
+        getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left, mDotParams.iconBounds.top,
+                outlineSize / 2);
+        if (isBadged) {
+            float borderSize = outlineSize - getIconSize();
+            float badgeSize = LauncherIcons.getBadgeSizeForIconSize(getIconSize()) + borderSize;
+            float badgeInset = outlineSize - badgeSize;
+            getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left + badgeInset,
+                    mDotParams.iconBounds.top + badgeInset, badgeSize / 2);
+        }
+        mHighlightPaint.setMaskFilter(mHighlightShadowFilter);
+        mHighlightPaint.setColor(mDotParams.color);
+        canvas.drawPath(mHighlightPath, mHighlightPaint);
+        mHighlightPaint.setMaskFilter(null);
+        mHighlightPaint.setColor(mHighlightColor);
+        canvas.drawPath(mHighlightPath, mHighlightPaint);
     }
 
     /**
@@ -787,10 +836,11 @@
 
     @Override
     public SafeCloseable prepareDrawDragView() {
+        int highlightColor = mHighlightColor;
+        mHighlightColor = Color.TRANSPARENT;
         resetIconScale();
         setForceHideDot(true);
-        return () -> {
-        };
+        return () -> mHighlightColor = highlightColor;
     }
 
     private void resetIconScale() {
@@ -827,4 +877,17 @@
         });
         iconUpdateAnimation.start();
     }
+
+
+    @Override
+    public void decorate(int color) {
+        mHighlightColor = color;
+        invalidate();
+    }
+
+    @Override
+    public void removeDecoration() {
+        mHighlightColor = Color.TRANSPARENT;
+        invalidate();
+    }
 }
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 2973cf7..aeed16a 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -188,6 +188,9 @@
 
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         Cursor result = qb.query(db, projection, args.where, args.args, null, null, sortOrder);
+        final Bundle extra = new Bundle();
+        extra.putString(LauncherSettings.Settings.EXTRA_DB_NAME, mOpenHelper.getDatabaseName());
+        result.setExtras(extra);
         result.setNotificationUri(getContext().getContentResolver(), uri);
 
         return result;
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 58a418e..d2758f5 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -358,6 +358,8 @@
 
         public static final String EXTRA_VALUE = "value";
 
+        public static final String EXTRA_DB_NAME = "db_name";
+
         public static Bundle call(ContentResolver cr, String method) {
             return call(cr, method, null /* arg */);
         }
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 603e9df..f773191 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -43,15 +43,12 @@
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.search.AllAppsSearchBarController.SearchTargetHandler;
-import com.android.launcher3.allapps.search.SearchEventTracker;
 import com.android.launcher3.allapps.search.SearchSectionInfo;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.util.PackageManagerHelper;
-import com.android.launcher3.views.HeroSearchResultView;
 import com.android.launcher3.views.SearchSliceWrapper;
 import com.android.systemui.plugins.shared.SearchTarget;
-import com.android.systemui.plugins.shared.SearchTargetEvent;
 
 import java.util.List;
 
@@ -94,9 +91,11 @@
 
     public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13;
 
+    public static final int VIEW_TYPE_SEARCH_ICON = 1 << 14;
+
     // Common view type masks
     public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
-    public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
+    public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON | VIEW_TYPE_SEARCH_ICON;
 
     /**
      * ViewHolder for each icon.
@@ -186,32 +185,22 @@
                     || viewType == VIEW_TYPE_SEARCH_PEOPLE
                     || viewType == VIEW_TYPE_SEARCH_THUMBNAIL
                     || viewType == VIEW_TYPE_SEARCH_ICON_ROW
+                    || viewType == VIEW_TYPE_SEARCH_ICON
                     || viewType == VIEW_TYPE_SEARCH_SUGGEST;
         }
     }
 
     /**
      * Extension of AdapterItem that contains an extra payload specific to item
-     *
-     * @param <T> Play load Type
      */
     public static class SearchAdapterItem extends AdapterItem {
         private SearchTarget mSearchTarget;
-        private String mSearchSessionId;
 
         public SearchAdapterItem(SearchTarget searchTarget, int type) {
             mSearchTarget = searchTarget;
             viewType = type;
         }
 
-        public void setSearchSessionId(String searchSessionId) {
-            mSearchSessionId = searchSessionId;
-        }
-
-        public String getSearchSessionId() {
-            return mSearchSessionId;
-        }
-
         public SearchTarget getSearchTarget() {
             return mSearchTarget;
         }
@@ -399,11 +388,8 @@
                         R.layout.all_apps_icon, parent, false);
                 icon.setLongPressTimeoutFactor(1f);
                 icon.setOnFocusChangeListener(mIconFocusListener);
-                if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
-                    icon.setOnClickListener(mOnIconClickListener);
-                    icon.setOnLongClickListener(mOnIconLongClickListener);
-                }
-
+                icon.setOnClickListener(mOnIconClickListener);
+                icon.setOnLongClickListener(mOnIconLongClickListener);
                 // Ensure the all apps icon height matches the workspace icons in portrait mode.
                 icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
                 return new ViewHolder(icon);
@@ -419,6 +405,9 @@
             case VIEW_TYPE_ALL_APPS_DIVIDER:
                 return new ViewHolder(mLayoutInflater.inflate(
                         R.layout.all_apps_divider, parent, false));
+            case VIEW_TYPE_SEARCH_ICON:
+                return new ViewHolder(mLayoutInflater.inflate(
+                        R.layout.search_result_icon, parent, false));
             case VIEW_TYPE_SEARCH_CORPUS_TITLE:
                 return new ViewHolder(
                         mLayoutInflater.inflate(R.layout.search_section_title, parent, false));
@@ -453,6 +442,10 @@
 
     @Override
     public void onBindViewHolder(ViewHolder holder, int position) {
+        if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()
+                && holder.itemView instanceof AllAppsSectionDecorator.SelfDecoratingView) {
+            ((AllAppsSectionDecorator.SelfDecoratingView) holder.itemView).removeDecoration();
+        }
         switch (holder.getItemViewType()) {
             case VIEW_TYPE_ICON:
                 AdapterItem adapterItem = mApps.getAdapterItems().get(position);
@@ -460,43 +453,6 @@
                 BubbleTextView icon = (BubbleTextView) holder.itemView;
                 icon.reset();
                 icon.applyFromApplicationInfo(info);
-                if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
-                    break;
-                }
-                //TODO: replace with custom TopHitBubbleTextView with support for both shortcut
-                // and apps
-                if (adapterItem instanceof SearchAdapterItem) {
-                    SearchAdapterItem item = (SearchAdapterItem) adapterItem;
-                    SearchTargetHandler searchTargetHandler = new SearchTargetHandler() {
-                        @Override
-                        public void applySearchTarget(SearchTarget searchTarget) {
-                            // Does nothing
-                        }
-
-                        @Override
-                        public void handleSelection(int type) {
-                            SearchTargetEvent e = new SearchTargetEvent(SearchTarget.ItemType.APP,
-                                    type, item.position, item.getSearchSessionId());
-                            e.bundle = HeroSearchResultView.getAppBundle(info);
-                            SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(e);
-                        }
-                    };
-                    SearchEventTracker.INSTANCE.get(mLauncher).registerWeakHandler(
-                            ((SearchAdapterItem) adapterItem).getSearchTarget(),
-                            searchTargetHandler);
-
-                    icon.setOnClickListener(view -> {
-                        searchTargetHandler.handleSelection(SearchTargetEvent.SELECT);
-                        mOnIconClickListener.onClick(view);
-                    });
-                    icon.setOnLongClickListener(view -> {
-                        searchTargetHandler.handleSelection(SearchTargetEvent.LONG_PRESS);
-                        return mOnIconLongClickListener.onLongClick(view);
-                    });
-                } else {
-                    icon.setOnClickListener(mOnIconClickListener);
-                    icon.setOnLongClickListener(mOnIconLongClickListener);
-                }
                 break;
             case VIEW_TYPE_EMPTY_SEARCH:
                 TextView emptyViewText = (TextView) holder.itemView;
@@ -517,14 +473,14 @@
                 SearchAdapterItem slicePayload = (SearchAdapterItem) mApps.getAdapterItems().get(
                         position);
                 SearchTarget searchTarget = slicePayload.getSearchTarget();
-                sliceView.setTag(new SearchSliceWrapper(mLauncher, sliceView, searchTarget,
-                        slicePayload.getSearchSessionId(), slicePayload.position));
+                sliceView.setTag(new SearchSliceWrapper(mLauncher, sliceView, searchTarget));
 
                 break;
             case VIEW_TYPE_SEARCH_CORPUS_TITLE:
             case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
             case VIEW_TYPE_SEARCH_HERO_APP:
             case VIEW_TYPE_SEARCH_ROW:
+            case VIEW_TYPE_SEARCH_ICON:
             case VIEW_TYPE_SEARCH_ICON_ROW:
             case VIEW_TYPE_SEARCH_PEOPLE:
             case VIEW_TYPE_SEARCH_THUMBNAIL:
@@ -532,7 +488,7 @@
                 SearchAdapterItem item =
                         (SearchAdapterItem) mApps.getAdapterItems().get(position);
                 SearchTargetHandler payloadResultView = (SearchTargetHandler) holder.itemView;
-                payloadResultView.setup(item);
+                payloadResultView.applySearchTarget(item.getSearchTarget());
                 break;
             case VIEW_TYPE_ALL_APPS_DIVIDER:
                 // nothing to do
@@ -544,11 +500,10 @@
     public void onViewRecycled(@NonNull ViewHolder holder) {
         super.onViewRecycled(holder);
         if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
-        if (holder.itemView instanceof BubbleTextView) {
-            BubbleTextView icon = (BubbleTextView) holder.itemView;
-            icon.setOnClickListener(null);
-            icon.setOnLongClickListener(null);
-        } else if (holder.itemView instanceof SliceView) {
+        if (holder.itemView instanceof AllAppsSectionDecorator.SelfDecoratingView) {
+            ((AllAppsSectionDecorator.SelfDecoratingView) holder.itemView).removeDecoration();
+        }
+        if (holder.itemView instanceof SliceView) {
             SliceView sliceView = (SliceView) holder.itemView;
             if (sliceView.getTag() instanceof SearchSliceWrapper) {
                 ((SearchSliceWrapper) sliceView.getTag()).destroy();
diff --git a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
index c131697..3c81811 100644
--- a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
+++ b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
@@ -54,6 +54,9 @@
         int i = 0;
         while (i < itemCount) {
             View view = parent.getChildAt(i);
+            if (view instanceof SelfDecoratingView) {
+                ((SelfDecoratingView) view).removeDecoration();
+            }
             int position = parent.getChildAdapterPosition(view);
             AllAppsGridAdapter.AdapterItem adapterItem = adapterItems.get(position);
             if (adapterItem.searchSectionInfo != null) {
@@ -93,7 +96,7 @@
             int index = mAppsView.getApps().getFocusedChildIndex();
             AppsGridLayoutManager layoutManager = (AppsGridLayoutManager)
                     mAppsView.getActiveRecyclerView().getLayoutManager();
-            if (layoutManager.findFirstVisibleItemPosition() == index
+            if (layoutManager.findFirstVisibleItemPosition() <= index
                     && index < parent.getChildCount()) {
                 decorationHandler.onFocusDraw(c, parent.getChildAt(index));
             }
@@ -156,6 +159,10 @@
             if (view == null) {
                 return;
             }
+            if (view instanceof SelfDecoratingView) {
+                ((SelfDecoratingView) view).decorate(mFocusColor);
+                return;
+            }
             mPaint.setColor(mFocusColor);
             canvas.drawRoundRect(view.getLeft(), view.getTop(),
                     view.getRight(), view.getBottom(), mRadius, mRadius, mPaint);
@@ -169,4 +176,18 @@
         }
     }
 
+    /**
+     * An interface for a view to draw highlight indicator
+     */
+    public interface SelfDecoratingView {
+        /**
+         * Removes decorations drawing if focus is acquired by another view
+         */
+        void removeDecoration();
+
+        /**
+         * Draws highlight indicator on view.
+         */
+        void decorate(int focusColor);
+    }
 }
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 6ba0421..9e6ca34 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -31,12 +31,10 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.AllAppsGridAdapter;
-import com.android.launcher3.allapps.AllAppsGridAdapter.SearchAdapterItem;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.systemui.plugins.AllAppsSearchPlugin;
 import com.android.systemui.plugins.shared.SearchTarget;
-import com.android.systemui.plugins.shared.SearchTargetEvent;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -208,22 +206,8 @@
 
     /**
      * An interface for supporting dynamic search results
-     *
-     * @param <T> Type of payload
      */
     public interface SearchTargetHandler {
-        /**
-         * Updates View using Adapter's payload
-         */
-
-        default void setup(SearchAdapterItem searchAdapterItem) {
-            Object[] targetInfo = getTargetInfo();
-            if (targetInfo != null) {
-                targetInfo[0] = searchAdapterItem.getSearchSessionId();
-                targetInfo[1] = searchAdapterItem.position;
-            }
-            applySearchTarget(searchAdapterItem.getSearchTarget());
-        }
 
         /**
          * Update view using values from {@link SearchTarget}
@@ -231,34 +215,6 @@
         void applySearchTarget(SearchTarget searchTarget);
 
         /**
-         * Gets object created by {@link SearchTargetHandler#createTargetInfo()}
-         */
-        default Object[] getTargetInfo() {
-            return null;
-        }
-
-        /**
-         * Creates a wrapper object to hold searchSessionId and item position
-         */
-        default Object[] createTargetInfo() {
-            return new Object[2];
-        }
-
-        /**
-         * Generates a SearchTargetEvent object for a PayloadHandlerView
-         */
-        default SearchTargetEvent getSearchTargetEvent(SearchTarget.ItemType itemType,
-                int eventType) {
-            Object[] targetInfo = getTargetInfo();
-            if (targetInfo == null) return null;
-
-            String searchSessionId = (String) targetInfo[0];
-            int position = (int) targetInfo[1];
-            return new SearchTargetEvent(itemType, eventType,
-                    position, searchSessionId);
-        }
-
-        /**
          * Handles selection of SearchTarget
          */
         default void handleSelection(int eventType) {
diff --git a/src/com/android/launcher3/allapps/search/SearchEventTracker.java b/src/com/android/launcher3/allapps/search/SearchEventTracker.java
index 6bcde6c..c276434 100644
--- a/src/com/android/launcher3/allapps/search/SearchEventTracker.java
+++ b/src/com/android/launcher3/allapps/search/SearchEventTracker.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.allapps.search;
 
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
 import android.content.Context;
 
 import androidx.annotation.Nullable;
@@ -61,7 +63,7 @@
      */
     public void notifySearchTargetEvent(SearchTargetEvent searchTargetEvent) {
         if (mPlugin != null) {
-            mPlugin.notifySearchTargetEvent(searchTargetEvent);
+            UI_HELPER_EXECUTOR.post(() -> mPlugin.notifySearchTargetEvent(searchTargetEvent));
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
index e026e84..464df68 100644
--- a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
+++ b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
@@ -22,7 +22,7 @@
  */
 public class SearchSectionInfo {
 
-    private String mTitle;
+    private String mSectionId;
     private SectionDecorationHandler mDecorationHandler;
 
     public int getPosStart() {
@@ -48,8 +48,8 @@
         this(null);
     }
 
-    public SearchSectionInfo(String title) {
-        mTitle = title;
+    public SearchSectionInfo(String sectionId) {
+        mSectionId = sectionId;
     }
 
     public void setDecorationHandler(SectionDecorationHandler sectionDecorationHandler) {
@@ -62,9 +62,9 @@
     }
 
     /**
-     * Returns the section's title
+     * Returns the section's ID
      */
-    public String getTitle() {
-        return mTitle == null ? "" : mTitle;
+    public String getSectionId() {
+        return mSectionId == null ? "" : mSectionId;
     }
 }
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index c0d5882..d47fafd 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -41,6 +41,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.TextUtils;
@@ -130,6 +131,7 @@
 
     private final Set<PackageUserKey> mPendingPackages = new HashSet<>();
     private boolean mItemsDeleted = false;
+    private String mDbName;
 
     public LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel,
             ModelDelegate modelDelegate, LoaderResults results) {
@@ -274,7 +276,14 @@
             if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
                 loadFolderNames();
             }
-            sanitizeData();
+
+            // Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
+            // sanitizeData should not be invoked if the workspace is loaded from a db different
+            // from the main db as defined in the invariant device profile.
+            // (e.g. both grid preview and minimal device mode uses a different db)
+            if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {
+                sanitizeData();
+            }
 
             verifyNotStopped();
             updateHandler.finish();
@@ -349,7 +358,9 @@
             final LoaderCursor c = new LoaderCursor(
                     contentResolver.query(contentUri, null, selection, null, null), contentUri,
                     mApp, mUserManagerState);
-
+            final Bundle extras = c.getExtras();
+            mDbName = extras == null
+                    ? null : extras.getString(LauncherSettings.Settings.EXTRA_DB_NAME);
             try {
                 final int appWidgetIdIndex = c.getColumnIndexOrThrow(
                         LauncherSettings.Favorites.APPWIDGET_ID);
diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java
index 9e56e00..a098df9 100644
--- a/src/com/android/launcher3/views/HeroSearchResultView.java
+++ b/src/com/android/launcher3/views/HeroSearchResultView.java
@@ -19,13 +19,9 @@
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ShortcutInfo;
 import android.graphics.Point;
-import android.os.Bundle;
-import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.view.View;
@@ -56,20 +52,23 @@
 import com.android.systemui.plugins.shared.SearchTargetEvent;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A view representing a high confidence app search result that includes shortcuts
+ * TODO (sfufa@) consolidate this with SearchResultIconRow
  */
 public class HeroSearchResultView extends LinearLayout implements DragSource, SearchTargetHandler {
 
+    public static final String TARGET_TYPE_HERO_APP = "hero_app";
+
     public static final int MAX_SHORTCUTS_COUNT = 2;
-    public static final String SHORTCUTS_KEY = "shortcut_infos";
 
+    private SearchTarget mSearchTarget;
+    private BubbleTextView mBubbleTextView;
+    private View mIconView;
+    private BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2];
 
-    private final Object[] mTargetInfo = createTargetInfo();
-    BubbleTextView mBubbleTextView;
-    View mIconView;
-    BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2];
 
     public HeroSearchResultView(Context context) {
         super(context);
@@ -110,11 +109,9 @@
                             grid.allAppsIconSizePx));
             bubbleTextView.setOnClickListener(view -> {
                 WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) bubbleTextView.getTag();
-                SearchTargetEvent event = getSearchTargetEvent(
-                        SearchTarget.ItemType.APP_HERO,
-                        SearchTargetEvent.CHILD_SELECT);
-                event.bundle = getAppBundle(itemInfo);
-                event.bundle.putString("shortcut_id", itemInfo.getDeepShortcutId());
+                SearchTargetEvent event = new SearchTargetEvent.Builder(mSearchTarget,
+                        SearchTargetEvent.CHILD_SELECT).setShortcutPosition(itemInfo.rank).build();
+                SearchEventTracker.getInstance(getContext()).notifySearchTargetEvent(event);
                 launcher.getItemOnClickListener().onClick(view);
             });
         }
@@ -122,19 +119,20 @@
 
     @Override
     public void applySearchTarget(SearchTarget searchTarget) {
-        AppInfo appInfo = getAppInfo(searchTarget.bundle);
-//        TODO: replace this with searchTarget.shortcuts
-        ArrayList<ShortcutInfo> infos = searchTarget.bundle.getParcelableArrayList(
-                SHORTCUTS_KEY);
+        mSearchTarget = searchTarget;
+        AllAppsStore apps = Launcher.getLauncher(getContext()).getAppsView().getAppsStore();
+        AppInfo appInfo = apps.getApp(new ComponentKey(searchTarget.getComponentName(),
+                searchTarget.getUserHandle()));
+        List<ShortcutInfo> infos = mSearchTarget.getShortcutInfos();
 
         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));
         }
 
-
         mBubbleTextView.applyFromApplicationInfo(appInfo);
         mIconView.setBackground(mBubbleTextView.getIcon());
         mIconView.setTag(appInfo);
@@ -156,18 +154,6 @@
         SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
     }
 
-    private AppInfo getAppInfo(Bundle bundle) {
-        AllAppsStore apps = Launcher.getLauncher(getContext()).getAppsView().getAppsStore();
-        ComponentName cn = bundle.getParcelable("component_name");
-        UserHandle userHandle = bundle.getParcelable("user_handle");
-        return (cn != null) ? apps.getApp(new ComponentKey(cn, userHandle)) : null;
-    }
-
-    @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
     @Override
     public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) {
         mBubbleTextView.setVisibility(VISIBLE);
@@ -203,9 +189,8 @@
             mLauncher.getWorkspace().beginDragShared(mContainer.mBubbleTextView,
                     draggableView, mContainer, itemInfo, previewProvider, new DragOptions());
 
-            SearchTargetEvent event = mContainer.getSearchTargetEvent(
-                    SearchTarget.ItemType.APP_HERO, SearchTargetEvent.LONG_PRESS);
-            event.bundle = getAppBundle(itemInfo);
+            SearchTargetEvent event = new SearchTargetEvent.Builder(mContainer.mSearchTarget,
+                    SearchTargetEvent.LONG_PRESS).build();
             SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(event);
             return false;
         }
@@ -218,19 +203,7 @@
         Launcher launcher = Launcher.getLauncher(getContext());
         launcher.startActivitySafely(this, itemInfo.getIntent(), itemInfo);
 
-        SearchTargetEvent event = getSearchTargetEvent(
-                SearchTarget.ItemType.APP_HERO, eventType);
-        event.bundle = getAppBundle(itemInfo);
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(event);
-    }
-
-    /**
-     * Helper method to generate {@link SearchTargetEvent} bundle from {@link ItemInfo}
-     */
-    public static Bundle getAppBundle(ItemInfo itemInfo) {
-        Bundle b = new Bundle();
-        b.putParcelable(Intent.EXTRA_COMPONENT_NAME, itemInfo.getTargetComponent());
-        b.putParcelable(Intent.EXTRA_USER, itemInfo.user);
-        return b;
+        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
     }
 }
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 15ff2f5..77cec80 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -42,7 +42,7 @@
  */
 public class ScrimView<T extends Launcher> extends View implements Insettable, OnChangeListener {
 
-    private static final float SCRIM_ALPHA = .8f;
+    private static final float SCRIM_ALPHA = .75f;
     protected final T mLauncher;
     private final WallpaperColorInfo mWallpaperColorInfo;
     protected final int mEndScrim;
diff --git a/src/com/android/launcher3/views/SearchResultIcon.java b/src/com/android/launcher3/views/SearchResultIcon.java
new file mode 100644
index 0000000..ea06d5b
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchResultIcon.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.allapps.AllAppsStore;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.launcher3.allapps.search.SearchEventTracker;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.touch.ItemLongClickListener;
+import com.android.launcher3.util.ComponentKey;
+import com.android.systemui.plugins.shared.SearchTarget;
+import com.android.systemui.plugins.shared.SearchTargetEvent;
+
+/**
+ * A {@link BubbleTextView} representing a single cell result in AllApps
+ */
+public class SearchResultIcon extends BubbleTextView implements
+        AllAppsSearchBarController.SearchTargetHandler, View.OnClickListener,
+        View.OnLongClickListener {
+
+
+    public static final String TARGET_TYPE_APP = "app";
+
+    private final Launcher mLauncher;
+
+    private SearchTarget mSearchTarget;
+
+    public SearchResultIcon(Context context) {
+        this(context, null, 0);
+    }
+
+    public SearchResultIcon(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SearchResultIcon(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mLauncher = Launcher.getLauncher(getContext());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        setLongPressTimeoutFactor(1f);
+        setOnFocusChangeListener(mLauncher.getFocusHandler());
+        setOnClickListener(this);
+        setOnLongClickListener(this);
+        getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
+    }
+
+    @Override
+    public void applySearchTarget(SearchTarget searchTarget) {
+        mSearchTarget = searchTarget;
+        AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
+        SearchEventTracker.getInstance(getContext()).registerWeakHandler(mSearchTarget, this);
+        if (searchTarget.getItemType().equals(TARGET_TYPE_APP)) {
+            AppInfo appInfo = appsStore.getApp(new ComponentKey(searchTarget.getComponentName(),
+                    searchTarget.getUserHandle()));
+            applyFromApplicationInfo(appInfo);
+        }
+    }
+
+    @Override
+    public void handleSelection(int eventType) {
+        mLauncher.getItemOnClickListener().onClick(this);
+        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
+    }
+
+    @Override
+    public void onClick(View view) {
+        handleSelection(SearchTargetEvent.SELECT);
+    }
+
+    @Override
+    public boolean onLongClick(View view) {
+        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, SearchTargetEvent.LONG_PRESS).build());
+        return ItemLongClickListener.INSTANCE_ALL_APPS.onLongClick(view);
+    }
+}
diff --git a/src/com/android/launcher3/views/SearchResultIconRow.java b/src/com/android/launcher3/views/SearchResultIconRow.java
index ddeefaf..fe904ff 100644
--- a/src/com/android/launcher3/views/SearchResultIconRow.java
+++ b/src/com/android/launcher3/views/SearchResultIconRow.java
@@ -23,9 +23,9 @@
 import android.content.Context;
 import android.content.pm.ShortcutInfo;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
-import android.os.Bundle;
 import android.util.AttributeSet;
 import android.widget.EditText;
 
@@ -44,8 +44,8 @@
 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.SearchTarget;
-import com.android.systemui.plugins.shared.SearchTarget.ItemType;
 import com.android.systemui.plugins.shared.SearchTargetEvent;
 
 /**
@@ -54,11 +54,19 @@
 public class SearchResultIconRow extends DoubleShadowBubbleTextView implements
         AllAppsSearchBarController.SearchTargetHandler {
 
-    private final Object[] mTargetInfo = createTargetInfo();
+
+    public static final String TARGET_TYPE_REMOTE_ACTION = "remote_action";
+    public static final String TARGET_TYPE_SUGGEST = "suggest";
+    public static final String TARGET_TYPE_SHORTCUT = "shortcut";
+
+
+    public static final String REMOTE_ACTION_SHOULD_START = "should_start_for_result";
+    public static final String REMOTE_ACTION_TOKEN = "action_token";
+
     private final int mCustomIconResId;
     private final boolean mMatchesInset;
 
-    private ShortcutInfo mShortcutInfo;
+    private SearchTarget mSearchTarget;
 
 
     public SearchResultIconRow(@NonNull Context context) {
@@ -98,27 +106,37 @@
     }
 
     @Override
+    protected void drawFocusHighlight(Canvas canvas) {
+        mHighlightPaint.setColor(mHighlightColor);
+        float r = Themes.getDialogCornerRadius(getContext());
+        canvas.drawRoundRect(0, 0, getWidth(), getHeight(), r, r, mHighlightPaint);
+    }
+
+
+    @Override
     public void applySearchTarget(SearchTarget searchTarget) {
-        if (searchTarget.mRemoteAction != null) {
-            prepareUsingRemoteAction(searchTarget.mRemoteAction,
-                    searchTarget.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
-                    searchTarget.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START),
-                    searchTarget.type == ItemType.ACTION);
-        } else {
-            prepareUsingShortcutInfo(searchTarget.shortcuts.get(0));
+        mSearchTarget = searchTarget;
+        String type = searchTarget.getItemType();
+        if (type.equals(TARGET_TYPE_REMOTE_ACTION) || type.equals(TARGET_TYPE_SUGGEST)) {
+            prepareUsingRemoteAction(searchTarget.getRemoteAction(),
+                    searchTarget.getExtras().getString(REMOTE_ACTION_TOKEN),
+                    searchTarget.getExtras().getBoolean(REMOTE_ACTION_SHOULD_START),
+                    type.equals(TARGET_TYPE_REMOTE_ACTION));
+
+        } else if (type.equals(TARGET_TYPE_SHORTCUT)) {
+            prepareUsingShortcutInfo(searchTarget.getShortcutInfos().get(0));
         }
         setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
         SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
     }
 
     private void prepareUsingShortcutInfo(ShortcutInfo shortcutInfo) {
-        mShortcutInfo = shortcutInfo;
-        WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext());
+        WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(shortcutInfo, getContext());
         applyFromWorkspaceItem(workspaceItemInfo);
         LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
         if (!loadIconFromResource()) {
             MODEL_EXECUTOR.execute(() -> {
-                launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo);
+                launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, shortcutInfo);
                 reapplyItemInfoAsync(workspaceItemInfo);
             });
         }
@@ -164,32 +182,15 @@
     }
 
     @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
-    @Override
     public void handleSelection(int eventType) {
         ItemInfo itemInfo = (ItemInfo) getTag();
         Launcher launcher = Launcher.getLauncher(getContext());
-        final SearchTargetEvent searchTargetEvent;
         if (itemInfo instanceof WorkspaceItemInfo) {
             ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher);
-            searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.SHORTCUT,
-                    eventType);
-            searchTargetEvent.shortcut = mShortcutInfo;
         } else {
-            RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
-            ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
-            searchTargetEvent = getSearchTargetEvent(ItemType.ACTION,
-                    eventType);
-            searchTargetEvent.bundle = new Bundle();
-            searchTargetEvent.remoteAction = remoteItemInfo.getRemoteAction();
-            searchTargetEvent.bundle.putBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START,
-                    remoteItemInfo.shouldStartInLauncher());
-            searchTargetEvent.bundle.putString(SearchTarget.REMOTE_ACTION_TOKEN,
-                    remoteItemInfo.getToken());
+            ItemClickHandler.onClickRemoteAction(launcher, (RemoteActionItemInfo) itemInfo);
         }
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(searchTargetEvent);
+        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
     }
 }
diff --git a/src/com/android/launcher3/views/SearchResultPeopleView.java b/src/com/android/launcher3/views/SearchResultPeopleView.java
index 18bc99a..e499bd5 100644
--- a/src/com/android/launcher3/views/SearchResultPeopleView.java
+++ b/src/com/android/launcher3/views/SearchResultPeopleView.java
@@ -57,6 +57,8 @@
 public class SearchResultPeopleView extends LinearLayout implements
         AllAppsSearchBarController.SearchTargetHandler {
 
+    public static final String TARGET_TYPE_PEOPLE = "people";
+
     private final int mIconSize;
     private final int mButtonSize;
     private final PackageManager mPackageManager;
@@ -64,7 +66,9 @@
     private TextView mTitleView;
     private ImageButton[] mProviderButtons = new ImageButton[3];
     private Intent mIntent;
-    private final Object[] mTargetInfo = createTargetInfo();
+
+
+    private SearchTarget mSearchTarget;
 
     public SearchResultPeopleView(Context context) {
         this(context, null, 0);
@@ -102,7 +106,8 @@
 
     @Override
     public void applySearchTarget(SearchTarget searchTarget) {
-        Bundle payload = searchTarget.bundle;
+        mSearchTarget = searchTarget;
+        Bundle payload = searchTarget.getExtras();
         mTitleView.setText(payload.getString("title"));
         mIntent = payload.getParcelable("intent");
         Bitmap contactIcon = payload.getParcelable("icon");
@@ -176,23 +181,15 @@
         }
     }
 
-    @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
     private void setupProviderButton(ImageButton button, Bundle provider, Intent intent) {
         Launcher launcher = Launcher.getLauncher(getContext());
         button.setOnClickListener(b -> {
             launcher.startActivitySafely(b, intent, null);
-            SearchTargetEvent event = getSearchTargetEvent(
-                    SearchTarget.ItemType.PEOPLE,
-                    SearchTargetEvent.CHILD_SELECT);
-            event.bundle = new Bundle();
-            event.bundle.putParcelable("intent", intent);
-            event.bundle.putString("title", mTitleView.getText().toString());
-            event.bundle.putBundle("provider", provider);
-            SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(event);
+            Bundle bundle = new Bundle();
+            bundle.putBundle("provider", provider);
+            SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
+                    new SearchTargetEvent.Builder(mSearchTarget,
+                            SearchTargetEvent.CHILD_SELECT).setExtras(bundle).build());
         });
     }
 
@@ -201,12 +198,8 @@
         if (mIntent != null) {
             Launcher launcher = Launcher.getLauncher(getContext());
             launcher.startActivitySafely(this, mIntent, null);
-            SearchTargetEvent event = getSearchTargetEvent(SearchTarget.ItemType.PEOPLE,
-                    eventType);
-            event.bundle = new Bundle();
-            event.bundle.putParcelable("intent", mIntent);
-            event.bundle.putString("title", mTitleView.getText().toString());
-            SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(event);
+            SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
+                    new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
         }
     }
 }
diff --git a/src/com/android/launcher3/views/SearchResultPlayItem.java b/src/com/android/launcher3/views/SearchResultPlayItem.java
index 39a8304..86ed436 100644
--- a/src/com/android/launcher3/views/SearchResultPlayItem.java
+++ b/src/com/android/launcher3/views/SearchResultPlayItem.java
@@ -58,11 +58,12 @@
 public class SearchResultPlayItem extends LinearLayout implements
         AllAppsSearchBarController.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 final Object[] mTargetInfo = createTargetInfo();
     private View mIconView;
     private TextView mTitleView;
     private TextView[] mDetailViews = new TextView[3];
@@ -70,6 +71,8 @@
     private String mPackageName;
     private boolean mIsInstantGame;
 
+    private SearchTarget mSearchTarget;
+
 
     public SearchResultPlayItem(Context context) {
         this(context, null, 0);
@@ -101,7 +104,6 @@
         iconParams.height = mDeviceProfile.allAppsIconSizePx;
         iconParams.width = mDeviceProfile.allAppsIconSizePx;
         setOnClickListener(view -> handleSelection(SearchTargetEvent.SELECT));
-
     }
 
 
@@ -128,7 +130,8 @@
 
     @Override
     public void applySearchTarget(SearchTarget searchTarget) {
-        Bundle bundle = searchTarget.bundle;
+        mSearchTarget = searchTarget;
+        Bundle bundle = searchTarget.getExtras();
         SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
         if (bundle.getString("package", "").equals(mPackageName)) {
             return;
@@ -160,11 +163,6 @@
         });
     }
 
-    @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
     private void showIfNecessary(TextView textView, @Nullable String string) {
         if (string == null || string.isEmpty()) {
             textView.setVisibility(GONE);
@@ -201,10 +199,7 @@
     }
 
     private void logSearchEvent(int eventType) {
-        SearchTargetEvent searchTargetEvent = getSearchTargetEvent(
-                SearchTarget.ItemType.PLAY_RESULTS, eventType);
-        searchTargetEvent.bundle = new Bundle();
-        searchTargetEvent.bundle.putString("package_name", mPackageName);
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(searchTargetEvent);
+        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
     }
 }
diff --git a/src/com/android/launcher3/views/SearchSectionHeaderView.java b/src/com/android/launcher3/views/SearchSectionHeaderView.java
index 370b921..326c23d 100644
--- a/src/com/android/launcher3/views/SearchSectionHeaderView.java
+++ b/src/com/android/launcher3/views/SearchSectionHeaderView.java
@@ -29,6 +29,8 @@
  */
 public class SearchSectionHeaderView extends TextView implements
         AllAppsSearchBarController.SearchTargetHandler {
+    public static final String TARGET_TYPE_SECTION_HEADER = "section_header";
+
     public SearchSectionHeaderView(Context context) {
         super(context);
     }
@@ -44,7 +46,7 @@
 
     @Override
     public void applySearchTarget(SearchTarget searchTarget) {
-        String title = searchTarget.type.getTitle();
+        String title = searchTarget.getExtras().getString("title");
         if (title == null || !title.isEmpty()) {
             setText(title);
             setVisibility(VISIBLE);
@@ -52,9 +54,4 @@
             setVisibility(INVISIBLE);
         }
     }
-
-    @Override
-    public Object[] getTargetInfo() {
-        return null;
-    }
 }
diff --git a/src/com/android/launcher3/views/SearchSettingsRowView.java b/src/com/android/launcher3/views/SearchSettingsRowView.java
index ac69548..30f686c 100644
--- a/src/com/android/launcher3/views/SearchSettingsRowView.java
+++ b/src/com/android/launcher3/views/SearchSettingsRowView.java
@@ -42,11 +42,14 @@
 public class SearchSettingsRowView extends LinearLayout implements
         View.OnClickListener, AllAppsSearchBarController.SearchTargetHandler {
 
+    public static final String TARGET_TYPE_SETTINGS_ROW = "settings_row";
+
+
     private TextView mTitleView;
     private TextView mDescriptionView;
     private TextView mBreadcrumbsView;
     private Intent mIntent;
-    private final Object[] mTargetInfo = createTargetInfo();
+    private SearchTarget mSearchTarget;
 
 
     public SearchSettingsRowView(@NonNull Context context) {
@@ -74,7 +77,8 @@
 
     @Override
     public void applySearchTarget(SearchTarget searchTarget) {
-        Bundle bundle = searchTarget.bundle;
+        mSearchTarget = searchTarget;
+        Bundle bundle = searchTarget.getExtras();
         mIntent = bundle.getParcelable("intent");
         showIfAvailable(mTitleView, bundle.getString("title"));
         showIfAvailable(mDescriptionView, bundle.getString("description"));
@@ -85,11 +89,6 @@
         SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
     }
 
-    @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
     private void showIfAvailable(TextView view, @Nullable String string) {
         if (TextUtils.isEmpty(string)) {
             view.setVisibility(GONE);
@@ -112,10 +111,7 @@
         Launcher launcher = Launcher.getLauncher(getContext());
         launcher.startActivityForResult(mIntent, 0);
 
-        SearchTargetEvent searchTargetEvent = getSearchTargetEvent(
-                SearchTarget.ItemType.SETTINGS_ROW, eventType);
-        searchTargetEvent.bundle = new Bundle();
-        searchTargetEvent.bundle.putParcelable("intent", mIntent);
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(searchTargetEvent);
+        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
     }
 }
diff --git a/src/com/android/launcher3/views/SearchSliceWrapper.java b/src/com/android/launcher3/views/SearchSliceWrapper.java
index b088237..f8a7dc0 100644
--- a/src/com/android/launcher3/views/SearchSliceWrapper.java
+++ b/src/com/android/launcher3/views/SearchSliceWrapper.java
@@ -17,7 +17,6 @@
 
 import android.content.Context;
 import android.net.Uri;
-import android.os.Bundle;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -38,6 +37,8 @@
  */
 public class SearchSliceWrapper implements 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";
 
@@ -45,16 +46,10 @@
     private final Launcher mLauncher;
     private final SearchTarget mSearchTarget;
     private final SliceView mSliceView;
-    //TODO: remove these as we move to tracking search results individually with unique ID
-    private final int mPosition;
-    private final String mSessionId;
     private LiveData<Slice> mSliceLiveData;
 
-    public SearchSliceWrapper(Context context, SliceView sliceView,
-            SearchTarget searchTarget, String sessionId, int position) {
+    public SearchSliceWrapper(Context context, SliceView sliceView, SearchTarget searchTarget) {
         mLauncher = Launcher.getLauncher(context);
-        mPosition = position;
-        mSessionId = sessionId;
         mSearchTarget = searchTarget;
         mSliceView = sliceView;
         sliceView.setOnSliceActionListener(this);
@@ -76,16 +71,12 @@
 
     @Override
     public void onSliceAction(@NonNull EventInfo info, @NonNull SliceItem item) {
-        SearchTargetEvent searchTargetEvent = new SearchTargetEvent(
-                SearchTarget.ItemType.SETTINGS_SLICE,
-                SearchTargetEvent.CHILD_SELECT, mPosition,
-                mSessionId);
-        searchTargetEvent.bundle = new Bundle();
-        searchTargetEvent.bundle.putParcelable(URI_EXTRA_KEY, getSliceUri());
-        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(searchTargetEvent);
+        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget,
+                        SearchTargetEvent.CHILD_SELECT).build());
     }
 
     private Uri getSliceUri() {
-        return mSearchTarget.bundle.getParcelable(URI_EXTRA_KEY);
+        return mSearchTarget.getExtras().getParcelable(URI_EXTRA_KEY);
     }
 }
diff --git a/src/com/android/launcher3/views/ThumbnailSearchResultView.java b/src/com/android/launcher3/views/ThumbnailSearchResultView.java
index 2121232..d11b1ef 100644
--- a/src/com/android/launcher3/views/ThumbnailSearchResultView.java
+++ b/src/com/android/launcher3/views/ThumbnailSearchResultView.java
@@ -15,6 +15,9 @@
  */
 package com.android.launcher3.views;
 
+import static com.android.launcher3.views.SearchResultIconRow.REMOTE_ACTION_SHOULD_START;
+import static com.android.launcher3.views.SearchResultIconRow.REMOTE_ACTION_TOKEN;
+
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -42,7 +45,10 @@
 public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView
         implements AllAppsSearchBarController.SearchTargetHandler {
 
-    private final Object[] mTargetInfo = createTargetInfo();
+    public static final String TARGET_TYPE_SCREENSHOT = "screenshot";
+    public static final String TARGET_TYPE_SCREENSHOT_LEGACY = "screenshot_legacy";
+
+    private SearchTarget mSearchTarget;
 
     public ThumbnailSearchResultView(Context context) {
         super(context);
@@ -66,29 +72,29 @@
         } else {
             ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher);
         }
-        SearchTargetEvent e = getSearchTargetEvent(SearchTarget.ItemType.SCREENSHOT, eventType);
-        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(e);
+        SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
     }
 
     @Override
     public void applySearchTarget(SearchTarget target) {
+        mSearchTarget = target;
         Bitmap bitmap;
-        if (target.mRemoteAction != null) {
-            RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(target.mRemoteAction,
-                    target.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
-                    target.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START));
-            bitmap = ((BitmapDrawable) target.mRemoteAction.getIcon()
+        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();
-            Bitmap crop = Bitmap.createBitmap(bitmap, 0,
+            // crop
+            bitmap = Bitmap.createBitmap(bitmap, 0,
                     bitmap.getHeight() / 2 - bitmap.getWidth() / 2,
                     bitmap.getWidth(), bitmap.getWidth());
-            bitmap = crop;
-            setTag(itemInfo);
         } else {
-            bitmap = (Bitmap) target.bundle.getParcelable("bitmap");
+            bitmap = (Bitmap) target.getExtras().getParcelable("bitmap");
             WorkspaceItemInfo itemInfo = new WorkspaceItemInfo();
             itemInfo.intent = new Intent(Intent.ACTION_VIEW)
-                    .setData(Uri.parse(target.bundle.getString("uri")))
+                    .setData(Uri.parse(target.getExtras().getString("uri")))
                     .setType("image/*")
                     .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             setTag(itemInfo);
@@ -99,9 +105,4 @@
         setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
         SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(target, this);
     }
-
-    @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
 }
diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
index 3f0dc39..2c7972e 100644
--- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
+++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java
@@ -16,8 +16,10 @@
 package com.android.systemui.plugins.shared;
 
 import android.app.RemoteAction;
+import android.content.ComponentName;
 import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
+import android.os.UserHandle;
 
 import java.util.List;
 
@@ -26,139 +28,145 @@
  */
 public class SearchTarget implements Comparable<SearchTarget> {
 
+    private final String mItemId;
+    private final String mItemType;
+    private final float mScore;
 
-    /**
-     * A bundle key for boolean value of whether remote action should be started in launcher or not
-     */
-    public static final String REMOTE_ACTION_SHOULD_START = "should_start_for_result";
-    public static final String REMOTE_ACTION_TOKEN = "action_token";
+    private final ComponentName mComponentName;
+    private final UserHandle mUserHandle;
+    private final List<ShortcutInfo> mShortcutInfos;
+    //TODO: (sfufa) replace with a list of a custom type
+    private final RemoteAction mRemoteAction;
+    private final Bundle mExtras;
 
-
-    public enum ViewType {
-
-        /**
-         * Consists of N number of icons. (N: launcher column count)
-         */
-        TOP_HIT(0),
-
-        /**
-         * Consists of 1 icon and two subsidiary icons.
-         */
-        HERO(1),
-
-        /**
-         * Main/sub/breadcrumb texts are rendered.
-         */
-        DETAIL(2),
-
-        /**
-         * Consists of an icon, three detail strings.
-         */
-        ROW(3),
-
-        /**
-         * Consists of an icon, three detail strings and a button.
-         */
-        ROW_WITH_BUTTON(4),
-
-        /**
-         * Consists of a single slice view
-         */
-        SLICE(5),
-
-        /**
-         * Similar to hero section.
-         */
-        SHORTCUT(6),
-
-        /**
-         * Person icon and handling app icons are rendered.
-         */
-        PEOPLE(7),
-
-        /**
-         * N number of 1x1 ratio thumbnail is rendered.
-         * (current N = 3)
-         */
-        THUMBNAIL(8),
-
-        /**
-         * Fallback search icon and relevant text is rendered.
-         */
-        SUGGEST(9);
-
-        private final int mId;
-
-        ViewType(int id) {
-            mId = id;
-        }
-
-        public int get() {
-            return mId;
-        }
+    private SearchTarget(String itemId, String itemType, float score,
+            ComponentName componentName, UserHandle userHandle, List<ShortcutInfo> shortcutInfos,
+            RemoteAction remoteAction, Bundle extras) {
+        mItemId = itemId;
+        mItemType = itemType;
+        mScore = score;
+        mComponentName = componentName;
+        mUserHandle = userHandle;
+        mShortcutInfos = shortcutInfos;
+        mExtras = extras;
+        mRemoteAction = remoteAction;
     }
 
-    public enum ItemType {
-        PLAY_RESULTS(0, "Play Store", ViewType.DETAIL),
-        SETTINGS_ROW(1, "Settings", ViewType.ROW),
-        SETTINGS_SLICE(2, "Settings", ViewType.SLICE),
-        APP(3, "", ViewType.TOP_HIT),
-        APP_HERO(4, "", ViewType.HERO),
-        SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT),
-        PEOPLE(6, "People", ViewType.PEOPLE),
-        SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL),
-        ACTION(8, "Actions", ViewType.SHORTCUT),
-        SUGGEST(9, "Fallback Search", ViewType.SUGGEST),
-        CHROME_TAB(10, "Chrome Tab", ViewType.SHORTCUT);
-
-        private final int mId;
-
-        /** Used to render section title. */
-        private final String mTitle;
-        private final ViewType mViewType;
-
-        ItemType(int id, String title, ViewType type) {
-            mId = id;
-            mTitle = title;
-            mViewType = type;
-        }
-
-        public ViewType getViewType() {
-            return mViewType;
-        }
-
-        public String getTitle() {
-            return mTitle;
-        }
-
-        public int getId() {
-            return mId;
-        }
+    public String getItemId() {
+        return mItemId;
     }
 
-    public ItemType type;
-    public List<ShortcutInfo> shortcuts;
-    public Bundle bundle;
-    public float score;
-    public String mSessionId;
-    public RemoteAction mRemoteAction;
+    public String getItemType() {
+        return mItemType;
+    }
 
-    /**
-     * Constructor to create the search target. Bundle is currently temporary to hold
-     * search target primitives that cannot be expressed as java primitive objects
-     * or AOSP native objects.
-     */
-    public SearchTarget(ItemType itemType, List<ShortcutInfo> shortcuts,
-            Bundle bundle, float score, String sessionId) {
-        this.type = itemType;
-        this.shortcuts = shortcuts;
-        this.bundle = bundle;
-        this.score = score;
-        this.mSessionId = sessionId;
+    public ComponentName getComponentName() {
+        return mComponentName;
+    }
+
+    public UserHandle getUserHandle() {
+        return mUserHandle;
+    }
+
+    public float getScore() {
+        return mScore;
+    }
+
+    public List<ShortcutInfo> getShortcutInfos() {
+        return mShortcutInfos;
+    }
+
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    public RemoteAction getRemoteAction() {
+        return mRemoteAction;
     }
 
     @Override
     public int compareTo(SearchTarget o) {
-        return Float.compare(o.score, score);
+        return Float.compare(o.mScore, mScore);
+    }
+
+    /**
+     * A builder for {@link SearchTarget}
+     */
+    public static final class Builder {
+
+
+        private String mItemId;
+
+        private final String mItemType;
+        private final float mScore;
+
+
+        private ComponentName mComponentName;
+        private UserHandle mUserHandle;
+        private List<ShortcutInfo> mShortcutInfos;
+        private Bundle mExtras;
+        private RemoteAction mRemoteAction;
+
+        public Builder(String itemType, float score) {
+            this(itemType, score, null, null);
+        }
+
+        public Builder(String itemType, float score, ComponentName cn,
+                UserHandle user) {
+            mItemType = itemType;
+            mScore = score;
+            mComponentName = cn;
+            mUserHandle = user;
+        }
+
+        public String getItemId() {
+            return mItemId;
+        }
+
+        public float getScore() {
+            return mScore;
+        }
+
+        public Builder setItemId(String itemId) {
+            mItemId = itemId;
+            return this;
+        }
+
+        public Builder setComponentName(ComponentName componentName) {
+            mComponentName = componentName;
+            return this;
+        }
+
+        public Builder setUserHandle(UserHandle userHandle) {
+            mUserHandle = userHandle;
+            return this;
+        }
+
+        public Builder setShortcutInfos(List<ShortcutInfo> shortcutInfos) {
+            mShortcutInfos = shortcutInfos;
+            return this;
+        }
+
+        public Builder setExtras(Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        public Builder setRemoteAction(RemoteAction remoteAction) {
+            mRemoteAction = remoteAction;
+            return this;
+        }
+
+        /**
+         * Builds a {@link SearchTarget}
+         */
+        public SearchTarget build() {
+            if (mItemId == null) {
+                throw new IllegalStateException("Item ID is required for building SearchTarget");
+            }
+            return new SearchTarget(mItemId, mItemType, mScore, mComponentName, mUserHandle,
+                    mShortcutInfos,
+                    mRemoteAction, mExtras);
+        }
     }
 }
diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
index 5016abc..290fe54 100644
--- a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
+++ b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java
@@ -15,32 +15,76 @@
  */
 package com.android.systemui.plugins.shared;
 
-import android.app.RemoteAction;
-import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
 
 /**
  * Event used for the feedback loop to the plugin. (and future aiai)
  */
 public class SearchTargetEvent {
+    public static final int POSITION_NONE = -1;
+
     public static final int SELECT = 0;
     public static final int QUICK_SELECT = 1;
     public static final int LONG_PRESS = 2;
     public static final int CHILD_SELECT = 3;
 
-    public SearchTarget.ItemType type;
-    public ShortcutInfo shortcut;
-    public RemoteAction remoteAction;
-    public int eventType;
-    public Bundle bundle;
-    public int index;
-    public String sessionIdentifier;
+    private final SearchTarget mSearchTarget;
+    private final int mEventType;
+    private final int mShortcutPosition;
+    private final Bundle mExtras;
 
-    public SearchTargetEvent(SearchTarget.ItemType itemType, int eventType, int index,
-            String sessionId) {
-        this.type = itemType;
-        this.eventType = eventType;
-        this.index = index;
-        this.sessionIdentifier = sessionId;
+    public SearchTargetEvent(SearchTarget searchTarget, int eventType, int shortcutPosition,
+            Bundle extras) {
+        mSearchTarget = searchTarget;
+        mEventType = eventType;
+        mShortcutPosition = shortcutPosition;
+        mExtras = extras;
     }
+
+
+    public SearchTarget getSearchTarget() {
+        return mSearchTarget;
+    }
+
+    public int getShortcutPosition() {
+        return mShortcutPosition;
+    }
+
+    public int getEventType() {
+        return mEventType;
+    }
+
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    /**
+     * A builder for {@link SearchTarget}
+     */
+    public static final class Builder {
+        private final SearchTarget mSearchTarget;
+        private final int mEventType;
+        private int mShortcutPosition = POSITION_NONE;
+        private Bundle mExtras;
+
+        public Builder(SearchTarget searchTarget, int eventType) {
+            mSearchTarget = searchTarget;
+            mEventType = eventType;
+        }
+
+        public Builder setShortcutPosition(int shortcutPosition) {
+            mShortcutPosition = shortcutPosition;
+            return this;
+        }
+
+        public Builder setExtras(Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        public SearchTargetEvent build() {
+            return new SearchTargetEvent(mSearchTarget, mEventType, mShortcutPosition, mExtras);
+        }
+    }
+
 }