diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index 0abf84a798..f01f90be11 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -200,6 +200,7 @@ public class AllAppsGridAdapter extends */ public static class AdapterItemWithPayload extends AdapterItem { private T mPayload; + private String mSearchSessionId; private AllAppsSearchPlugin mPlugin; private IntConsumer mSelectionHandler; @@ -221,6 +222,14 @@ public class AllAppsGridAdapter extends mSelectionHandler = runnable; } + public void setSearchSessionId(String searchSessionId) { + mSearchSessionId = searchSessionId; + } + + public String getSearchSessionId() { + return mSearchSessionId; + } + public IntConsumer getSelectionHandler() { return mSelectionHandler; } @@ -228,6 +237,8 @@ public class AllAppsGridAdapter extends public T getPayload() { return mPayload; } + + } /** @@ -476,24 +487,23 @@ public class AllAppsGridAdapter extends //TODO: replace with custom TopHitBubbleTextView with support for both shortcut // and apps if (adapterItem instanceof AdapterItemWithPayload) { - AdapterItemWithPayload withPayload = (AdapterItemWithPayload) adapterItem; - IntConsumer selectionHandler = type -> { + AdapterItemWithPayload item = (AdapterItemWithPayload) adapterItem; + item.setSelectionHandler(type -> { SearchTargetEvent e = new SearchTargetEvent(SearchTarget.ItemType.APP, - type); + type, item.position, item.getSearchSessionId()); e.bundle = HeroSearchResultView.getAppBundle(info); - if (withPayload.getPlugin() != null) { - withPayload.getPlugin().notifySearchTargetEvent(e); + if (item.getPlugin() != null) { + item.getPlugin().notifySearchTargetEvent(e); } - }; + }); icon.setOnClickListener(view -> { - selectionHandler.accept(SearchTargetEvent.SELECT); + item.getSelectionHandler().accept(SearchTargetEvent.SELECT); mOnIconClickListener.onClick(view); }); icon.setOnLongClickListener(view -> { - selectionHandler.accept(SearchTargetEvent.LONG_PRESS); + item.getSelectionHandler().accept(SearchTargetEvent.SELECT); return mOnIconLongClickListener.onLongClick(view); }); - withPayload.setSelectionHandler(selectionHandler); } else { icon.setOnClickListener(mOnIconClickListener); @@ -516,20 +526,22 @@ public class AllAppsGridAdapter extends break; case VIEW_TYPE_SEARCH_SLICE: SliceView sliceView = (SliceView) holder.itemView; - AdapterItemWithPayload item = + AdapterItemWithPayload slicePayload = (AdapterItemWithPayload) mApps.getAdapterItems().get(position); sliceView.setOnSliceActionListener((info1, s) -> { - if (item.getPlugin() != null) { + if (slicePayload.getPlugin() != null) { SearchTargetEvent searchTargetEvent = new SearchTargetEvent( SearchTarget.ItemType.SETTINGS_SLICE, - SearchTargetEvent.CHILD_SELECT); + SearchTargetEvent.CHILD_SELECT, slicePayload.position, + slicePayload.getSearchSessionId()); searchTargetEvent.bundle = new Bundle(); - searchTargetEvent.bundle.putParcelable("uri", item.getPayload()); - item.getPlugin().notifySearchTargetEvent(searchTargetEvent); + searchTargetEvent.bundle.putParcelable("uri", slicePayload.getPayload()); + slicePayload.getPlugin().notifySearchTargetEvent(searchTargetEvent); } }); try { - LiveData liveData = SliceLiveData.fromUri(mLauncher, item.getPayload()); + LiveData liveData = SliceLiveData.fromUri(mLauncher, + slicePayload.getPayload()); liveData.observe((Launcher) mLauncher, sliceView); sliceView.setTag(liveData); } catch (Exception ignored) { @@ -542,9 +554,10 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_SHORTCUT: case VIEW_TYPE_SEARCH_PEOPLE: case VIEW_TYPE_SEARCH_THUMBNAIL: + AdapterItemWithPayload item = + (AdapterItemWithPayload) mApps.getAdapterItems().get(position); PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView; - payloadResultView.applyAdapterInfo( - (AdapterItemWithPayload) mApps.getAdapterItems().get(position)); + payloadResultView.setup(item); break; case VIEW_TYPE_ALL_APPS_DIVIDER: // nothing to do diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java index 3320189a1d..d7fa5bc479 100644 --- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java +++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java @@ -35,6 +35,8 @@ import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; 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; @@ -213,6 +215,44 @@ public class AllAppsSearchBarController /** * Updates View using Adapter's payload */ + + default void setup(AdapterItemWithPayload adapterItemWithPayload) { + Object[] targetInfo = getTargetInfo(); + if (targetInfo != null) { + targetInfo[0] = adapterItemWithPayload.getSearchSessionId(); + targetInfo[1] = adapterItemWithPayload.position; + } + applyAdapterInfo(adapterItemWithPayload); + } + void applyAdapterInfo(AdapterItemWithPayload adapterItemWithPayload); + + /** + * Gets object created by {@link PayloadResultHandler#createTargetInfo()} + */ + Object[] getTargetInfo(); + + /** + * 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); + } } + + } \ No newline at end of file diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java index 845c6de824..94b9ca1484 100644 --- a/src/com/android/launcher3/views/HeroSearchResultView.java +++ b/src/com/android/launcher3/views/HeroSearchResultView.java @@ -61,6 +61,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, PayloadResultHandler>> { public static final int MAX_SHORTCUTS_COUNT = 2; + private final Object[] mTargetInfo = createTargetInfo(); BubbleTextView mBubbleTextView; View mIconView; BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2]; @@ -107,7 +108,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, grid.allAppsIconSizePx)); bubbleTextView.setOnClickListener(view -> { WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) bubbleTextView.getTag(); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = getSearchTargetEvent( SearchTarget.ItemType.APP_HERO, SearchTargetEvent.CHILD_SELECT); event.bundle = getAppBundle(itemInfo); @@ -149,6 +150,11 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, adapterItem.setSelectionHandler(this::handleSelection); } + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + @Override public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) { mBubbleTextView.setVisibility(VISIBLE); @@ -184,7 +190,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, mLauncher.getWorkspace().beginDragShared(mContainer.mBubbleTextView, draggableView, mContainer, itemInfo, previewProvider, new DragOptions()); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = mContainer.getSearchTargetEvent( SearchTarget.ItemType.APP_HERO, SearchTargetEvent.LONG_PRESS); event.bundle = getAppBundle(itemInfo); if (mContainer.mPlugin != null) { @@ -201,7 +207,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivitySafely(this, itemInfo.getIntent(), itemInfo); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = getSearchTargetEvent( SearchTarget.ItemType.APP_HERO, eventType); event.bundle = getAppBundle(itemInfo); if (mPlugin != null) { diff --git a/src/com/android/launcher3/views/SearchResultPeopleView.java b/src/com/android/launcher3/views/SearchResultPeopleView.java index 6e45e88b32..eacc095188 100644 --- a/src/com/android/launcher3/views/SearchResultPeopleView.java +++ b/src/com/android/launcher3/views/SearchResultPeopleView.java @@ -67,7 +67,7 @@ public class SearchResultPeopleView extends LinearLayout implements private ImageButton[] mProviderButtons = new ImageButton[3]; private AllAppsSearchPlugin mPlugin; private Uri mContactUri; - + private final Object[] mTargetInfo = createTargetInfo(); public SearchResultPeopleView(Context context) { this(context, null, 0); @@ -129,14 +129,14 @@ public class SearchResultPeopleView extends LinearLayout implements Bundle provider = providers.get(i); Intent intent = Intent.parseUri(provider.getString("intent_uri_str"), URI_ANDROID_APP_SCHEME | URI_ALLOW_UNSAFE); - setupProviderButton(button, provider, intent); + setupProviderButton(button, provider, intent, adapterItemWithPayload); String pkg = provider.getString("package_name"); UI_HELPER_EXECUTOR.post(() -> { try { ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo( pkg, 0); Drawable appIcon = applicationInfo.loadIcon(mPackageManager); - MAIN_EXECUTOR.post(()-> button.setImageDrawable(appIcon)); + MAIN_EXECUTOR.post(() -> button.setImageDrawable(appIcon)); } catch (PackageManager.NameNotFoundException ignored) { } @@ -151,11 +151,17 @@ public class SearchResultPeopleView extends LinearLayout implements adapterItemWithPayload.setSelectionHandler(this::handleSelection); } - private void setupProviderButton(ImageButton button, Bundle provider, Intent intent) { + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + + private void setupProviderButton(ImageButton button, Bundle provider, Intent intent, + AllAppsGridAdapter.AdapterItem adapterItem) { Launcher launcher = Launcher.getLauncher(getContext()); button.setOnClickListener(b -> { launcher.startActivitySafely(b, intent, null); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( + SearchTargetEvent searchTargetEvent = getSearchTargetEvent( SearchTarget.ItemType.PEOPLE, SearchTargetEvent.CHILD_SELECT); searchTargetEvent.bundle = new Bundle(); @@ -173,8 +179,8 @@ public class SearchResultPeopleView extends LinearLayout implements Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivitySafely(this, new Intent(Intent.ACTION_VIEW, mContactUri).setFlags( Intent.FLAG_ACTIVITY_NEW_TASK), null); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( - SearchTarget.ItemType.PEOPLE, eventType); + SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.PEOPLE, + eventType); searchTargetEvent.bundle = new Bundle(); searchTargetEvent.bundle.putParcelable("contact_uri", mContactUri); if (mPlugin != null) { diff --git a/src/com/android/launcher3/views/SearchResultPlayItem.java b/src/com/android/launcher3/views/SearchResultPlayItem.java index 8624609f80..ff3ecc8bc3 100644 --- a/src/com/android/launcher3/views/SearchResultPlayItem.java +++ b/src/com/android/launcher3/views/SearchResultPlayItem.java @@ -58,6 +58,8 @@ public class SearchResultPlayItem extends LinearLayout implements private String mPackageName; private boolean mIsInstantGame; private AllAppsSearchPlugin mPlugin; + private final Object[] mTargetInfo = createTargetInfo(); + public SearchResultPlayItem(Context context) { this(context, null, 0); @@ -125,6 +127,11 @@ 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); @@ -160,7 +167,7 @@ public class SearchResultPlayItem extends LinearLayout implements } private void logSearchEvent(int eventType) { - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( + SearchTargetEvent searchTargetEvent = getSearchTargetEvent( SearchTarget.ItemType.PLAY_RESULTS, eventType); searchTargetEvent.bundle = new Bundle(); searchTargetEvent.bundle.putString("package_name", mPackageName); diff --git a/src/com/android/launcher3/views/SearchResultShortcut.java b/src/com/android/launcher3/views/SearchResultShortcut.java index 307cf34c7d..a409f0807f 100644 --- a/src/com/android/launcher3/views/SearchResultShortcut.java +++ b/src/com/android/launcher3/views/SearchResultShortcut.java @@ -50,6 +50,8 @@ public class SearchResultShortcut extends FrameLayout implements private View mIconView; private ShortcutInfo mShortcutInfo; private AllAppsSearchPlugin mPlugin; + private final Object[] mTargetInfo = createTargetInfo(); + public SearchResultShortcut(@NonNull Context context) { super(context); @@ -96,12 +98,17 @@ public class SearchResultShortcut extends FrameLayout implements adapterItemWithPayload.setSelectionHandler(this::handleSelection); } + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + private void handleSelection(int eventType) { WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) mBubbleTextView.getTag(); ItemClickHandler.onClickAppShortcut(this, itemInfo, Launcher.getLauncher(getContext())); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( - SearchTarget.ItemType.SHORTCUT, eventType); + SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.SHORTCUT, + eventType); searchTargetEvent.shortcut = mShortcutInfo; if (mPlugin != null) { mPlugin.notifySearchTargetEvent(searchTargetEvent); diff --git a/src/com/android/launcher3/views/SearchSectionHeaderView.java b/src/com/android/launcher3/views/SearchSectionHeaderView.java index d439ee3d68..0fe0a43ff5 100644 --- a/src/com/android/launcher3/views/SearchSectionHeaderView.java +++ b/src/com/android/launcher3/views/SearchSectionHeaderView.java @@ -52,4 +52,9 @@ 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 93bcee2585..a1a0172547 100644 --- a/src/com/android/launcher3/views/SearchSettingsRowView.java +++ b/src/com/android/launcher3/views/SearchSettingsRowView.java @@ -48,6 +48,8 @@ public class SearchSettingsRowView extends LinearLayout implements private TextView mBreadcrumbsView; private Intent mIntent; private AllAppsSearchPlugin mPlugin; + private final Object[] mTargetInfo = createTargetInfo(); + public SearchSettingsRowView(@NonNull Context context) { super(context); @@ -87,6 +89,11 @@ public class SearchSettingsRowView extends LinearLayout implements adapterItemWithPayload.setSelectionHandler(this::handleSelection); } + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + private void showIfAvailable(TextView view, @Nullable String string) { if (TextUtils.isEmpty(string)) { view.setVisibility(GONE); @@ -108,7 +115,7 @@ public class SearchSettingsRowView extends LinearLayout implements Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivityForResult(mIntent, 0); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( + SearchTargetEvent searchTargetEvent = getSearchTargetEvent( SearchTarget.ItemType.SETTINGS_ROW, eventType); searchTargetEvent.bundle = new Bundle(); searchTargetEvent.bundle.putParcelable("intent", mIntent); diff --git a/src/com/android/launcher3/views/ThumbnailSearchResultView.java b/src/com/android/launcher3/views/ThumbnailSearchResultView.java index decc861565..1d58a063b9 100644 --- a/src/com/android/launcher3/views/ThumbnailSearchResultView.java +++ b/src/com/android/launcher3/views/ThumbnailSearchResultView.java @@ -39,8 +39,10 @@ import com.android.systemui.plugins.shared.SearchTargetEvent; public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView implements AllAppsSearchBarController.PayloadResultHandler { + private final Object[] mTargetInfo = createTargetInfo(); Intent mIntent; AllAppsSearchPlugin mPlugin; + int mPosition; public ThumbnailSearchResultView(Context context) { super(context); @@ -58,7 +60,7 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivitySafely(this, mIntent, null); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = getSearchTargetEvent( SearchTarget.ItemType.SCREENSHOT, eventType); if (mPlugin != null) { mPlugin.notifySearchTargetEvent(event); @@ -67,6 +69,7 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp @Override public void applyAdapterInfo(AdapterItemWithPayload adapterItem) { + mPosition = adapterItem.position; RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, (Bitmap) adapterItem.getPayload().getParcelable("bitmap")); drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext())); @@ -78,4 +81,9 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp mPlugin = adapterItem.getPlugin(); adapterItem.setSelectionHandler(this::handleSelection); } + + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } } diff --git a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java index 48369a4890..aa3ab8f7e0 100644 --- a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java +++ b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java @@ -32,7 +32,7 @@ import java.util.function.Consumer; @ProvidesInterface(action = AllAppsSearchPlugin.ACTION, version = AllAppsSearchPlugin.VERSION) public interface AllAppsSearchPlugin extends Plugin { String ACTION = "com.android.systemui.action.PLUGIN_ALL_APPS_SEARCH_ACTIONS"; - int VERSION = 6; + int VERSION = 7; void setup(Activity activity, View view); diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java index 9144976f98..fb8dd723bc 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java @@ -122,6 +122,7 @@ public class SearchTarget implements Comparable { public List shortcuts; public Bundle bundle; public float score; + public String mSessionId; /** * Constructor to create the search target. Bundle is currently temporary to hold @@ -130,11 +131,12 @@ public class SearchTarget implements Comparable { * */ public SearchTarget(ItemType itemType, List shortcuts, - Bundle bundle, float score) { + Bundle bundle, float score, String sessionId) { this.type = itemType; this.shortcuts = shortcuts; this.bundle = bundle; this.score = score; + this.mSessionId = sessionId; } @Override diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java index ac4bc333c6..00a78de9af 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java @@ -31,10 +31,14 @@ public class SearchTargetEvent { public ShortcutInfo shortcut; public int eventType; public Bundle bundle; - public float score; + public int index; + public String sessionIdentifier; - public SearchTargetEvent(SearchTarget.ItemType itemType, int eventType) { + public SearchTargetEvent(SearchTarget.ItemType itemType, int eventType, int index, + String sessionId) { this.type = itemType; this.eventType = eventType; + this.index = index; + this.sessionIdentifier = sessionId; } }