Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80466c08 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support people search results" into sc-dev

parents 6d46fff2 1ab83de4
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -57,9 +57,10 @@
        style="@style/BaseIcon"
        android:layout_width="@dimen/deep_shortcut_icon_size"
        android:layout_height="match_parent"
        android:gravity="start|center_vertical"
        android:layout_marginStart="4dp"
        android:gravity="center"
        launcher:iconDisplay="shortcut_popup"
        android:textSize="@dimen/search_hero_subtitle_size"
        android:textSize="@dimen/search_hero_inline_button_size"
        launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
        launcher:layoutHorizontal="false" />

@@ -68,6 +69,20 @@
        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" />

    <com.android.launcher3.search.SearchResultIcon
        android:id="@+id/shortcut_2"
        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"
+0 −63
Original line number Diff line number Diff line
<?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.SearchResultPeopleView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:gravity="center_vertical"
    android:layout_height="wrap_content"
    android:padding="8dp"
    android:orientation="horizontal">

    <View
        android:id="@+id/icon"
        android:layout_marginRight="8dp"
        android:layout_width="@dimen/deep_shortcut_icon_size"
        android:layout_height="@dimen/deep_shortcut_icon_size" />

    <TextView
        android:layout_width="0dp"
        android:textColor="?android:attr/textColorPrimary"
        android:id="@+id/title"
        android:textSize="@dimen/search_hero_title_size"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <ImageButton
        android:id="@+id/provider_0"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true"
        android:layout_margin="5dp"
        android:background="?android:attr/selectableItemBackground"
        android:layout_width="@dimen/deep_shortcut_icon_size"
        android:layout_height="@dimen/deep_shortcut_icon_size" />

    <ImageButton
        android:id="@+id/provider_1"
        android:layout_margin="5dp"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true"
        android:background="?android:attr/selectableItemBackground"
        android:layout_width="@dimen/deep_shortcut_icon_size"
        android:layout_height="@dimen/deep_shortcut_icon_size" />

    <ImageButton
        android:id="@+id/provider_2"
        android:layout_margin="5dp"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true"
        android:background="?android:attr/selectableItemBackground"
        android:layout_width="@dimen/deep_shortcut_icon_size"
        android:layout_height="@dimen/deep_shortcut_icon_size" />

</com.android.launcher3.search.SearchResultPeopleView>
 No newline at end of file
+1 −2
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ 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;
@@ -59,7 +58,6 @@ 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,
@@ -125,6 +123,7 @@ 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) {
+4 −4
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ 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;
@@ -42,9 +41,10 @@ public class SearchAdapterItem extends AllAppsGridAdapter.AdapterItem {


    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_SLICE | 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;
+92 −39
Original line number Diff line number Diff line
@@ -15,12 +15,9 @@
 */
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_BADGE_WITH_PACKAGE;
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;

@@ -30,9 +27,14 @@ import android.app.search.SearchTargetEvent;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Drawable;
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.Icon;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.AttributeSet;
@@ -45,6 +47,7 @@ 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;
@@ -54,14 +57,25 @@ 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 {
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;

    private final Launcher mLauncher;

@@ -99,7 +113,7 @@ public class SearchResultIcon extends BubbleTextView implements SearchTargetHand
     * Applies {@link SearchTarget} to view. registers a consumer after a corresponding
     * {@link ItemInfoWithIcon} is created
     */
    public void applySearchTarget(SearchTarget searchTarget, List<SearchTarget> inlineItems,
    public void apply(SearchTarget searchTarget, List<SearchTarget> inlineItems,
            Consumer<ItemInfoWithIcon> cb) {
        mOnItemInfoChanged = cb;
        apply(searchTarget, inlineItems);
@@ -115,8 +129,8 @@ public class SearchResultIcon extends BubbleTextView implements SearchTargetHand
            prepareUsingSearchAction(parentTarget);
            mLongPressSupported = false;
        } else {
            prepareUsingApp(new ComponentName(parentTarget.getPackageName(),
                    parentTarget.getExtras().getString(SearchTargetUtil.EXTRA_CLASS)),
            String className = parentTarget.getExtras().getString(SearchTargetUtil.EXTRA_CLASS);
            prepareUsingApp(new ComponentName(parentTarget.getPackageName(), className),
                    parentTarget.getUserHandle());
            mLongPressSupported = true;
        }
@@ -136,14 +150,17 @@ public class SearchResultIcon extends BubbleTextView implements SearchTargetHand
        //TODO: remove this after flags are introduced in SearchAction. Settings results require
        // startActivityForResult
        boolean isSettingsResult = searchTarget.getResultType() == ResultType.SETTING;
        if ((extras != null && extras.getBoolean(BUNDLE_EXTRA_SHOULD_START_FOR_RESULT))
        if ((extras != null && extras.getBoolean(
                SearchTargetUtil.BUNDLE_EXTRA_SHOULD_START_FOR_RESULT))
                || isSettingsResult) {
            itemInfo.setFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT);
        } else if (extras != null && extras.getBoolean(BUNDLE_EXTRA_SHOULD_START)) {
        } else if (extras != null && extras.getBoolean(
                SearchTargetUtil.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(
                SearchTargetUtil.BUNDLE_EXTRA_BADGE_WITH_PACKAGE)) {
            itemInfo.setFlags(FLAG_BADGE_WITH_PACKAGE);
        }
        if (extras != null && extras.getBoolean(BUNDLE_EXTRA_PRIMARY_ICON_FROM_TITLE)) {
            itemInfo.setFlags(FLAG_PRIMARY_ICON_FROM_TITLE);
@@ -154,39 +171,76 @@ public class SearchResultIcon extends BubbleTextView implements SearchTargetHand
        MODEL_EXECUTOR.post(() -> {
            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);
                    bitmapInfo = pkgInfo.bitmap;
                } else {
                    d = itemInfo.getIcon().loadDrawable(getContext());
                    bitmapInfo = li.createBadgedIconBitmap(d, itemInfo.user,
                            Build.VERSION.SDK_INT);
                }

                BitmapInfo bitmapMainIcon;
                BitmapInfo pkgBitmap = getPackageBitmap(appState, searchTarget);
                if (itemInfo.hasFlags(FLAG_PRIMARY_ICON_FROM_TITLE)) {
                    bitmapMainIcon = li.createIconBitmap(
                            String.valueOf(itemInfo.title.charAt(0)),
                            bitmapInfo.color);
                    // 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;
                } else {
                    bitmapMainIcon = bitmapInfo;
                }
                if (itemInfo.hasFlags(FLAG_BADGE_FROM_ICON)) {
                    itemInfo.bitmap = li.badgeBitmap(bitmapMainIcon.icon, bitmapInfo);
                    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 = bitmapInfo;
                        itemInfo.bitmap = li.createBadgedIconBitmap(icon.loadDrawable(getContext()),
                                itemInfo.user, false);
                    }
                }

                // badge with package name
                if (itemInfo.hasFlags(FLAG_BADGE_WITH_PACKAGE) && itemInfo.bitmap != pkgBitmap) {
                    itemInfo.bitmap = li.badgeBitmap(itemInfo.bitmap.icon, pkgBitmap);
                }
            }
            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));
@@ -233,7 +287,6 @@ public class SearchResultIcon extends BubbleTextView implements SearchTargetHand
    }



    private void notifyItemInfoChanged(ItemInfoWithIcon itemInfoWithIcon) {
        if (mOnItemInfoChanged != null) {
            mOnItemInfoChanged.accept(itemInfoWithIcon);
Loading