Merge "Move a11y indexing from DynamicContentMonitor to loader" into oc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0bfe384b93
@@ -20,7 +20,6 @@ import android.accessibilityservice.AccessibilityServiceInfo;
|
|||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@@ -52,7 +51,6 @@ import com.android.settings.SettingsPreferenceFragment;
|
|||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
import com.android.settings.search.Indexable;
|
import com.android.settings.search.Indexable;
|
||||||
import com.android.settings.search.SearchIndexableRaw;
|
|
||||||
import com.android.settingslib.RestrictedLockUtils;
|
import com.android.settingslib.RestrictedLockUtils;
|
||||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||||
import com.android.settingslib.RestrictedPreference;
|
import com.android.settingslib.RestrictedPreference;
|
||||||
@@ -727,40 +725,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
|||||||
|
|
||||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
new BaseSearchIndexProvider() {
|
new BaseSearchIndexProvider() {
|
||||||
@Override
|
|
||||||
public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
|
|
||||||
List<SearchIndexableRaw> indexables = new ArrayList<>();
|
|
||||||
|
|
||||||
PackageManager packageManager = context.getPackageManager();
|
|
||||||
AccessibilityManager accessibilityManager =
|
|
||||||
context.getSystemService(AccessibilityManager.class);
|
|
||||||
|
|
||||||
String screenTitle = context.getResources().getString(
|
|
||||||
R.string.accessibility_settings);
|
|
||||||
|
|
||||||
// Indexing all services, regardless if enabled.
|
|
||||||
List<AccessibilityServiceInfo> services = accessibilityManager
|
|
||||||
.getInstalledAccessibilityServiceList();
|
|
||||||
final int serviceCount = services.size();
|
|
||||||
for (int i = 0; i < serviceCount; i++) {
|
|
||||||
AccessibilityServiceInfo service = services.get(i);
|
|
||||||
if (service == null || service.getResolveInfo() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
|
|
||||||
ComponentName componentName = new ComponentName(serviceInfo.packageName,
|
|
||||||
serviceInfo.name);
|
|
||||||
|
|
||||||
SearchIndexableRaw indexable = new SearchIndexableRaw(context);
|
|
||||||
indexable.key = componentName.flattenToString();
|
|
||||||
indexable.title = service.getResolveInfo().loadLabel(packageManager).toString();
|
|
||||||
indexable.screenTitle = screenTitle;
|
|
||||||
indexables.add(indexable);
|
|
||||||
}
|
|
||||||
|
|
||||||
return indexables;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||||
|
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* 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.InstalledAppResultLoader.getWordDifference;
|
||||||
|
|
||||||
|
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.content.pm.ServiceInfo;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.support.annotation.VisibleForTesting;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.accessibility.AccessibilitySettings;
|
||||||
|
import com.android.settings.dashboard.SiteMapManager;
|
||||||
|
import com.android.settings.utils.AsyncLoader;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends SearchResult>> {
|
||||||
|
|
||||||
|
private static final int NAME_NO_MATCH = -1;
|
||||||
|
|
||||||
|
private List<String> mBreadcrumb;
|
||||||
|
private SiteMapManager mSiteMapManager;
|
||||||
|
@VisibleForTesting
|
||||||
|
final String mQuery;
|
||||||
|
private final AccessibilityManager mAccessibilityManager;
|
||||||
|
private final PackageManager mPackageManager;
|
||||||
|
|
||||||
|
|
||||||
|
public AccessibilityServiceResultLoader(Context context, String query,
|
||||||
|
SiteMapManager mapManager) {
|
||||||
|
super(context);
|
||||||
|
mSiteMapManager = mapManager;
|
||||||
|
mPackageManager = context.getPackageManager();
|
||||||
|
mAccessibilityManager =
|
||||||
|
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||||
|
mQuery = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends SearchResult> loadInBackground() {
|
||||||
|
final Set<SearchResult> results = new HashSet<>();
|
||||||
|
final Context context = getContext();
|
||||||
|
final List<AccessibilityServiceInfo> services = mAccessibilityManager
|
||||||
|
.getInstalledAccessibilityServiceList();
|
||||||
|
final String screenTitle = context.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(context, R.mipmap.ic_accessibility_generic);
|
||||||
|
} else {
|
||||||
|
icon = resolveInfo.loadIcon(mPackageManager);
|
||||||
|
}
|
||||||
|
final String componentName = new ComponentName(serviceInfo.packageName,
|
||||||
|
serviceInfo.name).flattenToString();
|
||||||
|
final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(context,
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getBreadCrumb() {
|
||||||
|
if (mBreadcrumb == null || mBreadcrumb.isEmpty()) {
|
||||||
|
final Context context = getContext();
|
||||||
|
mBreadcrumb = mSiteMapManager.buildBreadCrumb(
|
||||||
|
context, AccessibilitySettings.class.getName(),
|
||||||
|
context.getString(R.string.accessibility_settings));
|
||||||
|
}
|
||||||
|
return mBreadcrumb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDiscardResult(Set<? extends SearchResult> result) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,6 @@
|
|||||||
package com.android.settings.search;
|
package com.android.settings.search;
|
||||||
|
|
||||||
import android.accessibilityservice.AccessibilityService;
|
import android.accessibilityservice.AccessibilityService;
|
||||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.LoaderManager;
|
import android.app.LoaderManager;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
@@ -41,13 +40,11 @@ import android.provider.UserDictionary;
|
|||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.VisibleForTesting;
|
import android.support.annotation.VisibleForTesting;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
|
||||||
import android.view.inputmethod.InputMethod;
|
import android.view.inputmethod.InputMethod;
|
||||||
import android.view.inputmethod.InputMethodInfo;
|
import android.view.inputmethod.InputMethodInfo;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
import com.android.internal.content.PackageMonitor;
|
import com.android.internal.content.PackageMonitor;
|
||||||
import com.android.settings.accessibility.AccessibilitySettings;
|
|
||||||
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
|
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
|
||||||
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
|
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
|
||||||
import com.android.settings.inputmethod.VirtualKeyboardFragment;
|
import com.android.settings.inputmethod.VirtualKeyboardFragment;
|
||||||
@@ -89,7 +86,6 @@ public final class DynamicIndexableContentMonitor implements
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static void resetForTesting() {
|
static void resetForTesting() {
|
||||||
InputDevicesMonitor.getInstance().resetForTesting();
|
InputDevicesMonitor.getInstance().resetForTesting();
|
||||||
AccessibilityServicesMonitor.getInstance().resetForTesting();
|
|
||||||
InputMethodServicesMonitor.getInstance().resetForTesting();
|
InputMethodServicesMonitor.getInstance().resetForTesting();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +140,6 @@ public final class DynamicIndexableContentMonitor implements
|
|||||||
InputDevicesMonitor.getInstance().initialize(context, mIndexManager);
|
InputDevicesMonitor.getInstance().initialize(context, mIndexManager);
|
||||||
|
|
||||||
// Start tracking packages.
|
// Start tracking packages.
|
||||||
AccessibilityServicesMonitor.getInstance().initialize(context, mIndexManager);
|
|
||||||
InputMethodServicesMonitor.getInstance().initialize(context, mIndexManager);
|
InputMethodServicesMonitor.getInstance().initialize(context, mIndexManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,86 +296,17 @@ public final class DynamicIndexableContentMonitor implements
|
|||||||
|
|
||||||
private void postPackageAvailable(final String packageName) {
|
private void postPackageAvailable(final String packageName) {
|
||||||
getRegisteredHandler().postDelayed(() -> {
|
getRegisteredHandler().postDelayed(() -> {
|
||||||
AccessibilityServicesMonitor.getInstance().onPackageAvailable(packageName);
|
|
||||||
InputMethodServicesMonitor.getInstance().onPackageAvailable(packageName);
|
InputMethodServicesMonitor.getInstance().onPackageAvailable(packageName);
|
||||||
}, DELAY_PROCESS_PACKAGE_CHANGE);
|
}, DELAY_PROCESS_PACKAGE_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postPackageUnavailable(final String packageName) {
|
private void postPackageUnavailable(final String packageName) {
|
||||||
getRegisteredHandler().postDelayed(() -> {
|
getRegisteredHandler().postDelayed(() -> {
|
||||||
AccessibilityServicesMonitor.getInstance().onPackageUnavailable(packageName);
|
|
||||||
InputMethodServicesMonitor.getInstance().onPackageUnavailable(packageName);
|
InputMethodServicesMonitor.getInstance().onPackageUnavailable(packageName);
|
||||||
}, DELAY_PROCESS_PACKAGE_CHANGE);
|
}, DELAY_PROCESS_PACKAGE_CHANGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A singleton that holds list of available accessibility services and updates search index.
|
|
||||||
private static class AccessibilityServicesMonitor {
|
|
||||||
|
|
||||||
// Null if not initialized.
|
|
||||||
@Nullable private DatabaseIndexingManager mIndexManager;
|
|
||||||
private PackageManager mPackageManager;
|
|
||||||
private final List<String> mAccessibilityServices = new ArrayList<>();
|
|
||||||
|
|
||||||
private AccessibilityServicesMonitor() {}
|
|
||||||
|
|
||||||
private static class SingletonHolder {
|
|
||||||
private static final AccessibilityServicesMonitor INSTANCE =
|
|
||||||
new AccessibilityServicesMonitor();
|
|
||||||
}
|
|
||||||
|
|
||||||
static AccessibilityServicesMonitor getInstance() {
|
|
||||||
return SingletonHolder.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
synchronized void resetForTesting() {
|
|
||||||
mIndexManager = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void initialize(Context context, DatabaseIndexingManager index) {
|
|
||||||
if (mIndexManager != null) return;
|
|
||||||
mIndexManager = index;
|
|
||||||
mPackageManager = context.getPackageManager();
|
|
||||||
mAccessibilityServices.clear();
|
|
||||||
buildIndex();
|
|
||||||
|
|
||||||
// Cache accessibility service packages to know when they go away.
|
|
||||||
AccessibilityManager accessibilityManager = (AccessibilityManager) context
|
|
||||||
.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
|
||||||
for (final AccessibilityServiceInfo accessibilityService
|
|
||||||
: accessibilityManager.getInstalledAccessibilityServiceList()) {
|
|
||||||
ResolveInfo resolveInfo = accessibilityService.getResolveInfo();
|
|
||||||
if (resolveInfo != null && resolveInfo.serviceInfo != null) {
|
|
||||||
mAccessibilityServices.add(resolveInfo.serviceInfo.packageName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildIndex() {
|
|
||||||
mIndexManager.updateFromClassNameResource(AccessibilitySettings.class.getName(),
|
|
||||||
true /* includeInSearchResults */);
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void onPackageAvailable(String packageName) {
|
|
||||||
if (mIndexManager == null) return;
|
|
||||||
if (mAccessibilityServices.contains(packageName)) return;
|
|
||||||
|
|
||||||
final Intent intent = getAccessibilityServiceIntent(packageName);
|
|
||||||
final List<ResolveInfo> services = mPackageManager
|
|
||||||
.queryIntentServices(intent, 0 /* flags */);
|
|
||||||
if (services == null || services.isEmpty()) return;
|
|
||||||
mAccessibilityServices.add(packageName);
|
|
||||||
buildIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void onPackageUnavailable(String packageName) {
|
|
||||||
if (mIndexManager == null) return;
|
|
||||||
if (!mAccessibilityServices.remove(packageName)) return;
|
|
||||||
buildIndex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A singleton that holds list of available input methods and updates search index.
|
// A singleton that holds list of available input methods and updates search index.
|
||||||
// Also it monitors user dictionary changes and updates search index.
|
// Also it monitors user dictionary changes and updates search index.
|
||||||
private static class InputMethodServicesMonitor extends ContentObserver {
|
private static class InputMethodServicesMonitor extends ContentObserver {
|
||||||
|
@@ -163,8 +163,9 @@ public class InstalledAppResultLoader extends AsyncLoader<Set<? extends SearchRe
|
|||||||
* appName: Abcde, query: bc, Returns NAME_NO_MATCH
|
* appName: Abcde, query: bc, Returns NAME_NO_MATCH
|
||||||
* appName: Abcde, query: xyz, Returns NAME_NO_MATCH
|
* appName: Abcde, query: xyz, Returns NAME_NO_MATCH
|
||||||
* appName: Abc de, query: de, Returns 4
|
* appName: Abc de, query: de, Returns 4
|
||||||
|
* TODO: Move this to a common util class.
|
||||||
*/
|
*/
|
||||||
private int getWordDifference(String appName, String query) {
|
static int getWordDifference(String appName, String query) {
|
||||||
if (TextUtils.isEmpty(appName) || TextUtils.isEmpty(query)) {
|
if (TextUtils.isEmpty(appName) || TextUtils.isEmpty(query)) {
|
||||||
return NAME_NO_MATCH;
|
return NAME_NO_MATCH;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,12 @@ public interface SearchFeatureProvider {
|
|||||||
*/
|
*/
|
||||||
InstalledAppResultLoader getInstalledAppSearchLoader(Context context, String query);
|
InstalledAppResultLoader getInstalledAppSearchLoader(Context context, String query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new loader to search accessibility services.
|
||||||
|
*/
|
||||||
|
AccessibilityServiceResultLoader getAccessibilityServiceResultLoader(Context context,
|
||||||
|
String query);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new loader to get all recently saved queries search terms.
|
* Returns a new loader to get all recently saved queries search terms.
|
||||||
*/
|
*/
|
||||||
|
@@ -54,6 +54,13 @@ public class SearchFeatureProviderImpl implements SearchFeatureProvider {
|
|||||||
cleanQuery(query), getSiteMapManager());
|
cleanQuery(query), getSiteMapManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessibilityServiceResultLoader getAccessibilityServiceResultLoader(Context context,
|
||||||
|
String query) {
|
||||||
|
return new AccessibilityServiceResultLoader(context, cleanQuery(query),
|
||||||
|
getSiteMapManager());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SavedQueryLoader getSavedQueryLoader(Context context) {
|
public SavedQueryLoader getSavedQueryLoader(Context context) {
|
||||||
return new SavedQueryLoader(context);
|
return new SavedQueryLoader(context);
|
||||||
|
@@ -82,8 +82,10 @@ public class SearchFragment extends InstrumentedFragment implements SearchView.O
|
|||||||
static final int LOADER_ID_DATABASE = 1;
|
static final int LOADER_ID_DATABASE = 1;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int LOADER_ID_INSTALLED_APPS = 2;
|
static final int LOADER_ID_INSTALLED_APPS = 2;
|
||||||
|
@VisibleForTesting
|
||||||
|
static final int LOADER_ID_ACCESSIBILITY_SERVICES = 3;
|
||||||
|
|
||||||
private static final int NUM_QUERY_LOADERS = 2;
|
private static final int NUM_QUERY_LOADERS = 3;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);
|
AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);
|
||||||
@@ -281,6 +283,7 @@ public class SearchFragment extends InstrumentedFragment implements SearchView.O
|
|||||||
final LoaderManager loaderManager = getLoaderManager();
|
final LoaderManager loaderManager = getLoaderManager();
|
||||||
loaderManager.destroyLoader(LOADER_ID_DATABASE);
|
loaderManager.destroyLoader(LOADER_ID_DATABASE);
|
||||||
loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
|
loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
|
||||||
|
loaderManager.destroyLoader(LOADER_ID_ACCESSIBILITY_SERVICES);
|
||||||
mShowingSavedQuery = true;
|
mShowingSavedQuery = true;
|
||||||
mSavedQueryController.loadSavedQueries();
|
mSavedQueryController.loadSavedQueries();
|
||||||
mSearchFeatureProvider.hideFeedbackButton();
|
mSearchFeatureProvider.hideFeedbackButton();
|
||||||
@@ -309,6 +312,8 @@ public class SearchFragment extends InstrumentedFragment implements SearchView.O
|
|||||||
return mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
|
return mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
|
||||||
case LOADER_ID_INSTALLED_APPS:
|
case LOADER_ID_INSTALLED_APPS:
|
||||||
return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
|
return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
|
||||||
|
case LOADER_ID_ACCESSIBILITY_SERVICES:
|
||||||
|
return mSearchFeatureProvider.getAccessibilityServiceResultLoader(activity, mQuery);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -341,8 +346,11 @@ public class SearchFragment extends InstrumentedFragment implements SearchView.O
|
|||||||
mSavedQueryController.loadSavedQueries();
|
mSavedQueryController.loadSavedQueries();
|
||||||
} else {
|
} else {
|
||||||
final LoaderManager loaderManager = getLoaderManager();
|
final LoaderManager loaderManager = getLoaderManager();
|
||||||
loaderManager.initLoader(LOADER_ID_DATABASE, null, this);
|
loaderManager.initLoader(LOADER_ID_DATABASE, null /* args */, this /* callback */);
|
||||||
loaderManager.initLoader(LOADER_ID_INSTALLED_APPS, null, this);
|
loaderManager.initLoader(
|
||||||
|
LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
|
||||||
|
loaderManager.initLoader(
|
||||||
|
LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */, this /* callback */);
|
||||||
}
|
}
|
||||||
|
|
||||||
requery();
|
requery();
|
||||||
@@ -382,6 +390,8 @@ public class SearchFragment extends InstrumentedFragment implements SearchView.O
|
|||||||
mUnfinishedLoadersCount.set(NUM_QUERY_LOADERS);
|
mUnfinishedLoadersCount.set(NUM_QUERY_LOADERS);
|
||||||
loaderManager.restartLoader(LOADER_ID_DATABASE, null /* args */, this /* callback */);
|
loaderManager.restartLoader(LOADER_ID_DATABASE, null /* args */, this /* callback */);
|
||||||
loaderManager.restartLoader(LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
|
loaderManager.restartLoader(LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
|
||||||
|
loaderManager.restartLoader(LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */,
|
||||||
|
this /* callback */);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getQuery() {
|
public String getQuery() {
|
||||||
|
@@ -56,6 +56,8 @@ public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder>
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String APP_RESULTS_LOADER_KEY = InstalledAppResultLoader.class.getName();
|
static final String APP_RESULTS_LOADER_KEY = InstalledAppResultLoader.class.getName();
|
||||||
|
@VisibleForTesting
|
||||||
|
static final String ACCESSIBLITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int MSG_RANKING_TIMED_OUT = 1;
|
static final int MSG_RANKING_TIMED_OUT = 1;
|
||||||
@@ -262,11 +264,16 @@ public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder>
|
|||||||
getSortedLoadedResults(DB_RESULTS_LOADER_KEY);
|
getSortedLoadedResults(DB_RESULTS_LOADER_KEY);
|
||||||
List<? extends SearchResult> installedAppResults =
|
List<? extends SearchResult> installedAppResults =
|
||||||
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
|
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
|
||||||
|
List<? extends SearchResult> accessibilityResults =
|
||||||
|
getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
|
||||||
|
|
||||||
int dbSize = databaseResults.size();
|
int dbSize = databaseResults.size();
|
||||||
int appSize = installedAppResults.size();
|
int appSize = installedAppResults.size();
|
||||||
|
int a11ySize = accessibilityResults.size();
|
||||||
|
|
||||||
int dbIndex = 0;
|
int dbIndex = 0;
|
||||||
int appIndex = 0;
|
int appIndex = 0;
|
||||||
|
int a11yIndex = 0;
|
||||||
int rank = SearchResult.TOP_RANK;
|
int rank = SearchResult.TOP_RANK;
|
||||||
|
|
||||||
mStaticallyRankedSearchResults.clear();
|
mStaticallyRankedSearchResults.clear();
|
||||||
@@ -277,6 +284,9 @@ public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder>
|
|||||||
while ((appIndex < appSize) && (installedAppResults.get(appIndex).rank == rank)) {
|
while ((appIndex < appSize) && (installedAppResults.get(appIndex).rank == rank)) {
|
||||||
mStaticallyRankedSearchResults.add(installedAppResults.get(appIndex++));
|
mStaticallyRankedSearchResults.add(installedAppResults.get(appIndex++));
|
||||||
}
|
}
|
||||||
|
while ((a11yIndex < a11ySize) && (accessibilityResults.get(a11yIndex).rank == rank)) {
|
||||||
|
mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
|
||||||
|
}
|
||||||
rank++;
|
rank++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,6 +296,9 @@ public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder>
|
|||||||
while (appIndex < appSize) {
|
while (appIndex < appSize) {
|
||||||
mStaticallyRankedSearchResults.add(installedAppResults.get(appIndex++));
|
mStaticallyRankedSearchResults.add(installedAppResults.get(appIndex++));
|
||||||
}
|
}
|
||||||
|
while(a11yIndex < a11ySize) {
|
||||||
|
mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSearchResults() {
|
private void updateSearchResults() {
|
||||||
@@ -318,10 +331,13 @@ public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder>
|
|||||||
getUnsortedLoadedResults(DB_RESULTS_LOADER_KEY);
|
getUnsortedLoadedResults(DB_RESULTS_LOADER_KEY);
|
||||||
List<? extends SearchResult> installedAppResults =
|
List<? extends SearchResult> installedAppResults =
|
||||||
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
|
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
|
||||||
|
List<? extends SearchResult> accessibilityResults =
|
||||||
|
getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
|
||||||
int dbSize = databaseResults.size();
|
int dbSize = databaseResults.size();
|
||||||
int appSize = installedAppResults.size();
|
int appSize = installedAppResults.size();
|
||||||
|
int a11ySize = accessibilityResults.size();
|
||||||
|
|
||||||
final List<SearchResult> asyncRankingResults = new ArrayList<>(dbSize + appSize);
|
final List<SearchResult> asyncRankingResults = new ArrayList<>(dbSize + appSize + a11ySize);
|
||||||
TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>(
|
TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>(
|
||||||
new Comparator<SearchResult>() {
|
new Comparator<SearchResult>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -339,8 +355,9 @@ public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder>
|
|||||||
});
|
});
|
||||||
dbResultsSortedByScores.addAll(databaseResults);
|
dbResultsSortedByScores.addAll(databaseResults);
|
||||||
asyncRankingResults.addAll(dbResultsSortedByScores);
|
asyncRankingResults.addAll(dbResultsSortedByScores);
|
||||||
// App results are not ranked by async ranking and appended at the end of the list.
|
// Other results are not ranked by async ranking and appended at the end of the list.
|
||||||
asyncRankingResults.addAll(installedAppResults);
|
asyncRankingResults.addAll(installedAppResults);
|
||||||
|
asyncRankingResults.addAll(accessibilityResults);
|
||||||
return asyncRankingResults;
|
return asyncRankingResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* 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.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 AccessibilityServiceResultLoaderTest {
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
private AccessibilityServiceResultLoader mLoader;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
when(mContext.getSystemService(Context.ACCESSIBILITY_SERVICE))
|
||||||
|
.thenReturn(mAccessibilityManager);
|
||||||
|
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||||
|
|
||||||
|
mLoader = new AccessibilityServiceResultLoader(mContext, QUERY, mSiteMapManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void query_noService_shouldNotReturnAnything() {
|
||||||
|
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void query_hasServiceMatchingTitle_shouldReturnResult() {
|
||||||
|
addFakeAccessibilityService();
|
||||||
|
|
||||||
|
List<? extends SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
|
||||||
|
assertThat(results).hasSize(1);
|
||||||
|
|
||||||
|
SearchResult result = results.get(0);
|
||||||
|
assertThat(result.title).isEqualTo(QUERY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void query_serviceDoesNotMatchTitle_shouldReturnResult() {
|
||||||
|
addFakeAccessibilityService();
|
||||||
|
|
||||||
|
mLoader = new AccessibilityServiceResultLoader(mContext,
|
||||||
|
QUERY + "no_match", mSiteMapManager);
|
||||||
|
|
||||||
|
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFakeAccessibilityService() {
|
||||||
|
final List<AccessibilityServiceInfo> 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);
|
||||||
|
}
|
||||||
|
}
|
@@ -16,6 +16,19 @@
|
|||||||
|
|
||||||
package com.android.settings.search;
|
package com.android.settings.search;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyBoolean;
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
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.only;
|
||||||
|
import static org.mockito.Mockito.reset;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
@@ -40,15 +53,14 @@ import android.provider.UserDictionary;
|
|||||||
import android.view.inputmethod.InputMethodInfo;
|
import android.view.inputmethod.InputMethodInfo;
|
||||||
|
|
||||||
import com.android.internal.content.PackageMonitor;
|
import com.android.internal.content.PackageMonitor;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.accessibility.AccessibilitySettings;
|
|
||||||
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
|
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
|
||||||
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
|
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
|
||||||
import com.android.settings.inputmethod.VirtualKeyboardFragment;
|
import com.android.settings.inputmethod.VirtualKeyboardFragment;
|
||||||
import com.android.settings.language.LanguageAndInputSettings;
|
import com.android.settings.language.LanguageAndInputSettings;
|
||||||
import com.android.settings.print.PrintSettingsFragment;
|
import com.android.settings.print.PrintSettingsFragment;
|
||||||
import com.android.settings.testutils.DatabaseTestUtils;
|
import com.android.settings.testutils.DatabaseTestUtils;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
import com.android.settings.testutils.shadow.ShadowActivityWithLoadManager;
|
import com.android.settings.testutils.shadow.ShadowActivityWithLoadManager;
|
||||||
import com.android.settings.testutils.shadow.ShadowContextImplWithRegisterReceiver;
|
import com.android.settings.testutils.shadow.ShadowContextImplWithRegisterReceiver;
|
||||||
import com.android.settings.testutils.shadow.ShadowInputManager;
|
import com.android.settings.testutils.shadow.ShadowInputManager;
|
||||||
@@ -77,19 +89,6 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
import static org.mockito.Matchers.any;
|
|
||||||
import static org.mockito.Matchers.anyBoolean;
|
|
||||||
import static org.mockito.Matchers.anyInt;
|
|
||||||
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.only;
|
|
||||||
import static org.mockito.Mockito.reset;
|
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(
|
@Config(
|
||||||
manifest = TestConfig.MANIFEST_PATH,
|
manifest = TestConfig.MANIFEST_PATH,
|
||||||
@@ -271,67 +270,6 @@ public class DynamicIndexableContentMonitorTest {
|
|||||||
verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
|
verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAccessibilityServicesMonitor() throws Exception {
|
|
||||||
mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
|
|
||||||
|
|
||||||
verifyIncrementalIndexing(AccessibilitySettings.class);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When an accessibility service package is installed, incremental indexing happen.
|
|
||||||
*/
|
|
||||||
reset(mIndexManager);
|
|
||||||
|
|
||||||
installAccessibilityService(A11Y_PACKAGE_1);
|
|
||||||
|
|
||||||
verifyIncrementalIndexing(AccessibilitySettings.class);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When another accessibility service package is installed, incremental indexing happens.
|
|
||||||
*/
|
|
||||||
reset(mIndexManager);
|
|
||||||
|
|
||||||
installAccessibilityService(A11Y_PACKAGE_2);
|
|
||||||
|
|
||||||
verifyIncrementalIndexing(AccessibilitySettings.class);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When an accessibility service is disabled, rebuild indexing happens.
|
|
||||||
*/
|
|
||||||
reset(mIndexManager);
|
|
||||||
|
|
||||||
disableInstalledPackage(A11Y_PACKAGE_1);
|
|
||||||
|
|
||||||
verifyIncrementalIndexing(AccessibilitySettings.class);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When an accessibility service is enabled, incremental indexing happens.
|
|
||||||
*/
|
|
||||||
reset(mIndexManager);
|
|
||||||
|
|
||||||
enableInstalledPackage(A11Y_PACKAGE_1);
|
|
||||||
|
|
||||||
verifyIncrementalIndexing(AccessibilitySettings.class);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When an accessibility service package is uninstalled, rebuild indexing happens.
|
|
||||||
*/
|
|
||||||
reset(mIndexManager);
|
|
||||||
|
|
||||||
uninstallAccessibilityService(A11Y_PACKAGE_1);
|
|
||||||
|
|
||||||
verifyIncrementalIndexing(AccessibilitySettings.class);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When an input method service package is installed, nothing happens.
|
|
||||||
*/
|
|
||||||
reset(mIndexManager);
|
|
||||||
|
|
||||||
installInputMethodService(IME_PACKAGE_1);
|
|
||||||
|
|
||||||
verifyNoIndexing(AccessibilitySettings.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInputMethodServicesMonitor() throws Exception {
|
public void testInputMethodServicesMonitor() throws Exception {
|
||||||
mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
|
mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
|
||||||
|
@@ -17,6 +17,20 @@
|
|||||||
|
|
||||||
package com.android.settings.search;
|
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.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
@@ -26,12 +40,12 @@ import android.os.UserHandle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.applications.PackageManagerWrapper;
|
import com.android.settings.applications.PackageManagerWrapper;
|
||||||
import com.android.settings.dashboard.SiteMapManager;
|
import com.android.settings.dashboard.SiteMapManager;
|
||||||
import com.android.settings.testutils.ApplicationTestUtils;
|
import com.android.settings.testutils.ApplicationTestUtils;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -50,20 +64,6 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
public class InstalledAppResultLoaderTest {
|
public class InstalledAppResultLoaderTest {
|
||||||
@@ -82,8 +82,8 @@ public class InstalledAppResultLoaderTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
FakeFeatureFactory.setupForTest(mContext);
|
|
||||||
FakeFeatureFactory factory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
|
final FakeFeatureFactory factory = FakeFeatureFactory.setupForTest(mContext);
|
||||||
when(factory.searchFeatureProvider.getSiteMapManager())
|
when(factory.searchFeatureProvider.getSiteMapManager())
|
||||||
.thenReturn(mSiteMapManager);
|
.thenReturn(mSiteMapManager);
|
||||||
final List<UserInfo> infos = new ArrayList<>();
|
final List<UserInfo> infos = new ArrayList<>();
|
||||||
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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 java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class MockAccessiblityLoader extends AccessibilityServiceResultLoader {
|
||||||
|
|
||||||
|
public MockAccessiblityLoader(Context context) {
|
||||||
|
super(context, "test_query", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<? extends SearchResult> loadInBackground() {
|
||||||
|
return new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDiscardResult(Set<? extends SearchResult> result) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -81,6 +81,8 @@ public class SearchFragmentTest {
|
|||||||
private DatabaseResultLoader mDatabaseResultLoader;
|
private DatabaseResultLoader mDatabaseResultLoader;
|
||||||
@Mock
|
@Mock
|
||||||
private InstalledAppResultLoader mInstalledAppResultLoader;
|
private InstalledAppResultLoader mInstalledAppResultLoader;
|
||||||
|
@Mock
|
||||||
|
private AccessibilityServiceResultLoader mAccessibilityServiceResultLoader;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private SavedQueryLoader mSavedQueryLoader;
|
private SavedQueryLoader mSavedQueryLoader;
|
||||||
@@ -113,6 +115,9 @@ public class SearchFragmentTest {
|
|||||||
when(mFeatureFactory.searchFeatureProvider
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||||
.thenReturn(mInstalledAppResultLoader);
|
.thenReturn(mInstalledAppResultLoader);
|
||||||
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
|
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||||
|
.thenReturn(mAccessibilityServiceResultLoader);
|
||||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||||
.thenReturn(mSavedQueryLoader);
|
.thenReturn(mSavedQueryLoader);
|
||||||
|
|
||||||
@@ -170,6 +175,9 @@ public class SearchFragmentTest {
|
|||||||
when(mFeatureFactory.searchFeatureProvider
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||||
.thenReturn(mInstalledAppResultLoader);
|
.thenReturn(mInstalledAppResultLoader);
|
||||||
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
|
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||||
|
.thenReturn(mAccessibilityServiceResultLoader);
|
||||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||||
.thenReturn(mSavedQueryLoader);
|
.thenReturn(mSavedQueryLoader);
|
||||||
|
|
||||||
@@ -225,6 +233,9 @@ public class SearchFragmentTest {
|
|||||||
when(mFeatureFactory.searchFeatureProvider
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||||
.thenReturn(mInstalledAppResultLoader);
|
.thenReturn(mInstalledAppResultLoader);
|
||||||
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
|
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||||
|
.thenReturn(mAccessibilityServiceResultLoader);
|
||||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||||
.thenReturn(mSavedQueryLoader);
|
.thenReturn(mSavedQueryLoader);
|
||||||
ActivityController<SearchActivity> activityController =
|
ActivityController<SearchActivity> activityController =
|
||||||
@@ -256,6 +267,9 @@ public class SearchFragmentTest {
|
|||||||
when(mFeatureFactory.searchFeatureProvider
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||||
.thenReturn(mInstalledAppResultLoader);
|
.thenReturn(mInstalledAppResultLoader);
|
||||||
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
|
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||||
|
.thenReturn(mAccessibilityServiceResultLoader);
|
||||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||||
.thenReturn(mSavedQueryLoader);
|
.thenReturn(mSavedQueryLoader);
|
||||||
|
|
||||||
@@ -333,6 +347,9 @@ public class SearchFragmentTest {
|
|||||||
when(mFeatureFactory.searchFeatureProvider
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||||
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
|
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
|
||||||
|
when(mFeatureFactory.searchFeatureProvider
|
||||||
|
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||||
|
.thenReturn(new MockAccessiblityLoader(RuntimeEnvironment.application));
|
||||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||||
.thenReturn(mSavedQueryLoader);
|
.thenReturn(mSavedQueryLoader);
|
||||||
ActivityController<SearchActivity> activityController =
|
ActivityController<SearchActivity> activityController =
|
||||||
|
Reference in New Issue
Block a user