Track search results with position and search Identifier

Bug: 169087008
Test: Manual
Change-Id: I54c74093b90e5aea03a7810f55fcc32f0ddf8dda
This commit is contained in:
Samuel Fufa 2020-09-22 20:52:45 -07:00
parent 2508239d1e
commit f01064953b
12 changed files with 141 additions and 36 deletions

View File

@ -200,6 +200,7 @@ public class AllAppsGridAdapter extends
*/
public static class AdapterItemWithPayload<T> 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<Uri> item =
AdapterItemWithPayload<Uri> slicePayload =
(AdapterItemWithPayload<Uri>) 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<Slice> liveData = SliceLiveData.fromUri(mLauncher, item.getPayload());
LiveData<Slice> 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

View File

@ -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
*/
void applyAdapterInfo(AdapterItemWithPayload<T> adapterItemWithPayload);
default void setup(AdapterItemWithPayload<T> adapterItemWithPayload) {
Object[] targetInfo = getTargetInfo();
if (targetInfo != null) {
targetInfo[0] = adapterItemWithPayload.getSearchSessionId();
targetInfo[1] = adapterItemWithPayload.position;
}
applyAdapterInfo(adapterItemWithPayload);
}
void applyAdapterInfo(AdapterItemWithPayload<T> 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);
}
}
}

View File

@ -61,6 +61,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource,
PayloadResultHandler<List<Pair<ShortcutInfo, ItemInfoWithIcon>>> {
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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -52,4 +52,9 @@ public class SearchSectionHeaderView extends TextView implements
setVisibility(INVISIBLE);
}
}
@Override
public Object[] getTargetInfo() {
return null;
}
}

View File

@ -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);

View File

@ -39,8 +39,10 @@ import com.android.systemui.plugins.shared.SearchTargetEvent;
public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView
implements AllAppsSearchBarController.PayloadResultHandler<Bundle> {
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<Bundle> 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;
}
}

View File

@ -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);

View File

@ -122,6 +122,7 @@ public class SearchTarget implements Comparable<SearchTarget> {
public List<ShortcutInfo> 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<SearchTarget> {
*
*/
public SearchTarget(ItemType itemType, List<ShortcutInfo> 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

View File

@ -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;
}
}