import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import com.android.settings.Utils;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedPreference;
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
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
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
--- /dev/null
+/*
+ * 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) {
+
+ }
+}
package com.android.settings.search;
import android.accessibilityservice.AccessibilityService;
-import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.ContentResolver;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
-import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.content.PackageMonitor;
-import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
import com.android.settings.inputmethod.VirtualKeyboardFragment;
@VisibleForTesting
static void resetForTesting() {
InputDevicesMonitor.getInstance().resetForTesting();
- AccessibilityServicesMonitor.getInstance().resetForTesting();
InputMethodServicesMonitor.getInstance().resetForTesting();
}
InputDevicesMonitor.getInstance().initialize(context, mIndexManager);
// Start tracking packages.
- AccessibilityServicesMonitor.getInstance().initialize(context, mIndexManager);
InputMethodServicesMonitor.getInstance().initialize(context, mIndexManager);
}
private void postPackageAvailable(final String packageName) {
getRegisteredHandler().postDelayed(() -> {
- AccessibilityServicesMonitor.getInstance().onPackageAvailable(packageName);
InputMethodServicesMonitor.getInstance().onPackageAvailable(packageName);
}, DELAY_PROCESS_PACKAGE_CHANGE);
}
private void postPackageUnavailable(final String packageName) {
getRegisteredHandler().postDelayed(() -> {
- AccessibilityServicesMonitor.getInstance().onPackageUnavailable(packageName);
InputMethodServicesMonitor.getInstance().onPackageUnavailable(packageName);
}, 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.
// Also it monitors user dictionary changes and updates search index.
private static class InputMethodServicesMonitor extends ContentObserver {
* 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.
*/
- private int getWordDifference(String appName, String query) {
+ static int getWordDifference(String appName, String query) {
if (TextUtils.isEmpty(appName) || TextUtils.isEmpty(query)) {
return NAME_NO_MATCH;
}
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.
*/
SavedQueryLoader getSavedQueryLoader(Context context);
/**
* Query search results based on the input query.
*
- * @param context application context
- * @param query input user query
+ * @param context application context
+ * @param query input user query
* @param searchResultsRankerCallback {@link SearchResultsRankerCallback}
*/
default void querySearchResults(Context context, String query,
/**
* Notify that a search result is clicked.
*
- * @param context application context
- * @param query input user query
+ * @param context application context
+ * @param query input user query
* @param searchResult clicked result
*/
default void searchResultClicked(Context context, String query, SearchResult searchResult) {
}
@Override
+ public AccessibilityServiceResultLoader getAccessibilityServiceResultLoader(Context context,
+ String query) {
+ return new AccessibilityServiceResultLoader(context, cleanQuery(query),
+ getSiteMapManager());
+ }
+
+ @Override
public SavedQueryLoader getSavedQueryLoader(Context context) {
return new SavedQueryLoader(context);
}
static final int LOADER_ID_DATABASE = 1;
@VisibleForTesting
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
AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(LOADER_ID_DATABASE);
loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
+ loaderManager.destroyLoader(LOADER_ID_ACCESSIBILITY_SERVICES);
mShowingSavedQuery = true;
mSavedQueryController.loadSavedQueries();
mSearchFeatureProvider.hideFeedbackButton();
return mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
case LOADER_ID_INSTALLED_APPS:
return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
+ case LOADER_ID_ACCESSIBILITY_SERVICES:
+ return mSearchFeatureProvider.getAccessibilityServiceResultLoader(activity, mQuery);
default:
return null;
}
mSavedQueryController.loadSavedQueries();
} else {
final LoaderManager loaderManager = getLoaderManager();
- loaderManager.initLoader(LOADER_ID_DATABASE, null, this);
- loaderManager.initLoader(LOADER_ID_INSTALLED_APPS, null, this);
+ loaderManager.initLoader(LOADER_ID_DATABASE, null /* args */, this /* callback */);
+ loaderManager.initLoader(
+ LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
+ loaderManager.initLoader(
+ LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */, this /* callback */);
}
requery();
mUnfinishedLoadersCount.set(NUM_QUERY_LOADERS);
loaderManager.restartLoader(LOADER_ID_DATABASE, 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() {
@VisibleForTesting
static final String APP_RESULTS_LOADER_KEY = InstalledAppResultLoader.class.getName();
+ @VisibleForTesting
+ static final String ACCESSIBLITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
@VisibleForTesting
static final int MSG_RANKING_TIMED_OUT = 1;
getSortedLoadedResults(DB_RESULTS_LOADER_KEY);
List<? extends SearchResult> installedAppResults =
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
+ List<? extends SearchResult> accessibilityResults =
+ getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
+
int dbSize = databaseResults.size();
int appSize = installedAppResults.size();
+ int a11ySize = accessibilityResults.size();
int dbIndex = 0;
int appIndex = 0;
+ int a11yIndex = 0;
int rank = SearchResult.TOP_RANK;
mStaticallyRankedSearchResults.clear();
while ((appIndex < appSize) && (installedAppResults.get(appIndex).rank == rank)) {
mStaticallyRankedSearchResults.add(installedAppResults.get(appIndex++));
}
+ while ((a11yIndex < a11ySize) && (accessibilityResults.get(a11yIndex).rank == rank)) {
+ mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
+ }
rank++;
}
while (appIndex < appSize) {
mStaticallyRankedSearchResults.add(installedAppResults.get(appIndex++));
}
+ while(a11yIndex < a11ySize) {
+ mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
+ }
}
private void updateSearchResults() {
getUnsortedLoadedResults(DB_RESULTS_LOADER_KEY);
List<? extends SearchResult> installedAppResults =
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
+ List<? extends SearchResult> accessibilityResults =
+ getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
int dbSize = databaseResults.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<>(
new Comparator<SearchResult>() {
@Override
});
dbResultsSortedByScores.addAll(databaseResults);
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(accessibilityResults);
return asyncRankingResults;
}
--- /dev/null
+/*
+ * 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);
+ }
+}
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.app.Activity;
import android.app.Application;
import android.view.inputmethod.InputMethodInfo;
import com.android.internal.content.PackageMonitor;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
-import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
import com.android.settings.inputmethod.VirtualKeyboardFragment;
import com.android.settings.language.LanguageAndInputSettings;
import com.android.settings.print.PrintSettingsFragment;
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.ShadowContextImplWithRegisterReceiver;
import com.android.settings.testutils.shadow.ShadowInputManager;
import java.util.Collections;
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)
@Config(
manifest = TestConfig.MANIFEST_PATH,
}
@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
public void testInputMethodServicesMonitor() throws Exception {
mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
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.os.UserManager;
import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
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 org.junit.Before;
import org.junit.Test;
import java.util.Set;
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)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class InstalledAppResultLoaderTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- FakeFeatureFactory.setupForTest(mContext);
- FakeFeatureFactory factory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
+ final FakeFeatureFactory factory = FakeFeatureFactory.setupForTest(mContext);
when(factory.searchFeatureProvider.getSiteMapManager())
.thenReturn(mSiteMapManager);
final List<UserInfo> infos = new ArrayList<>();
--- /dev/null
+/*
+ * 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) {
+
+ }
+}
private DatabaseResultLoader mDatabaseResultLoader;
@Mock
private InstalledAppResultLoader mInstalledAppResultLoader;
+ @Mock
+ private AccessibilityServiceResultLoader mAccessibilityServiceResultLoader;
@Mock
private SavedQueryLoader mSavedQueryLoader;
when(mFeatureFactory.searchFeatureProvider
.getInstalledAppSearchLoader(any(Context.class), anyString()))
.thenReturn(mInstalledAppResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mAccessibilityServiceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
when(mFeatureFactory.searchFeatureProvider
.getInstalledAppSearchLoader(any(Context.class), anyString()))
.thenReturn(mInstalledAppResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mAccessibilityServiceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
when(mFeatureFactory.searchFeatureProvider
.getInstalledAppSearchLoader(any(Context.class), anyString()))
.thenReturn(mInstalledAppResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mAccessibilityServiceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
ActivityController<SearchActivity> activityController =
when(mFeatureFactory.searchFeatureProvider
.getInstalledAppSearchLoader(any(Context.class), anyString()))
.thenReturn(mInstalledAppResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mAccessibilityServiceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
when(mFeatureFactory.searchFeatureProvider
.getInstalledAppSearchLoader(any(Context.class), anyString()))
.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)))
.thenReturn(mSavedQueryLoader);
ActivityController<SearchActivity> activityController =