From 1f79eeda76246534697e92740defc7f73c3c8d14 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Fri, 16 Oct 2020 02:01:31 -0700 Subject: [PATCH] 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 --- .../launcher3/allapps/AllAppsGridAdapter.java | 16 +- .../launcher3/allapps/AllAppsStore.java | 16 -- .../search/AllAppsSearchBarController.java | 44 --- .../allapps/search/SearchSectionInfo.java | 12 +- .../launcher3/views/HeroSearchResultView.java | 60 ++--- .../launcher3/views/SearchResultIcon.java | 25 +- .../launcher3/views/SearchResultIconRow.java | 59 ++-- .../views/SearchResultPeopleView.java | 35 +-- .../launcher3/views/SearchResultPlayItem.java | 20 +- .../views/SearchSectionHeaderView.java | 9 +- .../views/SearchSettingsRowView.java | 20 +- .../launcher3/views/SearchSliceWrapper.java | 23 +- .../views/ThumbnailSearchResultView.java | 37 +-- .../systemui/plugins/shared/SearchTarget.java | 254 +++++++++--------- .../plugins/shared/SearchTargetEvent.java | 74 +++-- 15 files changed, 313 insertions(+), 391 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index a1bf7ed5dc..f7731915e3 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -192,26 +192,15 @@ public class AllAppsGridAdapter extends /** * Extension of AdapterItem that contains an extra payload specific to item - * - * @param 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 @@ public class AllAppsGridAdapter extends 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 @@ public class AllAppsGridAdapter extends 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 50fb60a841..3ae0a18137 100644 --- a/src/com/android/launcher3/allapps/AllAppsStore.java +++ b/src/com/android/launcher3/allapps/AllAppsStore.java @@ -18,8 +18,6 @@ package com.android.launcher3.allapps; 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.ItemInfo; 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 @@ public class AllAppsStore { 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 6ba0421d57..9e6ca3403b 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.ExtendedEditText; 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,56 +206,14 @@ public class AllAppsSearchBarController /** * An interface for supporting dynamic search results - * - * @param 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} */ 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 */ diff --git a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java index e026e8449d..464df68c96 100644 --- a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java +++ b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java @@ -22,7 +22,7 @@ import com.android.launcher3.allapps.AllAppsSectionDecorator.SectionDecorationHa */ public class SearchSectionInfo { - private String mTitle; + private String mSectionId; private SectionDecorationHandler mDecorationHandler; public int getPosStart() { @@ -48,8 +48,8 @@ public class SearchSectionInfo { this(null); } - public SearchSectionInfo(String title) { - mTitle = title; + public SearchSectionInfo(String sectionId) { + mSectionId = sectionId; } public void setDecorationHandler(SectionDecorationHandler sectionDecorationHandler) { @@ -62,9 +62,9 @@ public class SearchSectionInfo { } /** - * 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 e2ba93b5db..a098df9f31 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.MAIN_EXECUTOR; 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.ItemInfoWithIcon; 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 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Se 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 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Se @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 infos = searchTarget.bundle.getParcelableArrayList( - SHORTCUTS_KEY); + AppInfo appInfo = apps.getApp(new ComponentKey(searchTarget.getComponentName(), + searchTarget.getUserHandle())); + List infos = mSearchTarget.getShortcutInfos(); ArrayList> 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); @@ -154,11 +154,6 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Se SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this); } - @Override - public Object[] getTargetInfo() { - return mTargetInfo; - } - @Override public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) { mBubbleTextView.setVisibility(VISIBLE); @@ -194,9 +189,8 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Se 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 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Se 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 e0f9ab751a..51214aec0b 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.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.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 @@ import com.android.systemui.plugins.shared.SearchTargetEvent; 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 class SearchResultIcon extends BubbleTextView implements 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 5115f69534..5fb36b9da9 100644 --- a/src/com/android/launcher3/views/SearchResultIconRow.java +++ b/src/com/android/launcher3/views/SearchResultIconRow.java @@ -26,7 +26,6 @@ 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; @@ -47,7 +46,6 @@ 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; /** @@ -56,11 +54,19 @@ import com.android.systemui.plugins.shared.SearchTargetEvent; 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 @@ public class SearchResultIconRow extends DoubleShadowBubbleTextView implements @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); }); } @@ -173,33 +181,16 @@ public class SearchResultIconRow extends DoubleShadowBubbleTextView implements MAIN_EXECUTOR.post(() -> reapplyItemInfo(itemInfoWithIcon)); } - @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 18bc99a3f9..e499bd5b66 100644 --- a/src/com/android/launcher3/views/SearchResultPeopleView.java +++ b/src/com/android/launcher3/views/SearchResultPeopleView.java @@ -57,6 +57,8 @@ import java.util.ArrayList; 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 @@ public class SearchResultPeopleView extends LinearLayout implements 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 @@ public class SearchResultPeopleView extends LinearLayout implements @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 @@ public class SearchResultPeopleView extends LinearLayout implements } } - @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 @@ public class SearchResultPeopleView extends LinearLayout implements 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 39a83045e4..6d85955f91 100644 --- a/src/com/android/launcher3/views/SearchResultPlayItem.java +++ b/src/com/android/launcher3/views/SearchResultPlayItem.java @@ -58,11 +58,12 @@ import java.net.URLConnection; 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 @@ public class SearchResultPlayItem extends LinearLayout implements private String mPackageName; private boolean mIsInstantGame; + private SearchTarget mSearchTarget; + public SearchResultPlayItem(Context context) { this(context, null, 0); @@ -128,7 +131,8 @@ public class SearchResultPlayItem extends LinearLayout implements @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 @@ public class SearchResultPlayItem extends LinearLayout implements }); } - @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 @@ public class SearchResultPlayItem extends LinearLayout implements } 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 370b92148c..326c23d1dc 100644 --- a/src/com/android/launcher3/views/SearchSectionHeaderView.java +++ b/src/com/android/launcher3/views/SearchSectionHeaderView.java @@ -29,6 +29,8 @@ import com.android.systemui.plugins.shared.SearchTarget; */ 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 @@ public class SearchSectionHeaderView extends TextView implements @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 @@ public class SearchSectionHeaderView extends TextView implements 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 ac69548840..30f686c86e 100644 --- a/src/com/android/launcher3/views/SearchSettingsRowView.java +++ b/src/com/android/launcher3/views/SearchSettingsRowView.java @@ -42,11 +42,14 @@ import java.util.ArrayList; 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 @@ public class SearchSettingsRowView extends LinearLayout implements @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 @@ public class SearchSettingsRowView extends LinearLayout implements 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 @@ public class SearchSettingsRowView extends LinearLayout implements 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 b088237034..f8a7dc08d6 100644 --- a/src/com/android/launcher3/views/SearchSliceWrapper.java +++ b/src/com/android/launcher3/views/SearchSliceWrapper.java @@ -17,7 +17,6 @@ package com.android.launcher3.views; import android.content.Context; import android.net.Uri; -import android.os.Bundle; import android.util.Log; import androidx.annotation.NonNull; @@ -38,6 +37,8 @@ import com.android.systemui.plugins.shared.SearchTargetEvent; */ 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 @@ public class SearchSliceWrapper implements SliceView.OnSliceActionListener { 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 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 @@ public class SearchSliceWrapper implements SliceView.OnSliceActionListener { @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 21212327b6..d11b1ef8bd 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 @@ import com.android.systemui.plugins.shared.SearchTargetEvent; 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 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp } 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 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp 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 3f0dc39cc1..2c7972e908 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 @@ import java.util.List; */ public class SearchTarget implements Comparable { + 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 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 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 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 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 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 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 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 5016abc1e9..290fe54a27 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); + } + } + }