diff --git a/quickstep/res/layout/search_result_icon_row.xml b/quickstep/res/layout/search_result_icon_row.xml index 81190cfc56..2119fc3425 100644 --- a/quickstep/res/layout/search_result_icon_row.xml +++ b/quickstep/res/layout/search_result_icon_row.xml @@ -57,10 +57,9 @@ style="@style/BaseIcon" android:layout_width="@dimen/deep_shortcut_icon_size" android:layout_height="match_parent" - android:layout_marginStart="4dp" - android:gravity="center" + android:gravity="start|center_vertical" launcher:iconDisplay="shortcut_popup" - android:textSize="@dimen/search_hero_inline_button_size" + android:textSize="@dimen/search_hero_subtitle_size" launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size" launcher:layoutHorizontal="false" /> @@ -69,20 +68,6 @@ style="@style/BaseIcon" android:layout_width="@dimen/deep_shortcut_icon_size" android:layout_height="match_parent" - android:layout_marginStart="4dp" - android:gravity="center" - launcher:iconDisplay="shortcut_popup" - android:textSize="@dimen/search_hero_inline_button_size" - launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size" - launcher:layoutHorizontal="false" /> - - + + + + + + + + + + + + + \ 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 acf6c150cf..02be0b94ed 100644 --- a/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java +++ b/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java @@ -41,6 +41,7 @@ public class DeviceSearchAdapterProvider extends SearchAdapterProvider { public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 7; public static final int VIEW_TYPE_SEARCH_ICON = (1 << 8) | VIEW_TYPE_ICON; 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_WIDGET_LIVE = 1 << 15; public static final int VIEW_TYPE_SEARCH_WIDGET_PREVIEW = 1 << 16; @@ -58,6 +59,7 @@ public class DeviceSearchAdapterProvider extends SearchAdapterProvider { mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_ICON, R.layout.search_result_icon); mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_ICON_ROW, R.layout.search_result_icon_row); 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_WIDGET_LIVE, R.layout.search_result_widget_live); mViewTypeToLayoutMap.put(VIEW_TYPE_SEARCH_WIDGET_PREVIEW, @@ -123,7 +125,6 @@ public class DeviceSearchAdapterProvider extends SearchAdapterProvider { break; case LayoutType.ICON_DOUBLE_HORIZONTAL_TEXT: case LayoutType.ICON_SINGLE_HORIZONTAL_TEXT: - case LayoutType.ICON_DOUBLE_HORIZONTAL_TEXT_BUTTON: return VIEW_TYPE_SEARCH_ICON_ROW; case LayoutType.THUMBNAIL: if (t.getSearchAction() != null) { diff --git a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java index b402f61979..0eb3edb555 100644 --- a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java +++ b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java @@ -18,6 +18,7 @@ package com.android.launcher3.search; import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_ICON; 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_THUMBNAIL; import static com.android.launcher3.search.DeviceSearchAdapterProvider.VIEW_TYPE_SEARCH_WIDGET_LIVE; @@ -41,10 +42,9 @@ public class SearchAdapterItem extends AllAppsGridAdapter.AdapterItem { private static final int AVAILABLE_FOR_ACCESSIBILITY = - VIEW_TYPE_SEARCH_SLICE | 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_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; public SearchAdapterItem(SearchTargetLegacy searchTargetLegacy, int type) { mSearchTargetLegacy = searchTargetLegacy; diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java index c353d7aa3c..3d89ac5e27 100644 --- a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java +++ b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java @@ -15,9 +15,12 @@ */ package com.android.launcher3.search; -import static com.android.launcher3.model.data.SearchActionItemInfo.FLAG_BADGE_WITH_PACKAGE; +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; @@ -27,14 +30,9 @@ import android.app.search.SearchTargetEvent; import android.content.ComponentName; import android.content.Context; import android.content.pm.ShortcutInfo; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; +import android.os.Build; import android.os.Bundle; import android.os.UserHandle; import android.util.AttributeSet; @@ -47,7 +45,6 @@ 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.BitmapRenderer; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; @@ -57,25 +54,14 @@ 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; -import com.android.launcher3.util.Themes; -import java.io.IOException; -import java.net.URL; -import java.net.URLConnection; import java.util.List; import java.util.function.Consumer; /** * A {@link BubbleTextView} representing a single cell result in AllApps */ -public class SearchResultIcon extends BubbleTextView implements - SearchTargetHandler, View.OnClickListener, - View.OnLongClickListener { - - //Play store thumbnail process workaround - private final Rect mTempRect = new Rect(); - private final Paint mIconPaint = new Paint(); - private static final int BITMAP_CROP_MASK_COLOR = 0xff424242; +public class SearchResultIcon extends BubbleTextView implements SearchTargetHandler { private final Launcher mLauncher; @@ -113,7 +99,7 @@ public class SearchResultIcon extends BubbleTextView implements * Applies {@link SearchTarget} to view. registers a consumer after a corresponding * {@link ItemInfoWithIcon} is created */ - public void apply(SearchTarget searchTarget, List inlineItems, + public void applySearchTarget(SearchTarget searchTarget, List inlineItems, Consumer cb) { mOnItemInfoChanged = cb; apply(searchTarget, inlineItems); @@ -129,8 +115,8 @@ public class SearchResultIcon extends BubbleTextView implements prepareUsingSearchAction(parentTarget); mLongPressSupported = false; } else { - String className = parentTarget.getExtras().getString(SearchTargetUtil.EXTRA_CLASS); - prepareUsingApp(new ComponentName(parentTarget.getPackageName(), className), + prepareUsingApp(new ComponentName(parentTarget.getPackageName(), + parentTarget.getExtras().getString(SearchTargetUtil.EXTRA_CLASS)), parentTarget.getUserHandle()); mLongPressSupported = true; } @@ -150,17 +136,14 @@ public class SearchResultIcon extends BubbleTextView implements //TODO: remove this after flags are introduced in SearchAction. Settings results require // startActivityForResult boolean isSettingsResult = searchTarget.getResultType() == ResultType.SETTING; - if ((extras != null && extras.getBoolean( - SearchTargetUtil.BUNDLE_EXTRA_SHOULD_START_FOR_RESULT)) + if ((extras != null && extras.getBoolean(BUNDLE_EXTRA_SHOULD_START_FOR_RESULT)) || isSettingsResult) { itemInfo.setFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT); - } else if (extras != null && extras.getBoolean( - SearchTargetUtil.BUNDLE_EXTRA_SHOULD_START)) { + } else if (extras != null && extras.getBoolean(BUNDLE_EXTRA_SHOULD_START)) { itemInfo.setFlags(SearchActionItemInfo.FLAG_SHOULD_START); } - if (extras != null && extras.getBoolean( - SearchTargetUtil.BUNDLE_EXTRA_BADGE_WITH_PACKAGE)) { - itemInfo.setFlags(FLAG_BADGE_WITH_PACKAGE); + 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); @@ -171,76 +154,39 @@ public class SearchResultIcon extends BubbleTextView implements MODEL_EXECUTOR.post(() -> { try (LauncherIcons li = LauncherIcons.obtain(getContext())) { Icon icon = searchTarget.getSearchAction().getIcon(); - BitmapInfo pkgBitmap = getPackageBitmap(appState, searchTarget); - if (itemInfo.hasFlags(FLAG_PRIMARY_ICON_FROM_TITLE)) { - // create a bitmap with first char if FLAG_PRIMARY_ICON_FROM_TITLE is set - itemInfo.bitmap = li.createIconBitmap(String.valueOf(itemInfo.title.charAt(0)), - pkgBitmap.color); - } else if (icon == null) { - // Use default icon from package name - itemInfo.bitmap = pkgBitmap; + 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); + bitmapInfo = pkgInfo.bitmap; } else { - boolean isPlayResult = searchTarget.getResultType() == ResultType.PLAY; - if (isPlayResult) { - Bitmap b = getPlayResultBitmap(searchAction.getIcon()); - itemInfo.bitmap = b == null - ? BitmapInfo.LOW_RES_INFO : BitmapInfo.fromBitmap(b); - } else { - itemInfo.bitmap = li.createBadgedIconBitmap(icon.loadDrawable(getContext()), - itemInfo.user, false); - } + d = itemInfo.getIcon().loadDrawable(getContext()); + bitmapInfo = li.createBadgedIconBitmap(d, itemInfo.user, + Build.VERSION.SDK_INT); } - // badge with package name - if (itemInfo.hasFlags(FLAG_BADGE_WITH_PACKAGE) && itemInfo.bitmap != pkgBitmap) { - itemInfo.bitmap = li.badgeBitmap(itemInfo.bitmap.icon, pkgBitmap); + 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)); }); } - private static BitmapInfo getPackageBitmap(LauncherAppState appState, SearchTarget target) { - PackageItemInfo pkgInfo = new PackageItemInfo(target.getPackageName()); - pkgInfo.user = target.getUserHandle(); - appState.getIconCache().getTitleAndIconForApp(pkgInfo, false); - return pkgInfo.bitmap; - } - - private Bitmap getPlayResultBitmap(Icon icon) { - try { - int iconSize = getIconSize(); - URL url = new URL(icon.getUri().toString()); - URLConnection con = url.openConnection(); - con.addRequestProperty("Cache-Control", "max-age: 0"); - con.setUseCaches(true); - Bitmap bitmap = BitmapFactory.decodeStream(con.getInputStream()); - return getRoundedBitmap(Bitmap.createScaledBitmap(bitmap, iconSize, iconSize, false)); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - private Bitmap getRoundedBitmap(Bitmap bitmap) { - final int iconSize = bitmap.getWidth(); - final float radius = Themes.getDialogCornerRadius(getContext()); - - return BitmapRenderer.createHardwareBitmap(iconSize, iconSize, (canvas) -> { - mTempRect.set(0, 0, iconSize, iconSize); - final RectF rectF = new RectF(mTempRect); - - mIconPaint.setAntiAlias(true); - mIconPaint.reset(); - canvas.drawARGB(0, 0, 0, 0); - mIconPaint.setColor(BITMAP_CROP_MASK_COLOR); - canvas.drawRoundRect(rectF, radius, radius, mIconPaint); - - mIconPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); - canvas.drawBitmap(bitmap, mTempRect, mTempRect, mIconPaint); - }); - } - private void prepareUsingApp(ComponentName componentName, UserHandle userHandle) { AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore(); AppInfo appInfo = appsStore.getApp(new ComponentKey(componentName, userHandle)); @@ -287,6 +233,7 @@ public class SearchResultIcon extends BubbleTextView implements } + 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 7c3ed69a00..eafbc73f11 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.Context; 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; @@ -43,15 +44,15 @@ import java.util.List; */ public class SearchResultIconRow extends LinearLayout implements SearchTargetHandler { - public static final int MAX_INLINE_ITEMS = 3; + public static final int MAX_INLINE_ITEMS = 2; protected final Launcher mLauncher; private final LauncherAppState mLauncherAppState; - protected SearchResultIcon mResultIcon; + private SearchResultIcon mResultIcon; private TextView mTitleView; private TextView mSubTitleView; - protected final SearchResultIcon[] mInlineIcons = new SearchResultIcon[MAX_INLINE_ITEMS]; + private final SearchResultIcon[] mInlineIcons = new SearchResultIcon[MAX_INLINE_ITEMS]; private PackageItemInfo mProviderInfo; @@ -90,9 +91,9 @@ public class SearchResultIconRow extends LinearLayout implements SearchTargetHan mInlineIcons[0] = findViewById(R.id.shortcut_0); mInlineIcons[1] = findViewById(R.id.shortcut_1); - mInlineIcons[2] = findViewById(R.id.shortcut_2); for (SearchResultIcon inlineIcon : mInlineIcons) { inlineIcon.getLayoutParams().width = getIconSize(); + // TODO: inlineIcon.setOnClickListener(); } setOnClickListener(mResultIcon); @@ -102,7 +103,7 @@ public class SearchResultIconRow extends LinearLayout implements SearchTargetHan @Override public void apply(SearchTarget parentTarget, List children) { showSubtitleIfNeeded(null); - mResultIcon.apply(parentTarget, children, this::onItemInfoCreated); + mResultIcon.applySearchTarget(parentTarget, children, this::onItemInfoCreated); if (parentTarget.getShortcutInfo() != null) { updateWithShortcutInfo(parentTarget.getShortcutInfo()); } else if (parentTarget.getSearchAction() != null) { @@ -141,7 +142,7 @@ public class SearchResultIconRow extends LinearLayout implements SearchTargetHan protected void showInlineItems(List children) { for (int i = 0; i < MAX_INLINE_ITEMS; i++) { if (i < children.size()) { - mInlineIcons[i].apply(children.get(i), new ArrayList<>()); + mInlineIcons[i].apply(children.get(0), new ArrayList<>()); mInlineIcons[i].setVisibility(VISIBLE); } else { mInlineIcons[i].setVisibility(GONE); @@ -153,4 +154,15 @@ public class SearchResultIconRow extends LinearLayout implements SearchTargetHan 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 0ea2f8b86e..f6e5eba9a3 100644 --- a/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java +++ b/quickstep/src/com/android/launcher3/search/SearchResultIconSlice.java @@ -22,6 +22,7 @@ import android.app.search.SearchTargetEvent; import android.content.Context; import android.util.AttributeSet; import android.util.Log; +import android.view.View; import android.widget.LinearLayout; import androidx.annotation.NonNull; @@ -132,4 +133,15 @@ public class SearchResultIconSlice extends LinearLayout implements SearchTargetH public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) { notifyEvent(mLauncher, mTargetId, SearchTargetEvent.ACTION_TAP); } + + @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 new file mode 100644 index 0000000000..99e6aa561c --- /dev/null +++ b/quickstep/src/com/android/launcher3/search/SearchResultPeopleView.java @@ -0,0 +1,199 @@ +/* + * 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 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; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.os.Process; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.icons.BitmapInfo; +import com.android.launcher3.icons.LauncherIcons; +import com.android.systemui.plugins.shared.SearchTargetLegacy; + +import java.util.ArrayList; + +/** + * A view representing a single people search result in all apps + */ +public class SearchResultPeopleView extends LinearLayout implements SearchTargetHandler { + + public static final String TARGET_TYPE_PEOPLE = "people"; + + private final int mIconSize; + private final int mButtonSize; + private final PackageManager mPackageManager; + private View mIconView; + private TextView mTitleView; + private ImageButton[] mProviderButtons = new ImageButton[3]; + private Intent mIntent; + + private SearchTargetLegacy mSearchTarget; + + public SearchResultPeopleView(Context context) { + this(context, null, 0); + } + + public SearchResultPeopleView(Context context, + @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public SearchResultPeopleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + DeviceProfile deviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile(); + mPackageManager = getContext().getPackageManager(); + mIconSize = deviceProfile.iconSizePx; + mButtonSize = (int) (deviceProfile.iconSizePx / 1.5f); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mIconView = findViewById(R.id.icon); + mIconView.getLayoutParams().height = mIconSize; + mIconView.getLayoutParams().width = mIconSize; + mTitleView = findViewById(R.id.title); + mProviderButtons[0] = findViewById(R.id.provider_0); + mProviderButtons[1] = findViewById(R.id.provider_1); + mProviderButtons[2] = findViewById(R.id.provider_2); + for (ImageButton button : mProviderButtons) { + button.getLayoutParams().width = mButtonSize; + button.getLayoutParams().height = mButtonSize; + } + } + + /* + @Override + public void applySearchTarget(SearchTargetLegacy searchTarget) { + mSearchTarget = searchTarget; + Bundle payload = searchTarget.getExtras(); + mTitleView.setText(payload.getString("title")); + mIntent = payload.getParcelable("intent"); + Bitmap contactIcon = payload.getParcelable("icon"); + try (LauncherIcons li = LauncherIcons.obtain(getContext())) { + BitmapInfo badgeInfo = li.createBadgedIconBitmap( + getAppIcon(mIntent.getPackage()), Process.myUserHandle(), + Build.VERSION.SDK_INT); + setIcon(li.badgeBitmap(roundBitmap(contactIcon), badgeInfo).icon, false); + } catch (Exception e) { + setIcon(contactIcon, true); + } + + ArrayList providers = payload.getParcelableArrayList("providers"); + for (int i = 0; i < mProviderButtons.length; i++) { + ImageButton button = mProviderButtons[i]; + if (providers != null && i < providers.size()) { + Bundle provider = providers.get(i); + Intent intent = provider.getParcelable("intent"); + setupProviderButton(button, provider, intent); + UI_HELPER_EXECUTOR.post(() -> { + String pkg = provider.getString("package_name"); + Drawable appIcon = getAppIcon(pkg); + if (appIcon != null) { + MAIN_EXECUTOR.post(() -> button.setImageDrawable(appIcon)); + } + }); + button.setVisibility(VISIBLE); + } else { + button.setVisibility(GONE); + } + } + } + */ + + /** + * Normalizes the bitmap to look like rounded App Icon + * TODO(b/170234747) to support styling, generate adaptive icon drawable and generate + * bitmap from it. + */ + private Bitmap roundBitmap(Bitmap icon) { + final RoundedBitmapDrawable d = RoundedBitmapDrawableFactory.create(getResources(), icon); + d.setCornerRadius(R.attr.folderIconRadius); + d.setBounds(0, 0, mIconSize, mIconSize); + final Bitmap bitmap = Bitmap.createBitmap(d.getBounds().width(), d.getBounds().height(), + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + d.draw(canvas); + return bitmap; + } + + private void setIcon(Bitmap icon, Boolean round) { + if (round) { + RoundedBitmapDrawable d = RoundedBitmapDrawableFactory.create(getResources(), icon); + d.setCornerRadius(R.attr.folderIconRadius); + d.setBounds(0, 0, mIconSize, mIconSize); + mIconView.setBackground(d); + } else { + mIconView.setBackground(new BitmapDrawable(getResources(), icon)); + } + } + + + private Drawable getAppIcon(String pkg) { + try { + ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo( + pkg, 0); + return applicationInfo.loadIcon(mPackageManager); + } catch (PackageManager.NameNotFoundException ignored) { + return null; + } + } + + private void setupProviderButton(ImageButton button, Bundle provider, Intent intent) { + Launcher launcher = Launcher.getLauncher(getContext()); + button.setOnClickListener(b -> { + launcher.startActivitySafely(b, intent, null); + Bundle bundle = new Bundle(); + 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/SearchResultThumbnailView.java b/quickstep/src/com/android/launcher3/search/SearchResultThumbnailView.java index 81e9c758a0..b1cbe7d36f 100644 --- a/quickstep/src/com/android/launcher3/search/SearchResultThumbnailView.java +++ b/quickstep/src/com/android/launcher3/search/SearchResultThumbnailView.java @@ -38,9 +38,10 @@ 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, View.OnClickListener { + implements SearchTargetHandler { private SearchTarget mSearchTarget; + private SearchResultIcon mResultIcon; public SearchResultThumbnailView(Context context) { super(context); @@ -89,4 +90,10 @@ public class SearchResultThumbnailView extends androidx.appcompat.widget.AppComp (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 4c64265cc3..da1495930e 100644 --- a/quickstep/src/com/android/launcher3/search/SearchResultWidget.java +++ b/quickstep/src/com/android/launcher3/search/SearchResultWidget.java @@ -186,6 +186,10 @@ public class SearchResultWidget extends LinearLayout implements SearchTargetHand 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 5bf19087d8..1786baf47c 100644 --- a/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java +++ b/quickstep/src/com/android/launcher3/search/SearchResultWidgetPreview.java @@ -47,8 +47,7 @@ import java.util.List; /** * displays preview of a widget upon receiving {@link AppWidgetProviderInfo} from Search provider */ -public class SearchResultWidgetPreview extends LinearLayout implements SearchTargetHandler, - View.OnClickListener, View.OnLongClickListener { +public class SearchResultWidgetPreview extends LinearLayout implements SearchTargetHandler { private final Launcher mLauncher; private final LauncherAppState mAppState; diff --git a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java index 9276841734..d7c5c5d157 100644 --- a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java +++ b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java @@ -18,6 +18,7 @@ package com.android.launcher3.search; 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; @@ -47,4 +48,15 @@ public class SearchSectionHeaderView extends TextView implements SearchTargetHan 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 fac6ba7474..197aecbc28 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; @@ -41,6 +39,8 @@ import java.util.LinkedHashMap; 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} */ diff --git a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java index acf6f8a02a..0e7b8f20c9 100644 --- a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java +++ b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java @@ -19,13 +19,15 @@ package com.android.launcher3.search; import android.app.search.SearchTarget; 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 SearchTarget} diff --git a/quickstep/src/com/android/launcher3/search/SearchTargetUtil.java b/quickstep/src/com/android/launcher3/search/SearchTargetUtil.java index c036f19f96..ceef429595 100644 --- a/quickstep/src/com/android/launcher3/search/SearchTargetUtil.java +++ b/quickstep/src/com/android/launcher3/search/SearchTargetUtil.java @@ -15,13 +15,6 @@ */ package com.android.launcher3.search; -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; - import android.app.PendingIntent; import android.app.search.SearchAction; import android.app.search.SearchTarget; @@ -38,11 +31,18 @@ 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_WITH_PACKAGE = "badge_with_package"; + 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"; @@ -56,10 +56,10 @@ public class SearchTargetUtil { /** * 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)); + 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) { @@ -83,7 +83,7 @@ public class SearchTargetUtil { Bundle b = new Bundle(); b.putBoolean(BUNDLE_EXTRA_SHOULD_START_FOR_RESULT, true); - b.putBoolean(BUNDLE_EXTRA_BADGE_WITH_PACKAGE, 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) @@ -96,7 +96,7 @@ public class SearchTargetUtil { } /** - * Inside SearchServicePipeline, add following samples to test the search target. + * 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)); @@ -129,10 +129,11 @@ public class SearchTargetUtil { } /** + * * targets.add(SearchTargetUtil.generateIconHorizontalText_SearchAction( - * mContext, "red", Color.RED)); + * mContext, "red", Color.RED)); * targets.add(SearchTargetUtil.generateIconHorizontalText_SearchAction( - * mContext, "yellow", Color.YELLOW)); + * mContext, "yellow", Color.YELLOW)); */ public static SearchTarget generateIconHorizontalText_SearchAction( Context context, String id, int color) { diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java index 8469569c25..36afe50fa1 100644 --- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java +++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java @@ -30,7 +30,7 @@ public class SearchActionItemInfo extends ItemInfoWithIcon { 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_WITH_PACKAGE = 1 << 3; + 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; diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEventLegacy.java b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEventLegacy.java index 0fc61f04dc..7fbd6ac814 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEventLegacy.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEventLegacy.java @@ -20,7 +20,7 @@ import android.os.Bundle; /** * Event used for the feedback loop to the plugin. (and future aiai) * - * @deprecated Use {@link android.app.search.SearchTargetEvent} + * @deprecated Use SearchTargetEvent */ @Deprecated public class SearchTargetEventLegacy {