Remove hardcoded itemTypes from SearchTarget

- Introduces componentName and userHandle members to SearchTarget
- SearchTargetEvent now has searchTarget member
- Builder pattern for SearchTarget and SearchTargetEvent
- Search backend should add headers manually instead of launcher inferring sections

Bug: 171026321
Test: Manual
Change-Id: I28e0455e82b925277a17703b9aa061c8f9f15262
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index a1bf7ed..f773191 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -192,26 +192,15 @@
 
     /**
      * 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;
         }
@@ -484,8 +473,7 @@
                 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:
@@ -500,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
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index 50fb60a..3ae0a18 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -18,8 +18,6 @@
 import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
 import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
 
-import android.content.ComponentName;
-import android.os.UserHandle;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -29,7 +27,6 @@
 import com.android.launcher3.model.data.PromiseAppInfo;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.PackageUserKey;
-import com.android.systemui.plugins.shared.SearchTarget;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -89,19 +86,6 @@
         return index < 0 ? null : mApps[index];
     }
 
-    /**
-     * Gets AppInfo from {@link SearchTarget}
-     * TODO: SearchTarget should have userHandle and ComponentKey members
-     */
-    public AppInfo getAppFromSearchTarget(SearchTarget searchTarget) {
-        ComponentName cn = searchTarget.bundle.getParcelable("component_name");
-        UserHandle userHandle = searchTarget.bundle.getParcelable("user_handle");
-        if (cn == null) {
-            throw new IllegalStateException("Component name is required for AppInfo");
-        }
-        return getApp(new ComponentKey(cn, userHandle));
-    }
-
     public void enableDeferUpdates(int flag) {
         mDeferUpdatesFlags |= flag;
     }
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/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/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java
index e2ba93b..a098df9 100644
--- a/src/com/android/launcher3/views/HeroSearchResultView.java
+++ b/src/com/android/launcher3/views/HeroSearchResultView.java
@@ -20,10 +20,8 @@
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ShortcutInfo;
 import android.graphics.Point;
-import android.os.Bundle;
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.view.View;
@@ -49,24 +47,28 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
 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;
 
 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);
@@ -107,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);
             });
         }
@@ -119,20 +119,20 @@
 
     @Override
     public void applySearchTarget(SearchTarget searchTarget) {
+        mSearchTarget = searchTarget;
         AllAppsStore apps = Launcher.getLauncher(getContext()).getAppsView().getAppsStore();
-        AppInfo appInfo = apps.getAppFromSearchTarget(searchTarget);
-//        TODO: replace this with searchTarget.shortcuts
-        ArrayList<ShortcutInfo> infos = searchTarget.bundle.getParcelableArrayList(
-                SHORTCUTS_KEY);
+        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);
@@ -155,11 +155,6 @@
     }
 
     @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
-    @Override
     public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) {
         mBubbleTextView.setVisibility(VISIBLE);
         mBubbleTextView.setIconVisible(true);
@@ -194,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;
         }
@@ -209,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/SearchResultIcon.java b/src/com/android/launcher3/views/SearchResultIcon.java
index e0f9ab7..51214ae 100644
--- a/src/com/android/launcher3/views/SearchResultIcon.java
+++ b/src/com/android/launcher3/views/SearchResultIcon.java
@@ -25,8 +25,8 @@
 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.model.data.ItemInfo;
 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;
 
@@ -36,7 +36,10 @@
 public class SearchResultIcon extends BubbleTextView implements
         AllAppsSearchBarController.SearchTargetHandler, View.OnClickListener,
         View.OnLongClickListener {
-    private final Object[] mTargetInfo = createTargetInfo();
+
+
+    public static final String TARGET_TYPE_APP = "app";
+
     private final Launcher mLauncher;
 
     private SearchTarget mSearchTarget;
@@ -68,25 +71,17 @@
     public void applySearchTarget(SearchTarget searchTarget) {
         mSearchTarget = searchTarget;
         AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
-        if (searchTarget.type == SearchTarget.ItemType.APP) {
-            AppInfo appInfo = appsStore.getAppFromSearchTarget(searchTarget);
+        if (searchTarget.getItemType().equals(TARGET_TYPE_APP)) {
+            AppInfo appInfo = appsStore.getApp(new ComponentKey(searchTarget.getComponentName(),
+                    searchTarget.getUserHandle()));
             applyFromApplicationInfo(appInfo);
         }
     }
 
     @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
-    @Override
     public void handleSelection(int eventType) {
-        SearchTargetEvent event = getSearchTargetEvent(mSearchTarget.type,
-                eventType);
-        if (mSearchTarget.type.equals(SearchTarget.ItemType.APP)) {
-            event.bundle = HeroSearchResultView.getAppBundle((ItemInfo) getTag());
-        }
-        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(event);
+        SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
+                new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
     }
 
     @Override
diff --git a/src/com/android/launcher3/views/SearchResultIconRow.java b/src/com/android/launcher3/views/SearchResultIconRow.java
index 5115f69..5fb36b9 100644
--- a/src/com/android/launcher3/views/SearchResultIconRow.java
+++ b/src/com/android/launcher3/views/SearchResultIconRow.java
@@ -26,7 +26,6 @@
 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;
 
@@ -47,7 +46,6 @@
 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;
 
 /**
@@ -56,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) {
@@ -109,26 +115,28 @@
 
     @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_SUGGEST));
+
+        } 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);
             });
         }
@@ -174,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..6d85955 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);
@@ -128,7 +131,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 +164,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 +200,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);
+        }
+    }
+
 }