Merge "Simplifying all-apps seach pipeline" into sc-dev

This commit is contained in:
Sunny Goyal
2021-03-30 19:50:23 +00:00
committed by Android (Google) Code Review
6 changed files with 53 additions and 141 deletions
@@ -234,7 +234,6 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
@Override
public void onDestroy() {
super.onDestroy();
getAppsView().getSearchUiManager().destroySearch();
mHotseatPredictionController.destroy();
}
@@ -48,11 +48,6 @@ public interface SearchUiManager {
*/
float getScrollRangeDelta(Rect insets);
/**
* Called when activity is destroyed. Used to close search system services
*/
default void destroySearch() { }
/**
* @return the edit text object
*/
@@ -36,7 +36,6 @@ import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Insettable;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
@@ -136,7 +135,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText
mApps = appsView.getApps();
mAppsView = appsView;
mSearchBarController.initialize(
new DefaultAppSearchAlgorithm(mLauncher, LauncherAppState.getInstance(mLauncher)),
new DefaultAppSearchAlgorithm(mLauncher),
this, mLauncher, this);
}
@@ -1,85 +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.allapps.search;
import android.content.Context;
import android.os.CancellationSignal;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.search.StringMatcherUtility;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* A device search section for handling app searches
*/
public class AppsSearchPipeline implements SearchPipeline {
private static final int MAX_RESULTS_COUNT = 5;
private final LauncherAppState mLauncherAppState;
public AppsSearchPipeline(Context context, LauncherAppState launcherAppState) {
mLauncherAppState = launcherAppState;
}
@Override
public void query(String input, Consumer<ArrayList<AdapterItem>> callback,
CancellationSignal cancellationSignal) {
mLauncherAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
List<AppInfo> matchingResults = getTitleMatchResult(apps.data, input);
callback.accept(getAdapterItems(matchingResults));
}
});
}
/**
* Filters {@link AppInfo}s matching specified query
*/
public static ArrayList<AppInfo> getTitleMatchResult(List<AppInfo> apps, String query) {
// Do an intersection of the words in the query and each title, and filter out all the
// apps that don't match all of the words in the query.
final String queryTextLower = query.toLowerCase();
final ArrayList<AppInfo> result = new ArrayList<>();
StringMatcherUtility.StringMatcher matcher =
StringMatcherUtility.StringMatcher.getInstance();
for (AppInfo info : apps) {
if (StringMatcherUtility.matches(queryTextLower, info.title.toString(), matcher)) {
result.add(info);
}
}
return result;
}
private ArrayList<AdapterItem> getAdapterItems(List<AppInfo> matchingApps) {
ArrayList<AdapterItem> items = new ArrayList<>();
for (int i = 0; i < matchingApps.size() && i < MAX_RESULTS_COUNT; i++) {
AdapterItem appItem = AdapterItem.asApp(i, "", matchingApps.get(i), i);
items.add(appItem);
}
return items;
}
}
@@ -15,25 +15,39 @@
*/
package com.android.launcher3.allapps.search;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
import android.os.Handler;
import androidx.annotation.AnyThread;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.search.SearchAlgorithm;
import com.android.launcher3.search.SearchCallback;
import com.android.launcher3.search.StringMatcherUtility;
import java.util.ArrayList;
import java.util.List;
/**
* The default search implementation.
*/
public class DefaultAppSearchAlgorithm implements SearchAlgorithm<AdapterItem> {
protected final Handler mResultHandler;
private final AppsSearchPipeline mAppsSearchPipeline;
private static final int MAX_RESULTS_COUNT = 5;
public DefaultAppSearchAlgorithm(Context context, LauncherAppState launcherAppState) {
mResultHandler = new Handler();
mAppsSearchPipeline = new AppsSearchPipeline(context, launcherAppState);
private final LauncherAppState mAppState;
private final Handler mResultHandler;
public DefaultAppSearchAlgorithm(Context context) {
mAppState = LauncherAppState.getInstance(context);
mResultHandler = new Handler(MAIN_EXECUTOR.getLooper());
}
@Override
@@ -44,11 +58,38 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm<AdapterItem> {
}
@Override
public void doSearch(final String query,
final SearchCallback<AdapterItem> callback) {
mAppsSearchPipeline.query(query,
results -> mResultHandler.post(
() -> callback.onSearchResult(query, results)),
null);
public void doSearch(String query, SearchCallback<AdapterItem> callback) {
mAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
ArrayList<AdapterItem> result = getTitleMatchResult(apps.data, query);
mResultHandler.post(() -> callback.onSearchResult(query, result));
}
});
}
/**
* Filters {@link AppInfo}s matching specified query
*/
@AnyThread
public static ArrayList<AdapterItem> getTitleMatchResult(List<AppInfo> apps, String query) {
// Do an intersection of the words in the query and each title, and filter out all the
// apps that don't match all of the words in the query.
final String queryTextLower = query.toLowerCase();
final ArrayList<AdapterItem> result = new ArrayList<>();
StringMatcherUtility.StringMatcher matcher =
StringMatcherUtility.StringMatcher.getInstance();
int resultCount = 0;
int total = apps.size();
for (int i = 0; i < total && resultCount < MAX_RESULTS_COUNT; i++) {
AppInfo info = apps.get(i);
if (StringMatcherUtility.matches(queryTextLower, info.title.toString(), matcher)) {
AdapterItem appItem = AdapterItem.asApp(resultCount, "", info, resultCount);
result.add(appItem);
resultCount++;
}
}
return result;
}
}
@@ -1,37 +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.allapps.search;
import android.os.CancellationSignal;
import com.android.launcher3.allapps.AllAppsGridAdapter;
import java.util.ArrayList;
import java.util.function.Consumer;
/**
* An interface for handling search within pipeline
*/
// Remove when System Service API is added.
public interface SearchPipeline {
/**
* Perform query
*/
void query(String input,
Consumer<ArrayList<AllAppsGridAdapter.AdapterItem>> callback,
CancellationSignal cancellationSignal);
}