diff --git a/AndroidManifest.xml b/AndroidManifest.xml index fe3b792843b..d0ae16b4e16 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -242,13 +242,6 @@ - - - > { - - private static final String TAG = "A11yResultFutureTask"; - - public AccessibilityServiceResultLoader(Context context, String query, - SiteMapManager manager) { - super(new AccessibilityServiceResultCallable(context, query, manager)); - } - - static class AccessibilityServiceResultCallable implements - Callable> { - - private static final int NAME_NO_MATCH = -1; - - private final Context mContext; - private List mBreadcrumb; - private SiteMapManager mSiteMapManager; - @VisibleForTesting - final String mQuery; - private final AccessibilityManager mAccessibilityManager; - private final PackageManager mPackageManager; - private final int mUserId; - - public AccessibilityServiceResultCallable(Context context, String query, - SiteMapManager mapManager) { - mUserId = UserHandle.myUserId(); - mContext = context; - mSiteMapManager = mapManager; - mPackageManager = context.getPackageManager(); - mAccessibilityManager = - (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); - mQuery = query; - } - - @Override - public List call() throws Exception { - long startTime = System.currentTimeMillis(); - final List results = new ArrayList<>(); - final List services = mAccessibilityManager - .getInstalledAccessibilityServiceList(); - final IconDrawableFactory iconFactory = IconDrawableFactory.newInstance(mContext); - final String screenTitle = mContext.getString(R.string.accessibility_settings); - for (AccessibilityServiceInfo service : services) { - if (service == null) { - continue; - } - final ResolveInfo resolveInfo = service.getResolveInfo(); - if (service.getResolveInfo() == null) { - continue; - } - final ServiceInfo serviceInfo = resolveInfo.serviceInfo; - final CharSequence title = resolveInfo.loadLabel(mPackageManager); - final int wordDiff = getWordDifference(title.toString(), mQuery); - if (wordDiff == NAME_NO_MATCH) { - continue; - } - final Drawable icon; - if (resolveInfo.getIconResource() == 0) { - icon = ContextCompat.getDrawable(mContext, R.mipmap.ic_accessibility_generic); - } else { - icon = iconFactory.getBadgedIcon( - resolveInfo.serviceInfo, - resolveInfo.serviceInfo.applicationInfo, - mUserId); - } - final String componentName = new ComponentName(serviceInfo.packageName, - serviceInfo.name).flattenToString(); - final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(mContext, - AccessibilitySettings.class.getName(), componentName, screenTitle); - - results.add(new SearchResult.Builder() - .setTitle(title) - .addBreadcrumbs(getBreadCrumb()) - .setPayload(new ResultPayload(intent)) - .setRank(wordDiff) - .setIcon(icon) - .setStableId(Objects.hash(screenTitle, componentName)) - .build()); - } - Collections.sort(results); - Log.i(TAG, "A11y search loading took:" + (System.currentTimeMillis() - startTime)); - return results; - } - - private List getBreadCrumb() { - if (mBreadcrumb == null || mBreadcrumb.isEmpty()) { - mBreadcrumb = mSiteMapManager.buildBreadCrumb( - mContext, AccessibilitySettings.class.getName(), - mContext.getString(R.string.accessibility_settings)); - } - return mBreadcrumb; - } - } -} diff --git a/src/com/android/settings/search/AppSearchResult.java b/src/com/android/settings/search/AppSearchResult.java deleted file mode 100644 index b59e32e5666..00000000000 --- a/src/com/android/settings/search/AppSearchResult.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.pm.ApplicationInfo; -import android.os.UserHandle; - -public class AppSearchResult extends SearchResult { - /** - * Installed app's ApplicationInfo for delayed loading of icons - */ - public final ApplicationInfo info; - - public AppSearchResult(Builder builder) { - super(builder); - info = builder.mInfo; - } - - public UserHandle getAppUserHandle() { - return new UserHandle(UserHandle.getUserId(info.uid)); - } - - public static class Builder extends SearchResult.Builder { - protected ApplicationInfo mInfo; - - public SearchResult.Builder setAppInfo(ApplicationInfo info) { - mInfo = info; - return this; - } - - public AppSearchResult build() { - return new AppSearchResult(this); - } - } -} diff --git a/src/com/android/settings/search/DatabaseResultLoader.java b/src/com/android/settings/search/DatabaseResultLoader.java index 66548a4d8d6..3b5cc476c2e 100644 --- a/src/com/android/settings/search/DatabaseResultLoader.java +++ b/src/com/android/settings/search/DatabaseResultLoader.java @@ -18,35 +18,11 @@ package com.android.settings.search; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns; -import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX; - -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.support.annotation.VisibleForTesting; -import android.util.Log; -import android.util.Pair; - -import com.android.settings.dashboard.SiteMapManager; -import com.android.settings.overlay.FeatureFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; /** * AsyncTask to retrieve Settings, first party app and any intent based results. */ -public class DatabaseResultLoader extends FutureTask> { +public class DatabaseResultLoader { private static final String TAG = "DatabaseResultLoader"; @@ -66,18 +42,6 @@ public class DatabaseResultLoader extends FutureTask> { - - public final String[] MATCH_COLUMNS_TERTIARY = { - IndexColumns.DATA_KEYWORDS, - IndexColumns.DATA_ENTRIES - }; - - @VisibleForTesting - final String mQueryText; - private final Context mContext; - private final CursorToSearchResultConverter mConverter; - private final SiteMapManager mSiteMapManager; - private final SearchFeatureProvider mFeatureProvider; - - public StaticSearchResultCallable(Context context, String queryText, - SiteMapManager mapManager) { - mContext = context; - mSiteMapManager = mapManager; - mQueryText = queryText; - mConverter = new CursorToSearchResultConverter(context); - mFeatureProvider = FeatureFactory.getFactory(context).getSearchFeatureProvider(); - } - - @Override - public List call() { - if (mQueryText == null || mQueryText.isEmpty()) { - return new ArrayList<>(); - } - - // TODO (b/68656233) Consolidate timing metrics - long startTime = System.currentTimeMillis(); - // Start a Future to get search result scores. - FutureTask>> rankerTask = mFeatureProvider.getRankerTask( - mContext, mQueryText); - - if (rankerTask != null) { - ExecutorService executorService = mFeatureProvider.getExecutorService(); - executorService.execute(rankerTask); - } - - final Set resultSet = new HashSet<>(); - - resultSet.addAll(firstWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[0])); - resultSet.addAll(secondaryWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[1])); - resultSet.addAll(anyWordQuery(MATCH_COLUMNS_SECONDARY, BASE_RANKS[2])); - resultSet.addAll(anyWordQuery(MATCH_COLUMNS_TERTIARY, BASE_RANKS[3])); - - // Try to retrieve the scores in time. Otherwise use static ranking. - if (rankerTask != null) { - try { - final long timeoutMs = mFeatureProvider.smartSearchRankingTimeoutMs(mContext); - List> searchRankScores = rankerTask.get(timeoutMs, - TimeUnit.MILLISECONDS); - return getDynamicRankedResults(resultSet, searchRankScores); - } catch (TimeoutException | InterruptedException | ExecutionException e) { - Log.d(TAG, "Error waiting for result scores: " + e); - } - } - - List resultList = new ArrayList<>(resultSet); - Collections.sort(resultList); - Log.i(TAG, "Static search loading took:" + (System.currentTimeMillis() - startTime)); - return resultList; - } - - // TODO (b/33577327) Retrieve all search results with a single query. - - /** - * Creates and executes the query which matches prefixes of the first word of the given - * columns. - * - * @param matchColumns The columns to match on - * @param baseRank The highest rank achievable by these results - * @return A set of the matching results. - */ - private Set firstWordQuery(String[] matchColumns, int baseRank) { - final String whereClause = buildSingleWordWhereClause(matchColumns); - final String query = mQueryText + "%"; - final String[] selection = buildSingleWordSelection(query, matchColumns.length); - - return query(whereClause, selection, baseRank); - } - - /** - * Creates and executes the query which matches prefixes of the non-first words of the - * given columns. - * - * @param matchColumns The columns to match on - * @param baseRank The highest rank achievable by these results - * @return A set of the matching results. - */ - private Set secondaryWordQuery(String[] matchColumns, int baseRank) { - final String whereClause = buildSingleWordWhereClause(matchColumns); - final String query = "% " + mQueryText + "%"; - final String[] selection = buildSingleWordSelection(query, matchColumns.length); - - return query(whereClause, selection, baseRank); - } - - /** - * Creates and executes the query which matches prefixes of the any word of the given - * columns. - * - * @param matchColumns The columns to match on - * @param baseRank The highest rank achievable by these results - * @return A set of the matching results. - */ - private Set anyWordQuery(String[] matchColumns, int baseRank) { - final String whereClause = buildTwoWordWhereClause(matchColumns); - final String[] selection = buildAnyWordSelection(matchColumns.length * 2); - - return query(whereClause, selection, baseRank); - } - - /** - * Generic method used by all of the query methods above to execute a query. - * - * @param whereClause Where clause for the SQL query which uses bindings. - * @param selection List of the transformed query to match each bind in the whereClause - * @param baseRank The highest rank achievable by these results. - * @return A set of the matching results. - */ - private Set query(String whereClause, String[] selection, int baseRank) { - final SQLiteDatabase database = - IndexDatabaseHelper.getInstance(mContext).getReadableDatabase(); - try (Cursor resultCursor = database.query(TABLE_PREFS_INDEX, SELECT_COLUMNS, - whereClause, - selection, null, null, null)) { - return mConverter.convertCursor(mSiteMapManager, resultCursor, baseRank); - } - } - - /** - * Builds the SQLite WHERE clause that matches all matchColumns for a single query. - * - * @param matchColumns List of columns that will be used for matching. - * @return The constructed WHERE clause. - */ - private static String buildSingleWordWhereClause(String[] matchColumns) { - StringBuilder sb = new StringBuilder(" ("); - final int count = matchColumns.length; - for (int n = 0; n < count; n++) { - sb.append(matchColumns[n]); - sb.append(" like ? "); - if (n < count - 1) { - sb.append(" OR "); - } - } - sb.append(") AND enabled = 1"); - return sb.toString(); - } - - /** - * Builds the SQLite WHERE clause that matches all matchColumns to two different queries. - * - * @param matchColumns List of columns that will be used for matching. - * @return The constructed WHERE clause. - */ - private static String buildTwoWordWhereClause(String[] matchColumns) { - StringBuilder sb = new StringBuilder(" ("); - final int count = matchColumns.length; - for (int n = 0; n < count; n++) { - sb.append(matchColumns[n]); - sb.append(" like ? OR "); - sb.append(matchColumns[n]); - sb.append(" like ?"); - if (n < count - 1) { - sb.append(" OR "); - } - } - sb.append(") AND enabled = 1"); - return sb.toString(); - } - - /** - * Fills out the selection array to match the query as the prefix of a single word. - * - * @param size is the number of columns to be matched. - */ - private String[] buildSingleWordSelection(String query, int size) { - String[] selection = new String[size]; - - for (int i = 0; i < size; i++) { - selection[i] = query; - } - return selection; - } - - /** - * Fills out the selection array to match the query as the prefix of a word. - * - * @param size is twice the number of columns to be matched. The first match is for the - * prefix - * of the first word in the column. The second match is for any subsequent word - * prefix match. - */ - private String[] buildAnyWordSelection(int size) { - String[] selection = new String[size]; - final String query = mQueryText + "%"; - final String subStringQuery = "% " + mQueryText + "%"; - - for (int i = 0; i < (size - 1); i += 2) { - selection[i] = query; - selection[i + 1] = subStringQuery; - } - return selection; - } - - private List getDynamicRankedResults(Set unsortedSet, - List> searchRankScores) { - TreeSet dbResultsSortedByScores = new TreeSet<>( - (o1, o2) -> { - float score1 = getRankingScoreByStableId(searchRankScores, o1.stableId); - float score2 = getRankingScoreByStableId(searchRankScores, o2.stableId); - if (score1 > score2) { - return -1; - } else if (score1 == score2) { - return 0; - } else { - return 1; - } - }); - dbResultsSortedByScores.addAll(unsortedSet); - - return new ArrayList<>(dbResultsSortedByScores); - } - - /** - * Looks up ranking score for stableId - * - * @param stableId String of stableId - * @return the ranking score corresponding to the given stableId. If there is no score - * available for this stableId, -Float.MAX_VALUE is returned. - */ - @VisibleForTesting - Float getRankingScoreByStableId(List> searchRankScores, int stableId) { - for (Pair rankingScore : searchRankScores) { - if (Integer.toString(stableId).compareTo(rankingScore.first) == 0) { - return rankingScore.second; - } - } - // If stableId not found in the list, we assign the minimum score so it will appear at - // the end of the list. - Log.w(TAG, "stableId " + stableId + " was not in the ranking scores."); - return -Float.MAX_VALUE; - } - } } \ No newline at end of file diff --git a/src/com/android/settings/search/InlineSwitchViewHolder.java b/src/com/android/settings/search/InlineSwitchViewHolder.java deleted file mode 100644 index bb8320d3b36..00000000000 --- a/src/com/android/settings/search/InlineSwitchViewHolder.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.Context; -import android.util.Pair; -import android.view.View; -import android.widget.Switch; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.R; - -/** - * ViewHolder for Settings represented as SwitchPreferences. - */ -public class InlineSwitchViewHolder extends SearchViewHolder { - - public final Switch switchView; - - private final Context mContext; - - public InlineSwitchViewHolder(View view, Context context) { - super(view); - mContext = context; - switchView = view.findViewById(R.id.switchView); - } - - @Override - public int getClickActionMetricName() { - return MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_INLINE_RESULT; - } - - @Override - public void onBind(SearchFragment fragment, final SearchResult result) { - super.onBind(fragment, result); - if (mContext == null) { - return; - } - final InlineSwitchPayload payload = (InlineSwitchPayload) result.payload; - switchView.setChecked(payload.getValue(mContext) == InlineSwitchPayload.TRUE); - switchView.setOnCheckedChangeListener((buttonView, isChecked) -> { - final Pair value = Pair.create( - MetricsEvent.FIELD_SETTINGS_SEARCH_INLINE_RESULT_VALUE, isChecked - ? 1L : 0L); - fragment.onSearchResultClicked(this, result, value); - int newValue = isChecked ? InlineSwitchPayload.TRUE : InlineSwitchPayload.FALSE; - payload.setValue(mContext, newValue); - }); - } -} diff --git a/src/com/android/settings/search/InputDeviceResultLoader.java b/src/com/android/settings/search/InputDeviceResultLoader.java deleted file mode 100644 index 598281c0b67..00000000000 --- a/src/com/android/settings/search/InputDeviceResultLoader.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static android.content.Context.INPUT_METHOD_SERVICE; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ServiceInfo; -import android.hardware.input.InputManager; -import android.hardware.input.KeyboardLayout; -import android.support.annotation.VisibleForTesting; -import android.util.Log; -import android.view.InputDevice; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.InputMethodSubtype; - -import com.android.settings.R; -import com.android.settings.dashboard.SiteMapManager; -import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment; -import com.android.settings.inputmethod.PhysicalKeyboardFragment; -import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; - -/** - * Search result for input devices (physical/virtual keyboard, game controllers, etc) - */ - -public class InputDeviceResultLoader extends FutureTask> { - - private static final String TAG = "InputResultFutureTask"; - - @VisibleForTesting - static final String PHYSICAL_KEYBOARD_FRAGMENT = PhysicalKeyboardFragment.class.getName(); - @VisibleForTesting - static final String VIRTUAL_KEYBOARD_FRAGMENT = - AvailableVirtualKeyboardFragment.class.getName(); - - public InputDeviceResultLoader(Context context, String query, SiteMapManager manager) { - super(new InputDeviceResultCallable(context, query, manager)); - } - - static class InputDeviceResultCallable implements - Callable> { - private static final int NAME_NO_MATCH = -1; - - private final Context mContext; - private final SiteMapManager mSiteMapManager; - private final InputManager mInputManager; - private final InputMethodManager mImm; - private final PackageManager mPackageManager; - @VisibleForTesting - final String mQuery; - - private List mPhysicalKeyboardBreadcrumb; - private List mVirtualKeyboardBreadcrumb; - - public InputDeviceResultCallable(Context context, String query, SiteMapManager mapManager) { - mContext = context; - mQuery = query; - mSiteMapManager = mapManager; - mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE); - mImm = (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE); - mPackageManager = context.getPackageManager(); - } - - @Override - public List call() { - long startTime = System.currentTimeMillis(); - final List results = new ArrayList<>(); - results.addAll(buildPhysicalKeyboardSearchResults()); - results.addAll(buildVirtualKeyboardSearchResults()); - Collections.sort(results); - Log.i(TAG, "Input search loading took:" + (System.currentTimeMillis() - startTime)); - return results; - } - - private Set buildPhysicalKeyboardSearchResults() { - final Set results = new HashSet<>(); - final String screenTitle = mContext.getString(R.string.physical_keyboard_title); - - for (final InputDevice device : getPhysicalFullKeyboards()) { - final String deviceName = device.getName(); - final int wordDiff = InstalledAppResultLoader.getWordDifference(deviceName, - mQuery); - if (wordDiff == NAME_NO_MATCH) { - continue; - } - final String keyboardLayoutDescriptor = mInputManager - .getCurrentKeyboardLayoutForInputDevice(device.getIdentifier()); - final KeyboardLayout keyboardLayout = (keyboardLayoutDescriptor != null) - ? mInputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null; - final String summary = (keyboardLayout != null) - ? keyboardLayout.toString() - : mContext.getString(R.string.keyboard_layout_default_label); - - final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(mContext, - PHYSICAL_KEYBOARD_FRAGMENT, deviceName, screenTitle); - results.add(new SearchResult.Builder() - .setTitle(deviceName) - .setPayload(new ResultPayload(intent)) - .setStableId(Objects.hash(PHYSICAL_KEYBOARD_FRAGMENT, deviceName)) - .setSummary(summary) - .setRank(wordDiff) - .addBreadcrumbs(getPhysicalKeyboardBreadCrumb()) - .build()); - } - return results; - } - - private Set buildVirtualKeyboardSearchResults() { - final Set results = new HashSet<>(); - final String screenTitle = mContext.getString(R.string.add_virtual_keyboard); - final List inputMethods = mImm.getInputMethodList(); - for (InputMethodInfo info : inputMethods) { - final String title = info.loadLabel(mPackageManager).toString(); - final String summary = InputMethodAndSubtypeUtil - .getSubtypeLocaleNameListAsSentence(getAllSubtypesOf(info), mContext, info); - int wordDiff = InstalledAppResultLoader.getWordDifference(title, mQuery); - if (wordDiff == NAME_NO_MATCH) { - wordDiff = InstalledAppResultLoader.getWordDifference(summary, mQuery); - } - if (wordDiff == NAME_NO_MATCH) { - continue; - } - final ServiceInfo serviceInfo = info.getServiceInfo(); - final String key = new ComponentName(serviceInfo.packageName, serviceInfo.name) - .flattenToString(); - final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(mContext, - VIRTUAL_KEYBOARD_FRAGMENT, key, screenTitle); - results.add(new SearchResult.Builder() - .setTitle(title) - .setSummary(summary) - .setRank(wordDiff) - .setStableId(Objects.hash(VIRTUAL_KEYBOARD_FRAGMENT, key)) - .addBreadcrumbs(getVirtualKeyboardBreadCrumb()) - .setPayload(new ResultPayload(intent)) - .build()); - } - return results; - } - - private List getPhysicalKeyboardBreadCrumb() { - if (mPhysicalKeyboardBreadcrumb == null || mPhysicalKeyboardBreadcrumb.isEmpty()) { - mPhysicalKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb( - mContext, PHYSICAL_KEYBOARD_FRAGMENT, - mContext.getString(R.string.physical_keyboard_title)); - } - return mPhysicalKeyboardBreadcrumb; - } - - - private List getVirtualKeyboardBreadCrumb() { - if (mVirtualKeyboardBreadcrumb == null || mVirtualKeyboardBreadcrumb.isEmpty()) { - final Context context = mContext; - mVirtualKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb( - context, VIRTUAL_KEYBOARD_FRAGMENT, - context.getString(R.string.add_virtual_keyboard)); - } - return mVirtualKeyboardBreadcrumb; - } - - private List getPhysicalFullKeyboards() { - final List keyboards = new ArrayList<>(); - final int[] deviceIds = InputDevice.getDeviceIds(); - if (deviceIds != null) { - for (int deviceId : deviceIds) { - final InputDevice device = InputDevice.getDevice(deviceId); - if (device != null && !device.isVirtual() && device.isFullKeyboard()) { - keyboards.add(device); - } - } - } - return keyboards; - } - - private static List getAllSubtypesOf(final InputMethodInfo imi) { - final int subtypeCount = imi.getSubtypeCount(); - final List allSubtypes = new ArrayList<>(subtypeCount); - for (int index = 0; index < subtypeCount; index++) { - allSubtypes.add(imi.getSubtypeAt(index)); - } - return allSubtypes; - } - } -} diff --git a/src/com/android/settings/search/InstalledAppResultLoader.java b/src/com/android/settings/search/InstalledAppResultLoader.java deleted file mode 100644 index e5d8ac1f343..00000000000 --- a/src/com/android/settings/search/InstalledAppResultLoader.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.UserInfo; -import android.net.Uri; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.support.annotation.VisibleForTesting; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.logging.nano.MetricsProto; -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.applications.manageapplications.ManageApplications; -import com.android.settings.dashboard.SiteMapManager; -import com.android.settingslib.wrapper.PackageManagerWrapper; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; - -/** - * Search loader for installed apps. - */ -public class InstalledAppResultLoader extends FutureTask> { - - private static final String TAG = "InstalledAppFutureTask"; - - private static final int NAME_NO_MATCH = -1; - private static final Intent LAUNCHER_PROBE = new Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_LAUNCHER); - - public InstalledAppResultLoader(Context context, PackageManagerWrapper wrapper, - String query, SiteMapManager manager) { - super(new InstalledAppResultCallable(context, wrapper, query, manager)); - } - - /** - * Returns "difference" between appName and query string. appName must contain all - * characters from query as a prefix to a word, in the same order. - * If not, returns NAME_NO_MATCH. - * If they do match, returns an int value representing how different they are, - * and larger values means they are less similar. - *

- * Example: - * appName: Abcde, query: Abcde, Returns 0 - * appName: Abcde, query: abc, Returns 2 - * appName: Abcde, query: ab, Returns 3 - * appName: Abcde, query: bc, Returns NAME_NO_MATCH - * appName: Abcde, query: xyz, Returns NAME_NO_MATCH - * appName: Abc de, query: de, Returns 4 - * TODO: Move this to a common util class. - */ - static int getWordDifference(String appName, String query) { - if (TextUtils.isEmpty(appName) || TextUtils.isEmpty(query)) { - return NAME_NO_MATCH; - } - - final char[] queryTokens = query.toLowerCase().toCharArray(); - final char[] appTokens = appName.toLowerCase().toCharArray(); - final int appLength = appTokens.length; - if (queryTokens.length > appLength) { - return NAME_NO_MATCH; - } - - int i = 0; - int j; - - while (i < appLength) { - j = 0; - // Currently matching a prefix - while ((i + j < appLength) && (queryTokens[j] == appTokens[i + j])) { - // Matched the entire query - if (++j >= queryTokens.length) { - // Use the diff in length as a proxy of how close the 2 words match. - // Value range from 0 to infinity. - return appLength - queryTokens.length; - } - } - - i += j; - - // Remaining string is longer that the query or we have search the whole app name. - if (queryTokens.length > appLength - i) { - return NAME_NO_MATCH; - } - - // This is the first index where app name and query name are different - // Find the next space in the app name or the end of the app name. - while ((i < appLength) && (!Character.isWhitespace(appTokens[i++]))) ; - - // Find the start of the next word - while ((i < appLength) && !(Character.isLetter(appTokens[i]) - || Character.isDigit(appTokens[i]))) { - // Increment in body because we cannot guarantee which condition was true - i++; - } - } - return NAME_NO_MATCH; - } - - static class InstalledAppResultCallable implements - Callable> { - - private final Context mContext; - private List mBreadcrumb; - private SiteMapManager mSiteMapManager; - @VisibleForTesting - final String mQuery; - private final UserManager mUserManager; - private final PackageManagerWrapper mPackageManager; - private final List mHomeActivities = new ArrayList<>(); - - public InstalledAppResultCallable(Context context, PackageManagerWrapper pmWrapper, - String query, SiteMapManager mapManager) { - mContext = context; - mSiteMapManager = mapManager; - mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - mPackageManager = pmWrapper; - mQuery = query; - } - - @Override - public List call() throws Exception { - long startTime = System.currentTimeMillis(); - final List results = new ArrayList<>(); - final PackageManager pm = mPackageManager.getPackageManager(); - - mHomeActivities.clear(); - mPackageManager.getHomeActivities(mHomeActivities); - - for (UserInfo user : getUsersToCount()) { - final List apps = - mPackageManager.getInstalledApplicationsAsUser( - PackageManager.MATCH_DISABLED_COMPONENTS - | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS - | (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0), - user.id); - for (ApplicationInfo info : apps) { - if (!shouldIncludeAsCandidate(info, user)) { - continue; - } - final CharSequence label = info.loadLabel(pm); - final int wordDiff = getWordDifference(label.toString(), mQuery); - if (wordDiff == NAME_NO_MATCH) { - continue; - } - final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.fromParts("package", info.packageName, null)) - .putExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY, - MetricsProto.MetricsEvent.DASHBOARD_SEARCH_RESULTS); - - final AppSearchResult.Builder builder = new AppSearchResult.Builder(); - builder.setAppInfo(info) - .setStableId(Objects.hash(info.packageName, user.id)) - .setTitle(info.loadLabel(pm)) - .setRank(getRank(wordDiff)) - .addBreadcrumbs(getBreadCrumb()) - .setPayload(new ResultPayload(intent)); - results.add(builder.build()); - } - } - Collections.sort(results); - Log.i(TAG, "App search loading took:" + (System.currentTimeMillis() - startTime)); - return results; - } - - /** - * Returns true if the candidate should be included in candidate list - *

- * This method matches logic in {@code ApplicationState#FILTER_DOWNLOADED_AND_LAUNCHER}. - */ - private boolean shouldIncludeAsCandidate(ApplicationInfo info, UserInfo user) { - // Not system app - if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 - || (info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { - return true; - } - // Shows up in launcher - final Intent launchIntent = new Intent(LAUNCHER_PROBE) - .setPackage(info.packageName); - final List intents = mPackageManager.queryIntentActivitiesAsUser( - launchIntent, - PackageManager.MATCH_DISABLED_COMPONENTS - | PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - user.id); - if (intents != null && intents.size() != 0) { - return true; - } - // Is launcher app itself - return isPackageInList(mHomeActivities, info.packageName); - } - - private List getUsersToCount() { - return mUserManager.getProfiles(UserHandle.myUserId()); - } - - private boolean isPackageInList(List resolveInfos, String pkg) { - for (ResolveInfo info : resolveInfos) { - if (TextUtils.equals(info.activityInfo.packageName, pkg)) { - return true; - } - } - return false; - } - - private List getBreadCrumb() { - if (mBreadcrumb == null || mBreadcrumb.isEmpty()) { - mBreadcrumb = mSiteMapManager.buildBreadCrumb( - mContext, ManageApplications.class.getName(), - mContext.getString(R.string.applications_settings)); - } - return mBreadcrumb; - } - - /** - * A temporary ranking scheme for installed apps. - * - * @param wordDiff difference between query length and app name length. - * @return the ranking. - */ - private int getRank(int wordDiff) { - if (wordDiff < 6) { - return 2; - } - return 3; - } - } -} diff --git a/src/com/android/settings/search/IntentSearchViewHolder.java b/src/com/android/settings/search/IntentSearchViewHolder.java deleted file mode 100644 index 8f6aa2ce094..00000000000 --- a/src/com/android/settings/search/IntentSearchViewHolder.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.os.UserHandle; -import android.support.annotation.VisibleForTesting; -import android.util.Log; -import android.view.View; - -import com.android.internal.logging.nano.MetricsProto; - -import java.util.List; - -/** - * ViewHolder for intent based search results. - * The DatabaseResultLoader is the primary use case for this ViewHolder. - */ -public class IntentSearchViewHolder extends SearchViewHolder { - - private static final String TAG = "IntentSearchViewHolder"; - @VisibleForTesting - static final int REQUEST_CODE_NO_OP = 0; - - public IntentSearchViewHolder(View view) { - super(view); - } - - @Override - public int getClickActionMetricName() { - return MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT; - } - - @Override - public void onBind(final SearchFragment fragment, final SearchResult result) { - super.onBind(fragment, result); - - itemView.setOnClickListener(v -> { - fragment.onSearchResultClicked(this, result); - final Intent intent = result.payload.getIntent(); - // Use app user id to support work profile use case. - if (result instanceof AppSearchResult) { - AppSearchResult appResult = (AppSearchResult) result; - UserHandle userHandle = appResult.getAppUserHandle(); - fragment.getActivity().startActivityAsUser(intent, userHandle); - } else { - final PackageManager pm = fragment.getActivity().getPackageManager(); - final List info = pm.queryIntentActivities(intent, 0 /* flags */); - if (info != null && !info.isEmpty()) { - fragment.startActivityForResult(intent, REQUEST_CODE_NO_OP); - } else { - Log.e(TAG, "Cannot launch search result, title: " - + result.title + ", " + intent); - } - } - }); - } -} diff --git a/src/com/android/settings/search/SavedQueryController.java b/src/com/android/settings/search/SavedQueryController.java deleted file mode 100644 index eaba3d6bba4..00000000000 --- a/src/com/android/settings/search/SavedQueryController.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.app.LoaderManager; -import android.content.Context; -import android.content.Loader; -import android.os.Bundle; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; - -import com.android.settings.R; -import com.android.settings.overlay.FeatureFactory; - -import java.util.List; - -public class SavedQueryController implements LoaderManager.LoaderCallbacks, - MenuItem.OnMenuItemClickListener { - - // TODO: make a generic background task manager to handle one-off tasks like this one. - private static final String ARG_QUERY = "remove_query"; - private static final String TAG = "SearchSavedQueryCtrl"; - - private static final int MENU_SEARCH_HISTORY = 1000; - - private final Context mContext; - private final LoaderManager mLoaderManager; - private final SearchFeatureProvider mSearchFeatureProvider; - private final SearchResultsAdapter mResultAdapter; - - public SavedQueryController(Context context, LoaderManager loaderManager, - SearchResultsAdapter resultsAdapter) { - mContext = context; - mLoaderManager = loaderManager; - mResultAdapter = resultsAdapter; - mSearchFeatureProvider = FeatureFactory.getFactory(context) - .getSearchFeatureProvider(); - } - - @Override - public Loader onCreateLoader(int id, Bundle args) { - switch (id) { - case SearchFragment.SearchLoaderId.SAVE_QUERY_TASK: - return new SavedQueryRecorder(mContext, args.getString(ARG_QUERY)); - case SearchFragment.SearchLoaderId.REMOVE_QUERY_TASK: - return new SavedQueryRemover(mContext); - case SearchFragment.SearchLoaderId.SAVED_QUERIES: - return mSearchFeatureProvider.getSavedQueryLoader(mContext); - } - return null; - } - - @Override - public void onLoadFinished(Loader loader, Object data) { - switch (loader.getId()) { - case SearchFragment.SearchLoaderId.REMOVE_QUERY_TASK: - mLoaderManager.restartLoader(SearchFragment.SearchLoaderId.SAVED_QUERIES, - null /* args */, this /* callback */); - break; - case SearchFragment.SearchLoaderId.SAVED_QUERIES: - if (SettingsSearchIndexablesProvider.DEBUG) { - Log.d(TAG, "Saved queries loaded"); - } - mResultAdapter.displaySavedQuery((List) data); - break; - } - } - - @Override - public void onLoaderReset(Loader loader) { - } - - @Override - public boolean onMenuItemClick(MenuItem item) { - if (item.getItemId() != MENU_SEARCH_HISTORY) { - return false; - } - removeQueries(); - return true; - } - - public void buildMenuItem(Menu menu) { - final MenuItem item = - menu.add(Menu.NONE, MENU_SEARCH_HISTORY, Menu.NONE, R.string.search_clear_history); - item.setOnMenuItemClickListener(this); - } - - public void saveQuery(String query) { - final Bundle args = new Bundle(); - args.putString(ARG_QUERY, query); - mLoaderManager.restartLoader(SearchFragment.SearchLoaderId.SAVE_QUERY_TASK, args, - this /* callback */); - } - - /** - * Remove all saved queries from DB - */ - public void removeQueries() { - final Bundle args = new Bundle(); - mLoaderManager.restartLoader(SearchFragment.SearchLoaderId.REMOVE_QUERY_TASK, args, - this /* callback */); - } - - public void loadSavedQueries() { - if (SettingsSearchIndexablesProvider.DEBUG) { - Log.d(TAG, "loading saved queries"); - } - mLoaderManager.restartLoader(SearchFragment.SearchLoaderId.SAVED_QUERIES, null /* args */, - this /* callback */); - } -} diff --git a/src/com/android/settings/search/SavedQueryLoader.java b/src/com/android/settings/search/SavedQueryLoader.java deleted file mode 100644 index 5df3610354f..00000000000 --- a/src/com/android/settings/search/SavedQueryLoader.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.support.annotation.VisibleForTesting; - -import com.android.settings.search.IndexDatabaseHelper.SavedQueriesColumns; -import com.android.settingslib.utils.AsyncLoader; - -import java.util.ArrayList; -import java.util.List; - -/** - * Loader for recently searched queries. - */ -public class SavedQueryLoader extends AsyncLoader> { - - // Max number of proposed suggestions - @VisibleForTesting - static final int MAX_PROPOSED_SUGGESTIONS = 5; - - private final SQLiteDatabase mDatabase; - - public SavedQueryLoader(Context context) { - super(context); - mDatabase = IndexDatabaseHelper.getInstance(context).getReadableDatabase(); - } - - @Override - protected void onDiscardResult(List result) { - - } - - @Override - public List loadInBackground() { - try (final Cursor cursor = mDatabase.query( - IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES /* table */, - new String[]{SavedQueriesColumns.QUERY} /* columns */, - null /* selection */, - null /* selectionArgs */, - null /* groupBy */, - null /* having */, - "rowId DESC" /* orderBy */, - String.valueOf(MAX_PROPOSED_SUGGESTIONS) /* limit */)) { - return convertCursorToResult(cursor); - } - } - - private List convertCursorToResult(Cursor cursor) { - final List results = new ArrayList<>(); - while (cursor.moveToNext()) { - final SavedQueryPayload payload = new SavedQueryPayload( - cursor.getString(cursor.getColumnIndex(SavedQueriesColumns.QUERY))); - results.add(new SearchResult.Builder() - .setStableId(payload.hashCode()) - .setTitle(payload.query) - .setPayload(payload) - .build()); - } - return results; - } -} diff --git a/src/com/android/settings/search/SavedQueryPayload.java b/src/com/android/settings/search/SavedQueryPayload.java deleted file mode 100644 index 0a151fc08ff..00000000000 --- a/src/com/android/settings/search/SavedQueryPayload.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.os.Parcel; -import android.support.annotation.VisibleForTesting; - -/** - * {@link ResultPayload} for saved query. - */ -public class SavedQueryPayload extends ResultPayload { - - public final String query; - - public SavedQueryPayload(String query) { - super(null /* Intent */); - this.query = query; - } - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - SavedQueryPayload(Parcel in) { - super(null /* Intent */); - query = in.readString(); - } - - @Override - public int getType() { - return PayloadType.SAVED_QUERY; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(query); - } - - public static final Creator CREATOR = new Creator() { - @Override - public SavedQueryPayload createFromParcel(Parcel in) { - return new SavedQueryPayload(in); - } - - @Override - public SavedQueryPayload[] newArray(int size) { - return new SavedQueryPayload[size]; - } - }; -} diff --git a/src/com/android/settings/search/SavedQueryRecorder.java b/src/com/android/settings/search/SavedQueryRecorder.java deleted file mode 100644 index b3b0bb80506..00000000000 --- a/src/com/android/settings/search/SavedQueryRecorder.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.ContentValues; -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.util.Log; - -import com.android.settings.search.IndexDatabaseHelper; -import com.android.settingslib.utils.AsyncLoader; - -import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES; - -/** - * A background task to update saved queries. - */ -public class SavedQueryRecorder extends AsyncLoader { - - private static final String LOG_TAG = "SavedQueryRecorder"; - - // Max number of saved search queries (who will be used for proposing suggestions) - private static long MAX_SAVED_SEARCH_QUERY = 64; - - private final String mQuery; - - public SavedQueryRecorder(Context context, String query) { - super(context); - mQuery = query; - } - - @Override - protected void onDiscardResult(Void result) { - - } - - @Override - public Void loadInBackground() { - final long now = System.currentTimeMillis(); - - final ContentValues values = new ContentValues(); - values.put(IndexDatabaseHelper.SavedQueriesColumns.QUERY, mQuery); - values.put(IndexDatabaseHelper.SavedQueriesColumns.TIME_STAMP, now); - - final SQLiteDatabase database = getWritableDatabase(); - if (database == null) { - return null; - } - - long lastInsertedRowId; - try { - // First, delete all saved queries that are the same - database.delete(TABLE_SAVED_QUERIES, - IndexDatabaseHelper.SavedQueriesColumns.QUERY + " = ?", - new String[]{mQuery}); - - // Second, insert the saved query - lastInsertedRowId = database.insertOrThrow(TABLE_SAVED_QUERIES, null, values); - - // Last, remove "old" saved queries - final long delta = lastInsertedRowId - MAX_SAVED_SEARCH_QUERY; - if (delta > 0) { - int count = database.delete(TABLE_SAVED_QUERIES, - "rowId <= ?", - new String[]{Long.toString(delta)}); - Log.d(LOG_TAG, "Deleted '" + count + "' saved Search query(ies)"); - } - } catch (Exception e) { - Log.d(LOG_TAG, "Cannot update saved Search queries", e); - } - return null; - } - - private SQLiteDatabase getWritableDatabase() { - try { - return IndexDatabaseHelper.getInstance(getContext()).getWritableDatabase(); - } catch (SQLiteException e) { - Log.e(LOG_TAG, "Cannot open writable database", e); - return null; - } - } -} diff --git a/src/com/android/settings/search/SavedQueryRemover.java b/src/com/android/settings/search/SavedQueryRemover.java deleted file mode 100644 index c6abe978f65..00000000000 --- a/src/com/android/settings/search/SavedQueryRemover.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.util.Log; - -import com.android.settingslib.utils.AsyncLoader; - -public class SavedQueryRemover extends AsyncLoader { - - private static final String LOG_TAG = "SavedQueryRemover"; - - public SavedQueryRemover(Context context) { - super(context); - } - - @Override - public Void loadInBackground() { - final SQLiteDatabase database = getWritableDatabase(); - try { - // First, delete all saved queries that are the same - database.delete(TABLE_SAVED_QUERIES, - null /* where */, - null /* whereArgs */); - } catch (Exception e) { - Log.d(LOG_TAG, "Cannot update saved Search queries", e); - } - return null; - } - - @Override - protected void onDiscardResult(Void result) { - - } - - private SQLiteDatabase getWritableDatabase() { - try { - return IndexDatabaseHelper.getInstance(getContext()).getWritableDatabase(); - } catch (SQLiteException e) { - Log.e(LOG_TAG, "Cannot open writable database", e); - return null; - } - } -} diff --git a/src/com/android/settings/search/SavedQueryViewHolder.java b/src/com/android/settings/search/SavedQueryViewHolder.java deleted file mode 100644 index a8d449d45f9..00000000000 --- a/src/com/android/settings/search/SavedQueryViewHolder.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.view.View; -import android.widget.TextView; - -import com.android.internal.logging.nano.MetricsProto; - -public class SavedQueryViewHolder extends SearchViewHolder { - - public final TextView titleView; - - public SavedQueryViewHolder(View view) { - super(view); - titleView = view.findViewById(android.R.id.title); - } - - @Override - public int getClickActionMetricName() { - return MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_SAVED_QUERY; - } - - @Override - public void onBind(SearchFragment fragment, SearchResult result) { - itemView.setOnClickListener(v -> fragment.onSavedQueryClicked(result.title)); - titleView.setText(result.title); - } -} \ No newline at end of file diff --git a/src/com/android/settings/search/SearchActivity.java b/src/com/android/settings/search/SearchActivity.java deleted file mode 100644 index 61a580b0f17..00000000000 --- a/src/com/android/settings/search/SearchActivity.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.app.Activity; -import android.app.Fragment; -import android.app.FragmentManager; -import android.os.Bundle; - -import android.view.WindowManager; -import com.android.settings.R; - -public class SearchActivity extends Activity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.search_main); - // Keeps layouts in-place when keyboard opens. - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); - - FragmentManager fragmentManager = getFragmentManager(); - Fragment fragment = fragmentManager.findFragmentById(R.id.main_content); - if (fragment == null) { - fragmentManager.beginTransaction() - .add(R.id.main_content, new SearchFragment()) - .commit(); - } - } -} diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java index b9d5045b452..72ebc30e5c4 100644 --- a/src/com/android/settings/search/SearchFeatureProvider.java +++ b/src/com/android/settings/search/SearchFeatureProvider.java @@ -21,12 +21,9 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.util.FeatureFlagUtils; import android.util.Pair; -import android.view.View; import android.widget.Toolbar; -import com.android.settings.core.FeatureFlags; import com.android.settings.dashboard.SiteMapManager; import com.android.settings.overlay.FeatureFactory; @@ -50,58 +47,18 @@ public interface SearchFeatureProvider { void verifyLaunchSearchResultPageCaller(Context context, @NonNull ComponentName caller) throws SecurityException, IllegalArgumentException; - /** - * Returns a new loader to get settings search results. - */ - SearchResultLoader getSearchResultLoader(Context context, String query); - - /** - * Returns a new loader to search in index database. - */ - DatabaseResultLoader getStaticSearchResultTask(Context context, String query); - - /** - * Returns a new loader to search installed apps. - */ - InstalledAppResultLoader getInstalledAppSearchTask(Context context, String query); - - /** - * Returns a new loader to search accessibility services. - */ - AccessibilityServiceResultLoader getAccessibilityServiceResultTask(Context context, - String query); - - /** - * Returns a new loader to search input devices. - */ - InputDeviceResultLoader getInputDeviceResultTask(Context context, String query); - - /** - * Returns a new loader to get all recently saved queries search terms. - */ - SavedQueryLoader getSavedQueryLoader(Context context); - - /** - * Returns the manager for indexing Settings data. - */ - DatabaseIndexingManager getIndexingManager(Context context); - /** * Returns the manager for looking up breadcrumbs. */ SiteMapManager getSiteMapManager(); - /** - * Updates the Settings indexes and calls {@link IndexingCallback#onIndexingFinished()} on - * {@param callback} when indexing is complete. - */ - void updateIndexAsync(Context context, IndexingCallback callback); - /** * Synchronously updates the Settings database. */ void updateIndex(Context context); + DatabaseIndexingManager getIndexingManager(Context context); + /** * @returns true when indexing is complete. */ @@ -112,55 +69,6 @@ public interface SearchFeatureProvider { */ ExecutorService getExecutorService(); - /** - * Initializes the feedback button in case it was dismissed. - */ - default void initFeedbackButton() { - } - - /** - * Show a button users can click to submit feedback on the quality of the search results. - */ - default void showFeedbackButton(SearchFragment fragment, View view) { - } - - /** - * Hide the feedback button shown by - * {@link #showFeedbackButton(SearchFragment fragment, View view) showFeedbackButton} - */ - default void hideFeedbackButton() { - } - - /** - * Notify that a search result is clicked. - * - * @param context application context - * @param query input user query - * @param searchResult clicked result - */ - default void searchResultClicked(Context context, String query, SearchResult searchResult) { - } - - /** - * @return true to enable search ranking. - */ - default boolean isSmartSearchRankingEnabled(Context context) { - return false; - } - - /** - * @return smart ranking timeout in milliseconds. - */ - default long smartSearchRankingTimeoutMs(Context context) { - return 300L; - } - - /** - * Prepare for search ranking predictions to avoid latency on the first prediction call. - */ - default void searchRankingWarmup(Context context) { - } - /** * Return a FutureTask to get a list of scores for search results. */ @@ -168,10 +76,6 @@ public interface SearchFeatureProvider { return null; } - default boolean isSearchV2Enabled(Context context) { - return FeatureFlagUtils.isEnabled(context, FeatureFlags.SEARCH_V2); - } - /** * Initializes the search toolbar. */ @@ -180,12 +84,8 @@ public interface SearchFeatureProvider { return; } toolbar.setOnClickListener(tb -> { - final Intent intent; - if (isSearchV2Enabled(activity)) { - intent = SEARCH_UI_INTENT; - } else { - intent = new Intent(activity, SearchActivity.class); - } + final Intent intent = SEARCH_UI_INTENT; + FeatureFactory.getFactory( activity.getApplicationContext()).getSlicesFeatureProvider() .indexSliceDataAsync(activity.getApplicationContext()); diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java index 1c96714feef..db8541f625f 100644 --- a/src/com/android/settings/search/SearchFeatureProviderImpl.java +++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java @@ -20,13 +20,11 @@ package com.android.settings.search; import android.content.ComponentName; import android.content.Context; import android.text.TextUtils; -import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.dashboard.SiteMapManager; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.indexing.IndexData; -import com.android.settingslib.wrapper.PackageManagerWrapper; import java.util.Locale; import java.util.concurrent.ExecutorService; @@ -62,40 +60,6 @@ public class SearchFeatureProviderImpl implements SearchFeatureProvider { + "whitelisted package."); } - @Override - public SearchResultLoader getSearchResultLoader(Context context, String query) { - return new SearchResultLoader(context, cleanQuery(query)); - } - - @Override - public DatabaseResultLoader getStaticSearchResultTask(Context context, String query) { - return new DatabaseResultLoader(context, cleanQuery(query), getSiteMapManager()); - } - - @Override - public InstalledAppResultLoader getInstalledAppSearchTask(Context context, String query) { - return new InstalledAppResultLoader( - context, new PackageManagerWrapper(context.getPackageManager()), - cleanQuery(query), getSiteMapManager()); - } - - @Override - public AccessibilityServiceResultLoader getAccessibilityServiceResultTask(Context context, - String query) { - return new AccessibilityServiceResultLoader(context, cleanQuery(query), - getSiteMapManager()); - } - - @Override - public InputDeviceResultLoader getInputDeviceResultTask(Context context, String query) { - return new InputDeviceResultLoader(context, cleanQuery(query), getSiteMapManager()); - } - - @Override - public SavedQueryLoader getSavedQueryLoader(Context context) { - return new SavedQueryLoader(context); - } - @Override public DatabaseIndexingManager getIndexingManager(Context context) { if (mDatabaseIndexingManager == null) { @@ -116,14 +80,6 @@ public class SearchFeatureProviderImpl implements SearchFeatureProvider { return mSiteMapManager; } - @Override - public void updateIndexAsync(Context context, IndexingCallback callback) { - if (SettingsSearchIndexablesProvider.DEBUG) { - Log.d(TAG, "updating index async"); - } - getIndexingManager(context).indexDatabase(callback); - } - @Override public void updateIndex(Context context) { long indexStartTime = System.currentTimeMillis(); diff --git a/src/com/android/settings/search/SearchFragment.java b/src/com/android/settings/search/SearchFragment.java deleted file mode 100644 index ed7a2ee3e3f..00000000000 --- a/src/com/android/settings/search/SearchFragment.java +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.app.Activity; -import android.app.LoaderManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.Loader; -import android.os.Bundle; -import android.support.annotation.VisibleForTesting; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.text.TextUtils; -import android.util.EventLog; -import android.util.Log; -import android.util.Pair; -import android.util.TypedValue; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.LinearLayout; -import android.widget.SearchView; -import android.widget.TextView; -import android.widget.Toolbar; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.EventLogTags; -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.Utils; -import com.android.settings.core.InstrumentedFragment; -import com.android.settings.core.instrumentation.MetricsFeatureProvider; -import com.android.settings.overlay.FeatureFactory; -import com.android.settings.widget.ActionBarShadowController; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * This fragment manages the lifecycle of indexing and searching. - * - * In onCreate, the indexing process is initiated in DatabaseIndexingManager. - * While the indexing is happening, loaders are blocked from accessing the database, but the user - * is free to start typing their query. - * - * When the indexing is complete, the fragment gets a callback to initialize the loaders and search - * the query if the user has entered text. - */ -public class SearchFragment extends InstrumentedFragment implements SearchView.OnQueryTextListener, - LoaderManager.LoaderCallbacks>, IndexingCallback { - private static final String TAG = "SearchFragment"; - - // State values - private static final String STATE_QUERY = "state_query"; - private static final String STATE_SHOWING_SAVED_QUERY = "state_showing_saved_query"; - private static final String STATE_NEVER_ENTERED_QUERY = "state_never_entered_query"; - - static final class SearchLoaderId { - // Search Query IDs - public static final int SEARCH_RESULT = 1; - - // Saved Query IDs - public static final int SAVE_QUERY_TASK = 2; - public static final int REMOVE_QUERY_TASK = 3; - public static final int SAVED_QUERIES = 4; - } - - @VisibleForTesting - String mQuery; - - private boolean mNeverEnteredQuery = true; - @VisibleForTesting - boolean mShowingSavedQuery; - private MetricsFeatureProvider mMetricsFeatureProvider; - @VisibleForTesting - SavedQueryController mSavedQueryController; - - @VisibleForTesting - SearchFeatureProvider mSearchFeatureProvider; - - @VisibleForTesting - SearchResultsAdapter mSearchAdapter; - - @VisibleForTesting - RecyclerView mResultsRecyclerView; - @VisibleForTesting - SearchView mSearchView; - @VisibleForTesting - LinearLayout mNoResultsView; - - @VisibleForTesting - final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - if (dy != 0) { - hideKeyboard(); - } - } - }; - - @Override - public int getMetricsCategory() { - return MetricsEvent.DASHBOARD_SEARCH_RESULTS; - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - mSearchFeatureProvider = FeatureFactory.getFactory(context).getSearchFeatureProvider(); - mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - long startTime = System.currentTimeMillis(); - setHasOptionsMenu(true); - - final LoaderManager loaderManager = getLoaderManager(); - mSearchAdapter = new SearchResultsAdapter(this /* fragment */); - mSavedQueryController = new SavedQueryController( - getContext(), loaderManager, mSearchAdapter); - mSearchFeatureProvider.initFeedbackButton(); - - if (savedInstanceState != null) { - mQuery = savedInstanceState.getString(STATE_QUERY); - mNeverEnteredQuery = savedInstanceState.getBoolean(STATE_NEVER_ENTERED_QUERY); - mShowingSavedQuery = savedInstanceState.getBoolean(STATE_SHOWING_SAVED_QUERY); - } else { - mShowingSavedQuery = true; - } - - final Activity activity = getActivity(); - // Run the Index update only if we have some space - if (!Utils.isLowStorage(activity)) { - mSearchFeatureProvider.updateIndexAsync(activity, this /* indexingCallback */); - } else { - Log.w(TAG, "Cannot update the Indexer as we are running low on storage space!"); - } - if (SettingsSearchIndexablesProvider.DEBUG) { - Log.d(TAG, "onCreate spent " + (System.currentTimeMillis() - startTime) + " ms"); - } - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - mSavedQueryController.buildMenuItem(menu); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.search_panel, container, false); - mResultsRecyclerView = view.findViewById(R.id.list_results); - mResultsRecyclerView.setAdapter(mSearchAdapter); - mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - mResultsRecyclerView.addOnScrollListener(mScrollListener); - - mNoResultsView = view.findViewById(R.id.no_results_layout); - - Toolbar toolbar = view.findViewById(R.id.search_toolbar); - getActivity().setActionBar(toolbar); - getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); - - mSearchView = toolbar.findViewById(R.id.search_view); - mSearchView.setQuery(mQuery, false /* submitQuery */); - mSearchView.setOnQueryTextListener(this); - mSearchView.requestFocus(); - - // Updating internal views inside SearchView was the easiest way to get this too look right. - // Instead of grabbing the TextView directly, we grab it as a view and do an instanceof - // check. This ensures if we return, say, a LinearLayout in the tests, they won't fail. - View searchText = mSearchView.findViewById(com.android.internal.R.id.search_src_text); - if (searchText instanceof TextView) { - TextView searchTextView = (TextView) searchText; - searchTextView.setTextColor(getContext().getColorStateList( - com.android.internal.R.color.text_color_primary)); - searchTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, - getResources().getDimension(R.dimen.search_bar_text_size)); - - } - View editFrame = mSearchView.findViewById(com.android.internal.R.id.search_edit_frame); - if (editFrame != null) { - ViewGroup.MarginLayoutParams params = - (ViewGroup.MarginLayoutParams) editFrame.getLayoutParams(); - params.setMarginStart(0); - editFrame.setLayoutParams(params); - } - ActionBarShadowController.attachToRecyclerView( - view.findViewById(R.id.search_bar_container), getLifecycle(), mResultsRecyclerView); - return view; - } - - @Override - public void onResume() { - super.onResume(); - Context appContext = getContext().getApplicationContext(); - if (mSearchFeatureProvider.isSmartSearchRankingEnabled(appContext)) { - mSearchFeatureProvider.searchRankingWarmup(appContext); - } - requery(); - } - - @Override - public void onStop() { - super.onStop(); - final Activity activity = getActivity(); - if (activity != null && activity.isFinishing()) { - if (mNeverEnteredQuery) { - mMetricsFeatureProvider.action(activity, - MetricsEvent.ACTION_LEAVE_SEARCH_RESULT_WITHOUT_QUERY); - } - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(STATE_QUERY, mQuery); - outState.putBoolean(STATE_NEVER_ENTERED_QUERY, mNeverEnteredQuery); - outState.putBoolean(STATE_SHOWING_SAVED_QUERY, mShowingSavedQuery); - } - - @Override - public boolean onQueryTextChange(String query) { - if (TextUtils.equals(query, mQuery)) { - return true; - } - - final boolean isEmptyQuery = TextUtils.isEmpty(query); - - // Hide no-results-view when the new query is not a super-string of the previous - if (mQuery != null - && mNoResultsView.getVisibility() == View.VISIBLE - && query.length() < mQuery.length()) { - mNoResultsView.setVisibility(View.GONE); - } - - mNeverEnteredQuery = false; - mQuery = query; - - // If indexing is not finished, register the query text, but don't search. - if (!mSearchFeatureProvider.isIndexingComplete(getActivity())) { - return true; - } - - if (isEmptyQuery) { - final LoaderManager loaderManager = getLoaderManager(); - loaderManager.destroyLoader(SearchLoaderId.SEARCH_RESULT); - mShowingSavedQuery = true; - mSavedQueryController.loadSavedQueries(); - mSearchFeatureProvider.hideFeedbackButton(); - } else { - restartLoaders(); - } - - return true; - } - - @Override - public boolean onQueryTextSubmit(String query) { - // Save submitted query. - mSavedQueryController.saveQuery(mQuery); - hideKeyboard(); - return true; - } - - @Override - public Loader> onCreateLoader(int id, Bundle args) { - final Activity activity = getActivity(); - - switch(id) { - case SearchLoaderId.SEARCH_RESULT: - return mSearchFeatureProvider.getSearchResultLoader(activity, mQuery); - default: - return null; - } - } - - @Override - public void onLoadFinished(Loader> loader, - List data) { - mSearchAdapter.postSearchResults(data); - } - - @Override - public void onLoaderReset(Loader> loader) { - } - - /** - * Gets called when Indexing is completed. - */ - @Override - public void onIndexingFinished() { - if (getActivity() == null) { - return; - } - if (mShowingSavedQuery) { - mSavedQueryController.loadSavedQueries(); - } else { - final LoaderManager loaderManager = getLoaderManager(); - loaderManager.initLoader(SearchLoaderId.SEARCH_RESULT, null /* args */, - this /* callback */); - } - - requery(); - } - - public void onSearchResultClicked(SearchViewHolder resultViewHolder, SearchResult result, - Pair... logTaggedData) { - logSearchResultClicked(resultViewHolder, result, logTaggedData); - mSearchFeatureProvider.searchResultClicked(getContext(), mQuery, result); - mSavedQueryController.saveQuery(mQuery); - } - - public void onSearchResultsDisplayed(int resultCount) { - if (resultCount == 0) { - mNoResultsView.setVisibility(View.VISIBLE); - mMetricsFeatureProvider.visible(getContext(), getMetricsCategory(), - MetricsEvent.SETTINGS_SEARCH_NO_RESULT); - // Log settings_latency for search end-to-end. - EventLog.writeEvent(EventLogTags.SETTINGS_LATENCY, 1, 10); - } else { - mNoResultsView.setVisibility(View.GONE); - mResultsRecyclerView.scrollToPosition(0); - } - mMetricsFeatureProvider.action( - getVisibilityLogger(), MetricsEvent.ACTION_SEARCH_RESULTS, 1); - mSearchFeatureProvider.showFeedbackButton(this, getView()); - } - - public void onSavedQueryClicked(CharSequence query) { - final String queryString = query.toString(); - mMetricsFeatureProvider.action(getContext(), - MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_SAVED_QUERY); - mSearchView.setQuery(queryString, false /* submit */); - onQueryTextChange(queryString); - } - - private void restartLoaders() { - mShowingSavedQuery = false; - final LoaderManager loaderManager = getLoaderManager(); - loaderManager.restartLoader( - SearchLoaderId.SEARCH_RESULT, null /* args */, this /* callback */); - } - - public String getQuery() { - return mQuery; - } - - public List getSearchResults() { - return mSearchAdapter.getSearchResults(); - } - - private void requery() { - if (TextUtils.isEmpty(mQuery)) { - return; - } - final String query = mQuery; - mQuery = ""; - onQueryTextChange(query); - } - - private void hideKeyboard() { - final Activity activity = getActivity(); - if (activity != null) { - View view = activity.getCurrentFocus(); - InputMethodManager imm = (InputMethodManager) - activity.getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(view.getWindowToken(), 0); - } - - if (mResultsRecyclerView != null) { - mResultsRecyclerView.requestFocus(); - } - } - - private void logSearchResultClicked(SearchViewHolder resultViewHolder, SearchResult result, - Pair... logTaggedData) { - final Intent intent = result.payload.getIntent(); - if (intent == null) { - Log.w(TAG, "Skipped logging click on search result because of null intent, which can " + - "happen on saved query results."); - return; - } - final ComponentName cn = intent.getComponent(); - String resultName = intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT); - if (TextUtils.isEmpty(resultName) && cn != null) { - resultName = cn.flattenToString(); - } - final List> taggedData = new ArrayList<>(); - if (logTaggedData != null) { - taggedData.addAll(Arrays.asList(logTaggedData)); - } - taggedData.add(Pair.create( - MetricsEvent.FIELD_SETTINGS_SEARCH_RESULT_COUNT, - mSearchAdapter.getItemCount())); - taggedData.add(Pair.create( - MetricsEvent.FIELD_SETTINGS_SEARCH_RESULT_RANK, - resultViewHolder.getAdapterPosition())); - // TODO (b/67744820) Move metrics to SettingsIntelligence (including ranking state). - taggedData.add(Pair.create( - MetricsEvent.FIELD_SETTINGS_SEARCH_QUERY_LENGTH, - TextUtils.isEmpty(mQuery) ? 0 : mQuery.length())); - - mMetricsFeatureProvider.action(getContext(), - resultViewHolder.getClickActionMetricName(), - resultName, - taggedData.toArray(new Pair[0])); - } -} diff --git a/src/com/android/settings/search/SearchResultAggregator.java b/src/com/android/settings/search/SearchResultAggregator.java deleted file mode 100644 index 890e3f0db60..00000000000 --- a/src/com/android/settings/search/SearchResultAggregator.java +++ /dev/null @@ -1,177 +0,0 @@ -package com.android.settings.search; - -import android.annotation.NonNull; -import android.content.Context; -import android.util.Log; -import android.util.SparseArray; - -import com.android.settings.overlay.FeatureFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Collects the sorted list of all setting search results. - * - * TODO (b/64939692) Convert the timing logs to metrics - */ -public class SearchResultAggregator { - - private static final String TAG = "SearchResultAggregator"; - - /** - * Timeout for first task. Allows for longer delay. - */ - private static final long LONG_CHECK_TASK_TIMEOUT_MS = 500; - - /** - * Timeout for subsequent tasks to allow for fast returning tasks. - */ - private static final long SHORT_CHECK_TASK_TIMEOUT_MS = 150; - - private static SearchResultAggregator sResultAggregator; - - // TODO (b/33577327) Merge the other loaders into a single dynamic loader - static final class ResultLoaderId { - static final int STATIC_RESULTS = 1; - static final int INSTALLED_RESULTS = 2; - static final int INPUT_RESULTS = 3; - static final int ACCESSIBILITY_RESULTS = 4; - } - - private SearchResultAggregator() { - } - - public static SearchResultAggregator getInstance() { - if (sResultAggregator == null) { - sResultAggregator = new SearchResultAggregator(); - } - - return sResultAggregator; - } - - @NonNull - public synchronized List fetchResults(Context context, String query) { - SearchFeatureProvider mFeatureProvider = FeatureFactory.getFactory( - context).getSearchFeatureProvider(); - ExecutorService executorService = mFeatureProvider.getExecutorService(); - - final DatabaseResultLoader staticResultsTask = - mFeatureProvider.getStaticSearchResultTask(context, query); - final InstalledAppResultLoader installedAppTask = - mFeatureProvider.getInstalledAppSearchTask(context, query); - final InputDeviceResultLoader inputDevicesTask = - mFeatureProvider.getInputDeviceResultTask(context, query); - final AccessibilityServiceResultLoader accessibilityServicesTask = - mFeatureProvider.getAccessibilityServiceResultTask(context, - query); - - executorService.execute(staticResultsTask); - executorService.execute(installedAppTask); - executorService.execute(inputDevicesTask); - executorService.execute(accessibilityServicesTask); - - SparseArray> resultsArray = new SparseArray<>(); - List EMPTY_LIST = new ArrayList<>(); - - long allTasksStart = System.currentTimeMillis(); - try { - resultsArray.put(ResultLoaderId.INPUT_RESULTS, - inputDevicesTask.get(SHORT_CHECK_TASK_TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } catch (TimeoutException | InterruptedException | ExecutionException e) { - Log.d(TAG, "Could not retrieve input devices results in time: " + e); - resultsArray.put(ResultLoaderId.INPUT_RESULTS, EMPTY_LIST); - } - - try { - resultsArray.put(ResultLoaderId.ACCESSIBILITY_RESULTS, - accessibilityServicesTask.get(SHORT_CHECK_TASK_TIMEOUT_MS, - TimeUnit.MILLISECONDS)); - } catch (TimeoutException | InterruptedException | ExecutionException e) { - Log.d(TAG, "Could not retrieve accessibility results in time: " + e); - resultsArray.put(ResultLoaderId.ACCESSIBILITY_RESULTS, EMPTY_LIST); - } - - try { - resultsArray.put(ResultLoaderId.STATIC_RESULTS, - staticResultsTask.get(LONG_CHECK_TASK_TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } catch (TimeoutException | InterruptedException | ExecutionException e) { - Log.d(TAG, "Could not retrieve static results: " + e); - resultsArray.put(ResultLoaderId.STATIC_RESULTS, EMPTY_LIST); - } - - try { - resultsArray.put(ResultLoaderId.INSTALLED_RESULTS, - installedAppTask.get(SHORT_CHECK_TASK_TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } catch (TimeoutException | InterruptedException | ExecutionException e) { - Log.d(TAG, "Could not retrieve installed app results in time: " + e); - - resultsArray.put(ResultLoaderId.INSTALLED_RESULTS, EMPTY_LIST); - } - - long mergeStartTime = System.currentTimeMillis(); - Log.i(TAG, "Total result loader time: " + (mergeStartTime - allTasksStart)); - List mergedResults = mergeSearchResults(resultsArray); - Log.i(TAG, "Total merge time: " + (System.currentTimeMillis() - mergeStartTime)); - Log.i(TAG, "Total aggregator time: " + (System.currentTimeMillis() - allTasksStart)); - - return mergedResults; - } - - // TODO (b/68255021) scale the dynamic search results ranks and do a k-way merge - private List mergeSearchResults( - SparseArray> resultsArray) { - List staticResults = resultsArray.get( - ResultLoaderId.STATIC_RESULTS); - List installedAppResults = resultsArray.get( - ResultLoaderId.INSTALLED_RESULTS); - List accessibilityResults = resultsArray.get( - ResultLoaderId.ACCESSIBILITY_RESULTS); - List inputDeviceResults = resultsArray.get( - ResultLoaderId.INPUT_RESULTS); - List searchResults; - - int staticSize = staticResults.size(); - int appSize = installedAppResults.size(); - int a11ySize = accessibilityResults.size(); - int inputDeviceSize = inputDeviceResults.size(); - int appIndex = 0; - int a11yIndex = 0; - int inputDeviceIndex = 0; - int rank = SearchResult.TOP_RANK; - - // TODO: We need a helper method to do k-way merge. - searchResults = new ArrayList<>(staticSize + appSize + a11ySize + inputDeviceSize); - searchResults.addAll(resultsArray.get(ResultLoaderId.STATIC_RESULTS)); - - while (rank <= SearchResult.BOTTOM_RANK) { - while ((appIndex < appSize) && (installedAppResults.get(appIndex).rank == rank)) { - searchResults.add(installedAppResults.get(appIndex++)); - } - while ((a11yIndex < a11ySize) && (accessibilityResults.get(a11yIndex).rank == rank)) { - searchResults.add(accessibilityResults.get(a11yIndex++)); - } - while (inputDeviceIndex < inputDeviceSize - && inputDeviceResults.get(inputDeviceIndex).rank == rank) { - searchResults.add(inputDeviceResults.get(inputDeviceIndex++)); - } - rank++; - } - - while (appIndex < appSize) { - searchResults.add(installedAppResults.get(appIndex++)); - } - while (a11yIndex < a11ySize) { - searchResults.add(accessibilityResults.get(a11yIndex++)); - } - while (inputDeviceIndex < inputDeviceSize) { - searchResults.add(inputDeviceResults.get(inputDeviceIndex++)); - } - - return searchResults; - } -} diff --git a/src/com/android/settings/search/SearchResultDiffCallback.java b/src/com/android/settings/search/SearchResultDiffCallback.java deleted file mode 100644 index 0f0b9778c13..00000000000 --- a/src/com/android/settings/search/SearchResultDiffCallback.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.support.v7.util.DiffUtil; - -import java.util.List; - -/** - * Callback for DiffUtil to elegantly update search data when the query changes. - */ -public class SearchResultDiffCallback extends DiffUtil.Callback { - - private List mOldList; - private List mNewList; - - public SearchResultDiffCallback(List oldList, - List newList) { - mOldList = oldList; - mNewList = newList; - } - - @Override - public int getOldListSize() { - return mOldList.size(); - } - - @Override - public int getNewListSize() { - return mNewList.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return mOldList.get(oldItemPosition).equals(mNewList.get(newItemPosition)); - } - - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return mOldList.get(oldItemPosition).equals(mNewList.get(newItemPosition)); - } -} diff --git a/src/com/android/settings/search/SearchResultLoader.java b/src/com/android/settings/search/SearchResultLoader.java deleted file mode 100644 index f4abd8e40b9..00000000000 --- a/src/com/android/settings/search/SearchResultLoader.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.android.settings.search; - -import com.android.settingslib.utils.AsyncLoader; - -import android.content.Context; - -import java.util.List; - -/** - * Loads a sorted list of Search results for a given query. - */ -public class SearchResultLoader extends AsyncLoader> { - - private final String mQuery; - - public SearchResultLoader(Context context, String query) { - super(context); - mQuery = query; - } - - @Override - public List loadInBackground() { - SearchResultAggregator aggregator = SearchResultAggregator.getInstance(); - return aggregator.fetchResults(getContext(), mQuery); - } - - @Override - protected void onDiscardResult(List result) { - } -} diff --git a/src/com/android/settings/search/SearchResultsAdapter.java b/src/com/android/settings/search/SearchResultsAdapter.java deleted file mode 100644 index c05ce184130..00000000000 --- a/src/com/android/settings/search/SearchResultsAdapter.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.Context; -import android.support.v7.util.DiffUtil; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.android.settings.R; - -import java.util.ArrayList; -import java.util.List; - -public class SearchResultsAdapter extends RecyclerView.Adapter { - - private final SearchFragment mFragment; - private final List mSearchResults; - - public SearchResultsAdapter(SearchFragment fragment) { - mFragment = fragment; - mSearchResults = new ArrayList<>(); - - setHasStableIds(true); - } - - @Override - public SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - final Context context = parent.getContext(); - final LayoutInflater inflater = LayoutInflater.from(context); - final View view; - switch (viewType) { - case ResultPayload.PayloadType.INTENT: - view = inflater.inflate(R.layout.search_intent_item, parent, false); - return new IntentSearchViewHolder(view); - case ResultPayload.PayloadType.INLINE_SWITCH: - // TODO (b/62807132) replace layout InlineSwitchViewHolder and return an - // InlineSwitchViewHolder. - view = inflater.inflate(R.layout.search_intent_item, parent, false); - return new IntentSearchViewHolder(view); - case ResultPayload.PayloadType.INLINE_LIST: - // TODO (b/62807132) build a inline-list view holder & layout. - view = inflater.inflate(R.layout.search_intent_item, parent, false); - return new IntentSearchViewHolder(view); - case ResultPayload.PayloadType.SAVED_QUERY: - view = inflater.inflate(R.layout.search_saved_query_item, parent, false); - return new SavedQueryViewHolder(view); - default: - return null; - } - } - - @Override - public void onBindViewHolder(SearchViewHolder holder, int position) { - holder.onBind(mFragment, mSearchResults.get(position)); - } - - @Override - public long getItemId(int position) { - return mSearchResults.get(position).stableId; - } - - @Override - public int getItemViewType(int position) { - return mSearchResults.get(position).viewType; - } - - @Override - public int getItemCount() { - return mSearchResults.size(); - } - - /** - * Displays recent searched queries. - */ - public void displaySavedQuery(List data) { - clearResults(); - mSearchResults.addAll(data); - notifyDataSetChanged(); - } - - public void clearResults() { - mSearchResults.clear(); - notifyDataSetChanged(); - } - - public List getSearchResults() { - return mSearchResults; - } - - public void postSearchResults(List newSearchResults) { - final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( - new SearchResultDiffCallback(mSearchResults, newSearchResults)); - mSearchResults.clear(); - mSearchResults.addAll(newSearchResults); - diffResult.dispatchUpdatesTo(this); - mFragment.onSearchResultsDisplayed(mSearchResults.size()); - } -} diff --git a/src/com/android/settings/search/SearchViewHolder.java b/src/com/android/settings/search/SearchViewHolder.java deleted file mode 100644 index 7667a060f28..00000000000 --- a/src/com/android/settings/search/SearchViewHolder.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.os.UserHandle; -import android.support.v7.widget.RecyclerView; -import android.text.TextUtils; -import android.util.IconDrawableFactory; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import android.support.annotation.VisibleForTesting; - -import com.android.settings.R; -import com.android.settings.core.instrumentation.MetricsFeatureProvider; -import com.android.settings.overlay.FeatureFactory; - -/** - * The ViewHolder for the Search RecyclerView. - * There are multiple search result types in the same Recycler view with different UI requirements. - * Some examples include Intent results, Inline results, and Help articles. - */ -public abstract class SearchViewHolder extends RecyclerView.ViewHolder { - - private final String DYNAMIC_PLACEHOLDER = "%s"; - - private final String mPlaceholderSummary; - - public final TextView titleView; - public final TextView summaryView; - public final TextView breadcrumbView; - public final ImageView iconView; - - protected final MetricsFeatureProvider mMetricsFeatureProvider; - protected final SearchFeatureProvider mSearchFeatureProvider; - private final IconDrawableFactory mIconDrawableFactory; - - public SearchViewHolder(View view) { - super(view); - final FeatureFactory featureFactory = FeatureFactory - .getFactory(view.getContext().getApplicationContext()); - mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider(); - mSearchFeatureProvider = featureFactory.getSearchFeatureProvider(); - titleView = view.findViewById(android.R.id.title); - summaryView = view.findViewById(android.R.id.summary); - iconView = view.findViewById(android.R.id.icon); - breadcrumbView = view.findViewById(R.id.breadcrumb); - - mPlaceholderSummary = view.getContext().getString(R.string.summary_placeholder); - mIconDrawableFactory = IconDrawableFactory.newInstance(view.getContext()); - } - - public abstract int getClickActionMetricName(); - - public void onBind(SearchFragment fragment, SearchResult result) { - titleView.setText(result.title); - // TODO (b/36101902) remove check for DYNAMIC_PLACEHOLDER - if (TextUtils.isEmpty(result.summary) - || TextUtils.equals(result.summary, mPlaceholderSummary) - || TextUtils.equals(result.summary, DYNAMIC_PLACEHOLDER)) { - summaryView.setVisibility(View.GONE); - } else { - summaryView.setText(result.summary); - summaryView.setVisibility(View.VISIBLE); - } - - if (result instanceof AppSearchResult) { - AppSearchResult appResult = (AppSearchResult) result; - PackageManager pm = fragment.getActivity().getPackageManager(); - UserHandle userHandle = appResult.getAppUserHandle(); - Drawable badgedIcon = getBadgedIcon(appResult.info, userHandle.getIdentifier()); - iconView.setImageDrawable(badgedIcon); - titleView.setContentDescription( - pm.getUserBadgedLabel(appResult.info.loadLabel(pm), userHandle)); - } else { - // Valid even when result.icon is null. - iconView.setImageDrawable(result.icon); - } - - bindBreadcrumbView(result); - } - - private void bindBreadcrumbView(SearchResult result) { - if (result.breadcrumbs == null || result.breadcrumbs.isEmpty()) { - breadcrumbView.setVisibility(View.GONE); - return; - } - final Context context = breadcrumbView.getContext(); - String breadcrumb = result.breadcrumbs.get(0); - final int count = result.breadcrumbs.size(); - for (int i = 1; i < count; i++) { - breadcrumb = context.getString(R.string.search_breadcrumb_connector, - breadcrumb, result.breadcrumbs.get(i)); - } - breadcrumbView.setText(breadcrumb); - breadcrumbView.setVisibility(View.VISIBLE); - } - - @VisibleForTesting - Drawable getBadgedIcon(ApplicationInfo info, int userId) { - return mIconDrawableFactory.getBadgedIcon(info, userId); - } -} \ No newline at end of file diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java index 28bde33f82e..b589c5e0568 100644 --- a/src/com/android/settings/search/actionbar/SearchMenuController.java +++ b/src/com/android/settings/search/actionbar/SearchMenuController.java @@ -18,14 +18,12 @@ package com.android.settings.search.actionbar; import android.annotation.NonNull; import android.app.Fragment; -import android.content.Context; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import com.android.settings.R; -import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.SearchFeatureProvider; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment; @@ -38,14 +36,7 @@ public class SearchMenuController implements LifecycleObserver, OnCreateOptionsM private final Fragment mHost; public static void init(@NonNull ObservablePreferenceFragment host) { - final Context context = host.getContext(); - final boolean isSearchV2Enabled = FeatureFactory.getFactory(context) - .getSearchFeatureProvider() - .isSearchV2Enabled(context); - - if (isSearchV2Enabled) { - host.getLifecycle().addObserver(new SearchMenuController(host)); - } + host.getLifecycle().addObserver(new SearchMenuController(host)); } private SearchMenuController(@NonNull Fragment host) { diff --git a/src/com/android/settings/search/ranking/SearchResultsRankerCallback.java b/src/com/android/settings/search/ranking/SearchResultsRankerCallback.java deleted file mode 100644 index c254a40144c..00000000000 --- a/src/com/android/settings/search/ranking/SearchResultsRankerCallback.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search.ranking; - -import android.util.Pair; - -import java.util.List; - -public interface SearchResultsRankerCallback { - - /** - * Called when ranker provides the ranking scores. - * @param searchRankingScores Ordered List of Pairs of String and Float corresponding to - * stableIds and ranking scores. The list must be descendingly - * ordered based on scores. - */ - public void onRankingScoresAvailable(List> searchRankingScores); - - /** - * Called when for any reason ranker fails, which notifies the client to proceed - * without ranking results. - */ - public void onRankingFailed(); -} diff --git a/tests/robotests/src/com/android/settings/search/AccessibilityServiceResultFutureTaskTest.java b/tests/robotests/src/com/android/settings/search/AccessibilityServiceResultFutureTaskTest.java deleted file mode 100644 index b4f07d7297b..00000000000 --- a/tests/robotests/src/com/android/settings/search/AccessibilityServiceResultFutureTaskTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.accessibilityservice.AccessibilityServiceInfo; -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.os.UserManager; -import android.view.accessibility.AccessibilityManager; - -import com.android.settings.TestConfig; -import com.android.settings.dashboard.SiteMapManager; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class AccessibilityServiceResultFutureTaskTest { - - private static final String QUERY = "test_query"; - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; - @Mock - private PackageManager mPackageManager; - @Mock - private AccessibilityManager mAccessibilityManager; - @Mock - private SiteMapManager mSiteMapManager; - @Mock - private UserManager mUserManager; - - private AccessibilityServiceResultLoader.AccessibilityServiceResultCallable mCallable; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mContext.getSystemService(Context.ACCESSIBILITY_SERVICE)) - .thenReturn(mAccessibilityManager); - when((Object)mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - - mCallable = new AccessibilityServiceResultLoader.AccessibilityServiceResultCallable( - mContext, QUERY, mSiteMapManager); - } - - @Test - public void query_noService_shouldNotReturnAnything() throws Exception { - assertThat(mCallable.call()).isEmpty(); - } - - @Test - public void query_hasServiceMatchingTitle_shouldReturnResult() throws Exception { - addFakeAccessibilityService(); - - List results = mCallable.call(); - assertThat(results).hasSize(1); - - SearchResult result = results.get(0); - assertThat(result.title).isEqualTo(QUERY); - } - - @Test - public void query_serviceDoesNotMatchTitle_shouldReturnResult() throws Exception { - addFakeAccessibilityService(); - - mCallable = new AccessibilityServiceResultLoader.AccessibilityServiceResultCallable( - mContext, - QUERY + "no_match", mSiteMapManager); - - assertThat(mCallable.call()).isEmpty(); - } - - private void addFakeAccessibilityService() { - final List services = new ArrayList<>(); - final AccessibilityServiceInfo info = mock(AccessibilityServiceInfo.class); - final ResolveInfo resolveInfo = mock(ResolveInfo.class); - when(info.getResolveInfo()).thenReturn(resolveInfo); - when(resolveInfo.loadIcon(mPackageManager)).thenReturn(new ColorDrawable(Color.BLUE)); - when(resolveInfo.loadLabel(mPackageManager)).thenReturn(QUERY); - resolveInfo.serviceInfo = new ServiceInfo(); - resolveInfo.serviceInfo.packageName = "pkg"; - resolveInfo.serviceInfo.name = "class"; - services.add(info); - - when(mAccessibilityManager.getInstalledAccessibilityServiceList()).thenReturn(services); - } -} diff --git a/tests/robotests/src/com/android/settings/search/InlineSwitchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/InlineSwitchViewHolderTest.java deleted file mode 100644 index ca98c1576fa..00000000000 --- a/tests/robotests/src/com/android/settings/search/InlineSwitchViewHolderTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2016 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.settings.search; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.view.LayoutInflater; - -import com.android.settings.R; -import com.android.settings.TestConfig; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; -import org.robolectric.util.ReflectionHelpers; - -import java.util.ArrayList; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class InlineSwitchViewHolderTest { - - private static final String TITLE = "title"; - private static final String SUMMARY = "summary"; - - @Mock - private SearchFragment mFragment; - - @Mock - private InlineSwitchPayload mPayload; - - private FakeFeatureFactory mFeatureFactory; - private InlineSwitchViewHolder mHolder; - private Drawable mIcon; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - final Context context = RuntimeEnvironment.application; - mIcon = context.getDrawable(R.drawable.ic_search_24dp); - mFeatureFactory = FakeFeatureFactory.setupForTest(); - - mHolder = new InlineSwitchViewHolder( - LayoutInflater.from(context).inflate(R.layout.search_inline_switch_item, null), - context); - ReflectionHelpers.setField(mHolder, "mMetricsFeatureProvider", - mFeatureFactory.metricsFeatureProvider); - } - - @Test - public void testConstructor_MembersNotNull() { - assertThat(mHolder.titleView).isNotNull(); - assertThat(mHolder.summaryView).isNotNull(); - assertThat(mHolder.iconView).isNotNull(); - assertThat(mHolder.switchView).isNotNull(); - } - - @Test - public void testBindViewElements_AllUpdated() { - when(mPayload.getValue(any(Context.class))).thenReturn(1); - SearchResult result = getSearchResult(); - mHolder.onBind(mFragment, result); - // Precondition: switch is on. - assertThat(mHolder.switchView.isChecked()).isTrue(); - - mHolder.switchView.performClick(); - - assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); - assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); - assertThat(mHolder.iconView.getDrawable()).isEqualTo(mIcon); - assertThat(mHolder.switchView.isChecked()).isFalse(); - } - - private SearchResult getSearchResult() { - SearchResult.Builder builder = new SearchResult.Builder(); - - builder.setTitle(TITLE) - .setSummary(SUMMARY) - .setRank(1) - .setPayload(new InlineSwitchPayload("" /* uri */, 0 /* mSettingSource */, - 1 /* onValue */, null /* intent */, true /* isDeviceSupported */, - 1 /* default */)) - .addBreadcrumbs(new ArrayList<>()) - .setIcon(mIcon) - .setPayload(mPayload) - .setStableId(TITLE.hashCode()); - - return builder.build(); - } -} diff --git a/tests/robotests/src/com/android/settings/search/InputDeviceResultFutureTaskTest.java b/tests/robotests/src/com/android/settings/search/InputDeviceResultFutureTaskTest.java deleted file mode 100644 index e31b3d76997..00000000000 --- a/tests/robotests/src/com/android/settings/search/InputDeviceResultFutureTaskTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static android.content.Context.INPUT_METHOD_SERVICE; - -import static com.android.settings.search.InputDeviceResultLoader.PHYSICAL_KEYBOARD_FRAGMENT; -import static com.android.settings.search.InputDeviceResultLoader.VIRTUAL_KEYBOARD_FRAGMENT; -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.pm.ServiceInfo; -import android.hardware.input.InputManager; -import android.view.InputDevice; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodManager; - -import com.android.settings.R; -import com.android.settings.TestConfig; -import com.android.settings.dashboard.SiteMapManager; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.testutils.shadow.ShadowInputDevice; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, - sdk = TestConfig.SDK_VERSION, - shadows = { - ShadowInputDevice.class - }) -public class InputDeviceResultFutureTaskTest { - - private static final String QUERY = "test_query"; - private static final List PHYSICAL_KEYBOARD_BREADCRUMB; - private static final List VIRTUAL_KEYBOARD_BREADCRUMB; - - static { - PHYSICAL_KEYBOARD_BREADCRUMB = new ArrayList<>(); - VIRTUAL_KEYBOARD_BREADCRUMB = new ArrayList<>(); - PHYSICAL_KEYBOARD_BREADCRUMB.add("Settings"); - PHYSICAL_KEYBOARD_BREADCRUMB.add("physical keyboard"); - VIRTUAL_KEYBOARD_BREADCRUMB.add("Settings"); - VIRTUAL_KEYBOARD_BREADCRUMB.add("virtual keyboard"); - } - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; - @Mock - private SiteMapManager mSiteMapManager; - @Mock - private InputManager mInputManager; - @Mock - private InputMethodManager mImm; - @Mock - private PackageManager mPackageManager; - - private InputDeviceResultLoader.InputDeviceResultCallable mCallable; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mContext.getApplicationContext()).thenReturn(mContext); - when(mContext.getSystemService(Context.INPUT_SERVICE)) - .thenReturn(mInputManager); - when(mContext.getSystemService(INPUT_METHOD_SERVICE)) - .thenReturn(mImm); - when(mContext.getPackageManager()) - .thenReturn(mPackageManager); - when(mContext.getString(anyInt())) - .thenAnswer(invocation -> RuntimeEnvironment.application.getString( - (Integer) invocation.getArguments()[0])); - mCallable = new InputDeviceResultLoader.InputDeviceResultCallable(mContext, QUERY, - mSiteMapManager); - } - - @After - public void tearDown() { - ShadowInputDevice.reset(); - } - - @Test - public void query_noKeyboard_shouldNotReturnAnything() throws Exception { - - assertThat(mCallable.call()).isEmpty(); - } - - @Test - public void query_hasPhysicalKeyboard_match() throws Exception { - addPhysicalKeyboard(QUERY); - when(mSiteMapManager.buildBreadCrumb(mContext, PHYSICAL_KEYBOARD_FRAGMENT, - RuntimeEnvironment.application.getString(R.string.physical_keyboard_title))) - .thenReturn(PHYSICAL_KEYBOARD_BREADCRUMB); - - final List results = mCallable.call(); - - assertThat(results).hasSize(1); - assertThat(results.get(0).title).isEqualTo(QUERY); - assertThat(results.get(0).breadcrumbs) - .containsExactlyElementsIn(PHYSICAL_KEYBOARD_BREADCRUMB); - } - - @Test - public void query_hasVirtualKeyboard_match() throws Exception { - addVirtualKeyboard(QUERY); - when(mSiteMapManager.buildBreadCrumb(mContext, VIRTUAL_KEYBOARD_FRAGMENT, - RuntimeEnvironment.application.getString(R.string.add_virtual_keyboard))) - .thenReturn(VIRTUAL_KEYBOARD_BREADCRUMB); - - final List results = mCallable.call(); - assertThat(results).hasSize(1); - assertThat(results.get(0).title).isEqualTo(QUERY); - assertThat(results.get(0).breadcrumbs) - .containsExactlyElementsIn(VIRTUAL_KEYBOARD_BREADCRUMB); - } - - @Test - public void query_hasPhysicalVirtualKeyboard_doNotMatch() throws Exception { - addPhysicalKeyboard("abc"); - addVirtualKeyboard("def"); - - assertThat(mCallable.call()).isEmpty(); - verifyZeroInteractions(mSiteMapManager); - } - - private void addPhysicalKeyboard(String name) { - final InputDevice device = mock(InputDevice.class); - when(device.isVirtual()).thenReturn(false); - when(device.isFullKeyboard()).thenReturn(true); - when(device.getName()).thenReturn(name); - ShadowInputDevice.sDeviceIds = new int[]{0}; - ShadowInputDevice.addDevice(0, device); - } - - private void addVirtualKeyboard(String name) { - final List imis = new ArrayList<>(); - final InputMethodInfo info = mock(InputMethodInfo.class); - imis.add(info); - when(info.getServiceInfo()).thenReturn(new ServiceInfo()); - when(info.loadLabel(mPackageManager)).thenReturn(name); - info.getServiceInfo().packageName = "pkg"; - info.getServiceInfo().name = "class"; - when(mImm.getInputMethodList()).thenReturn(imis); - } - -} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/search/InstalledAppResultLoaderTest.java b/tests/robotests/src/com/android/settings/search/InstalledAppResultLoaderTest.java deleted file mode 100644 index 1cf148015f6..00000000000 --- a/tests/robotests/src/com/android/settings/search/InstalledAppResultLoaderTest.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static android.content.pm.ApplicationInfo.FLAG_SYSTEM; -import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyList; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.ResolveInfo; -import android.content.pm.UserInfo; -import android.os.UserHandle; -import android.os.UserManager; - -import com.android.settings.R; -import com.android.settings.TestConfig; -import com.android.settings.dashboard.SiteMapManager; -import com.android.settings.testutils.ApplicationTestUtils; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settingslib.wrapper.PackageManagerWrapper; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class InstalledAppResultLoaderTest { - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private PackageManagerWrapper mPackageManagerWrapper; - @Mock - private UserManager mUserManager; - @Mock - private SiteMapManager mSiteMapManager; - - private InstalledAppResultLoader.InstalledAppResultCallable mCallable; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - final FakeFeatureFactory factory = FakeFeatureFactory.setupForTest(); - when(factory.searchFeatureProvider.getSiteMapManager()) - .thenReturn(mSiteMapManager); - final List infos = new ArrayList<>(); - infos.add(new UserInfo(1, "user 1", 0)); - when(mUserManager.getProfiles(anyInt())).thenReturn(infos); - when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); - when(mContext.getString(R.string.applications_settings)) - .thenReturn("app"); - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM, - 0 /* targetSdkVersion */), - ApplicationTestUtils.buildInfo(0 /* uid */, "app2", FLAG_SYSTEM, - 0 /* targetSdkVersion */), - ApplicationTestUtils.buildInfo(0 /* uid */, "app3", FLAG_SYSTEM, - 0 /* targetSdkVersion */), - ApplicationTestUtils.buildInfo(0 /* uid */, "app4", 0 /* flags */, - 0 /* targetSdkVersion */), - ApplicationTestUtils.buildInfo(0 /* uid */, "app", 0 /* flags */, - 0 /* targetSdkVersion */), - ApplicationTestUtils.buildInfo(0 /* uid */, "appBuffer", 0 /* flags */, - 0 /* targetSdkVersion */))); - } - - @Test - public void query_noMatchingQuery_shouldReturnEmptyResult() throws Exception { - final String query = "abc"; - - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).isEmpty(); - } - - @Test - public void query_matchingQuery_shouldReturnNonSystemApps() throws Exception { - final String query = "app"; - - mCallable = spy(new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager)); - when(mSiteMapManager.buildBreadCrumb(eq(mContext), anyString(), anyString())) - .thenReturn(Arrays.asList(new String[] {"123"})); - - assertThat(mCallable.call()).hasSize(3); - verify(mSiteMapManager) - .buildBreadCrumb(eq(mContext), anyString(), anyString()); - } - - @Test - public void query_matchingQuery_shouldReturnSystemAppUpdates() throws Exception { - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_UPDATED_SYSTEM_APP, - 0 /* targetSdkVersion */))); - final String query = "app"; - - mCallable = spy(new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager)); - - assertThat(mCallable.call()).hasSize(1); - verify(mSiteMapManager) - .buildBreadCrumb(eq(mContext), anyString(), anyString()); - } - - @Test - public void query_matchingQuery_shouldReturnSystemAppIfLaunchable() throws Exception { - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM, - 0 /* targetSdkVersion */))); - final List list = mock(List.class); - when(list.size()).thenReturn(1); - when(mPackageManagerWrapper.queryIntentActivitiesAsUser( - any(Intent.class), anyInt(), anyInt())) - .thenReturn(list); - - final String query = "app"; - - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_matchingQuery_shouldReturnSystemAppIfHomeApp() throws Exception { - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM, - 0 /* targetSdkVersion */))); - when(mPackageManagerWrapper.queryIntentActivitiesAsUser( - any(Intent.class), anyInt(), anyInt())) - .thenReturn(null); - - when(mPackageManagerWrapper.getHomeActivities(anyList())).thenAnswer(invocation -> { - final List list = (List) invocation.getArguments()[0]; - final ResolveInfo info = new ResolveInfo(); - info.activityInfo = new ActivityInfo(); - info.activityInfo.packageName = "app1"; - list.add(info); - return null; - }); - - final String query = "app"; - - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_matchingQuery_shouldNotReturnSystemAppIfNotLaunchable() throws Exception { - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM, - 0 /* targetSdkVersion */))); - when(mPackageManagerWrapper.queryIntentActivitiesAsUser( - any(Intent.class), anyInt(), anyInt())) - .thenReturn(null); - - final String query = "app"; - - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).isEmpty(); - verify(mSiteMapManager, never()) - .buildBreadCrumb(eq(mContext), anyString(), anyString()); - } - - @Test - public void query_matchingQuery_multipleResults() throws Exception { - final String query = "app"; - - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - final List results = mCallable.call(); - - Set expectedTitles = new HashSet<>(Arrays.asList("app4", "app", "appBuffer")); - Set actualTitles = new HashSet<>(); - for (SearchResult result : results) { - actualTitles.add(result.title); - } - assertThat(actualTitles).isEqualTo(expectedTitles); - } - - @Test - public void query_normalWord_MatchPrefix() throws Exception { - final String query = "ba"; - final String packageName = "Bananas"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_CapitalCase_DoestMatchSecondWord() throws Exception { - final String query = "Apples"; - final String packageName = "BananasApples"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).isEmpty(); - } - - @Test - public void query_TwoWords_MatchesFirstWord() throws Exception { - final String query = "Banana"; - final String packageName = "Bananas Apples"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_TwoWords_MatchesSecondWord() throws Exception { - final String query = "Apple"; - final String packageName = "Bananas Apples"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_ThreeWords_MatchesThirdWord() throws Exception { - final String query = "Pear"; - final String packageName = "Bananas Apples Pears"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_DoubleSpacedWords_MatchesSecondWord() throws Exception { - final String query = "Apple"; - final String packageName = "Bananas Apples"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_SpecialChar_MatchesSecondWord() throws Exception { - final String query = "Apple"; - final String packageName = "Bananas & Apples"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_TabSeparated_MatchesSecondWord() throws Exception { - final String query = "Apple"; - final String packageName = "Bananas\tApples"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_LeadingNumber_MatchesWord() throws Exception { - final String query = "4"; - final String packageName = "4Bananas"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).hasSize(1); - } - - @Test - public void query_FirstWordPrefixOfQuery_NoMatch() throws Exception { - final String query = "Bananass"; - final String packageName = "Bananas Apples"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).isEmpty(); - } - - @Test - public void query_QueryLongerThanAppName_NoMatch() throws Exception { - final String query = "BananasApples"; - final String packageName = "Bananas"; - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - assertThat(mCallable.call()).isEmpty(); - } - - @Test - public void query_appExistsInBothProfiles() throws Exception { - final String query = "carrot"; - final String packageName = "carrot"; - final int user1 = 0; - final int user2 = 10; - final int uid = 67672; - List infos = new ArrayList<>(); - infos.add(new UserInfo(user1, "user 1", 0)); - infos.add(new UserInfo(user2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); - - when(mUserManager.getProfiles(anyInt())).thenReturn(infos); - - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), eq(user1))) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(UserHandle.getUid(user1, uid) /* uid */, - packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), eq(user2))) - .thenReturn(Arrays.asList( - ApplicationTestUtils.buildInfo(UserHandle.getUid(user2, uid) /* uid */, - packageName, 0 /* flags */, - 0 /* targetSdkVersion */))); - - mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext, - mPackageManagerWrapper, query, - mSiteMapManager); - - List searchResults = (List) mCallable.call(); - assertThat(searchResults).hasSize(2); - - Set uidResults = searchResults.stream().map(result -> result.info.uid).collect( - Collectors.toSet()); - assertThat(uidResults).containsExactly( - UserHandle.getUid(user1, uid), - UserHandle.getUid(user2, uid)); - } -} diff --git a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java deleted file mode 100644 index 1c5a67e8f64..00000000000 --- a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.os.UserHandle; -import android.view.LayoutInflater; -import android.view.View; - -import com.android.settings.R; -import com.android.settings.TestConfig; -import com.android.settings.search.SearchResult.Builder; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class IntentSearchViewHolderTest { - - private static final String TITLE = "title"; - private static final String SUMMARY = "summary"; - private static final int USER_ID = 10; - private static final String BADGED_LABEL = "work title"; - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private SearchFragment mFragment; - @Mock - private PackageManager mPackageManager; - private FakeFeatureFactory mFeatureFactory; - private IntentSearchViewHolder mHolder; - private Drawable mIcon; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mFeatureFactory = FakeFeatureFactory.setupForTest(); - - final Context context = RuntimeEnvironment.application; - final View view = LayoutInflater.from(context).inflate(R.layout.search_intent_item, null); - mHolder = new IntentSearchViewHolder(view); - - mIcon = context.getDrawable(R.drawable.ic_search_24dp); - when(mFragment.getActivity().getPackageManager()).thenReturn(mPackageManager); - } - - @Test - public void testConstructor_membersNotNull() { - assertThat(mHolder.titleView).isNotNull(); - assertThat(mHolder.summaryView).isNotNull(); - assertThat(mHolder.iconView).isNotNull(); - assertThat(mHolder.breadcrumbView).isNotNull(); - } - - @Test - public void testBindViewElements_allUpdated() { - final SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon); - mHolder.onBind(mFragment, result); - mHolder.itemView.performClick(); - - assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); - assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); - assertThat(mHolder.iconView.getDrawable()).isEqualTo(mIcon); - assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.GONE); - - verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class)); - } - - @Test - public void testBindViewIcon_nullIcon_imageDrawableIsNull() { - final SearchResult result = getSearchResult(TITLE, SUMMARY, null); - mHolder.onBind(mFragment, result); - - assertThat(mHolder.iconView.getDrawable()).isNull(); - } - - @Test - public void testBindViewElements_emptySummary_hideSummaryView() { - final SearchResult result = new Builder() - .setTitle(TITLE) - .setRank(1) - .setPayload(new ResultPayload(null)) - .setIcon(mIcon) - .setStableId(1) - .build(); - - mHolder.onBind(mFragment, result); - assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE); - } - - @Test - public void testBindViewElements_withBreadcrumb_shouldFormatBreadcrumb() { - final List breadcrumbs = new ArrayList<>(); - breadcrumbs.add("a"); - breadcrumbs.add("b"); - breadcrumbs.add("c"); - final SearchResult result = new Builder() - .setTitle(TITLE) - .setRank(1) - .setPayload(new ResultPayload(null)) - .addBreadcrumbs(breadcrumbs) - .setIcon(mIcon) - .setStableId(1) - .build(); - - mHolder.onBind(mFragment, result); - assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mHolder.breadcrumbView.getText()).isEqualTo("a > b > c"); - } - - @Test - public void testBindElements_placeholderSummary_visibilityIsGone() { - final String nonBreakingSpace = mContext.getString(R.string.summary_placeholder); - final SearchResult result = new Builder() - .setTitle(TITLE) - .setSummary(nonBreakingSpace) - .setPayload(new ResultPayload(null)) - .setStableId(1) - .build(); - - mHolder.onBind(mFragment, result); - - assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE); - } - - @Test - public void testBindElements_dynamicSummary_visibilityIsGone() { - final String dynamicSummary = "%s"; - final SearchResult result = new Builder() - .setTitle(TITLE) - .setSummary(dynamicSummary) - .setPayload(new ResultPayload(null)) - .setStableId(1) - .build(); - - mHolder.onBind(mFragment, result); - - assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE); - } - - @Test - public void testBindViewElements_appSearchResult() { - mHolder = spy(mHolder); - doReturn(new ColorDrawable(0)).when(mHolder).getBadgedIcon(any(ApplicationInfo.class), - anyInt()); - when(mPackageManager.getUserBadgedLabel(any(CharSequence.class), - eq(new UserHandle(USER_ID)))).thenReturn(BADGED_LABEL); - - final SearchResult result = getAppSearchResult( - TITLE, SUMMARY, mIcon, getApplicationInfo(USER_ID, TITLE, mIcon)); - mHolder.onBind(mFragment, result); - mHolder.itemView.performClick(); - - assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); - assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); - assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.GONE); - assertThat(mHolder.titleView.getContentDescription()).isEqualTo(BADGED_LABEL); - - verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class)); - verify(mFragment.getActivity()).startActivityAsUser( - any(Intent.class), eq(new UserHandle(USER_ID))); - } - - @Test - public void testBindViewElements_validSubSettingIntent_shouldLaunch() { - final SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon); - when(mPackageManager.queryIntentActivities(result.payload.getIntent(), 0 /* flags */)) - .thenReturn(Arrays.asList(new ResolveInfo())); - - mHolder.onBind(mFragment, result); - mHolder.itemView.performClick(); - - assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); - assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); - assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE); - verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class)); - verify(mFragment).startActivityForResult(result.payload.getIntent(), - IntentSearchViewHolder.REQUEST_CODE_NO_OP); - } - - @Test - public void testBindViewElements_invalidSubSettingIntent_shouldNotLaunchAnything() { - final SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon); - when(mPackageManager.queryIntentActivities(result.payload.getIntent(), 0 /* flags */)) - .thenReturn(null); - - mHolder.onBind(mFragment, result); - mHolder.itemView.performClick(); - - assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); - assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); - assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE); - verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class)); - verify(mFragment, never()).startActivityForResult(result.payload.getIntent(), - IntentSearchViewHolder.REQUEST_CODE_NO_OP); - } - - private SearchResult getSearchResult(String title, String summary, Drawable icon) { - Builder builder = new Builder(); - builder.setStableId(Objects.hash(title, summary, icon)) - .setTitle(title) - .setSummary(summary) - .setRank(1) - .setPayload(new ResultPayload( - new Intent().setComponent(new ComponentName("pkg", "class")))) - .addBreadcrumbs(new ArrayList<>()) - .setStableId(1) - .setIcon(icon); - - return builder.build(); - } - - private SearchResult getAppSearchResult( - String title, String summary, Drawable icon, ApplicationInfo applicationInfo) { - AppSearchResult.Builder builder = new AppSearchResult.Builder(); - builder.setTitle(title) - .setSummary(summary) - .setRank(1) - .setPayload(new ResultPayload( - new Intent().setComponent(new ComponentName("pkg", "class")))) - .addBreadcrumbs(new ArrayList<>()) - .setIcon(icon); - builder.setAppInfo(applicationInfo); - return builder.build(); - } - - private ApplicationInfo getApplicationInfo(int userId, CharSequence appLabel, Drawable icon) { - ApplicationInfo applicationInfo = spy(new ApplicationInfo()); - applicationInfo.uid = UserHandle.getUid(userId, 12345); - doReturn(icon).when(applicationInfo).loadIcon(any(PackageManager.class)); - doReturn(appLabel).when(applicationInfo).loadLabel(any(PackageManager.class)); - return applicationInfo; - } -} diff --git a/tests/robotests/src/com/android/settings/search/MockSearchResultLoader.java b/tests/robotests/src/com/android/settings/search/MockSearchResultLoader.java deleted file mode 100644 index 6af258ab1de..00000000000 --- a/tests/robotests/src/com/android/settings/search/MockSearchResultLoader.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.android.settings.search; - -import android.content.Context; - -import com.android.settings.search.SearchResult; -import com.android.settings.search.SearchResultLoader; - -import java.util.ArrayList; -import java.util.List; - -/** - * Mock loader to subvert the requirements of returning data while also driving the Loader - * lifecycle. - */ -public class MockSearchResultLoader extends SearchResultLoader { - - public MockSearchResultLoader(Context context) { - super(context, "test"); - } - - @Override - public List loadInBackground() { - return new ArrayList<>(); - } - - @Override - protected void onDiscardResult(List result) { - } -} diff --git a/tests/robotests/src/com/android/settings/search/SavedQueryLoaderTest.java b/tests/robotests/src/com/android/settings/search/SavedQueryLoaderTest.java deleted file mode 100644 index 780a8a5dbc9..00000000000 --- a/tests/robotests/src/com/android/settings/search/SavedQueryLoaderTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - - -import android.content.ContentValues; -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; - -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.TestConfig; -import com.android.settings.testutils.DatabaseTestUtils; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import java.util.List; - -import static com.google.common.truth.Truth.assertThat; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class SavedQueryLoaderTest { - - private Context mContext; - private SQLiteDatabase mDb; - private SavedQueryLoader mLoader; - - @Before - public void setUp() { - mContext = RuntimeEnvironment.application; - mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase(); - mLoader = new SavedQueryLoader(mContext); - setUpDb(); - } - - @After - public void cleanUp() { - DatabaseTestUtils.clearDb(mContext); - } - - @Test - public void loadInBackground_shouldReturnSavedQueries() { - final List results = mLoader.loadInBackground(); - assertThat(results.size()).isEqualTo(SavedQueryLoader.MAX_PROPOSED_SUGGESTIONS); - for (SearchResult result : results) { - assertThat(result.viewType).isEqualTo(ResultPayload.PayloadType.SAVED_QUERY); - } - } - - private void setUpDb() { - final long now = System.currentTimeMillis(); - for (int i = 0; i < SavedQueryLoader.MAX_PROPOSED_SUGGESTIONS + 2; i++) { - ContentValues values = new ContentValues(); - values.put(IndexDatabaseHelper.SavedQueriesColumns.QUERY, String.valueOf(i)); - values.put(IndexDatabaseHelper.SavedQueriesColumns.TIME_STAMP, now); - mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES, null, values); - } - } -} diff --git a/tests/robotests/src/com/android/settings/search/SavedQueryPayloadTest.java b/tests/robotests/src/com/android/settings/search/SavedQueryPayloadTest.java deleted file mode 100644 index 7421d1a1e24..00000000000 --- a/tests/robotests/src/com/android/settings/search/SavedQueryPayloadTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - - -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.TestConfig; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; - -import static com.google.common.truth.Truth.assertThat; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class SavedQueryPayloadTest { - - private SavedQueryPayload mPayload; - - @Test - public void getType_shouldBeSavedQueryType() { - mPayload = new SavedQueryPayload("Test"); - assertThat(mPayload.getType()).isEqualTo(ResultPayload.PayloadType.SAVED_QUERY); - } -} diff --git a/tests/robotests/src/com/android/settings/search/SavedQueryRecorderAndRemoverTest.java b/tests/robotests/src/com/android/settings/search/SavedQueryRecorderAndRemoverTest.java deleted file mode 100644 index af8cfe40bd3..00000000000 --- a/tests/robotests/src/com/android/settings/search/SavedQueryRecorderAndRemoverTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - - -import static com.google.common.truth.Truth.assertThat; - -import android.content.Context; - -import com.android.settings.TestConfig; -import com.android.settings.testutils.DatabaseTestUtils; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import java.util.List; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class SavedQueryRecorderAndRemoverTest { - - private Context mContext; - private SavedQueryRecorder mRecorder; - private SavedQueryRemover mRemover; - - @Before - public void setUp() { - mContext = RuntimeEnvironment.application; - } - - @After - public void cleanUp() { - DatabaseTestUtils.clearDb(mContext); - } - - @Test - public void canSaveAndRemoveQuery() { - final String query = "test"; - mRecorder = new SavedQueryRecorder(mContext, query); - mRemover = new SavedQueryRemover(mContext); - - // Record a new query and load all queries from DB - mRecorder.loadInBackground(); - final SavedQueryLoader loader = new SavedQueryLoader(mContext); - List results = loader.loadInBackground(); - - // Should contain the newly recorded query - assertThat(results.size()).isEqualTo(1); - assertThat(results.get(0).title).isEqualTo(query); - - // Remove the query and load all queries from DB - mRemover.loadInBackground(); - results = loader.loadInBackground(); - - // Saved query list should be empty because it's removed. - assertThat(results).isEmpty(); - } - - @Test - public void canRemoveAllQueriesAtOnce() { - mRemover = new SavedQueryRemover(mContext);; - - // Record a new query and load all queries from DB - new SavedQueryRecorder(mContext, "Test1").loadInBackground(); - new SavedQueryRecorder(mContext, "Test2").loadInBackground(); - final SavedQueryLoader loader = new SavedQueryLoader(mContext); - List results = loader.loadInBackground(); - assertThat(results.size()).isEqualTo(2); - - mRemover.loadInBackground(); - results = loader.loadInBackground(); - - // Saved query list should be empty because it's removed. - assertThat(results).isEmpty(); - } -} diff --git a/tests/robotests/src/com/android/settings/search/SavedQueryViewHolderTest.java b/tests/robotests/src/com/android/settings/search/SavedQueryViewHolderTest.java deleted file mode 100644 index bb8f6d12da8..00000000000 --- a/tests/robotests/src/com/android/settings/search/SavedQueryViewHolderTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; - -import com.android.settings.R; -import com.android.settings.TestConfig; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class SavedQueryViewHolderTest { - - @Mock - private SearchFragment mSearchFragment; - private Context mContext; - private SavedQueryViewHolder mHolder; - private View mView; - private View mTitleView; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mView = LayoutInflater.from(mContext) - .inflate(R.layout.search_saved_query_item, null); - mTitleView = mView.findViewById(android.R.id.title); - mHolder = new SavedQueryViewHolder(mView); - } - - @Test - public void onBind_shouldBindClickCallback() { - final SearchResult result = mock(SearchResult.class); - mHolder.onBind(mSearchFragment, result); - - mHolder.itemView.performClick(); - - verify(mSearchFragment).onSavedQueryClicked(nullable(CharSequence.class)); - } -} diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java index 4349ab47869..9584e42a33e 100644 --- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java @@ -18,19 +18,15 @@ package com.android.settings.search; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; import static org.robolectric.Shadows.shadowOf; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; -import android.util.FeatureFlagUtils; import android.widget.Toolbar; import com.android.settings.TestConfig; -import com.android.settings.core.FeatureFlags; import com.android.settings.dashboard.SiteMapManager; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowSystemProperties; @@ -73,31 +69,10 @@ public class SearchFeatureProviderImplTest { } @Test - public void getDatabaseSearchLoader_shouldCleanupQuery() { - final String query = " space "; - - mProvider.getStaticSearchResultTask(mActivity, query); - - verify(mProvider).cleanQuery(eq(query)); - } - - @Test - public void getInstalledAppSearchLoader_shouldCleanupQuery() { - final String query = " space "; - - mProvider.getInstalledAppSearchTask(mActivity, query); - - verify(mProvider).cleanQuery(eq(query)); - } - - @Test - public void initSearchToolbar_searchV2_shouldInitWithOnClickListener() { + public void initSearchToolbar_shouldInitWithOnClickListener() { mProvider.initSearchToolbar(mActivity, null); // Should not crash. - SettingsShadowSystemProperties.set( - FeatureFlagUtils.FFLAG_PREFIX + FeatureFlags.SEARCH_V2, - "true"); final Toolbar toolbar = new Toolbar(mActivity); mProvider.initSearchToolbar(mActivity, toolbar); @@ -109,25 +84,6 @@ public class SearchFeatureProviderImplTest { .isEqualTo("com.android.settings.action.SETTINGS_SEARCH"); } - @Test - public void initSearchToolbar_searchV1_shouldInitWithOnClickListener() { - mProvider.initSearchToolbar(mActivity, null); - // Should not crash. - - SettingsShadowSystemProperties.set( - FeatureFlagUtils.FFLAG_PREFIX + FeatureFlags.SEARCH_V2, - "false"); - final Toolbar toolbar = new Toolbar(mActivity); - mProvider.initSearchToolbar(mActivity, toolbar); - - toolbar.performClick(); - - final Intent launchIntent = shadowOf(mActivity).getNextStartedActivity(); - - assertThat(launchIntent.getComponent().getClassName()) - .isEqualTo(SearchActivity.class.getName()); - } - @Test(expected = IllegalArgumentException.class) public void verifyLaunchSearchResultPageCaller_nullCaller_shouldCrash() { mProvider.verifyLaunchSearchResultPageCaller(mActivity, null /* caller */); diff --git a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java b/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java deleted file mode 100644 index f547fe8863f..00000000000 --- a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.LoaderManager; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.Pair; -import android.view.View; - -import com.android.internal.logging.nano.MetricsProto; -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.TestConfig; -import com.android.settings.core.instrumentation.VisibilityLoggerMixin; -import com.android.settings.testutils.DatabaseTestUtils; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.testutils.shadow.SettingsShadowResources; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.Robolectric; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.android.controller.ActivityController; -import org.robolectric.annotation.Config; -import org.robolectric.util.ReflectionHelpers; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, - sdk = TestConfig.SDK_VERSION, - shadows = { - SettingsShadowResources.class, - SettingsShadowResources.SettingsShadowTheme.class, - }) -public class SearchFragmentTest { - @Mock - private SearchResultLoader mSearchResultLoader; - @Mock - private SavedQueryLoader mSavedQueryLoader; - @Mock - private SavedQueryController mSavedQueryController; - @Mock - private SearchResultsAdapter mSearchResultsAdapter; - - private FakeFeatureFactory mFeatureFactory; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mFeatureFactory = FakeFeatureFactory.setupForTest(); - } - - @After - public void tearDown() { - DatabaseTestUtils.clearDb(RuntimeEnvironment.application); - } - - @Test - public void screenRotate_shouldPersistQuery() { - when(mFeatureFactory.searchFeatureProvider - .getSearchResultLoader(any(Context.class), anyString())) - .thenReturn(new MockSearchResultLoader(RuntimeEnvironment.application)); - when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class))) - .thenReturn(mSavedQueryLoader); - - final Bundle bundle = new Bundle(); - final String testQuery = "test"; - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - - ReflectionHelpers.setField(fragment, "mShowingSavedQuery", false); - fragment.mQuery = testQuery; - - activityController.saveInstanceState(bundle).pause().stop().destroy(); - - activityController = Robolectric.buildActivity(SearchActivity.class); - activityController.setup(bundle); - - assertThat(fragment.mQuery).isEqualTo(testQuery); - } - - @Test - public void screenRotateEmptyString_ShouldNotCrash() { - when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class))) - .thenReturn(mSavedQueryLoader); - - final Bundle bundle = new Bundle(); - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(true); - - fragment.mQuery = ""; - - activityController.saveInstanceState(bundle).pause().stop().destroy(); - - activityController = Robolectric.buildActivity(SearchActivity.class); - activityController.setup(bundle); - - verify(mFeatureFactory.searchFeatureProvider, never()) - .getStaticSearchResultTask(any(Context.class), anyString()); - verify(mFeatureFactory.searchFeatureProvider, never()) - .getInstalledAppSearchTask(any(Context.class), anyString()); - } - - @Test - public void queryTextChange_shouldTriggerLoader() { - when(mFeatureFactory.searchFeatureProvider - .getSearchResultLoader(any(Context.class), anyString())) - .thenReturn(mSearchResultLoader); - when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class))) - .thenReturn(mSavedQueryLoader); - - final String testQuery = "test"; - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(true); - - fragment.onQueryTextChange(testQuery); - activityController.get().onBackPressed(); - - activityController.pause().stop().destroy(); - - verify(mFeatureFactory.metricsFeatureProvider, never()).action( - any(Context.class), - eq(MetricsProto.MetricsEvent.ACTION_LEAVE_SEARCH_RESULT_WITHOUT_QUERY)); - verify(mFeatureFactory.searchFeatureProvider) - .getSearchResultLoader(any(Context.class), anyString()); - } - - @Test - public void onSearchResultsDisplayed_noResult_shouldShowNoResultView() { - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = spy((SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content)); - fragment.onSearchResultsDisplayed(0 /* count */); - - assertThat(fragment.mNoResultsView.getVisibility()).isEqualTo(View.VISIBLE); - verify(mFeatureFactory.metricsFeatureProvider).visible( - any(Context.class), - anyInt(), - eq(MetricsProto.MetricsEvent.SETTINGS_SEARCH_NO_RESULT)); - verify(mFeatureFactory.metricsFeatureProvider).action( - any(VisibilityLoggerMixin.class), - eq(MetricsProto.MetricsEvent.ACTION_SEARCH_RESULTS), - eq(1)); - } - - @Test - public void queryTextChangeToEmpty_shouldLoadSavedQueryAndNotInitializeSearch() { - when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class))) - .thenReturn(mSavedQueryLoader); - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = spy((SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content)); - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(true); - ReflectionHelpers.setField(fragment, "mSavedQueryController", mSavedQueryController); - ReflectionHelpers.setField(fragment, "mSearchAdapter", mSearchResultsAdapter); - fragment.mQuery = "123"; - - fragment.onQueryTextChange(""); - - verify(mFeatureFactory.searchFeatureProvider, never()) - .getStaticSearchResultTask(any(Context.class), anyString()); - verify(mFeatureFactory.searchFeatureProvider, never()) - .getInstalledAppSearchTask(any(Context.class), anyString()); - verify(mSavedQueryController).loadSavedQueries(); - } - - @Test - public void updateIndex_TriggerOnCreate() { - when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class))) - .thenReturn(mSavedQueryLoader); - - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(true); - - fragment.onAttach(null); - verify(mFeatureFactory.searchFeatureProvider).updateIndexAsync(any(Context.class), - any(IndexingCallback.class)); - } - - @Test - public void whenNoQuery_HideFeedbackIsCalled() { - when(mFeatureFactory.searchFeatureProvider - .getSearchResultLoader(any(Context.class), anyString())) - .thenReturn(new MockSearchResultLoader(RuntimeEnvironment.application)); - when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class))) - .thenReturn(mSavedQueryLoader); - - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content)); - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(true); - when(fragment.getLoaderManager()).thenReturn(mock(LoaderManager.class)); - - fragment.onQueryTextChange(""); - Robolectric.flushForegroundThreadScheduler(); - - verify(mFeatureFactory.searchFeatureProvider).hideFeedbackButton(); - } - - @Test - public void onLoadFinished_ShowsFeedback() { - when(mFeatureFactory.searchFeatureProvider - .getSearchResultLoader(any(Context.class), anyString())) - .thenReturn(new MockSearchResultLoader(RuntimeEnvironment.application)); - when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class))) - .thenReturn(mSavedQueryLoader); - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(true); - - fragment.onQueryTextChange("non-empty"); - Robolectric.flushForegroundThreadScheduler(); - - verify(mFeatureFactory.searchFeatureProvider).showFeedbackButton(any(SearchFragment.class), - any(View.class)); - } - - @Test - public void preIndexingFinished_isIndexingFinishedFlag_isFalse() { - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(false); - } - - @Test - public void onIndexingFinished_notShowingSavedQuery_initLoaders() { - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content)); - final LoaderManager loaderManager = mock(LoaderManager.class); - when(fragment.getLoaderManager()).thenReturn(loaderManager); - fragment.mShowingSavedQuery = false; - fragment.mQuery = null; - - fragment.onIndexingFinished(); - - verify(loaderManager).initLoader(eq(SearchFragment.SearchLoaderId.SEARCH_RESULT), - eq(null), any(LoaderManager.LoaderCallbacks.class)); - } - - @Test - public void onIndexingFinished_showingSavedQuery_loadsSavedQueries() { - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content)); - fragment.mShowingSavedQuery = true; - ReflectionHelpers.setField(fragment, "mSavedQueryController", mSavedQueryController); - - fragment.onIndexingFinished(); - - verify(fragment.mSavedQueryController).loadSavedQueries(); - } - - @Test - public void onIndexingFinished_noActivity_shouldNotCrash() { - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content)); - when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class))) - .thenReturn(true); - fragment.mQuery = "bright"; - ReflectionHelpers.setField(fragment, "mLoaderManager", null); - ReflectionHelpers.setField(fragment, "mHost", null); - - fragment.onIndexingFinished(); - // no crash - } - - @Test - public void onSearchResultClicked_shouldLogResultMeta() { - SearchFragment fragment = new SearchFragment(); - ReflectionHelpers.setField(fragment, "mMetricsFeatureProvider", - mFeatureFactory.metricsFeatureProvider); - ReflectionHelpers.setField(fragment, "mSearchFeatureProvider", - mFeatureFactory.searchFeatureProvider); - ReflectionHelpers.setField(fragment, "mSearchAdapter", mock(SearchResultsAdapter.class)); - fragment.mSavedQueryController = mock(SavedQueryController.class); - - // Should log result name, result count, clicked rank, etc. - final SearchViewHolder resultViewHolder = mock(SearchViewHolder.class); - when(resultViewHolder.getClickActionMetricName()) - .thenReturn(MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT); - ResultPayload payLoad = new ResultPayload( - (new Intent()).putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, "test_setting")); - SearchResult searchResult = new SearchResult.Builder() - .setStableId(payLoad.hashCode()) - .setPayload(payLoad) - .setTitle("setting_title") - .build(); - fragment.onSearchResultClicked(resultViewHolder, searchResult); - - verify(mFeatureFactory.metricsFeatureProvider).action( - nullable(Context.class), - eq(MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT), - eq("test_setting"), - argThat(pairMatches(MetricsProto.MetricsEvent.FIELD_SETTINGS_SEARCH_RESULT_COUNT)), - argThat(pairMatches(MetricsProto.MetricsEvent.FIELD_SETTINGS_SEARCH_RESULT_RANK)), - argThat(pairMatches(MetricsProto.MetricsEvent.FIELD_SETTINGS_SEARCH_QUERY_LENGTH))); - verify(mFeatureFactory.searchFeatureProvider).searchResultClicked(nullable(Context.class), - nullable(String.class), eq(searchResult)); - } - - @Test - public void onResume_shouldCallSearchRankingWarmupIfSmartSearchRankingEnabled() { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any(Context.class))) - .thenReturn(true); - - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - - verify(mFeatureFactory.searchFeatureProvider) - .searchRankingWarmup(any(Context.class)); - } - - @Test - public void onResume_shouldNotCallSearchRankingWarmupIfSmartSearchRankingDisabled() { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any(Context.class))) - .thenReturn(false); - - ActivityController activityController = - Robolectric.buildActivity(SearchActivity.class); - activityController.setup(); - SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager() - .findFragmentById(R.id.main_content); - - verify(mFeatureFactory.searchFeatureProvider, never()) - .searchRankingWarmup(any(Context.class)); - } - - private ArgumentMatcher> pairMatches(int tag) { - return pair -> pair.first == tag; - } -} diff --git a/tests/robotests/src/com/android/settings/search/SearchResultAggregatorTest.java b/tests/robotests/src/com/android/settings/search/SearchResultAggregatorTest.java deleted file mode 100644 index 27fcd6a6120..00000000000 --- a/tests/robotests/src/com/android/settings/search/SearchResultAggregatorTest.java +++ /dev/null @@ -1,269 +0,0 @@ -package com.android.settings.search; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.Intent; - -import com.android.settings.TestConfig; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class SearchResultAggregatorTest { - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; - - private FakeFeatureFactory mFeatureFactory; - - private SearchResultAggregator mAggregator; - - @Mock - private DatabaseResultLoader mStaticTask; - @Mock - private InstalledAppResultLoader mAppTask; - @Mock - private InputDeviceResultLoader mInputTask; - @Mock - private AccessibilityServiceResultLoader mMAccessibilityTask; - @Mock - private ExecutorService mService; - - - private String[] DB_TITLES = {"static_one", "static_two"}; - private String[] INPUT_TITLES = {"input_one", "input_two"}; - private String[] ACCESS_TITLES = {"access_one", "access_two"}; - private String[] APP_TITLES = {"app_one", "app_two"}; - - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mAggregator = spy(SearchResultAggregator.getInstance()); - mFeatureFactory = FakeFeatureFactory.setupForTest(); - - // Return mock loaders from feature provider - when(mFeatureFactory.searchFeatureProvider.getStaticSearchResultTask(any(Context.class), - anyString())).thenReturn(mStaticTask); - when(mFeatureFactory.searchFeatureProvider.getInstalledAppSearchTask(any(Context.class), - anyString())).thenReturn(mAppTask); - when(mFeatureFactory.searchFeatureProvider.getInputDeviceResultTask(any(Context.class), - anyString())).thenReturn(mInputTask); - when(mFeatureFactory.searchFeatureProvider.getAccessibilityServiceResultTask( - any(Context.class), - anyString())).thenReturn(mMAccessibilityTask); - when(mFeatureFactory.searchFeatureProvider.getExecutorService()).thenReturn(mService); - - // Return fake data from the loaders - List dbResults = getDummyDbResults(); - doReturn(dbResults).when(mStaticTask).get(anyLong(), any(TimeUnit.class)); - - List appResults = getDummyAppResults(); - doReturn(appResults).when(mAppTask).get(anyLong(), any(TimeUnit.class)); - - List inputResults = getDummyInputDeviceResults(); - doReturn(inputResults).when(mInputTask).get(anyLong(), any(TimeUnit.class)); - - List accessResults = getDummyAccessibilityResults(); - doReturn(accessResults).when(mMAccessibilityTask).get(anyLong(), any(TimeUnit.class)); - } - - @Test - public void testStaticResults_mergedProperly() { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext)) - .thenReturn(false); - - List results = mAggregator.fetchResults(mContext, "test"); - - assertThat(results).hasSize(8); - assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]); - assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]); - assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]); - assertThat(results.get(3).title).isEqualTo(ACCESS_TITLES[0]); - assertThat(results.get(4).title).isEqualTo(INPUT_TITLES[0]); - assertThat(results.get(5).title).isEqualTo(APP_TITLES[1]); - assertThat(results.get(6).title).isEqualTo(ACCESS_TITLES[1]); - assertThat(results.get(7).title).isEqualTo(INPUT_TITLES[1]); - } - - @Test - public void testStaticRanking_staticThrowsException_dbResultsAreMissing() throws Exception { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext)) - .thenReturn(false); - when(mStaticTask.get(anyLong(), any(TimeUnit.class))).thenThrow(new InterruptedException()); - - List results = mAggregator.fetchResults(mContext, "test"); - - assertThat(results).hasSize(6); - assertThat(results.get(0).title).isEqualTo(APP_TITLES[0]); - assertThat(results.get(1).title).isEqualTo(ACCESS_TITLES[0]); - assertThat(results.get(2).title).isEqualTo(INPUT_TITLES[0]); - assertThat(results.get(3).title).isEqualTo(APP_TITLES[1]); - assertThat(results.get(4).title).isEqualTo(ACCESS_TITLES[1]); - assertThat(results.get(5).title).isEqualTo(INPUT_TITLES[1]); - } - - @Test - public void testStaticRanking_appsThrowException_appResultsAreMissing() throws Exception { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext)) - .thenReturn(false); - when(mAppTask.get(anyLong(), any(TimeUnit.class))).thenThrow(new InterruptedException()); - - List results = mAggregator.fetchResults(mContext, "test"); - - assertThat(results).hasSize(6); - assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]); - assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]); - assertThat(results.get(2).title).isEqualTo(ACCESS_TITLES[0]); - assertThat(results.get(3).title).isEqualTo(INPUT_TITLES[0]); - assertThat(results.get(4).title).isEqualTo(ACCESS_TITLES[1]); - assertThat(results.get(5).title).isEqualTo(INPUT_TITLES[1]); - } - - @Test - public void testStaticRanking_inputThrowException_inputResultsAreMissing() throws Exception { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext)) - .thenReturn(false); - when(mInputTask.get(anyLong(), any(TimeUnit.class))).thenThrow(new InterruptedException()); - - List results = mAggregator.fetchResults(mContext, "test"); - - assertThat(results).hasSize(6); - assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]); - assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]); - assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]); - assertThat(results.get(3).title).isEqualTo(ACCESS_TITLES[0]); - assertThat(results.get(4).title).isEqualTo(APP_TITLES[1]); - assertThat(results.get(5).title).isEqualTo(ACCESS_TITLES[1]); - } - - @Test - public void testStaticRanking_accessThrowException_accessResultsAreMissing() throws Exception { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext)) - .thenReturn(false); - when(mMAccessibilityTask.get(anyLong(), any(TimeUnit.class))).thenThrow( - new InterruptedException()); - - List results = mAggregator.fetchResults(mContext, "test"); - - assertThat(results).hasSize(6); - assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]); - assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]); - assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]); - assertThat(results.get(3).title).isEqualTo(INPUT_TITLES[0]); - assertThat(results.get(4).title).isEqualTo(APP_TITLES[1]); - assertThat(results.get(5).title).isEqualTo(INPUT_TITLES[1]); - } - - @Test - public void testDynamicRanking_sortsWithDynamicRanking() { - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn( - true); - - List results = mAggregator.fetchResults(mContext, "test"); - - assertThat(results).hasSize(8); - assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]); - assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]); - assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]); - assertThat(results.get(3).title).isEqualTo(ACCESS_TITLES[0]); - assertThat(results.get(4).title).isEqualTo(INPUT_TITLES[0]); - assertThat(results.get(5).title).isEqualTo(APP_TITLES[1]); - assertThat(results.get(6).title).isEqualTo(ACCESS_TITLES[1]); - assertThat(results.get(7).title).isEqualTo(INPUT_TITLES[1]); - } - - private List getDummyDbResults() { - List results = new ArrayList<>(); - ResultPayload payload = new ResultPayload(new Intent()); - SearchResult.Builder builder = new SearchResult.Builder(); - builder.setPayload(payload) - .setTitle(DB_TITLES[0]) - .setRank(1) - .setStableId(Objects.hash(DB_TITLES[0], "db")); - results.add(builder.build()); - - builder.setTitle(DB_TITLES[1]) - .setRank(2) - .setStableId(Objects.hash(DB_TITLES[1], "db")); - results.add(builder.build()); - - return results; - } - - private List getDummyAppResults() { - List results = new ArrayList<>(); - ResultPayload payload = new ResultPayload(new Intent()); - AppSearchResult.Builder builder = new AppSearchResult.Builder(); - builder.setPayload(payload) - .setTitle(APP_TITLES[0]) - .setRank(1) - .setStableId(Objects.hash(APP_TITLES[0], "app")); - results.add(builder.build()); - - builder.setTitle(APP_TITLES[1]) - .setRank(2) - .setStableId(Objects.hash(APP_TITLES[1], "app")); - results.add(builder.build()); - - return results; - } - - public List getDummyInputDeviceResults() { - List results = new ArrayList<>(); - ResultPayload payload = new ResultPayload(new Intent()); - AppSearchResult.Builder builder = new AppSearchResult.Builder(); - builder.setPayload(payload) - .setTitle(INPUT_TITLES[0]) - .setRank(1) - .setStableId(Objects.hash(INPUT_TITLES[0], "app")); - results.add(builder.build()); - - builder.setTitle(INPUT_TITLES[1]) - .setRank(2) - .setStableId(Objects.hash(INPUT_TITLES[1], "app")); - results.add(builder.build()); - - return results; - } - - public List getDummyAccessibilityResults() { - List results = new ArrayList<>(); - ResultPayload payload = new ResultPayload(new Intent()); - AppSearchResult.Builder builder = new AppSearchResult.Builder(); - builder.setPayload(payload) - .setTitle(ACCESS_TITLES[0]) - .setRank(1) - .setStableId(Objects.hash(ACCESS_TITLES[0], "app")); - results.add(builder.build()); - - builder.setTitle(ACCESS_TITLES[1]) - .setRank(2) - .setStableId(Objects.hash(ACCESS_TITLES[1], "app")); - results.add(builder.build()); - - return results; - } -} diff --git a/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java b/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java deleted file mode 100644 index 4baf8d2acd6..00000000000 --- a/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2016 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.settings.search; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.android.settings.TestConfig; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.Robolectric; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class SearchResultsAdapterTest { - - @Mock - private SearchFragment mFragment; - @Mock - private SearchFeatureProvider mSearchFeatureProvider; - @Mock - private Context mMockContext; - private SearchResultsAdapter mAdapter; - private Context mContext; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = Robolectric.buildActivity(Activity.class).get(); - when(mFragment.getContext()).thenReturn(mMockContext); - when(mMockContext.getApplicationContext()).thenReturn(mContext); - when(mSearchFeatureProvider.smartSearchRankingTimeoutMs(any(Context.class))) - .thenReturn(300L); - mAdapter = new SearchResultsAdapter(mFragment); - } - - @Test - public void testNoResultsAdded_emptyListReturned() { - List updatedResults = mAdapter.getSearchResults(); - assertThat(updatedResults).isEmpty(); - } - - @Test - public void testCreateViewHolder_returnsIntentResult() { - ViewGroup group = new FrameLayout(mContext); - SearchViewHolder view = mAdapter.onCreateViewHolder(group, - ResultPayload.PayloadType.INTENT); - assertThat(view).isInstanceOf(IntentSearchViewHolder.class); - } - - @Test - public void testCreateViewHolder_returnsIntentSwitchResult() { - // TODO (b/62807132) test for InlineResult - ViewGroup group = new FrameLayout(mContext); - SearchViewHolder view = mAdapter.onCreateViewHolder(group, - ResultPayload.PayloadType.INLINE_SWITCH); - assertThat(view).isInstanceOf(IntentSearchViewHolder.class); - } - - @Test - public void testPostSearchResults_addsDataAndDisplays() { - List results = getDummyDbResults(); - - mAdapter.postSearchResults(results); - - assertThat(mAdapter.getSearchResults()).containsExactlyElementsIn(results); - verify(mFragment).onSearchResultsDisplayed(anyInt()); - } - - private List getDummyDbResults() { - List results = new ArrayList<>(); - ResultPayload payload = new ResultPayload(new Intent()); - SearchResult.Builder builder = new SearchResult.Builder(); - builder.setPayload(payload) - .setTitle("one") - .setRank(1) - .setStableId(Objects.hash("one", "db")); - results.add(builder.build()); - - builder.setTitle("two") - .setRank(3) - .setStableId(Objects.hash("two", "db")); - results.add(builder.build()); - - builder.setTitle("three") - .setRank(6) - .setStableId(Objects.hash("three", "db")); - results.add(builder.build()); - - return results; - } -} diff --git a/tests/robotests/src/com/android/settings/search/StaticSearchResultFutureTaskTest.java b/tests/robotests/src/com/android/settings/search/StaticSearchResultFutureTaskTest.java deleted file mode 100644 index b1494e442d8..00000000000 --- a/tests/robotests/src/com/android/settings/search/StaticSearchResultFutureTaskTest.java +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.database.sqlite.SQLiteDatabase; -import android.util.Pair; - -import com.android.settings.TestConfig; -import com.android.settings.dashboard.SiteMapManager; -import com.android.settings.search.DatabaseResultLoader.StaticSearchResultCallable; -import com.android.settings.search.indexing.IndexData; -import com.android.settings.testutils.DatabaseTestUtils; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class StaticSearchResultFutureTaskTest { - - @Mock - private SiteMapManager mSiteMapManager; - @Mock - private ExecutorService mService; - private Context mContext; - - SQLiteDatabase mDb; - - FakeFeatureFactory mFeatureFactory; - - private final String[] STATIC_TITLES = {"static one", "static two", "static three"}; - private final int[] STABLE_IDS = - {"id_one".hashCode(), "id_two".hashCode(), "id_three".hashCode()}; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mFeatureFactory = FakeFeatureFactory.setupForTest(); - when(mFeatureFactory.searchFeatureProvider.getExecutorService()).thenReturn(mService); - when(mFeatureFactory.searchFeatureProvider.getSiteMapManager()) - .thenReturn(mSiteMapManager); - mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase(); - setUpDb(); - } - - @After - public void cleanUp() { - DatabaseTestUtils.clearDb(mContext); - } - - @Test - public void testMatchTitle() throws Exception { - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "title", - mSiteMapManager); - - assertThat(loader.call()).hasSize(2); - verify(mSiteMapManager, times(2)).buildBreadCrumb(eq(mContext), anyString(), anyString()); - } - - @Test - public void testMatchSummary() throws Exception { - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "summary", - mSiteMapManager); - - assertThat(loader.call()).hasSize(2); - } - - @Test - public void testMatchKeywords() throws Exception { - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "keywords", - mSiteMapManager); - - assertThat(loader.call()).hasSize(2); - } - - @Test - public void testMatchEntries() throws Exception { - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "entries", - mSiteMapManager); - - assertThat(loader.call()).hasSize(2); - } - - @Test - public void testSpecialCaseWord_matchesNonPrefix() throws Exception { - insertSpecialCase("Data usage"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "usage", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseDash_matchesWordNoDash() throws Exception { - insertSpecialCase("wi-fi calling"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "wifi", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseDash_matchesWordWithDash() throws Exception { - insertSpecialCase("priorités seulment"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "priorités", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseDash_matchesWordWithoutDash() throws Exception { - insertSpecialCase("priorités seulment"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "priorites", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseDash_matchesEntireQueryWithoutDash() throws Exception { - insertSpecialCase("wi-fi calling"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "wifi calling", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCasePrefix_matchesPrefixOfEntry() throws Exception { - insertSpecialCase("Photos"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "pho", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCasePrefix_DoesNotMatchNonPrefixSubstring() throws Exception { - insertSpecialCase("Photos"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "hot", - mSiteMapManager); - - assertThat(loader.call()).hasSize(0); - } - - @Test - public void testSpecialCaseMultiWordPrefix_matchesPrefixOfEntry() throws Exception { - insertSpecialCase("Apps Notifications"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "Apps", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseMultiWordPrefix_matchesSecondWordPrefixOfEntry() throws Exception { - insertSpecialCase("Apps Notifications"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "Not", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfFirstEntry() - throws Exception { - insertSpecialCase("Apps Notifications"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "pp", - mSiteMapManager); - - assertThat(loader.call()).hasSize(0); - } - - @Test - public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfSecondEntry() - throws Exception { - insertSpecialCase("Apps Notifications"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "tion", - mSiteMapManager); - - assertThat(loader.call()).hasSize(0); - } - - @Test - public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfEntry() throws - Exception { - insertSpecialCase("Apps & Notifications"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "App", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfSecondEntry() - throws Exception { - insertSpecialCase("Apps & Notifications"); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "No", - mSiteMapManager); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testResultMatchedByMultipleQueries_duplicatesRemoved() throws Exception { - String key = "durr"; - insertSameValueAllFieldsCase(key); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, key, null); - - assertThat(loader.call()).hasSize(1); - } - - @Test - public void testSpecialCaseTwoWords_multipleResults() throws Exception { - final String caseOne = "Apple pear"; - final String caseTwo = "Banana apple"; - insertSpecialCase(caseOne); - insertSpecialCase(caseTwo); - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "App", null); - - List results = loader.call(); - - Set actualTitles = new HashSet<>(); - for (SearchResult result : results) { - actualTitles.add(result.title.toString()); - } - assertThat(actualTitles).containsAllOf(caseOne, caseTwo); - } - - @Test - public void testGetRankingScoreByStableId_sortedDynamically() throws Exception { - FutureTask>> task = mock(FutureTask.class); - when(task.get(anyLong(), any(TimeUnit.class))).thenReturn(getDummyRankingScores()); - when(mFeatureFactory.searchFeatureProvider.getRankerTask(any(Context.class), - anyString())).thenReturn(task); - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn( - true); - - insertSpecialCase(STATIC_TITLES[0], STABLE_IDS[0]); - insertSpecialCase(STATIC_TITLES[1], STABLE_IDS[1]); - insertSpecialCase(STATIC_TITLES[2], STABLE_IDS[2]); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "Static", - null); - - List results = loader.call(); - - assertThat(results.get(0).title).isEqualTo(STATIC_TITLES[2]); - assertThat(results.get(1).title).isEqualTo(STATIC_TITLES[0]); - assertThat(results.get(2).title).isEqualTo(STATIC_TITLES[1]); - } - - @Test - public void testGetRankingScoreByStableId_scoresTimeout_sortedStatically() throws Exception { - Callable>> callable = mock(Callable.class); - when(callable.call()).thenThrow(new TimeoutException()); - FutureTask>> task = new FutureTask<>(callable); - when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn( - true); - when(mFeatureFactory.searchFeatureProvider.getRankerTask(any(Context.class), - anyString())).thenReturn(task); - insertSpecialCase("title", STABLE_IDS[0]); - - StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "title", null); - - List results = loader.call(); - assertThat(results.get(0).title).isEqualTo("title"); - assertThat(results.get(1).title).isEqualTo("alpha_title"); - assertThat(results.get(2).title).isEqualTo("bravo_title"); - } - - private void insertSpecialCase(String specialCase) { - insertSpecialCase(specialCase, specialCase.hashCode()); - } - - private void insertSpecialCase(String specialCase, int docId) { - String normalized = IndexData.normalizeHyphen(specialCase); - normalized = IndexData.normalizeString(normalized); - final ResultPayload payload = new ResultPayload(new Intent()); - - ContentValues values = new ContentValues(); - values.put(IndexDatabaseHelper.IndexColumns.DOCID, docId); - values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, specialCase); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, normalized); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, ""); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED, ""); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, ""); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, ""); - values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, ""); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, ""); - values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, - "com.android.settings.gestures.GestureSettings"); - values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, "Moves"); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); - values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); - values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, normalized.hashCode()); - values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, ResultPayloadUtils.marshall(payload)); - - mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); - } - - private void setUpDb() { - final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(new Intent())); - - ContentValues values = new ContentValues(); - values.put(IndexDatabaseHelper.IndexColumns.DOCID, 1); - values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "alpha_title"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, "alpha title"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, "alpha_summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED, "alpha summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, "alpha_summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, "alpha summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, "alpha entries"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, "alpha keywords"); - values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, - "com.android.settings.gestures.GestureSettings"); - values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, "Moves"); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); - values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); - values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power_0"); - values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload); - - mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); - - values = new ContentValues(); - values.put(IndexDatabaseHelper.IndexColumns.DOCID, 2); - values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "bravo_title"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, "bravo title"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, "bravo_summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED, "bravo summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, "bravo_summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, "bravo summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, "bravo entries"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, "bravo keywords"); - values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, - "com.android.settings.gestures.GestureSettings"); - values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, "Moves"); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); - values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); - values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power_1"); - values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload); - mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); - - values = new ContentValues(); - values.put(IndexDatabaseHelper.IndexColumns.DOCID, 3); - values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "charlie_title"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, "charlie title"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, "charlie_summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED, "charlie summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, "charlie_summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, "charlie summary"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, "charlie entries"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, "charlie keywords"); - values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, - "com.android.settings.gestures.GestureSettings"); - values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, "Moves"); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); - values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); - values.put(IndexDatabaseHelper.IndexColumns.ENABLED, false); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power_2"); - values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload); - - mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); - } - - private void insertSameValueAllFieldsCase(String key) { - final ResultPayload payload = new ResultPayload(new Intent()); - - ContentValues values = new ContentValues(); - values.put(IndexDatabaseHelper.IndexColumns.DOCID, key.hashCode()); - values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); - values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, key); - values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, key); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, key); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED, key); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, key); - values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, key); - values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, key); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, key); - values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, key); - values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, "Moves"); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, key); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, ""); - values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, key); - values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); - values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true); - values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, key.hashCode()); - values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); - values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, ResultPayloadUtils.marshall(payload)); - - mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); - } - - private List getDummyDbResults() { - List results = new ArrayList<>(); - ResultPayload payload = new ResultPayload(new Intent()); - SearchResult.Builder builder = new SearchResult.Builder(); - builder.setPayload(payload) - .setTitle(STATIC_TITLES[0]) - .setStableId(STABLE_IDS[0]); - results.add(builder.build()); - - builder.setTitle(STATIC_TITLES[1]) - .setStableId(STABLE_IDS[1]); - results.add(builder.build()); - - builder.setTitle(STATIC_TITLES[2]) - .setStableId(STABLE_IDS[2]); - results.add(builder.build()); - - return results; - } - - private List> getDummyRankingScores() { - List results = getDummyDbResults(); - List> scores = new ArrayList<>(); - scores.add(new Pair<>(Long.toString(results.get(2).stableId), 0.9f)); // static_three - scores.add(new Pair<>(Long.toString(results.get(0).stableId), 0.8f)); // static_one - scores.add(new Pair<>(Long.toString(results.get(1).stableId), 0.2f)); // static_two - return scores; - } -} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java index e79e2d01a33..e1c77cd37f7 100644 --- a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java +++ b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java @@ -16,20 +16,16 @@ package com.android.settings.search.actionbar; -import static org.mockito.Matchers.nullable; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; -import android.content.Context; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import com.android.settings.R; import com.android.settings.TestConfig; -import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment; @@ -47,30 +43,15 @@ public class SearchMenuControllerTest { @Mock private Menu mMenu; private TestFragment mHost; - private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { MockitoAnnotations.initMocks(this); mHost = new TestFragment(); - mFeatureFactory = FakeFeatureFactory.setupForTest(); } @Test - public void init_searchV2Disabled_shouldNotAddMenu() { - when(mFeatureFactory.searchFeatureProvider.isSearchV2Enabled(nullable(Context.class))) - .thenReturn(false); - - SearchMenuController.init(mHost); - mHost.getLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */); - - verifyZeroInteractions(mMenu); - } - - @Test - public void init_searchV2Enabled_shouldAddMenu() { - when(mFeatureFactory.searchFeatureProvider.isSearchV2Enabled(nullable(Context.class))) - .thenReturn(true); + public void init_shouldAddMenu() { when(mMenu.add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu)) .thenReturn(mock(MenuItem.class)); diff --git a/tests/unit/src/com/android/settings/search/SearchActivityTest.java b/tests/unit/src/com/android/settings/search/SearchActivityTest.java deleted file mode 100644 index 8a7e3fef81d..00000000000 --- a/tests/unit/src/com/android/settings/search/SearchActivityTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; - -import com.android.settings.Settings; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; - -import static com.google.common.truth.Truth.assertThat; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class SearchActivityTest { - - @Test - public void shouldHaveParentActivity() { - final Context context = InstrumentationRegistry.getTargetContext(); - final PackageManager packageManager = context.getPackageManager(); - final Intent intent = new Intent(context, SearchActivity.class); - final List resolveInfos = packageManager.queryIntentActivities( - intent, PackageManager.GET_META_DATA); - - assertThat(resolveInfos).isNotEmpty(); - assertThat(resolveInfos.get(0).activityInfo.parentActivityName) - .isEqualTo(Settings.class.getName()); - } -} diff --git a/tests/unit/src/com/android/settings/search/SearchFragmentEspressoTest.java b/tests/unit/src/com/android/settings/search/SearchFragmentEspressoTest.java deleted file mode 100644 index e89dc9ef1b4..00000000000 --- a/tests/unit/src/com/android/settings/search/SearchFragmentEspressoTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.search; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.ViewMatchers.hasFocus; -import static android.support.test.espresso.matcher.ViewMatchers.withClassName; -import static android.support.test.espresso.matcher.ViewMatchers.withId; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.core.AllOf.allOf; - -import android.support.test.filters.SmallTest; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; -import android.widget.SearchView; - -import com.android.settings.R; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class SearchFragmentEspressoTest { - @Rule - public ActivityTestRule mActivityRule = - new ActivityTestRule<>(SearchActivity.class, true, true); - - @Test - public void test_OpenKeyboardOnSearchLaunch() { - onView(allOf(hasFocus(), withId(R.id.search_view))) - .check(matches(withClassName(containsString(SearchView.class.getName())))); - } -}