mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 15:26:58 +00:00
Merge " Migrate from Plugin SearchTarget to API search Target [3/3]"
This commit is contained in:
@@ -23,6 +23,8 @@ import android.util.SparseIntArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.app.search.LayoutType;
|
||||
import com.android.app.search.ResultType;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
@@ -78,10 +80,10 @@ public class DeviceSearchAdapterProvider extends SearchAdapterProvider {
|
||||
SearchTargetHandler
|
||||
payloadResultView =
|
||||
(SearchTargetHandler) holder.itemView;
|
||||
if (FeatureFlags.SEARCH_TARGET_LEGACY.get()) {
|
||||
if (!FeatureFlags.USE_SEARCH_API.get()) {
|
||||
payloadResultView.applySearchTarget(item.getSearchTargetLegacy());
|
||||
} else {
|
||||
payloadResultView.applySearchTarget(item.getSearchTarget());
|
||||
payloadResultView.applySearchTarget(item.getSearchTarget(), item.getInlineItems());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,9 +125,24 @@ public class DeviceSearchAdapterProvider extends SearchAdapterProvider {
|
||||
* Returns -1 if viewType is not found
|
||||
*/
|
||||
public int getViewTypeForSearchTarget(SearchTarget t) {
|
||||
//TODO: Replace with values from :SearchUi
|
||||
if (t.getResultType() == 1 && t.getLayoutType().equals("icon")) {
|
||||
return VIEW_TYPE_SEARCH_ICON;
|
||||
if (t.getLayoutType().equals(LayoutType.TEXT_HEADER)) {
|
||||
return VIEW_TYPE_SEARCH_CORPUS_TITLE;
|
||||
}
|
||||
switch (t.getResultType()) {
|
||||
case ResultType.APPLICATION:
|
||||
if (t.getLayoutType().equals(LayoutType.ICON_SINGLE_VERTICAL_TEXT)) {
|
||||
return VIEW_TYPE_SEARCH_ICON;
|
||||
}
|
||||
break;
|
||||
case ResultType.SETTING:
|
||||
if (t.getLayoutType().equals(LayoutType.ICON_SLICE)) {
|
||||
return VIEW_TYPE_SEARCH_SLICE;
|
||||
}
|
||||
return VIEW_TYPE_SEARCH_ROW;
|
||||
case ResultType.SHORTCUT:
|
||||
return VIEW_TYPE_SEARCH_ICON_ROW;
|
||||
case ResultType.PLAY:
|
||||
return VIEW_TYPE_SEARCH_ROW_WITH_BUTTON;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -32,12 +32,16 @@ import android.app.search.SearchTarget;
|
||||
import com.android.launcher3.allapps.AllAppsGridAdapter;
|
||||
import com.android.systemui.plugins.shared.SearchTargetLegacy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Extension of AdapterItem that contains an extra payload specific to item
|
||||
*/
|
||||
public class SearchAdapterItem extends AllAppsGridAdapter.AdapterItem {
|
||||
private SearchTargetLegacy mSearchTargetLegacy;
|
||||
private SearchTarget mSearchTarget;
|
||||
private List<SearchTarget> mInlineItems = new ArrayList<>();
|
||||
|
||||
|
||||
private static final int AVAILABLE_FOR_ACCESSIBILITY = VIEW_TYPE_SEARCH_ROW_WITH_BUTTON
|
||||
@@ -65,6 +69,9 @@ public class SearchAdapterItem extends AllAppsGridAdapter.AdapterItem {
|
||||
return mSearchTarget;
|
||||
}
|
||||
|
||||
public List<SearchTarget> getInlineItems() {
|
||||
return mInlineItems;
|
||||
}
|
||||
@Override
|
||||
protected boolean isCountedForAccessibility() {
|
||||
return (AVAILABLE_FOR_ACCESSIBILITY & viewType) == viewType;
|
||||
|
||||
@@ -31,10 +31,12 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.app.search.ResultType;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
@@ -46,6 +48,7 @@ import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
|
||||
import com.android.systemui.plugins.shared.SearchTargetLegacy;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -128,10 +131,27 @@ public class SearchResultIcon extends BubbleTextView implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@link SearchTarget} to view. registers a consumer after a corresponding
|
||||
* {@link ItemInfoWithIcon} is created
|
||||
*/
|
||||
public void applySearchTarget(SearchTarget searchTarget, List<SearchTarget> inlineItems,
|
||||
Consumer<ItemInfoWithIcon> cb) {
|
||||
mOnItemInfoChanged = cb;
|
||||
applySearchTarget(searchTarget, inlineItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget searchTarget) {
|
||||
prepareUsingApp(new ComponentName(searchTarget.getPackageName(),
|
||||
searchTarget.getExtras().getString("class")), searchTarget.getUserHandle());
|
||||
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());
|
||||
break;
|
||||
case ResultType.SHORTCUT:
|
||||
prepareUsingShortcutInfo(parentTarget.getShortcutInfo());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareUsingApp(ComponentName componentName, UserHandle userHandle) {
|
||||
@@ -185,7 +205,9 @@ public class SearchResultIcon extends BubbleTextView implements
|
||||
@Override
|
||||
public void handleSelection(int eventType) {
|
||||
mLauncher.getItemOnClickListener().onClick(this);
|
||||
reportEvent(eventType);
|
||||
if (!FeatureFlags.USE_SEARCH_API.get()) {
|
||||
reportEvent(eventType);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportEvent(int eventType) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.search;
|
||||
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.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
@@ -32,6 +33,7 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.app.search.ResultType;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
@@ -111,6 +113,16 @@ public class SearchResultIconRow extends LinearLayout implements
|
||||
setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
|
||||
mResultIcon.applySearchTarget(parentTarget, children, this);
|
||||
if (parentTarget.getResultType() == ResultType.SHORTCUT) {
|
||||
ShortcutInfo shortcutInfo = parentTarget.getShortcutInfo();
|
||||
setProviderDetails(new ComponentName(shortcutInfo.getPackage(), ""),
|
||||
shortcutInfo.getUserHandle());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTargetLegacy searchTarget) {
|
||||
mSearchTarget = searchTarget;
|
||||
|
||||
@@ -17,6 +17,8 @@ package com.android.launcher3.search;
|
||||
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.app.search.SearchAction;
|
||||
import android.app.search.SearchTarget;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -27,8 +29,6 @@ import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -43,12 +43,11 @@ import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
|
||||
import com.android.systemui.plugins.shared.SearchTargetLegacy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A View representing a PlayStore item.
|
||||
@@ -67,9 +66,8 @@ public class SearchResultPlayItem extends LinearLayout implements
|
||||
private TextView[] mDetailViews = new TextView[3];
|
||||
private Button mPreviewButton;
|
||||
private String mPackageName;
|
||||
private boolean mIsInstantGame;
|
||||
|
||||
private SearchTargetLegacy mSearchTarget;
|
||||
private Intent mIntent;
|
||||
private Intent mSecondaryIntent;
|
||||
|
||||
|
||||
public SearchResultPlayItem(Context context) {
|
||||
@@ -93,7 +91,7 @@ public class SearchResultPlayItem extends LinearLayout implements
|
||||
mIconView = findViewById(R.id.icon);
|
||||
mTitleView = findViewById(R.id.title_view);
|
||||
mPreviewButton = findViewById(R.id.try_button);
|
||||
mPreviewButton.setOnClickListener(view -> launchInstantGame());
|
||||
mPreviewButton.setOnClickListener(view -> launchIntent(mSecondaryIntent));
|
||||
mDetailViews[0] = findViewById(R.id.detail_0);
|
||||
mDetailViews[1] = findViewById(R.id.detail_1);
|
||||
mDetailViews[2] = findViewById(R.id.detail_2);
|
||||
@@ -101,9 +99,59 @@ public class SearchResultPlayItem extends LinearLayout implements
|
||||
ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
|
||||
iconParams.height = mDeviceProfile.allAppsIconSizePx;
|
||||
iconParams.width = mDeviceProfile.allAppsIconSizePx;
|
||||
setOnClickListener(view -> handleSelection(SearchTargetEventLegacy.SELECT));
|
||||
setOnClickListener(view -> launchIntent(mIntent));
|
||||
}
|
||||
|
||||
private void showIfNecessary(TextView textView, @Nullable String string) {
|
||||
if (string == null || string.isEmpty()) {
|
||||
textView.setVisibility(GONE);
|
||||
} else {
|
||||
textView.setText(string);
|
||||
textView.setVisibility(VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void launchIntent(Intent intent) {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getContext().startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
|
||||
if (parentTarget.getPackageName().equals(mPackageName)) {
|
||||
return;
|
||||
}
|
||||
mPackageName = parentTarget.getPackageName();
|
||||
SearchAction action = parentTarget.getSearchAction();
|
||||
mTitleView.setText(action.getTitle());
|
||||
showIfNecessary(mDetailViews[0], action.getSubtitle().toString());
|
||||
mIntent = action.getIntent();
|
||||
|
||||
mIconView.setBackgroundResource(R.drawable.ic_deepshortcut_placeholder);
|
||||
loadIcon(action.getIcon().getUri().toString());
|
||||
|
||||
mSecondaryIntent = children.size() == 1 ? children.get(0).getSearchAction().getIntent()
|
||||
: null;
|
||||
mPreviewButton.setVisibility(mSecondaryIntent == null ? GONE : VISIBLE);
|
||||
}
|
||||
|
||||
private void loadIcon(String iconUrl) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
try {
|
||||
URL url = new URL(iconUrl);
|
||||
URLConnection con = url.openConnection();
|
||||
con.addRequestProperty("Cache-Control", "max-age: 0");
|
||||
con.setUseCaches(true);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(con.getInputStream());
|
||||
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), getRoundedBitmap(
|
||||
Bitmap.createScaledBitmap(bitmap, mDeviceProfile.allAppsIconSizePx,
|
||||
mDeviceProfile.allAppsIconSizePx, false)));
|
||||
mIconView.post(() -> mIconView.setBackground(bitmapDrawable));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Bitmap getRoundedBitmap(Bitmap bitmap) {
|
||||
final int iconSize = bitmap.getWidth();
|
||||
@@ -124,80 +172,4 @@ public class SearchResultPlayItem extends LinearLayout implements
|
||||
});
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTargetLegacy searchTarget) {
|
||||
mSearchTarget = searchTarget;
|
||||
Bundle bundle = searchTarget.getExtras();
|
||||
SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
|
||||
if (bundle.getString("package", "").equals(mPackageName)) {
|
||||
return;
|
||||
}
|
||||
mIsInstantGame = bundle.getBoolean("instant_game", false);
|
||||
mPackageName = bundle.getString("package");
|
||||
mPreviewButton.setVisibility(mIsInstantGame ? VISIBLE : GONE);
|
||||
mTitleView.setText(bundle.getString("title"));
|
||||
// TODO: Should use a generic type to get values b/165320033
|
||||
showIfNecessary(mDetailViews[0], bundle.getString("price"));
|
||||
showIfNecessary(mDetailViews[1], bundle.getString("rating"));
|
||||
|
||||
mIconView.setBackgroundResource(R.drawable.ic_deepshortcut_placeholder);
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
try {
|
||||
URL url = new URL(bundle.getString("icon_url"));
|
||||
URLConnection con = url.openConnection();
|
||||
// TODO: monitor memory and investigate if it's better to use glide
|
||||
con.addRequestProperty("Cache-Control", "max-age: 0");
|
||||
con.setUseCaches(true);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(con.getInputStream());
|
||||
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), getRoundedBitmap(
|
||||
Bitmap.createScaledBitmap(bitmap, mDeviceProfile.allAppsIconSizePx,
|
||||
mDeviceProfile.allAppsIconSizePx, false)));
|
||||
mIconView.post(() -> mIconView.setBackground(bitmapDrawable));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showIfNecessary(TextView textView, @Nullable String string) {
|
||||
if (string == null || string.isEmpty()) {
|
||||
textView.setVisibility(GONE);
|
||||
} else {
|
||||
textView.setText(string);
|
||||
textView.setVisibility(VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSelection(int eventType) {
|
||||
if (mPackageName == null) return;
|
||||
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(
|
||||
"https://play.google.com/store/apps/details?id="
|
||||
+ mPackageName));
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getContext().startActivity(i);
|
||||
logSearchEvent(eventType);
|
||||
}
|
||||
|
||||
private void launchInstantGame() {
|
||||
if (!mIsInstantGame) return;
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
String referrer = "Pixel_Launcher";
|
||||
String id = mPackageName;
|
||||
String deepLinkUrl = "market://details?id=" + id + "&launch=true&referrer=" + referrer;
|
||||
intent.setPackage("com.android.vending");
|
||||
intent.setData(Uri.parse(deepLinkUrl));
|
||||
intent.putExtra("overlay", true);
|
||||
intent.putExtra("callerId", getContext().getPackageName());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getContext().startActivity(intent);
|
||||
logSearchEvent(SearchTargetEventLegacy.CHILD_SELECT);
|
||||
}
|
||||
|
||||
private void logSearchEvent(int eventType) {
|
||||
SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
|
||||
new SearchTargetEventLegacy.Builder(mSearchTarget, eventType).build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.search;
|
||||
|
||||
import android.app.search.SearchTarget;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
@@ -35,6 +36,8 @@ import com.android.launcher3.R;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
|
||||
import com.android.systemui.plugins.shared.SearchTargetLegacy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A slice view wrapper with settings app icon at start
|
||||
*/
|
||||
@@ -88,6 +91,18 @@ public class SearchResultSettingsSlice extends LinearLayout implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
|
||||
reset();
|
||||
try {
|
||||
mSliceLiveData = mLauncher.getLiveSearchManager().getSliceForUri(
|
||||
parentTarget.getSliceUri());
|
||||
mSliceLiveData.observe(mLauncher, mSliceView);
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "unable to bind slice", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.search;
|
||||
|
||||
import android.app.search.SearchTarget;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
@@ -23,6 +24,8 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.systemui.plugins.shared.SearchTargetLegacy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Header text view that shows a title for a given section in All apps search
|
||||
*/
|
||||
@@ -53,4 +56,10 @@ public class SearchSectionHeaderView extends TextView implements
|
||||
setVisibility(INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
|
||||
setText(parentTarget.getSearchAction().getTitle());
|
||||
setVisibility(VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.app.search.Query;
|
||||
import android.app.search.SearchContext;
|
||||
import android.app.search.SearchSession;
|
||||
import android.app.search.SearchTarget;
|
||||
import android.app.search.SearchUiManager;
|
||||
import android.content.Context;
|
||||
import android.os.CancellationSignal;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.app.search.ResultType;
|
||||
import com.android.launcher3.allapps.AllAppsGridAdapter;
|
||||
import com.android.launcher3.allapps.AllAppsSectionDecorator;
|
||||
import com.android.launcher3.allapps.search.SearchPipeline;
|
||||
import com.android.launcher3.allapps.search.SearchSectionInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Search pipeline utilizing {@link android.app.search.SearchUiManager}
|
||||
*/
|
||||
public class SearchServicePipeline implements SearchPipeline {
|
||||
private static final int SUPPORTED_RESULT_TYPES =
|
||||
ResultType.APPLICATION | ResultType.SHORTCUT | ResultType.PLAY | ResultType.PEOPLE
|
||||
| ResultType.SETTING;
|
||||
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;
|
||||
|
||||
private boolean mCanceled = false;
|
||||
|
||||
|
||||
public SearchServicePipeline(Context context, DeviceSearchAdapterProvider adapterProvider) {
|
||||
mContext = context;
|
||||
mAdapterProvider = adapterProvider;
|
||||
SearchUiManager manager = context.getSystemService(SearchUiManager.class);
|
||||
mSession = manager.createSearchSession(
|
||||
new SearchContext(SUPPORTED_RESULT_TYPES, REQUEST_TIMEOUT, null));
|
||||
}
|
||||
|
||||
@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 -> {
|
||||
if (!mCanceled) {
|
||||
callback.accept(this.onResult(items));
|
||||
}
|
||||
Log.w(TAG, "Ignoring results due to cancel signal");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given A list of search Targets, pairs a group of search targets to a AdapterItem that can
|
||||
* be inflated in AllAppsRecyclerView
|
||||
*/
|
||||
private ArrayList<AllAppsGridAdapter.AdapterItem> onResult(List<SearchTarget> searchTargets) {
|
||||
HashMap<String, SearchAdapterItem> adapterMap = new LinkedHashMap<>();
|
||||
List<SearchTarget> unmappedChildren = new ArrayList<>();
|
||||
SearchSectionInfo section = new SearchSectionInfo();
|
||||
section.setDecorationHandler(
|
||||
new AllAppsSectionDecorator.SectionDecorationHandler(mContext, true));
|
||||
for (SearchTarget target : searchTargets) {
|
||||
if (!TextUtils.isEmpty(target.getParentId())) {
|
||||
if (!addChildToParent(target, adapterMap)) {
|
||||
unmappedChildren.add(target);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int viewType = mAdapterProvider.getViewTypeForSearchTarget(target);
|
||||
if (viewType != -1) {
|
||||
SearchAdapterItem adapterItem = new SearchAdapterItem(target, viewType);
|
||||
adapterItem.searchSectionInfo = section;
|
||||
adapterMap.put(target.getId(), adapterItem);
|
||||
}
|
||||
}
|
||||
for (SearchTarget s : unmappedChildren) {
|
||||
if (!addChildToParent(s, adapterMap)) {
|
||||
Log.w(TAG,
|
||||
"Unable to pair child " + s.getId() + " to parent " + s.getParentId());
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(adapterMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private boolean addChildToParent(SearchTarget target, HashMap<String, SearchAdapterItem> map) {
|
||||
if (!map.containsKey(target.getParentId())) return false;
|
||||
map.get(target.getParentId()).getInlineItems().add(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister callbacks and destroy search session
|
||||
*/
|
||||
public void destroy() {
|
||||
mSession.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels current ongoing search request.
|
||||
*/
|
||||
public void cancel() {
|
||||
mCanceled = true;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
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.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -97,6 +99,14 @@ public class SearchSettingsRowView extends LinearLayout implements
|
||||
SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
|
||||
SearchAction action = parentTarget.getSearchAction();
|
||||
mIconView.setContentDescription(action.getTitle());
|
||||
showIfAvailable(mTitleView, action.getTitle().toString());
|
||||
showIfAvailable(mBreadcrumbsView, action.getSubtitle().toString());
|
||||
}
|
||||
|
||||
private void showIfAvailable(TextView view, @Nullable String string) {
|
||||
if (TextUtils.isEmpty(string)) {
|
||||
view.setVisibility(GONE);
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.app.search.SearchTarget;
|
||||
|
||||
import com.android.systemui.plugins.shared.SearchTargetLegacy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An interface for supporting dynamic search results
|
||||
*/
|
||||
@@ -28,13 +30,14 @@ public interface SearchTargetHandler {
|
||||
/**
|
||||
* Update view using values from {@link SearchTargetLegacy}
|
||||
*/
|
||||
void applySearchTarget(SearchTargetLegacy searchTarget);
|
||||
default void applySearchTarget(SearchTargetLegacy searchTarget) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update view using values from {@link SearchTargetLegacy}
|
||||
*/
|
||||
default void applySearchTarget(SearchTarget searchTarget){
|
||||
|
||||
default void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -220,6 +220,7 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
getAppsView().getSearchUiManager().destroy();
|
||||
if (mHotseatPredictionController != null) {
|
||||
mHotseatPredictionController.destroy();
|
||||
mHotseatPredictionController = null;
|
||||
|
||||
@@ -58,6 +58,11 @@ public interface SearchUiManager {
|
||||
void setContentVisibility(int visibleElements, PropertySetter setter,
|
||||
Interpolator interpolator);
|
||||
|
||||
/**
|
||||
* Called when activity is destroyed. Used to close search system services
|
||||
*/
|
||||
default void destroy(){}
|
||||
|
||||
/**
|
||||
* Returns true if the QSB should be visible for the given set of visible elements
|
||||
*/
|
||||
|
||||
@@ -98,9 +98,8 @@ public final class FeatureFlags {
|
||||
public static final BooleanFlag ENABLE_DEVICE_SEARCH = getDebugFlag(
|
||||
"ENABLE_DEVICE_SEARCH", false, "Allows on device search in all apps");
|
||||
|
||||
public static final BooleanFlag SEARCH_TARGET_LEGACY = getDebugFlag(
|
||||
"SEARCH_TARGET_LEGACY", true,
|
||||
"Use SearchTarget provided by plugin lib (only during migration)");
|
||||
public static final BooleanFlag USE_SEARCH_API = getDebugFlag(
|
||||
"USE_SEARCH_API", true, "Use SearchUIManager api for device search");
|
||||
|
||||
public static final BooleanFlag DISABLE_INITIAL_IME_IN_ALLAPPS = getDebugFlag(
|
||||
"DISABLE_INITIAL_IME_IN_ALLAPPS", false, "Disable default IME state in all apps");
|
||||
|
||||
Reference in New Issue
Block a user