Merge "Fix missing grid for devices that upgrade from R" into sc-dev
diff --git a/quickstep/res/layout/search_result_suggest.xml b/quickstep/res/layout/search_result_suggest.xml
deleted file mode 100644
index eb5313c..0000000
--- a/quickstep/res/layout/search_result_suggest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.search.SearchResultSuggestion xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto"
- style="@style/BaseIcon"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="start|center_vertical"
- android:textAlignment="viewStart"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="18sp"
- android:padding="@dimen/dynamic_grid_edge_margin"
- launcher:iconDisplay="hero_app"
- android:drawableTint="?android:attr/textColorPrimary"
- launcher:customIcon="@drawable/ic_allapps_search"
- launcher:iconSizeOverride="24dp"
- launcher:matchTextInsetWithQuery="true"
- launcher:layoutHorizontal="true"
- android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding">
-
-</com.android.launcher3.search.SearchResultSuggestion>
\ No newline at end of file
diff --git a/quickstep/res/layout/search_result_thumbnail.xml b/quickstep/res/layout/search_result_thumbnail.xml
index 0f25336..5062b76 100644
--- a/quickstep/res/layout/search_result_thumbnail.xml
+++ b/quickstep/res/layout/search_result_thumbnail.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.launcher3.search.ThumbnailSearchResultView
+<com.android.launcher3.search.SearchResultThumbnailView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="125dp"
android:layout_height="125dp"/>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java b/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
index 834a624..1e6243c 100644
--- a/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
+++ b/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
@@ -18,7 +18,11 @@
import static com.android.launcher3.allapps.AllAppsGridAdapter.VIEW_TYPE_ICON;
+import android.app.search.Query;
+import android.app.search.SearchSession;
import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
+import android.util.Log;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.View;
@@ -30,7 +34,6 @@
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.config.FeatureFlags;
/**
* Provides views for on-device search results
@@ -43,12 +46,12 @@
public static final int VIEW_TYPE_SEARCH_ICON_ROW = (1 << 9);
public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11;
public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12;
- public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13;
public static final int VIEW_TYPE_SEARCH_WIDGET_LIVE = 1 << 15;
public static final int VIEW_TYPE_SEARCH_WIDGET_PREVIEW = 1 << 16;
- private final AllAppsContainerView mAppsView;
+ private static final String TAG = "SearchServiceAdapterProvider";
+ private final AllAppsContainerView mAppsView;
private final SparseIntArray mViewTypeToLayoutMap = new SparseIntArray();
public DeviceSearchAdapterProvider(Launcher launcher, AllAppsContainerView appsView) {
@@ -61,7 +64,6 @@
mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_SLICE, R.layout.search_result_slice);
mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_PEOPLE, R.layout.search_result_people_item);
mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_THUMBNAIL, R.layout.search_result_thumbnail);
- mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_SUGGEST, R.layout.search_result_suggest);
mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_WIDGET_LIVE, R.layout.search_result_widget_live);
mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_WIDGET_PREVIEW,
R.layout.search_result_widget_preview);
@@ -74,11 +76,7 @@
SearchTargetHandler
payloadResultView =
(SearchTargetHandler) holder.itemView;
- if (!FeatureFlags.USE_SEARCH_API.get()) {
- payloadResultView.applySearchTarget(item.getSearchTargetLegacy());
- } else {
- payloadResultView.applySearchTarget(item.getSearchTarget(), item.getInlineItems());
- }
+ payloadResultView.apply(item.getSearchTarget(), item.getInlineItems());
}
@Override
@@ -113,7 +111,8 @@
/**
* Determines what view type should be used to present search target.
- * Returns -1 if viewType is not found
+ * Returns -1 if viewType is not found or if required field is not present
+ * to render the viewType.
*/
public int getViewTypeForSearchTarget(SearchTarget t) {
switch (t.getLayoutType()) {
@@ -122,14 +121,20 @@
case LayoutType.ICON_SINGLE_VERTICAL_TEXT:
return VIEW_TYPE_SEARCH_ICON;
case LayoutType.ICON_SLICE:
- return VIEW_TYPE_SEARCH_SLICE;
- case LayoutType.ICON_DOUBLE_HORIZONTAL_TEXT_BUTTON:
+ if (t.getSliceUri() != null) {
+ return VIEW_TYPE_SEARCH_SLICE;
+ }
+ Log.w(TAG, "Dropping as LayoutType.ICON_SLICE target doesn't contain sliceUri.");
case LayoutType.ICON_DOUBLE_HORIZONTAL_TEXT:
case LayoutType.ICON_SINGLE_HORIZONTAL_TEXT:
return VIEW_TYPE_SEARCH_ICON_ROW;
- default:
- return -1;
-
+ case LayoutType.THUMBNAIL:
+ if (t.getSearchAction() != null) {
+ return VIEW_TYPE_SEARCH_THUMBNAIL;
+ }
+ Log.w(TAG, "Dropping as LayoutType.THUMBNAIL target doesn't contain searchAction.");
}
+
+ return -1;
}
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
index 01b1999..0eb3edb 100644
--- a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
+++ b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
@@ -20,7 +20,6 @@
import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_ICON_ROW;
import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_PEOPLE;
import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_SLICE;
-import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_SUGGEST;
import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_THUMBNAIL;
import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_WIDGET_LIVE;
import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_WIDGET_PREVIEW;
@@ -45,15 +44,13 @@
private static final int AVAILABLE_FOR_ACCESSIBILITY =
VIEW_TYPE_SEARCH_SLICE | VIEW_TYPE_SEARCH_PEOPLE | VIEW_TYPE_SEARCH_THUMBNAIL
| VIEW_TYPE_SEARCH_ICON_ROW | VIEW_TYPE_SEARCH_ICON
- | VIEW_TYPE_SEARCH_WIDGET_PREVIEW | VIEW_TYPE_SEARCH_WIDGET_LIVE
- | VIEW_TYPE_SEARCH_SUGGEST;
+ | VIEW_TYPE_SEARCH_WIDGET_PREVIEW | VIEW_TYPE_SEARCH_WIDGET_LIVE;
public SearchAdapterItem(SearchTargetLegacy searchTargetLegacy, int type) {
mSearchTargetLegacy = searchTargetLegacy;
viewType = type;
}
-
public SearchAdapterItem(SearchTarget searchTarget, int type) {
mSearchTarget = searchTarget;
viewType = type;
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
index 0b8d3cb..3d89ac5 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
@@ -15,11 +15,18 @@
*/
package com.android.launcher3.search;
+import static com.android.launcher3.model.data.SearchActionItemInfo.FLAG_BADGE_FROM_ICON;
+import static com.android.launcher3.model.data.SearchActionItemInfo.FLAG_PRIMARY_ICON_FROM_TITLE;
+import static com.android.launcher3.search.SearchTargetUtil.BUNDLE_EXTRA_BADGE_FROM_ICON;
+import static com.android.launcher3.search.SearchTargetUtil.BUNDLE_EXTRA_PRIMARY_ICON_FROM_TITLE;
+import static com.android.launcher3.search.SearchTargetUtil.BUNDLE_EXTRA_SHOULD_START;
+import static com.android.launcher3.search.SearchTargetUtil.BUNDLE_EXTRA_SHOULD_START_FOR_RESULT;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.app.search.SearchAction;
import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ShortcutInfo;
@@ -37,12 +44,14 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.allapps.AllAppsStore;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.model.data.SearchActionItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.ComponentKey;
@@ -52,17 +61,14 @@
/**
* A {@link BubbleTextView} representing a single cell result in AllApps
*/
-public class SearchResultIcon extends BubbleTextView implements
- SearchTargetHandler, View.OnClickListener,
- View.OnLongClickListener {
-
- private static final String BUNDLE_EXTRA_SHOULD_START = "should_start";
- private static final String BUNDLE_EXTRA_SHOULD_START_FOR_RESULT = "should_start_for_result";
+public class SearchResultIcon extends BubbleTextView implements SearchTargetHandler {
private final Launcher mLauncher;
+ private String mTargetId;
private Consumer<ItemInfoWithIcon> mOnItemInfoChanged;
+
public SearchResultIcon(Context context) {
this(context, null, 0);
}
@@ -96,34 +102,34 @@
public void applySearchTarget(SearchTarget searchTarget, List<SearchTarget> inlineItems,
Consumer<ItemInfoWithIcon> cb) {
mOnItemInfoChanged = cb;
- applySearchTarget(searchTarget, inlineItems);
+ apply(searchTarget, inlineItems);
}
@Override
- public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
- switch (parentTarget.getResultType()) {
- case ResultType.APPLICATION:
- prepareUsingApp(new ComponentName(parentTarget.getPackageName(),
- parentTarget.getExtras().getString("class")), parentTarget.getUserHandle());
- mLongPressSupported = true;
- break;
- case ResultType.SHORTCUT:
- prepareUsingShortcutInfo(parentTarget.getShortcutInfo());
- mLongPressSupported = true;
- break;
- default:
- prepareUsingSearchAction(parentTarget);
- mLongPressSupported = false;
- break;
+ public void apply(SearchTarget parentTarget, List<SearchTarget> children) {
+ mTargetId = parentTarget.getId();
+ if (parentTarget.getShortcutInfo() != null) {
+ prepareUsingShortcutInfo(parentTarget.getShortcutInfo());
+ mLongPressSupported = true;
+ } else if (parentTarget.getSearchAction() != null) {
+ prepareUsingSearchAction(parentTarget);
+ mLongPressSupported = false;
+ } else {
+ prepareUsingApp(new ComponentName(parentTarget.getPackageName(),
+ parentTarget.getExtras().getString(SearchTargetUtil.EXTRA_CLASS)),
+ parentTarget.getUserHandle());
+ mLongPressSupported = true;
}
}
private void prepareUsingSearchAction(SearchTarget searchTarget) {
SearchAction searchAction = searchTarget.getSearchAction();
Bundle extras = searchAction.getExtras();
+
SearchActionItemInfo itemInfo = new SearchActionItemInfo(searchAction.getIcon(),
searchTarget.getPackageName(), searchTarget.getUserHandle(),
- searchAction.getTitle());
+ searchAction.getTitle()
+ );
itemInfo.setIntent(searchAction.getIntent());
itemInfo.setPendingIntent(searchAction.getPendingIntent());
@@ -136,7 +142,12 @@
} else if (extras != null && extras.getBoolean(BUNDLE_EXTRA_SHOULD_START)) {
itemInfo.setFlags(SearchActionItemInfo.FLAG_SHOULD_START);
}
-
+ if (extras != null && extras.getBoolean(BUNDLE_EXTRA_BADGE_FROM_ICON)) {
+ itemInfo.setFlags(FLAG_BADGE_FROM_ICON);
+ }
+ if (extras != null && extras.getBoolean(BUNDLE_EXTRA_PRIMARY_ICON_FROM_TITLE)) {
+ itemInfo.setFlags(FLAG_PRIMARY_ICON_FROM_TITLE);
+ }
notifyItemInfoChanged(itemInfo);
LauncherAppState appState = LauncherAppState.getInstance(mLauncher);
@@ -144,17 +155,33 @@
try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
Icon icon = searchTarget.getSearchAction().getIcon();
Drawable d;
+ // This bitmapInfo can be used as main icon or as a badge
+ BitmapInfo bitmapInfo;
if (icon == null) {
PackageItemInfo pkgInfo = new PackageItemInfo(searchTarget.getPackageName());
pkgInfo.user = searchTarget.getUserHandle();
appState.getIconCache().getTitleAndIconForApp(pkgInfo, false);
- itemInfo.bitmap = pkgInfo.bitmap;
+ bitmapInfo = pkgInfo.bitmap;
} else {
d = itemInfo.getIcon().loadDrawable(getContext());
- itemInfo.bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
+ bitmapInfo = li.createBadgedIconBitmap(d, itemInfo.user,
Build.VERSION.SDK_INT);
}
+ BitmapInfo bitmapMainIcon;
+ if (itemInfo.hasFlags(FLAG_PRIMARY_ICON_FROM_TITLE)) {
+ bitmapMainIcon = li.createIconBitmap(
+ String.valueOf(itemInfo.title.charAt(0)),
+ bitmapInfo.color);
+ } else {
+ bitmapMainIcon = bitmapInfo;
+ }
+ if (itemInfo.hasFlags(FLAG_BADGE_FROM_ICON)) {
+ itemInfo.bitmap = li.badgeBitmap(bitmapMainIcon.icon, bitmapInfo);
+ } else {
+ itemInfo.bitmap = bitmapInfo;
+ }
+
}
MAIN_EXECUTOR.post(() -> applyFromSearchActionItemInfo(itemInfo));
});
@@ -185,26 +212,28 @@
@Override
public boolean quickSelect() {
- //TODO: event reporting
this.performClick();
+ notifyEvent(mLauncher, mTargetId, SearchTargetEvent.ACTION_LAUNCH_KEYBOARD_FOCUS);
return true;
}
@Override
public void onClick(View view) {
- //TODO: event reporting
- mLauncher.getItemOnClickListener().onClick(this);
+ ItemClickHandler.INSTANCE.onClick(view);
+ notifyEvent(mLauncher, mTargetId, SearchTargetEvent.ACTION_LAUNCH_TOUCH);
}
@Override
public boolean onLongClick(View view) {
- //TODO: event reporting
if (!mLongPressSupported) {
return false;
}
+ notifyEvent(mLauncher, mTargetId, SearchTargetEvent.ACTION_LONGPRESS);
return ItemLongClickListener.INSTANCE_ALL_APPS.onLongClick(this);
}
+
+
private void notifyItemInfoChanged(ItemInfoWithIcon itemInfoWithIcon) {
if (mOnItemInfoChanged != null) {
mOnItemInfoChanged.accept(itemInfoWithIcon);
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java b/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
index 4fb668e..66214f3 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
@@ -23,6 +23,7 @@
import android.content.pm.ShortcutInfo;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -92,6 +93,7 @@
mInlineIcons[1] = findViewById(R.id.shortcut_1);
for (SearchResultIcon inlineIcon : mInlineIcons) {
inlineIcon.getLayoutParams().width = getIconSize();
+ // TODO: inlineIcon.setOnClickListener();
}
setOnClickListener(mResultIcon);
@@ -99,7 +101,7 @@
}
@Override
- public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ public void apply(SearchTarget parentTarget, List<SearchTarget> children) {
mResultIcon.applySearchTarget(parentTarget, children, this::onItemInfoCreated);
if (parentTarget.getShortcutInfo() != null) {
updateWithShortcutInfo(parentTarget.getShortcutInfo());
@@ -127,7 +129,6 @@
});
}
-
protected void showSubtitleIfNeeded(CharSequence subTitle) {
if (!TextUtils.isEmpty(subTitle)) {
mSubTitleView.setText(subTitle);
@@ -137,11 +138,10 @@
}
}
-
protected void showInlineItems(List<SearchTarget> children) {
for (int i = 0; i < MAX_INLINE_ITEMS; i++) {
if (i < children.size()) {
- mInlineIcons[i].applySearchTarget(children.get(0), new ArrayList<>());
+ mInlineIcons[i].apply(children.get(0), new ArrayList<>());
mInlineIcons[i].setVisibility(VISIBLE);
} else {
mInlineIcons[i].setVisibility(GONE);
@@ -153,4 +153,15 @@
setTag(info);
mTitleView.setText(info.title);
}
+
+ @Override
+ public void onClick(View view) {
+ // do nothing.
+ }
+
+ @Override
+ public boolean onLongClick(View view) {
+ // do nothing.
+ return false;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java b/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java
index e6c952f..f6e5eba 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java
@@ -18,10 +18,11 @@
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
import android.content.Context;
-import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.View;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
@@ -36,7 +37,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
import java.util.ArrayList;
import java.util.List;
@@ -44,17 +44,17 @@
/**
* A slice view wrapper with settings app icon at start
*/
-public class SearchResultIconSlice extends LinearLayout implements
- SearchTargetHandler, SliceView.OnSliceActionListener {
+public class SearchResultIconSlice extends LinearLayout implements SearchTargetHandler,
+ SliceView.OnSliceActionListener {
private static final String TAG = "SearchSliceController";
- private static final String URI_EXTRA_KEY = "slice_uri";
+
+ private final Launcher mLauncher;
private SliceView mSliceView;
private SearchResultIcon mIcon;
private LiveData<Slice> mSliceLiveData;
- private SearchTargetLegacy mSearchTarget;
- private final Launcher mLauncher;
+ private String mTargetId;
public SearchResultIconSlice(Context context) {
this(context, null, 0);
@@ -83,7 +83,8 @@
}
@Override
- public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ public void apply(SearchTarget parentTarget, List<SearchTarget> children) {
+ mTargetId = parentTarget.getId();
reset();
updateIcon(parentTarget, children);
try {
@@ -97,7 +98,7 @@
private void updateIcon(SearchTarget parentTarget, List<SearchTarget> children) {
if (children.size() == 1) {
- mIcon.applySearchTarget(children.get(0), new ArrayList<>());
+ mIcon.apply(children.get(0), new ArrayList<>());
} else {
LauncherAppState appState = LauncherAppState.getInstance(getContext());
MODEL_EXECUTOR.post(() -> {
@@ -121,7 +122,6 @@
reset();
}
-
private void reset() {
mSliceView.setOnSliceActionListener(null);
if (mSliceLiveData != null) {
@@ -131,11 +131,17 @@
@Override
public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
- //TODO: event reporting
+ notifyEvent(mLauncher, mTargetId, SearchTargetEvent.ACTION_TAP);
}
- private Uri getSliceUri() {
- return mSearchTarget.getExtras().getParcelable(URI_EXTRA_KEY);
+ @Override
+ public void onClick(View view) {
+ notifyEvent(mLauncher, mTargetId, SearchTargetEvent.ACTION_LONGPRESS);
}
+ @Override
+ public boolean onLongClick(View view) {
+ // do nothing
+ return false;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java b/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java
index f3355da..99e6aa5 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import android.app.search.SearchTargetEvent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -51,8 +52,7 @@
/**
* A view representing a single people search result in all apps
*/
-public class SearchResultPeopleView extends LinearLayout implements
- SearchTargetHandler {
+public class SearchResultPeopleView extends LinearLayout implements SearchTargetHandler {
public static final String TARGET_TYPE_PEOPLE = "people";
@@ -64,7 +64,6 @@
private ImageButton[] mProviderButtons = new ImageButton[3];
private Intent mIntent;
-
private SearchTargetLegacy mSearchTarget;
public SearchResultPeopleView(Context context) {
@@ -100,6 +99,7 @@
}
}
+ /*
@Override
public void applySearchTarget(SearchTargetLegacy searchTarget) {
mSearchTarget = searchTarget;
@@ -136,6 +136,7 @@
}
}
}
+ */
/**
* Normalizes the bitmap to look like rounded App Icon
@@ -184,4 +185,15 @@
bundle.putBundle("provider", provider);
});
}
+
+ @Override
+ public void onClick(View view) {
+ // do nothing.
+ }
+
+ @Override
+ public boolean onLongClick(View view) {
+ // do nothing.
+ return false;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultSuggestion.java b/quickstep/src/com/android/launcher3/search/SearchResultSuggestion.java
deleted file mode 100644
index 6a6bd1b..0000000
--- a/quickstep/src/com/android/launcher3/search/SearchResultSuggestion.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.search;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-
-import com.android.launcher3.R;
-import com.android.launcher3.views.BaseDragLayer;
-
-/**
- * {@link SearchResultIconRow} with custom drawable resource
- */
-public class SearchResultSuggestion extends SearchResultIcon {
-
- public static final String TARGET_TYPE_SUGGEST = "suggest";
- private final Drawable mCustomIcon;
-
- public SearchResultSuggestion(Context context) {
- this(context, null, 0);
- }
-
- public SearchResultSuggestion(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public SearchResultSuggestion(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.SearchResultSuggestion, defStyle, 0);
- mCustomIcon = a.getDrawable(R.styleable.SearchResultSuggestion_customIcon);
- a.recycle();
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- ViewGroup.LayoutParams lp = getLayoutParams();
- lp.height = BaseDragLayer.LayoutParams.WRAP_CONTENT;
- }
-
- @Override
- protected void setIcon(Drawable icon) {
- super.setIcon(mCustomIcon);
- }
-}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultThumbnailView.java b/quickstep/src/com/android/launcher3/search/SearchResultThumbnailView.java
new file mode 100644
index 0000000..b1cbe7d
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/search/SearchResultThumbnailView.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.search;
+
+
+import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.model.data.SearchActionItemInfo;
+import com.android.launcher3.touch.ItemClickHandler;
+import com.android.launcher3.util.Themes;
+
+import java.util.List;
+
+/**
+ * A view representing a high confidence app search result that includes shortcuts
+ */
+public class SearchResultThumbnailView extends androidx.appcompat.widget.AppCompatImageView
+ implements SearchTargetHandler {
+
+ private SearchTarget mSearchTarget;
+ private SearchResultIcon mResultIcon;
+
+ public SearchResultThumbnailView(Context context) {
+ super(context);
+ }
+
+ public SearchResultThumbnailView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SearchResultThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public void apply(SearchTarget parentTarget, List<SearchTarget> children) {
+ mSearchTarget = parentTarget;
+ Bitmap bitmap;
+
+ SearchActionItemInfo itemInfo = new SearchActionItemInfo(
+ parentTarget.getSearchAction().getIcon(),
+ parentTarget.getPackageName(),
+ parentTarget.getUserHandle(),
+ parentTarget.getSearchAction().getTitle());
+ bitmap = ((BitmapDrawable) itemInfo.getIcon()
+ .loadDrawable(getContext())).getBitmap();
+ // crop
+ if (bitmap.getWidth() < bitmap.getHeight()) {
+ bitmap = Bitmap.createBitmap(bitmap, 0,
+ bitmap.getHeight() / 2 - bitmap.getWidth() / 2,
+ bitmap.getWidth(), bitmap.getWidth());
+ } else {
+ bitmap = Bitmap.createBitmap(bitmap, bitmap.getWidth() / 2 - bitmap.getHeight() / 2,
+ 0,
+ bitmap.getHeight(), bitmap.getHeight());
+ }
+ setTag(itemInfo);
+
+ RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, bitmap);
+ drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext()));
+ setImageDrawable(drawable);
+ }
+
+ @Override
+ public void onClick(View view) {
+ ItemClickHandler.onClickSearchAction(Launcher.getLauncher(getContext()),
+ (SearchActionItemInfo) view.getTag());
+ notifyEvent(getContext(), mSearchTarget.getId(), SearchTargetEvent.ACTION_LAUNCH_TOUCH);
+ }
+
+ @Override
+ public boolean onLongClick(View view) {
+ // do nothing.
+ return false;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultWidget.java b/quickstep/src/com/android/launcher3/search/SearchResultWidget.java
index c6bdb68..69da515 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultWidget.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultWidget.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.search;
+import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
@@ -28,22 +30,19 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.AppWidgetResizeFrame;
import com.android.launcher3.CheckLongPressHelper;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.search.SearchWidgetInfoContainer;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.touch.ItemLongClickListener;
-import com.android.launcher3.widget.PendingAddWidgetInfo;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
/**
* displays live version of a widget upon receiving {@link AppWidgetProviderInfo} from Search
* provider
*/
public class SearchResultWidget extends RelativeLayout implements
- SearchTargetHandler, DraggableView, View.OnLongClickListener {
+ SearchTargetHandler, DraggableView {
private static final String TAG = "SearchResultWidget";
@@ -57,7 +56,7 @@
private final AppWidgetHostView mHostView;
private final float mScaleToFit;
- private SearchTargetLegacy mSearchTarget;
+ private SearchTarget mSearchTarget;
private AppWidgetProviderInfo mProviderInfo;
private SearchWidgetInfoContainer mInfoContainer;
@@ -81,9 +80,7 @@
// detect tap event on widget container for search target event reporting
mClickDetector = new GestureDetector(context,
- new ClickListener(() -> {
- }));
-
+ new ClickListener(() -> handleSelection(SearchTargetEvent.ACTION_LAUNCH_TOUCH)));
mLongPressHelper = new CheckLongPressHelper(this);
mLongPressHelper.setLongPressTimeoutFactor(1);
setOnLongClickListener(this);
@@ -95,40 +92,6 @@
addView(mHostView);
}
- @Override
- public void applySearchTarget(SearchTargetLegacy searchTarget) {
- if (searchTarget.getExtras() == null
- || searchTarget.getExtras().getParcelable("provider") == null) {
- setVisibility(GONE);
- return;
- }
- AppWidgetProviderInfo providerInfo = searchTarget.getExtras().getParcelable("provider");
- if (mProviderInfo != null && providerInfo.provider.equals(mProviderInfo.provider)
- && providerInfo.getProfile().equals(mProviderInfo.getProfile())) {
- return;
- }
- removeListener();
-
- mSearchTarget = searchTarget;
- mProviderInfo = providerInfo;
-
- mInfoContainer = mLauncher.getLiveSearchManager().getPlaceHolderWidget(providerInfo);
- if (mInfoContainer == null) {
- setVisibility(GONE);
- return;
- }
- setVisibility(VISIBLE);
- mInfoContainer.attachWidget(mHostView);
- PendingAddWidgetInfo info = (PendingAddWidgetInfo) mHostView.getTag();
- int[] size = mLauncher.getWorkspace().estimateItemSize(info);
- mHostView.getLayoutParams().width = size[0];
- mHostView.getLayoutParams().height = size[1];
- AppWidgetResizeFrame.updateWidgetSizeRanges(mHostView, mLauncher, info.spanX,
- info.spanY);
- mHostView.requestLayout();
- setTag(info);
- }
-
/**
* Stops hostView from getting updates on a widget provider
*/
@@ -138,6 +101,11 @@
}
}
+ public void handleSelection(int eventType) {
+ SearchSessionTracker.INSTANCE.get(getContext()).notifyEvent(
+ new SearchTargetEvent.Builder("search target id", eventType).build());
+ }
+
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
mLongPressHelper.onTouchEvent(ev);
@@ -179,6 +147,11 @@
return false;
}
+ @Override
+ public void onClick(View view) {
+ // do nothing.
+ }
+
static class ClickListener extends GestureDetector.SimpleOnGestureListener {
private final Runnable mCb;
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java b/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java
index 22f0b76..c9fc8e1 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.Point;
@@ -39,22 +41,20 @@
import com.android.launcher3.widget.PendingItemDragHelper;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.WidgetImageView;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
+
+import java.util.List;
/**
* displays preview of a widget upon receiving {@link AppWidgetProviderInfo} from Search provider
*/
-public class SearchResultWidgetPreview extends LinearLayout implements
- SearchTargetHandler, View.OnLongClickListener,
- View.OnClickListener {
+public class SearchResultWidgetPreview extends LinearLayout implements SearchTargetHandler {
- public static final String TARGET_TYPE_WIDGET_PREVIEW = "widget_preview";
private final Launcher mLauncher;
private final LauncherAppState mAppState;
private WidgetCell mWidgetCell;
private Toast mWidgetToast;
- private SearchTargetLegacy mSearchTarget;
+ private SearchTarget mSearchTarget;
public SearchResultWidgetPreview(Context context) {
@@ -82,14 +82,9 @@
}
@Override
- public void applySearchTarget(SearchTargetLegacy searchTarget) {
- if (searchTarget.getExtras() == null
- || searchTarget.getExtras().getParcelable("provider") == null) {
- setVisibility(GONE);
- return;
- }
- mSearchTarget = searchTarget;
- AppWidgetProviderInfo providerInfo = searchTarget.getExtras().getParcelable("provider");
+ public void apply(SearchTarget parentTarget, List<SearchTarget> children) {
+ mSearchTarget = parentTarget;
+ AppWidgetProviderInfo providerInfo = parentTarget.getAppWidgetProviderInfo();
LauncherAppWidgetProviderInfo pInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(
getContext(), providerInfo);
MODEL_EXECUTOR.post(() -> {
@@ -100,7 +95,6 @@
mWidgetCell.ensurePreview();
});
});
-
}
@Override
@@ -120,11 +114,18 @@
new PendingItemDragHelper(mWidgetCell).startDrag(
imageView.getBitmapBounds(), imageView.getBitmap().getWidth(), imageView.getWidth(),
new Point(loc[0], loc[1]), mLauncher.getAppsView(), new DragOptions());
+ handleSelection(SearchTargetEvent.ACTION_LONGPRESS);
return true;
}
@Override
public void onClick(View view) {
mWidgetToast = BaseWidgetSheet.showWidgetToast(getContext(), mWidgetToast);
+ handleSelection(SearchTargetEvent.ACTION_LAUNCH_TOUCH);
+ }
+
+ public void handleSelection(int eventType) {
+ SearchSessionTracker.INSTANCE.get(getContext()).notifyEvent(
+ new SearchTargetEvent.Builder(mSearchTarget.getId(), eventType).build());
}
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
index e015122..d7c5c5d 100644
--- a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
+++ b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
@@ -18,6 +18,7 @@
import android.app.search.SearchTarget;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
@@ -27,8 +28,7 @@
/**
* Header text view that shows a title for a given section in All apps search
*/
-public class SearchSectionHeaderView extends TextView implements
- SearchTargetHandler {
+public class SearchSectionHeaderView extends TextView implements SearchTargetHandler {
public SearchSectionHeaderView(Context context) {
super(context);
@@ -44,8 +44,19 @@
}
@Override
- public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ public void apply(SearchTarget parentTarget, List<SearchTarget> children) {
setText(parentTarget.getSearchAction().getTitle());
setVisibility(VISIBLE);
}
+
+ @Override
+ public void onClick(View view) {
+ // do nothing.
+ }
+
+ @Override
+ public boolean onLongClick(View view) {
+ // do nothing.
+ return false;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchServicePipeline.java b/quickstep/src/com/android/launcher3/search/SearchServicePipeline.java
index 6585213..197aecb 100644
--- a/quickstep/src/com/android/launcher3/search/SearchServicePipeline.java
+++ b/quickstep/src/com/android/launcher3/search/SearchServicePipeline.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.search;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
import android.app.search.Query;
import android.app.search.SearchContext;
import android.app.search.SearchSession;
@@ -27,6 +25,8 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.WorkerThread;
+
import com.android.app.search.ResultType;
import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.launcher3.allapps.AllAppsSectionDecorator;
@@ -39,6 +39,8 @@
import java.util.List;
import java.util.function.Consumer;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
/**
* Search pipeline utilizing {@link android.app.search.SearchUiManager}
*/
@@ -46,10 +48,11 @@
private static final int SUPPORTED_RESULT_TYPES =
ResultType.APPLICATION | ResultType.SHORTCUT | ResultType.PLAY | ResultType.PEOPLE
| ResultType.SETTING;
+
+ private static final boolean DEBUG = true;
private static final int REQUEST_TIMEOUT = 200;
private static final String TAG = "SearchServicePipeline";
-
private final Context mContext;
private final SearchSession mSession;
private final DeviceSearchAdapterProvider mAdapterProvider;
@@ -63,16 +66,22 @@
SearchUiManager manager = context.getSystemService(SearchUiManager.class);
mSession = manager.createSearchSession(
new SearchContext(SUPPORTED_RESULT_TYPES, REQUEST_TIMEOUT, null));
+ SearchSessionTracker.getInstance(context).setSearchSession(mSession);
}
+ @WorkerThread
@Override
public void query(String input, Consumer<ArrayList<AllAppsGridAdapter.AdapterItem>> callback,
CancellationSignal cancellationSignal) {
mCanceled = false;
Query query = new Query(input, System.currentTimeMillis(), null);
- mSession.query(query, UI_HELPER_EXECUTOR, items -> {
+ mSession.query(query, UI_HELPER_EXECUTOR, targets -> {
if (!mCanceled) {
- callback.accept(this.onResult(items));
+ if (DEBUG) {
+ printSearchTargets(input, targets);
+ }
+ SearchSessionTracker.getInstance(mContext).setQuery(query);
+ callback.accept(this.onResult(targets));
}
Log.w(TAG, "Ignoring results due to cancel signal");
});
@@ -111,6 +120,13 @@
return new ArrayList<>(adapterMap.values());
}
+ private void printSearchTargets(String query, List<SearchTarget> results) {
+ Log.d(TAG, " query=" + query + " size=" + results.size());
+ for (SearchTarget s : results) {
+ Log.d(TAG, "layoutType=" + s.getLayoutType() + " resultType=" + s.getResultType());
+ }
+ }
+
/**
* Adds a child SearchTarget to a collection of searchTarget children with a shared parentId.
* Returns false if no parent searchTarget with id=$parentId does not exists.
diff --git a/quickstep/src/com/android/launcher3/search/SearchSessionTracker.java b/quickstep/src/com/android/launcher3/search/SearchSessionTracker.java
new file mode 100644
index 0000000..3079965
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/search/SearchSessionTracker.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.search;
+
+import android.app.search.Query;
+import android.app.search.SearchSession;
+import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.util.MainThreadInitializedObject;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+/**
+ * A singleton class to track and report search events back to SearchSession
+ */
+public class SearchSessionTracker {
+
+ private static final String TAG = "SearchSessionTracker";
+
+ @Nullable
+ private SearchSession mSession;
+ private Query mQuery;
+
+ public static final MainThreadInitializedObject<SearchSessionTracker> INSTANCE =
+ new MainThreadInitializedObject<>(SearchSessionTracker::new);
+
+ private SearchSessionTracker(Context context) {
+ }
+
+ /**
+ * Returns instance of SearchSessionTracker
+ */
+ public static SearchSessionTracker getInstance(Context context) {
+ return SearchSessionTracker.INSTANCE.get(context);
+ }
+
+ @WorkerThread
+ public void setSearchSession(SearchSession session) {
+ mSession = session;
+ }
+
+ @WorkerThread
+ public void setQuery(Query query) {
+ mQuery = query;
+ }
+
+ /**
+ * Send the user event handling back to the {@link SearchSession} object.
+ */
+ public void notifyEvent(SearchTargetEvent event) {
+ if (mSession == null) {
+ Log.d(TAG, "Dropping event " + event.getTargetId());
+ }
+ Log.d(TAG, "notifyEvent:" + mQuery.getInput() + ":" + event.getTargetId());
+ UI_HELPER_EXECUTOR.post(() -> mSession.notifyEvent(mQuery, event));
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
index 67502f6..0e7b8f2 100644
--- a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
+++ b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
@@ -17,31 +17,22 @@
package com.android.launcher3.search;
import android.app.search.SearchTarget;
-
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
+import android.app.search.SearchTargetEvent;
+import android.content.Context;
+import android.view.View;
import java.util.List;
+import java.util.function.Consumer;
/**
* An interface for supporting dynamic search results
*/
-public interface SearchTargetHandler {
+public interface SearchTargetHandler extends View.OnClickListener, View.OnLongClickListener {
/**
- * Update view using values from {@link SearchTargetLegacy}
- *
- * @deprecated Use {@link SearchTargetHandler#applySearchTarget(SearchTarget, List)} instead
+ * Update view using values from {@link SearchTarget}
*/
- @Deprecated
- default void applySearchTarget(SearchTargetLegacy searchTarget) {
- }
-
-
- /**
- * Update view using values from {@link SearchTargetLegacy}
- */
- default void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
- }
+ default void apply(SearchTarget parentTarget, List<SearchTarget> children) { }
/**
* Handle IME quick select event. returns whether event was handled.
@@ -50,4 +41,8 @@
return false;
}
+ default void notifyEvent(Context context, String id, int eventType) {
+ SearchTargetEvent.Builder builder = new SearchTargetEvent.Builder(id, eventType);
+ SearchSessionTracker.getInstance(context).notifyEvent(builder.build());
+ }
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchTargetUtil.java b/quickstep/src/com/android/launcher3/search/SearchTargetUtil.java
new file mode 100644
index 0000000..ceef429
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/search/SearchTargetUtil.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.search;
+
+import android.app.PendingIntent;
+import android.app.search.SearchAction;
+import android.app.search.SearchTarget;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
+
+import com.android.app.search.ResultType;
+
+import static com.android.app.search.LayoutType.ICON_DOUBLE_HORIZONTAL_TEXT;
+import static com.android.app.search.LayoutType.ICON_SINGLE_HORIZONTAL_TEXT;
+import static com.android.app.search.LayoutType.THUMBNAIL;
+import static com.android.app.search.ResultType.ACTION;
+import static com.android.app.search.ResultType.SCREENSHOT;
+import static com.android.app.search.ResultType.SUGGEST;
+
+public class SearchTargetUtil {
+
+ public static final String BUNDLE_EXTRA_SHOULD_START = "should_start";
+ public static final String BUNDLE_EXTRA_SHOULD_START_FOR_RESULT = "should_start_for_result";
+ public static final String BUNDLE_EXTRA_BADGE_FROM_ICON = "badge_from_icon";
+ public static final String BUNDLE_EXTRA_PRIMARY_ICON_FROM_TITLE = "primary_icon_from_title";
+
+ public static final String EXTRA_CLASS = "class";
+
+ private static final String TITLE = " title: weather ";
+ private static final String SUBTITLE = " subtitle: 68 degrees ";
+ private static final String PACKAGE2 = "com.google.android.gm";
+ private static final UserHandle USERHANDLE = Process.myUserHandle();
+
+
+ /**
+ * Generate SearchTargetUtil for ICON_DOUBLE_HORIZONTAL_TEXT layout type.
+ *
+ targets.add(SearchTargetUtil.generateIconDoubleHorizontalText_SearchAction(
+ mContext, "red", Color.RED));
+ targets.add(SearchTargetUtil.generateIconDoubleHorizontalText_SearchAction(
+ mContext, "yellow", Color.YELLOW));
+ */
+ public static SearchTarget generateIconDoubleHorizontalText_SearchAction(
+ Context context, String id, int color) {
+ SearchTarget.Builder builder =
+ new SearchTarget.Builder(ACTION, ICON_DOUBLE_HORIZONTAL_TEXT, id)
+ .setPackageName(PACKAGE2) /* required */
+ .setUserHandle(USERHANDLE); /* required */
+
+ Intent intent = new Intent("com.google.android.googlequicksearchbox.GENERIC_QUERY");
+ intent.putExtra("query", "weather");
+ intent.putExtra("full_screen", false);
+ PendingIntent pendingIntent =
+ PendingIntent.getActivity(
+ context, 1, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawColor(color);
+ Icon icon = Icon.createWithAdaptiveBitmap(bitmap);
+
+ Bundle b = new Bundle();
+ b.putBoolean(BUNDLE_EXTRA_SHOULD_START_FOR_RESULT, true);
+ b.putBoolean(BUNDLE_EXTRA_BADGE_FROM_ICON, true);
+ b.putBoolean(BUNDLE_EXTRA_PRIMARY_ICON_FROM_TITLE, true);
+
+ builder.setSearchAction(new SearchAction.Builder(id, id + TITLE)
+ .setSubtitle(id + SUBTITLE)
+ .setPendingIntent(pendingIntent)
+ .setIcon(icon)
+ .setExtras(b)
+ .build());
+ return builder.build();
+ }
+
+ /**
+ * Inside SearchServicePipeline, add following samples to test the search target.
+ *
+ * targets.add(SearchTargetUtil.generateThumbnail_SearchAction("blue", Color.BLUE));
+ * targets.add(SearchTargetUtil.generateThumbnail_SearchAction("red", Color.RED));
+ * targets.add(SearchTargetUtil.generateThumbnail_SearchAction("green", Color.GREEN));
+ */
+ public static SearchTarget generateThumbnail_SearchAction(String id, int color) {
+ SearchTarget.Builder builder =
+ new SearchTarget.Builder(SCREENSHOT, THUMBNAIL, id)
+ .setPackageName(PACKAGE2) /* required */
+ .setUserHandle(USERHANDLE); /* required */
+
+
+ Intent intent = new Intent(Intent.ACTION_VIEW)
+ .setData(Uri.parse("uri blah blah"))
+ .setType("image/*")
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ Bitmap bitmap = Bitmap.createBitmap(1000, 500, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawColor(color);
+ Icon icon = Icon.createWithBitmap(bitmap);
+
+ builder.setSearchAction(new SearchAction.Builder(id, TITLE)
+ .setSubtitle(SUBTITLE)
+ .setIcon(icon)
+ .setIntent(intent)
+ .build());
+ return builder.build();
+
+ }
+
+ /**
+ *
+ * targets.add(SearchTargetUtil.generateIconHorizontalText_SearchAction(
+ * mContext, "red", Color.RED));
+ * targets.add(SearchTargetUtil.generateIconHorizontalText_SearchAction(
+ * mContext, "yellow", Color.YELLOW));
+ */
+ public static SearchTarget generateIconHorizontalText_SearchAction(
+ Context context, String id, int color) {
+ String fallbackQuery = "How to make cookie";
+ SearchTarget.Builder builder =
+ new SearchTarget.Builder(SUGGEST, ICON_SINGLE_HORIZONTAL_TEXT, id)
+ .setPackageName(PACKAGE2) /* required */
+ .setUserHandle(USERHANDLE); /* required */
+
+ Intent intent3 = new Intent("com.google.android.googlequicksearchbox.GENERIC_QUERY");
+ intent3.putExtra("query", fallbackQuery);
+ intent3.putExtra("full_screen", false);
+ PendingIntent pendingIntent3 =
+ PendingIntent.getActivity(
+ context, 1, intent3,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawColor(color);
+ Icon icon = Icon.createWithAdaptiveBitmap(bitmap);
+
+ Bundle extra = new Bundle();
+ extra.putBoolean(BUNDLE_EXTRA_SHOULD_START_FOR_RESULT, true);
+
+ SearchAction searchAction = new SearchAction.Builder(id, fallbackQuery)
+ .setPendingIntent(pendingIntent3)
+ .setIcon(icon)
+ .setExtras(extra)
+ .build();
+ return builder.setSearchAction(searchAction).build();
+ }
+
+
+ /**
+ * Generate SearchTargetUtil for ICON_DOUBLE_HORIZONTAL_TEXT layout type.
+ */
+ public static SearchTarget generateIconDoubleHorizontalText_ShortcutInfo(Context context) {
+ String id = "23456";
+ SearchTarget.Builder builder =
+ new SearchTarget.Builder(ResultType.SHORTCUT, ICON_DOUBLE_HORIZONTAL_TEXT, id)
+ .setPackageName("com.google.android.gm") /* required */
+ .setUserHandle(UserHandle.CURRENT); /* required */
+
+ builder.setShortcutInfo(new ShortcutInfo.Builder(context, id).build());
+ return builder.build();
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/search/ThumbnailSearchResultView.java b/quickstep/src/com/android/launcher3/search/ThumbnailSearchResultView.java
deleted file mode 100644
index 7108d63..0000000
--- a/quickstep/src/com/android/launcher3/search/ThumbnailSearchResultView.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.search;
-
-
-import android.app.search.SearchTarget;
-import android.content.Context;
-import android.util.AttributeSet;
-
-import java.util.List;
-
-/**
- * A view representing a high confidence app search result that includes shortcuts
- */
-public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView
- implements SearchTargetHandler {
-
- public ThumbnailSearchResultView(Context context) {
- super(context);
- }
-
- public ThumbnailSearchResultView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public ThumbnailSearchResultView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- @Override
- public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
-
- }
-}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index d648dd6..13b7d8d 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -970,6 +970,9 @@
}
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
}
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ mRecentsView.getRunningTaskView().setIsClickableAsLiveTile(false);
+ }
}
// Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
@@ -1447,6 +1450,7 @@
private void finishCurrentTransitionToRecents() {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
+ mRecentsView.getRunningTaskView().setIsClickableAsLiveTile(true);
} else if (!hasTargets() || mRecentsAnimationController == null) {
// If there are no targets or the animation not started, then there is nothing to finish
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index b791d29..e8f590f 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -257,6 +257,8 @@
private final float[] mIconCenterCoords = new float[2];
private final float[] mChipCenterCoords = new float[2];
+ private boolean mIsClickableAsLiveTile = true;
+
public TaskView(Context context) {
this(context, null);
}
@@ -273,6 +275,11 @@
return;
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
+ if (!mIsClickableAsLiveTile) {
+ return;
+ }
+
+ mIsClickableAsLiveTile = false;
RecentsView recentsView = getRecentsView();
RemoteAnimationTargets targets = recentsView.getLiveTileParams().getTargetSet();
recentsView.getLiveTileTaskViewSimulator().setDrawsBelowRecents(false);
@@ -289,6 +296,7 @@
public void onAnimationEnd(Animator animator) {
recentsView.getLiveTileTaskViewSimulator().setDrawsBelowRecents(true);
recentsView.finishRecentsAnimation(false, null);
+ mIsClickableAsLiveTile = true;
}
});
anim.start();
@@ -348,6 +356,10 @@
return false;
}
+ public void setIsClickableAsLiveTile(boolean isClickableAsLiveTile) {
+ mIsClickableAsLiveTile = isClickableAsLiveTile;
+ }
+
private void computeAndSetIconTouchDelegate() {
float iconHalfSize = mIconView.getWidth() / 2f;
mIconCenterCoords[0] = mIconCenterCoords[1] = iconHalfSize;
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 067cf7f..dc7182f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -31,7 +31,7 @@
<style name="LauncherTheme" parent="@style/BaseLauncherTheme">
<item name="android:textColorSecondary">#DE000000</item>
- <item name="allAppsScrimColor">#FFFFFFFF</item>
+ <item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
<item name="allAppsInterimScrimAlpha">46</item>
<item name="allAppsNavBarScrimColor">#66FFFFFF</item>
<item name="allAppsTheme">@style/AllAppsTheme</item>
@@ -47,9 +47,9 @@
<item name="workspaceStatusBarScrim">@drawable/workspace_bg</item>
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
<item name="folderDotColor">?android:attr/colorPrimary</item>
- <item name="folderFillColor">#CDFFFFFF</item>
+ <item name="folderFillColor">?android:attr/colorBackground</item>
<item name="folderIconBorderColor">?android:attr/colorPrimary</item>
- <item name="folderTextColor">#FF212121</item>
+ <item name="folderTextColor">?android:attr/textColorPrimary</item>
<item name="folderHintColor">#89616161</item>
<item name="loadingIconColor">#CCFFFFFF</item>
<item name="iconOnlyShortcutColor">?android:attr/textColorSecondary</item>
@@ -94,7 +94,7 @@
<item name="android:textColorHint">#A0FFFFFF</item>
<item name="android:colorControlHighlight">#A0FFFFFF</item>
<item name="android:colorPrimary">#FF212121</item>
- <item name="allAppsScrimColor">#FF000000</item>
+ <item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
<item name="allAppsInterimScrimAlpha">102</item>
<item name="allAppsNavBarScrimColor">#80000000</item>
<item name="allAppsTheme">@style/AllAppsTheme.Dark</item>
@@ -102,10 +102,10 @@
<item name="popupColorSecondary">#202124</item>
<item name="popupColorTertiary">#757575</item> <!-- Gray 600 -->
<item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
- <item name="folderDotColor">#FF464646</item>
- <item name="folderFillColor">#DD3C4043</item> <!-- 87% GM2 800 -->
- <item name="folderIconBorderColor">#FF80868B</item>
- <item name="folderTextColor">@android:color/white</item>
+ <item name="folderDotColor">?android:attr/colorPrimary</item>
+ <item name="folderFillColor">?android:attr/colorBackground</item>
+ <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
+ <item name="folderTextColor">?android:attr/textColorPrimary</item>
<item name="folderHintColor">#89CCCCCC</item>
<item name="isMainColorDark">true</item>
<item name="loadingIconColor">#99FFFFFF</item>
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 511de30..a79ec43 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -16,7 +16,6 @@
package com.android.launcher3.allapps.search;
-
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index 1831ffd..36afe50 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -21,6 +21,8 @@
import android.os.Process;
import android.os.UserHandle;
+import androidx.annotation.Nullable;
+
/**
* Represents a SearchAction with in launcher
*/
@@ -28,9 +30,10 @@
public static final int FLAG_SHOULD_START = 1 << 1;
public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2;
+ public static final int FLAG_BADGE_FROM_ICON = 1 << 3;
+ public static final int FLAG_PRIMARY_ICON_FROM_TITLE = 1 << 4;
private final String mFallbackPackageName;
-
private int mFlags = 0;
private final Icon mIcon;
@@ -54,12 +57,15 @@
title = info.title;
}
- public void setFlags(int flags) {
- mFlags = flags;
+ /**
+ * Returns if multiple flags are all available.
+ */
+ public boolean hasFlags(int flags) {
+ return (mFlags & flags) != 0;
}
- public int getFlags() {
- return mFlags;
+ public void setFlags(int flags) {
+ mFlags |= flags ;
}
@Override
@@ -93,20 +99,13 @@
mPendingIntent = pendingIntent;
}
-
- /**
- * Returns if a flag is set on instance
- */
- public boolean hasFlag(int flag) {
- return (mFlags & flag) == flag;
+ @Nullable
+ public Icon getIcon() {
+ return mIcon;
}
@Override
public ItemInfoWithIcon clone() {
return new SearchActionItemInfo(this);
}
-
- public Icon getIcon() {
- return mIcon;
- }
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index d9483e5..3122c68 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -250,7 +250,7 @@
*/
public static void onClickSearchAction(Launcher launcher, SearchActionItemInfo itemInfo) {
if (itemInfo.getIntent() != null) {
- if (itemInfo.hasFlag(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+ if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
launcher.startActivityForResult(itemInfo.getIntent(), 0);
} else {
launcher.startActivity(itemInfo.getIntent());
@@ -258,9 +258,9 @@
} else if (itemInfo.getPendingIntent() != null) {
try {
PendingIntent pendingIntent = itemInfo.getPendingIntent();
- if (!itemInfo.hasFlag(SearchActionItemInfo.FLAG_SHOULD_START)) {
+ if (!itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START)) {
pendingIntent.send();
- } else if (itemInfo.hasFlag(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+ } else if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
launcher.startIntentSenderForResult(pendingIntent.getIntentSender(), 0, null, 0,
0, 0);
} else {