From ce6cc7e7052e08741399647691cedf3eb635d9e5 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 30 Mar 2021 16:51:08 -0700 Subject: [PATCH] Simplifying widget search pipeline Bug: 183607616 Test: Verified on device Change-Id: I3e5dd9e280f375475d1e1cf41dff6e6533175ebf --- .../SimpleWidgetsSearchAlgorithmTest.java | 173 ++++++++++++++-- .../SimpleWidgetsSearchPipelineTest.java | 185 ------------------ .../widget/picker/WidgetsFullSheet.java | 2 +- .../search/LauncherWidgetsSearchBar.java | 13 +- .../search/SimpleWidgetsSearchAlgorithm.java | 65 ++++-- .../search/SimpleWidgetsSearchPipeline.java | 72 ------- .../search/WidgetsPickerSearchPipeline.java | 44 ----- .../picker/search/WidgetsSearchBar.java | 6 +- 8 files changed, 208 insertions(+), 352 deletions(-) delete mode 100644 robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipelineTest.java delete mode 100644 src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipeline.java delete mode 100644 src/com/android/launcher3/widget/picker/search/WidgetsPickerSearchPipeline.java diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java index c2bf1ae2dc..36b6f01dc0 100644 --- a/robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java +++ b/robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java @@ -18,64 +18,197 @@ package com.android.launcher3.widget.picker.search; import static android.os.Looper.getMainLooper; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.matches; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.robolectric.Shadows.shadowOf; +import android.appwidget.AppWidgetProviderInfo; +import android.content.ComponentName; +import android.content.Context; +import android.graphics.Bitmap; +import android.os.UserHandle; + +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.icons.BitmapInfo; +import com.android.launcher3.icons.ComponentWithLabel; +import com.android.launcher3.icons.IconCache; +import com.android.launcher3.model.WidgetItem; +import com.android.launcher3.model.data.PackageItemInfo; +import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.search.SearchCallback; +import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.model.WidgetsListBaseEntry; +import com.android.launcher3.widget.model.WidgetsListContentEntry; +import com.android.launcher3.widget.model.WidgetsListHeaderEntry; +import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.shadows.ShadowPackageManager; +import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.function.Consumer; @RunWith(RobolectricTestRunner.class) public class SimpleWidgetsSearchAlgorithmTest { + @Mock private IconCache mIconCache; + + private InvariantDeviceProfile mTestProfile; + private WidgetsListHeaderEntry mCalendarHeaderEntry; + private WidgetsListContentEntry mCalendarContentEntry; + private WidgetsListHeaderEntry mCameraHeaderEntry; + private WidgetsListContentEntry mCameraContentEntry; + private WidgetsListHeaderEntry mClockHeaderEntry; + private WidgetsListContentEntry mClockContentEntry; + private Context mContext; + private SimpleWidgetsSearchAlgorithm mSimpleWidgetsSearchAlgorithm; @Mock - private WidgetsPickerSearchPipeline mSearchPipeline; + private PopupDataProvider mDataProvider; @Mock private SearchCallback mSearchCallback; - @Captor - private ArgumentCaptor>> mConsumerCaptor; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mSimpleWidgetsSearchAlgorithm = new SimpleWidgetsSearchAlgorithm(mSearchPipeline); + doAnswer(invocation -> { + ComponentWithLabel componentWithLabel = (ComponentWithLabel) invocation.getArgument(0); + return componentWithLabel.getComponent().getShortClassName(); + }).when(mIconCache).getTitleNoCache(any()); + mTestProfile = new InvariantDeviceProfile(); + mTestProfile.numRows = 5; + mTestProfile.numColumns = 5; + mContext = RuntimeEnvironment.application; + + mCalendarHeaderEntry = + createWidgetsHeaderEntry("com.example.android.Calendar", "Calendar", 2); + mCalendarContentEntry = + createWidgetsContentEntry("com.example.android.Calendar", "Calendar", 2); + mCameraHeaderEntry = createWidgetsHeaderEntry("com.example.android.Camera", "Camera", 11); + mCameraContentEntry = createWidgetsContentEntry("com.example.android.Camera", "Camera", 11); + mClockHeaderEntry = createWidgetsHeaderEntry("com.example.android.Clock", "Clock", 3); + mClockContentEntry = createWidgetsContentEntry("com.example.android.Clock", "Clock", 3); + + + mSimpleWidgetsSearchAlgorithm = new SimpleWidgetsSearchAlgorithm(mDataProvider); + doReturn(Collections.EMPTY_LIST).when(mDataProvider).getAllWidgets(); } @Test - public void doSearch_shouldQueryPipeline() { - mSimpleWidgetsSearchAlgorithm.doSearch("abc", mSearchCallback); + public void filter_shouldMatchOnAppName() { + doReturn(List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry, + mCameraContentEntry, mClockHeaderEntry, mClockContentEntry)) + .when(mDataProvider) + .getAllWidgets(); - verify(mSearchPipeline).query(eq("abc"), any()); + assertEquals(List.of( + new WidgetsListSearchHeaderEntry( + mCalendarHeaderEntry.mPkgItem, + mCalendarHeaderEntry.mTitleSectionName, + mCalendarHeaderEntry.mWidgets), + mCalendarContentEntry, + new WidgetsListSearchHeaderEntry( + mCameraHeaderEntry.mPkgItem, + mCameraHeaderEntry.mTitleSectionName, + mCameraHeaderEntry.mWidgets), + mCameraContentEntry), + SimpleWidgetsSearchAlgorithm.getFilteredWidgets(mDataProvider, "Ca")); } @Test - public void doSearch_shouldInformSearchCallbackOnQueryResult() { - ArrayList baseEntries = new ArrayList<>(); + public void filter_shouldMatchOnWidgetLabel() { + doReturn(List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry, + mCameraContentEntry)) + .when(mDataProvider) + .getAllWidgets(); - mSimpleWidgetsSearchAlgorithm.doSearch("abc", mSearchCallback); + assertEquals(List.of( + new WidgetsListSearchHeaderEntry( + mCalendarHeaderEntry.mPkgItem, + mCalendarHeaderEntry.mTitleSectionName, + mCalendarHeaderEntry.mWidgets.subList(1, 2)), + new WidgetsListContentEntry( + mCalendarHeaderEntry.mPkgItem, + mCalendarHeaderEntry.mTitleSectionName, + mCalendarHeaderEntry.mWidgets.subList(1, 2)), + new WidgetsListSearchHeaderEntry( + mCameraHeaderEntry.mPkgItem, + mCameraHeaderEntry.mTitleSectionName, + mCameraHeaderEntry.mWidgets.subList(1, 3)), + new WidgetsListContentEntry( + mCameraHeaderEntry.mPkgItem, + mCameraHeaderEntry.mTitleSectionName, + mCameraHeaderEntry.mWidgets.subList(1, 3))), + SimpleWidgetsSearchAlgorithm.getFilteredWidgets(mDataProvider, "Widget1")); + } - verify(mSearchPipeline).query(eq("abc"), mConsumerCaptor.capture()); - mConsumerCaptor.getValue().accept(baseEntries); + @Test + public void doSearch_shouldInformCallback() { + doReturn(List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry, + mCameraContentEntry, mClockHeaderEntry, mClockContentEntry)) + .when(mDataProvider) + .getAllWidgets(); + mSimpleWidgetsSearchAlgorithm.doSearch("Ca", mSearchCallback); shadowOf(getMainLooper()).idle(); - // Verify SearchCallback#onSearchResult receives a query token along with the search - // results. The query token is the original query string concatenated with the query - // timestamp. - verify(mSearchCallback).onSearchResult(matches("abc\t\\d*"), eq(baseEntries)); + verify(mSearchCallback).onSearchResult( + matches("Ca"), argThat(a -> a != null && !a.isEmpty())); + } + + private WidgetsListHeaderEntry createWidgetsHeaderEntry(String packageName, String appName, + int numOfWidgets) { + List widgetItems = generateWidgetItems(packageName, numOfWidgets); + PackageItemInfo pInfo = createPackageItemInfo(packageName, appName, + widgetItems.get(0).user); + + return new WidgetsListHeaderEntry(pInfo, /* titleSectionName= */ "", widgetItems); + } + + private WidgetsListContentEntry createWidgetsContentEntry(String packageName, String appName, + int numOfWidgets) { + List widgetItems = generateWidgetItems(packageName, numOfWidgets); + PackageItemInfo pInfo = createPackageItemInfo(packageName, appName, + widgetItems.get(0).user); + + return new WidgetsListContentEntry(pInfo, /* titleSectionName= */ "", widgetItems); + } + + private PackageItemInfo createPackageItemInfo(String packageName, String appName, + UserHandle userHandle) { + PackageItemInfo pInfo = new PackageItemInfo(packageName); + pInfo.title = appName; + pInfo.user = userHandle; + pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0); + return pInfo; + } + + private List generateWidgetItems(String packageName, int numOfWidgets) { + ShadowPackageManager packageManager = shadowOf(mContext.getPackageManager()); + ArrayList widgetItems = new ArrayList<>(); + for (int i = 0; i < numOfWidgets; i++) { + ComponentName cn = ComponentName.createRelative(packageName, ".SampleWidget" + i); + AppWidgetProviderInfo widgetInfo = new AppWidgetProviderInfo(); + widgetInfo.provider = cn; + ReflectionHelpers.setField(widgetInfo, "providerInfo", + packageManager.addReceiverIfNotPresent(cn)); + + WidgetItem widgetItem = new WidgetItem( + LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo), + mTestProfile, mIconCache); + widgetItems.add(widgetItem); + } + return widgetItems; } } diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipelineTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipelineTest.java deleted file mode 100644 index 17ededdb37..0000000000 --- a/robolectric_tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipelineTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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.widget.picker.search; - -import static android.os.Looper.getMainLooper; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.robolectric.Shadows.shadowOf; - -import android.appwidget.AppWidgetProviderInfo; -import android.content.ComponentName; -import android.content.Context; -import android.graphics.Bitmap; -import android.os.UserHandle; - -import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.icons.BitmapInfo; -import com.android.launcher3.icons.ComponentWithLabel; -import com.android.launcher3.icons.IconCache; -import com.android.launcher3.model.WidgetItem; -import com.android.launcher3.model.data.PackageItemInfo; -import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; -import com.android.launcher3.widget.model.WidgetsListContentEntry; -import com.android.launcher3.widget.model.WidgetsListHeaderEntry; -import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.shadows.ShadowPackageManager; -import org.robolectric.util.ReflectionHelpers; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(RobolectricTestRunner.class) -public class SimpleWidgetsSearchPipelineTest { - @Mock private IconCache mIconCache; - - private InvariantDeviceProfile mTestProfile; - private WidgetsListHeaderEntry mCalendarHeaderEntry; - private WidgetsListContentEntry mCalendarContentEntry; - private WidgetsListHeaderEntry mCameraHeaderEntry; - private WidgetsListContentEntry mCameraContentEntry; - private WidgetsListHeaderEntry mClockHeaderEntry; - private WidgetsListContentEntry mClockContentEntry; - private Context mContext; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - doAnswer(invocation -> { - ComponentWithLabel componentWithLabel = (ComponentWithLabel) invocation.getArgument(0); - return componentWithLabel.getComponent().getShortClassName(); - }).when(mIconCache).getTitleNoCache(any()); - mTestProfile = new InvariantDeviceProfile(); - mTestProfile.numRows = 5; - mTestProfile.numColumns = 5; - mContext = RuntimeEnvironment.application; - - mCalendarHeaderEntry = - createWidgetsHeaderEntry("com.example.android.Calendar", "Calendar", 2); - mCalendarContentEntry = - createWidgetsContentEntry("com.example.android.Calendar", "Calendar", 2); - mCameraHeaderEntry = createWidgetsHeaderEntry("com.example.android.Camera", "Camera", 11); - mCameraContentEntry = createWidgetsContentEntry("com.example.android.Camera", "Camera", 11); - mClockHeaderEntry = createWidgetsHeaderEntry("com.example.android.Clock", "Clock", 3); - mClockContentEntry = createWidgetsContentEntry("com.example.android.Clock", "Clock", 3); - } - - @Test - public void query_shouldMatchOnAppName() { - SimpleWidgetsSearchPipeline pipeline = new SimpleWidgetsSearchPipeline( - List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry, - mCameraContentEntry, mClockHeaderEntry, mClockContentEntry)); - - pipeline.query("Ca", results -> - assertEquals(results, - List.of( - new WidgetsListSearchHeaderEntry( - mCalendarHeaderEntry.mPkgItem, - mCalendarHeaderEntry.mTitleSectionName, - mCalendarHeaderEntry.mWidgets), - mCalendarContentEntry, - new WidgetsListSearchHeaderEntry( - mCameraHeaderEntry.mPkgItem, - mCameraHeaderEntry.mTitleSectionName, - mCameraHeaderEntry.mWidgets), - mCameraContentEntry))); - shadowOf(getMainLooper()).idle(); - } - - @Test - public void query_shouldMatchOnWidgetLabel() { - SimpleWidgetsSearchPipeline pipeline = new SimpleWidgetsSearchPipeline( - List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry, - mCameraContentEntry)); - - pipeline.query("Widget1", results -> - assertEquals(results, - List.of( - new WidgetsListSearchHeaderEntry( - mCalendarHeaderEntry.mPkgItem, - mCalendarHeaderEntry.mTitleSectionName, - mCalendarHeaderEntry.mWidgets.subList(1, 2)), - new WidgetsListContentEntry( - mCalendarHeaderEntry.mPkgItem, - mCalendarHeaderEntry.mTitleSectionName, - mCalendarHeaderEntry.mWidgets.subList(1, 2)), - new WidgetsListSearchHeaderEntry( - mCameraHeaderEntry.mPkgItem, - mCameraHeaderEntry.mTitleSectionName, - mCameraHeaderEntry.mWidgets.subList(1, 3)), - new WidgetsListContentEntry( - mCameraHeaderEntry.mPkgItem, - mCameraHeaderEntry.mTitleSectionName, - mCameraHeaderEntry.mWidgets.subList(1, 3))))); - shadowOf(getMainLooper()).idle(); - } - - private WidgetsListHeaderEntry createWidgetsHeaderEntry(String packageName, String appName, - int numOfWidgets) { - List widgetItems = generateWidgetItems(packageName, numOfWidgets); - PackageItemInfo pInfo = createPackageItemInfo(packageName, appName, - widgetItems.get(0).user); - - return new WidgetsListHeaderEntry(pInfo, /* titleSectionName= */ "", widgetItems); - } - - private WidgetsListContentEntry createWidgetsContentEntry(String packageName, String appName, - int numOfWidgets) { - List widgetItems = generateWidgetItems(packageName, numOfWidgets); - PackageItemInfo pInfo = createPackageItemInfo(packageName, appName, - widgetItems.get(0).user); - - return new WidgetsListContentEntry(pInfo, /* titleSectionName= */ "", widgetItems); - } - - private PackageItemInfo createPackageItemInfo(String packageName, String appName, - UserHandle userHandle) { - PackageItemInfo pInfo = new PackageItemInfo(packageName); - pInfo.title = appName; - pInfo.user = userHandle; - pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0); - return pInfo; - } - - private List generateWidgetItems(String packageName, int numOfWidgets) { - ShadowPackageManager packageManager = shadowOf(mContext.getPackageManager()); - ArrayList widgetItems = new ArrayList<>(); - for (int i = 0; i < numOfWidgets; i++) { - ComponentName cn = ComponentName.createRelative(packageName, ".SampleWidget" + i); - AppWidgetProviderInfo widgetInfo = new AppWidgetProviderInfo(); - widgetInfo.provider = cn; - ReflectionHelpers.setField(widgetInfo, "providerInfo", - packageManager.addReceiverIfNotPresent(cn)); - - WidgetItem widgetItem = new WidgetItem( - LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo), - mTestProfile, mIconCache); - widgetItems.add(widgetItem); - } - return widgetItems; - } -} diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java index d13884ad9e..a4257a208e 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java @@ -169,7 +169,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet onWidgetsBound(); mSearchAndRecommendationViewHolder.mSearchBar.initialize( - mLauncher.getPopupDataProvider().getAllWidgets(), /* searchModeListener= */ this); + mLauncher.getPopupDataProvider(), /* searchModeListener= */ this); } @Override diff --git a/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java b/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java index 56a08b16fb..42f1bb2d21 100644 --- a/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java +++ b/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java @@ -26,10 +26,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.ExtendedEditText; import com.android.launcher3.R; -import com.android.launcher3.search.SearchAlgorithm; -import com.android.launcher3.widget.model.WidgetsListBaseEntry; - -import java.util.List; +import com.android.launcher3.popup.PopupDataProvider; /** * View for a search bar with an edit text with a cancel button. @@ -54,12 +51,10 @@ public class LauncherWidgetsSearchBar extends LinearLayout implements WidgetsSea } @Override - public void initialize(List allWidgets, - SearchModeListener searchModeListener) { - SearchAlgorithm algo = - new SimpleWidgetsSearchAlgorithm(new SimpleWidgetsSearchPipeline(allWidgets)); + public void initialize(PopupDataProvider dataProvider, SearchModeListener searchModeListener) { mController = new WidgetsSearchBarController( - algo, mEditText, mCancelButton, searchModeListener); + new SimpleWidgetsSearchAlgorithm(dataProvider), + mEditText, mCancelButton, searchModeListener); } @Override diff --git a/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithm.java b/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithm.java index 15d245486b..9be3b5f1e4 100644 --- a/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithm.java +++ b/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithm.java @@ -16,42 +16,41 @@ package com.android.launcher3.widget.picker.search; -import android.os.Handler; -import android.util.Log; +import static com.android.launcher3.search.StringMatcherUtility.matches; +import android.os.Handler; + +import com.android.launcher3.model.WidgetItem; +import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.search.SearchAlgorithm; import com.android.launcher3.search.SearchCallback; +import com.android.launcher3.search.StringMatcherUtility.StringMatcher; import com.android.launcher3.widget.model.WidgetsListBaseEntry; +import com.android.launcher3.widget.model.WidgetsListContentEntry; +import com.android.launcher3.widget.model.WidgetsListHeaderEntry; +import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; /** * Implementation of {@link SearchAlgorithm} that posts a task to query on the main thread. */ public final class SimpleWidgetsSearchAlgorithm implements SearchAlgorithm { - private static final boolean DEBUG = false; - private static final String TAG = "SimpleWidgetsSearchAlgo"; - private static final String DELIM = "\t"; - private final Handler mResultHandler; - private final WidgetsPickerSearchPipeline mSearchPipeline; + private final PopupDataProvider mDataProvider; - public SimpleWidgetsSearchAlgorithm(WidgetsPickerSearchPipeline searchPipeline) { + public SimpleWidgetsSearchAlgorithm(PopupDataProvider dataProvider) { mResultHandler = new Handler(); - mSearchPipeline = searchPipeline; + mDataProvider = dataProvider; } @Override public void doSearch(String query, SearchCallback callback) { - long startTime = System.currentTimeMillis(); - String queryToken = query + DELIM + startTime; - if (DEBUG) { - Log.d(TAG, "doSearch queryToken:" + queryToken); - } - mSearchPipeline.query(query, - results -> mResultHandler.post( - () -> callback.onSearchResult(queryToken, new ArrayList(results)))); + ArrayList result = getFilteredWidgets(mDataProvider, query); + mResultHandler.post(() -> callback.onSearchResult(query, result)); } @Override @@ -60,4 +59,36 @@ public final class SimpleWidgetsSearchAlgorithm implements SearchAlgorithm getFilteredWidgets( + PopupDataProvider dataProvider, String input) { + ArrayList results = new ArrayList<>(); + dataProvider.getAllWidgets().stream() + .filter(entry -> entry instanceof WidgetsListHeaderEntry) + .forEach(headerEntry -> { + List matchedWidgetItems = filterWidgetItems( + input, headerEntry.mPkgItem.title.toString(), headerEntry.mWidgets); + if (matchedWidgetItems.size() > 0) { + results.add(new WidgetsListSearchHeaderEntry(headerEntry.mPkgItem, + headerEntry.mTitleSectionName, matchedWidgetItems)); + results.add(new WidgetsListContentEntry(headerEntry.mPkgItem, + headerEntry.mTitleSectionName, matchedWidgetItems)); + } + }); + return results; + } + + private static List filterWidgetItems(String query, String packageTitle, + List items) { + StringMatcher matcher = StringMatcher.getInstance(); + if (matches(query, packageTitle, matcher)) { + return items; + } + return items.stream() + .filter(item -> matches(query, item.label, matcher)) + .collect(Collectors.toList()); + } } diff --git a/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipeline.java b/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipeline.java deleted file mode 100644 index 5222e8ec59..0000000000 --- a/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchPipeline.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.widget.picker.search; - -import static com.android.launcher3.search.StringMatcherUtility.matches; - -import com.android.launcher3.model.WidgetItem; -import com.android.launcher3.search.StringMatcherUtility.StringMatcher; -import com.android.launcher3.widget.model.WidgetsListBaseEntry; -import com.android.launcher3.widget.model.WidgetsListContentEntry; -import com.android.launcher3.widget.model.WidgetsListHeaderEntry; -import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -/** - * Implementation of {@link WidgetsPickerSearchPipeline} that performs search by prefix matching on - * app names and widget labels. - */ -public final class SimpleWidgetsSearchPipeline implements WidgetsPickerSearchPipeline { - - private final List mAllEntries; - - public SimpleWidgetsSearchPipeline(List allEntries) { - mAllEntries = allEntries; - } - - @Override - public void query(String input, Consumer> callback) { - ArrayList results = new ArrayList<>(); - mAllEntries.stream().filter(entry -> entry instanceof WidgetsListHeaderEntry) - .forEach(headerEntry -> { - List matchedWidgetItems = filterWidgetItems( - input, headerEntry.mPkgItem.title.toString(), headerEntry.mWidgets); - if (matchedWidgetItems.size() > 0) { - results.add(new WidgetsListSearchHeaderEntry(headerEntry.mPkgItem, - headerEntry.mTitleSectionName, matchedWidgetItems)); - results.add(new WidgetsListContentEntry(headerEntry.mPkgItem, - headerEntry.mTitleSectionName, matchedWidgetItems)); - } - }); - callback.accept(results); - } - - private List filterWidgetItems(String query, String packageTitle, - List items) { - StringMatcher matcher = StringMatcher.getInstance(); - if (matches(query, packageTitle, matcher)) { - return items; - } - return items.stream() - .filter(item -> matches(query, item.label, matcher)) - .collect(Collectors.toList()); - } -} diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsPickerSearchPipeline.java b/src/com/android/launcher3/widget/picker/search/WidgetsPickerSearchPipeline.java deleted file mode 100644 index d12782c971..0000000000 --- a/src/com/android/launcher3/widget/picker/search/WidgetsPickerSearchPipeline.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.widget.picker.search; - -import com.android.launcher3.widget.model.WidgetsListBaseEntry; - -import java.util.List; -import java.util.function.Consumer; - -/** - * An interface for a pipeline to handle widgets search. - */ -public interface WidgetsPickerSearchPipeline { - - /** - * Performs a search query asynchronically. Invokes {@code callback} when the search is - * complete. - */ - void query(String input, Consumer> callback); - - /** - * Cancels any ongoing search request. - */ - default void cancel() {}; - - /** - * Cleans up after search is no longer needed. - */ - default void destroy() {}; -} diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java index 3ac82c0ca7..0ac47ce5f2 100644 --- a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java +++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java @@ -16,9 +16,7 @@ package com.android.launcher3.widget.picker.search; -import com.android.launcher3.widget.model.WidgetsListBaseEntry; - -import java.util.List; +import com.android.launcher3.popup.PopupDataProvider; /** * Interface for a widgets picker search bar. @@ -27,7 +25,7 @@ public interface WidgetsSearchBar { /** * Attaches a controller to the search bar which interacts with {@code searchModeListener}. */ - void initialize(List allWidgets, SearchModeListener searchModeListener); + void initialize(PopupDataProvider dataProvider, SearchModeListener searchModeListener); /** * Clears search bar.