Merge "Update icon and string for new device intro suggestion" into oc-mr1-dev
diff --git a/res/xml/available_virtual_keyboard.xml b/res/xml/available_virtual_keyboard.xml
new file mode 100644
index 0000000..9a0b3c6
--- /dev/null
+++ b/res/xml/available_virtual_keyboard.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:key="available_virtual_keyboard_page"
+ android:title="@string/add_virtual_keyboard">
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index f120b7f..609120d 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -59,7 +59,6 @@
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.development.DevelopmentSettings;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.DynamicIndexableContentMonitor;
import com.android.settings.search.SearchActivity;
import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.widget.SwitchBar;
@@ -76,8 +75,6 @@
private static final String LOG_TAG = "Settings";
- public static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
-
// Constants for state save/restore
private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
@VisibleForTesting
@@ -183,8 +180,6 @@
}
};
- private DynamicIndexableContentMonitor mDynamicIndexableContentMonitor;
-
private SwitchBar mSwitchBar;
private Button mNextButton;
@@ -535,10 +530,6 @@
mDevelopmentPreferencesListener);
registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- if (mDynamicIndexableContentMonitor == null) {
- mDynamicIndexableContentMonitor = new DynamicIndexableContentMonitor();
- }
- mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
updateTilesList();
}
@@ -550,9 +541,6 @@
mDevelopmentPreferencesListener);
mDevelopmentPreferencesListener = null;
unregisterReceiver(mBatteryInfoReceiver);
- if (mDynamicIndexableContentMonitor != null) {
- mDynamicIndexableContentMonitor.unregister(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
- }
}
@Override
diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
index 3b5dbba..6f334a5 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
@@ -17,29 +17,24 @@
package com.android.settings.gestures;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.support.v7.preference.Preference;
-import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.search.DatabaseIndexingUtils;
-import com.android.settings.search.InlineSwitchPayload;
-import com.android.settings.search.ResultPayload;
import com.android.settingslib.core.lifecycle.Lifecycle;
import static android.provider.Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED;
public class SwipeToNotificationPreferenceController extends GesturePreferenceController {
- private final int ON = 1;
- private final int OFF = 0;
+ private static final int ON = 1;
+ private static final int OFF = 0;
private static final String PREF_KEY_VIDEO = "gesture_swipe_down_fingerprint_video";
private final String mSwipeDownFingerPrefKey;
- private final String SECURE_KEY = SYSTEM_NAVIGATION_KEYS_ENABLED;
+ private static final String SECURE_KEY = SYSTEM_NAVIGATION_KEYS_ENABLED;
public SwipeToNotificationPreferenceController(Context context, Lifecycle lifecycle,
String key) {
@@ -70,28 +65,30 @@
@Override
public boolean isAvailable() {
- return isGestureAvailable(mContext);
+ return SwipeToNotificationPreferenceController.isAvailable(mContext);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY,
- (boolean) newValue ? ON : OFF);
+ setSwipeToNotification(mContext, (boolean) newValue);
return true;
}
@Override
protected boolean isSwitchPrefEnabled() {
- return Settings.Secure.getInt(mContext.getContentResolver(), SECURE_KEY, OFF) == ON;
+ return isSwipeToNotificationOn(mContext);
}
- @Override
- public ResultPayload getResultPayload() {
- final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(mContext,
- SwipeToNotificationSettings.class.getName(), mSwipeDownFingerPrefKey,
- mContext.getString(R.string.display_settings));
+ public static boolean isSwipeToNotificationOn(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(), SECURE_KEY, OFF) == ON;
+ }
- return new InlineSwitchPayload(SECURE_KEY, ResultPayload.SettingsSource.SECURE,
- ON /* onValue */, intent, isAvailable(), OFF /* defaultValue */);
+ public static boolean setSwipeToNotification(Context context, boolean isEnabled) {
+ return Settings.Secure.putInt(
+ context.getContentResolver(), SECURE_KEY, isEnabled ? ON : OFF);
+ }
+
+ public static boolean isAvailable(Context context) {
+ return isGestureAvailable(context);
}
}
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index a7862ae..48b0b4a 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -21,7 +21,6 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -31,17 +30,15 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.support.v7.preference.PreferenceScreen;
+import android.provider.SearchIndexableResource;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import com.android.settingslib.inputmethod.InputMethodPreference;
import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
@@ -60,10 +57,9 @@
@Override
public void onCreatePreferences(Bundle bundle, String s) {
+ addPreferencesFromResource(R.xml.available_virtual_keyboard);
Activity activity = getActivity();
- PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(activity);
- screen.setTitle(activity.getString(R.string.available_virtual_keyboard_category));
- setPreferenceScreen(screen);
+
mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(activity);
mImm = activity.getSystemService(InputMethodManager.class);
mDpm = activity.getSystemService(DevicePolicyManager.class);
@@ -105,7 +101,7 @@
}
try {
return packageManager.getDrawable(packageName, resId, applicationInfo);
- } catch (Exception e){
+ } catch (Exception e) {
return null;
}
}
@@ -172,48 +168,16 @@
}
}
- private static List<InputMethodSubtype> getAllSubtypesOf(final InputMethodInfo imi) {
- final int subtypeCount = imi.getSubtypeCount();
- final List<InputMethodSubtype> allSubtypes = new ArrayList<>(subtypeCount);
- for (int index = 0; index < subtypeCount; index++) {
- allSubtypes.add(imi.getSubtypeAt(index));
- }
- return allSubtypes;
- }
-
- static List<SearchIndexableRaw> buildSearchIndexOfInputMethods(final Context context,
- final List<InputMethodInfo> inputMethods, final String screenTitle) {
- final List<SearchIndexableRaw> indexes = new ArrayList<>();
- for (int i = 0; i < inputMethods.size(); i++) {
- final InputMethodInfo imi = inputMethods.get(i);
- final ServiceInfo serviceInfo = imi.getServiceInfo();
- final SearchIndexableRaw index = new SearchIndexableRaw(context);
- index.key = new ComponentName(serviceInfo.packageName, serviceInfo.name)
- .flattenToString();
- index.title = imi.loadLabel(context.getPackageManager()).toString();
- index.summaryOn = index.summaryOff = InputMethodAndSubtypeUtil
- .getSubtypeLocaleNameListAsSentence(getAllSubtypesOf(imi), context, imi);
- index.screenTitle = screenTitle;
- indexes.add(index);
- }
- return indexes;
- }
-
- public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
- final InputMethodManager imm = context.getSystemService(InputMethodManager.class);
- final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
- final List<InputMethodInfo> disabledInputMethods = new ArrayList<>();
- for (final InputMethodInfo imi : imm.getInputMethodList()) {
- if (!enabledInputMethods.contains(imi)) {
- disabledInputMethods.add(imi);
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ List<SearchIndexableResource> res = new ArrayList<>();
+ SearchIndexableResource index = new SearchIndexableResource(context);
+ index.xmlResId = R.xml.available_virtual_keyboard;
+ res.add(index);
+ return res;
}
- }
- final String screenTitle = context.getString(
- R.string.available_virtual_keyboard_category);
- return buildSearchIndexOfInputMethods(context, disabledInputMethods, screenTitle);
- }
- };
+ };
}
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 42eff15..83d501d 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -31,6 +31,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
+import android.provider.SearchIndexableResource;
import android.provider.Settings.Secure;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
@@ -51,11 +52,11 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import java.text.Collator;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -288,6 +289,7 @@
final PhysicalKeyboardFragment mPhysicalKeyboardFragment;
@NonNull
final List<HardKeyboardDeviceInfo> mHardKeyboards;
+
public Callbacks(
@NonNull Context context,
@NonNull PhysicalKeyboardFragment physicalKeyboardFragment,
@@ -532,43 +534,14 @@
}
}
- public static List<InputDevice> getPhysicalFullKeyboards() {
- List<InputDevice> keyboards = null;
- for (final int deviceId : InputDevice.getDeviceIds()) {
- final InputDevice device = InputDevice.getDevice(deviceId);
- if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
- if (keyboards == null) keyboards = new ArrayList<>();
- keyboards.add(device);
- }
- }
- return (keyboards == null) ? Collections.emptyList() : keyboards;
- }
-
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
- final InputManager inputManager = (InputManager) context.getSystemService(
- Context.INPUT_SERVICE);
- final String screenTitle = context.getString(R.string.physical_keyboard_title);
- final List<SearchIndexableRaw> indexes = new ArrayList<>();
- for (final InputDevice device : getPhysicalFullKeyboards()) {
- final String keyboardLayoutDescriptor = inputManager
- .getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
- final KeyboardLayout keyboardLayout = (keyboardLayoutDescriptor != null)
- ? inputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
- final String summary = (keyboardLayout != null)
- ? keyboardLayout.toString()
- : context.getString(R.string.keyboard_layout_default_label);
- final SearchIndexableRaw index = new SearchIndexableRaw(context);
- index.key = device.getName();
- index.title = device.getName();
- index.summaryOn = summary;
- index.summaryOff = summary;
- index.screenTitle = screenTitle;
- indexes.add(index);
- }
- return indexes;
- }
- };
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.physical_keyboard_settings;
+ return Arrays.asList(sir);
+ }
+ };
}
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
index 7b7c599..fbe9690 100644
--- a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -23,6 +23,7 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.provider.SearchIndexableResource;
import android.support.v7.preference.Preference;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -33,14 +34,12 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import com.android.settingslib.inputmethod.InputMethodPreference;
import java.text.Collator;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.Arrays;
import java.util.List;
public final class VirtualKeyboardFragment extends SettingsPreferenceFragment implements Indexable {
@@ -121,13 +120,19 @@
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
- final InputMethodManager imm = context.getSystemService(InputMethodManager.class);
- final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
- final String screenTitle = context.getString(R.string.virtual_keyboard_category);
- return AvailableVirtualKeyboardFragment
- .buildSearchIndexOfInputMethods(context, enabledInputMethods, screenTitle);
- }
- };
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.virtual_keyboard_settings;
+ return Arrays.asList(sir);
+ }
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ final List<String> keys = super.getNonIndexableKeys(context);
+ keys.add("add_virtual_keyboard_screen");
+ return keys;
+ }
+ };
}
diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java
index fbcb02f..4affc6e 100644
--- a/src/com/android/settings/language/LanguageAndInputSettings.java
+++ b/src/com/android/settings/language/LanguageAndInputSettings.java
@@ -52,6 +52,7 @@
private static final String TAG = "LangAndInputSettings";
private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary";
+ private static final String KEY_PHYSICAL_KEYBOARD = "physical_keyboard_pref";
@Override
public int getMetricsCategory() {
@@ -174,6 +175,7 @@
List<String> keys = super.getNonIndexableKeys(context);
// Duplicates in summary and details pages.
keys.add(KEY_TEXT_TO_SPEECH);
+ keys.add(KEY_PHYSICAL_KEYBOARD);
return keys;
}
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index d8b7745..6e2c2d5 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -33,7 +33,6 @@
import static android.os.UserHandle.myUserId;
import static android.os.UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
-import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
public class MobileNetworkPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
@@ -42,22 +41,30 @@
private final boolean mIsSecondaryUser;
private final TelephonyManager mTelephonyManager;
+ private final UserManager mUserManager;
private Preference mPreference;
@VisibleForTesting
PhoneStateListener mPhoneStateListener;
public MobileNetworkPreferenceController(Context context) {
super(context);
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- mIsSecondaryUser = !userManager.isAdminUser();
+ mIsSecondaryUser = !mUserManager.isAdminUser();
}
@Override
public boolean isAvailable() {
- return !mIsSecondaryUser
- && !Utils.isWifiOnly(mContext)
- && !hasBaseUserRestriction(mContext, DISALLOW_CONFIG_MOBILE_NETWORKS, myUserId());
+ return !isUserRestricted() && !Utils.isWifiOnly(mContext);
+ }
+
+ public boolean isUserRestricted() {
+ final RestrictedLockUtilsWrapper wrapper = new RestrictedLockUtilsWrapper();
+ return mIsSecondaryUser ||
+ wrapper.hasBaseUserRestriction(
+ mContext,
+ DISALLOW_CONFIG_MOBILE_NETWORKS,
+ myUserId());
}
@Override
diff --git a/src/com/android/settings/network/RestrictedLockUtilsWrapper.java b/src/com/android/settings/network/RestrictedLockUtilsWrapper.java
new file mode 100644
index 0000000..de5b808
--- /dev/null
+++ b/src/com/android/settings/network/RestrictedLockUtilsWrapper.java
@@ -0,0 +1,15 @@
+package com.android.settings.network;
+
+import android.content.Context;
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * Wrapper class needed to be able to test classes which use RestrictedLockUtils methods.
+ * Unfortunately there is no way to deal with this until robolectric is updated due to the fact
+ * that it is a static method and it uses new API's.
+ */
+public class RestrictedLockUtilsWrapper {
+ public boolean hasBaseUserRestriction(Context context, String userRestriction, int userId) {
+ return RestrictedLockUtils.hasBaseUserRestriction(context, userRestriction, userId);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 5bda1ad..14ee779 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -98,6 +98,7 @@
// Turn NFC on/off
final boolean desiredState = (Boolean) value;
+ mSwitch.setChecked(desiredState);
mSwitch.setEnabled(false);
if (desiredState) {
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index fa6c8ee..2f95dd2 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -351,7 +351,9 @@
if (mRingtone != null) {
mRingtone.onActivityResult(requestCode, resultCode, data);
}
- mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
+ if (mChannel != null) {
+ mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
+ }
}
boolean canPulseLight() {
diff --git a/src/com/android/settings/search/DynamicIndexableContentMonitor.java b/src/com/android/settings/search/DynamicIndexableContentMonitor.java
deleted file mode 100644
index a0e3c02..0000000
--- a/src/com/android/settings/search/DynamicIndexableContentMonitor.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2014 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.accessibilityservice.AccessibilityService;
-import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.print.PrintManager;
-import android.print.PrintServicesLoader;
-import android.printservice.PrintServiceInfo;
-import android.provider.Settings;
-import android.provider.UserDictionary;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.util.Log;
-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.inputmethod.AvailableVirtualKeyboardFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment;
-import com.android.settings.inputmethod.VirtualKeyboardFragment;
-import com.android.settings.language.LanguageAndInputSettings;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.print.PrintSettingsFragment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public final class DynamicIndexableContentMonitor implements
- LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
- // Shorten the class name because log TAG can be at most 23 chars.
- private static final String TAG = "DynamicContentMonitor";
-
- private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
- // A PackageMonitor shared among Settings activities.
- private static final PackageChangeMonitor PACKAGE_CHANGE_MONITOR = new PackageChangeMonitor();
-
- // Null if not initialized.
- @Nullable private DatabaseIndexingManager mIndexManager;
- private Context mContext;
- private boolean mHasFeaturePrinting;
-
- @VisibleForTesting
- static Intent getAccessibilityServiceIntent(String packageName) {
- final Intent intent = new Intent(AccessibilityService.SERVICE_INTERFACE);
- intent.setPackage(packageName);
- return intent;
- }
-
- @VisibleForTesting
- static Intent getIMEServiceIntent(String packageName) {
- final Intent intent = new Intent(InputMethod.SERVICE_INTERFACE);
- intent.setPackage(packageName);
- return intent;
- }
-
- @VisibleForTesting
- static void resetForTesting() {
- InputDevicesMonitor.getInstance().resetForTesting();
- InputMethodServicesMonitor.getInstance().resetForTesting();
- }
-
- /**
- * This instance holds a set of content monitor singleton objects.
- *
- * This object is created every time a sub-settings that extends {@code SettingsActivity}
- * is created.
- */
- public DynamicIndexableContentMonitor() {}
-
- /**
- * Creates and initializes a set of content monitor singleton objects if not yet exist.
- * Also starts loading the list of print services.
- * <code>mIndex</code> has non-null value after successfully initialized.
- *
- * @param activity used to get {@link LoaderManager}.
- * @param loaderId id for loading print services.
- */
- public void register(Activity activity, int loaderId) {
- final boolean isUserUnlocked = activity
- .getSystemService(UserManager.class)
- .isUserUnlocked();
- register(activity, loaderId, FeatureFactory.getFactory(activity)
- .getSearchFeatureProvider().getIndexingManager(activity), isUserUnlocked);
- }
-
- /**
- * For testing to inject {@link DatabaseIndexingManager} object.
- * Also because currently Robolectric doesn't support API 24, we can not test code that calls
- * {@link UserManager#isUserUnlocked()}.
- */
- @VisibleForTesting
- void register(Activity activity, int loaderId, DatabaseIndexingManager indexManager,
- boolean isUserUnlocked) {
- if (!isUserUnlocked) {
- Log.w(TAG, "Skipping content monitoring because user is locked");
- return;
- }
- final Context context = activity.getApplicationContext();
- mContext = context;
- mIndexManager = indexManager;
-
- PACKAGE_CHANGE_MONITOR.registerMonitor(context);
- mHasFeaturePrinting = context.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_PRINTING);
- if (mHasFeaturePrinting) {
- activity.getLoaderManager().initLoader(loaderId, null /* args */, this /* callbacks */);
- }
-
- // Watch for input device changes.
- InputDevicesMonitor.getInstance().initialize(context, mIndexManager);
-
- // Start tracking packages.
- InputMethodServicesMonitor.getInstance().initialize(context, mIndexManager);
- }
-
- /**
- * Aborts loading the list of print services.
- * Note that a set of content monitor singletons keep alive while Settings app is running.
- *
- * @param activity user to get {@link LoaderManager}.
- * @param loaderId id for loading print services.
- */
- public void unregister(Activity activity, int loaderId) {
- if (mIndexManager == null) return;
-
- PACKAGE_CHANGE_MONITOR.unregisterMonitor();
- if (mHasFeaturePrinting) {
- activity.getLoaderManager().destroyLoader(loaderId);
- }
- }
-
- @Override
- public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
- return new PrintServicesLoader(
- (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE), mContext,
- PrintManager.ALL_SERVICES);
- }
-
- @Override
- public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
- List<PrintServiceInfo> services) {
- mIndexManager.updateFromClassNameResource(PrintSettingsFragment.class.getName(),
- true /* includeInSearchResults */);
- }
-
- @Override
- public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
- // nothing to do
- }
-
- // A singleton that monitors input devices changes and updates indexes of physical keyboards.
- private static class InputDevicesMonitor implements InputManager.InputDeviceListener {
-
- // Null if not initialized.
- @Nullable private DatabaseIndexingManager mIndexManager;
- private InputManager mInputManager;
-
- private InputDevicesMonitor() {}
-
- private static class SingletonHolder {
- private static final InputDevicesMonitor INSTANCE = new InputDevicesMonitor();
- }
-
- static InputDevicesMonitor getInstance() {
- return SingletonHolder.INSTANCE;
- }
-
- @VisibleForTesting
- synchronized void resetForTesting() {
- if (mIndexManager != null) {
- mInputManager.unregisterInputDeviceListener(this /* listener */);
- }
- mIndexManager = null;
- }
-
- synchronized void initialize(Context context, DatabaseIndexingManager indexManager) {
- if (mIndexManager != null) return;
- mIndexManager = indexManager;
- mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
- buildIndex();
-
- // Watch for input device changes.
- mInputManager.registerInputDeviceListener(this /* listener */, null /* handler */);
- }
-
- private void buildIndex() {
- mIndexManager.updateFromClassNameResource(PhysicalKeyboardFragment.class.getName(),
- true /* includeInSearchResults */);
- }
-
- @Override
- public void onInputDeviceAdded(int deviceId) {
- buildIndex();
- }
-
- @Override
- public void onInputDeviceRemoved(int deviceId) {
- buildIndex();
- }
-
- @Override
- public void onInputDeviceChanged(int deviceId) {
- buildIndex();
- }
- }
-
- // A singleton that monitors package installing, uninstalling, enabling, and disabling.
- // Then updates indexes of accessibility services and input methods.
- private static class PackageChangeMonitor extends PackageMonitor {
- private static final String TAG = PackageChangeMonitor.class.getSimpleName();
-
- // Null if not initialized. Guarded by {@link #mLock}.
- @Nullable private PackageManager mPackageManager;
- private final Object mLock = new Object();
-
- public void registerMonitor(Context context) {
- synchronized (mLock) {
- if (mPackageManager != null) {
- return;
- }
- mPackageManager = context.getPackageManager();
-
- // Start tracking packages. Use background thread for monitoring. Note that no need
- // to unregister this monitor. This should be alive while Settings app is running.
- super.register(context, null /* thread */, UserHandle.CURRENT, false);
- }
- }
-
- public void unregisterMonitor() {
- synchronized (mLock) {
- if (mPackageManager == null) {
- return;
- }
- super.unregister();
- mPackageManager = null;
- }
- }
-
- // Covers installed, appeared external storage with the package, upgraded.
- @Override
- public void onPackageAppeared(String packageName, int reason) {
- postPackageAvailable(packageName);
- }
-
- // Covers uninstalled, removed external storage with the package.
- @Override
- public void onPackageDisappeared(String packageName, int reason) {
- postPackageUnavailable(packageName);
- }
-
- // Covers enabled, disabled.
- @Override
- public void onPackageModified(String packageName) {
- try {
- final int state = mPackageManager.getApplicationEnabledSetting(packageName);
- if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- || state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
- postPackageAvailable(packageName);
- } else {
- postPackageUnavailable(packageName);
- }
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Package does not exist: " + packageName, e);
- }
- }
-
- private void postPackageAvailable(final String packageName) {
- getRegisteredHandler().postDelayed(() -> {
- InputMethodServicesMonitor.getInstance().onPackageAvailable(packageName);
- }, DELAY_PROCESS_PACKAGE_CHANGE);
- }
-
- private void postPackageUnavailable(final String packageName) {
- getRegisteredHandler().postDelayed(() -> {
- InputMethodServicesMonitor.getInstance().onPackageUnavailable(packageName);
- }, DELAY_PROCESS_PACKAGE_CHANGE);
- }
- }
-
- // 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 {
-
- private static final Uri ENABLED_INPUT_METHODS_CONTENT_URI =
- Settings.Secure.getUriFor(Settings.Secure.ENABLED_INPUT_METHODS);
-
- // Null if not initialized.
- @Nullable private DatabaseIndexingManager mIndexManager;
- private PackageManager mPackageManager;
- private ContentResolver mContentResolver;
- private final List<String> mInputMethodServices = new ArrayList<>();
-
- private InputMethodServicesMonitor() {
- // No need for handler because {@link #onChange(boolean,Uri)} is short and quick.
- super(null /* handler */);
- }
-
- private static class SingletonHolder {
- private static final InputMethodServicesMonitor INSTANCE =
- new InputMethodServicesMonitor();
- }
-
- static InputMethodServicesMonitor getInstance() {
- return SingletonHolder.INSTANCE;
- }
-
- @VisibleForTesting
- synchronized void resetForTesting() {
- if (mIndexManager != null) {
- mContentResolver.unregisterContentObserver(this /* observer */);
- }
- mIndexManager = null;
- }
-
- synchronized void initialize(Context context, DatabaseIndexingManager indexManager) {
- final boolean hasFeatureIme = context.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS);
- if (!hasFeatureIme) return;
-
- if (mIndexManager != null) return;
- mIndexManager = indexManager;
- mPackageManager = context.getPackageManager();
- mContentResolver = context.getContentResolver();
- mInputMethodServices.clear();
- // Build index of {@link UserDictionary}.
- buildIndex(LanguageAndInputSettings.class);
- // Build index of IMEs.
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
-
- // Cache IME service packages to know when they go away.
- final InputMethodManager inputMethodManager = (InputMethodManager) context
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- for (final InputMethodInfo inputMethod : inputMethodManager.getInputMethodList()) {
- ServiceInfo serviceInfo = inputMethod.getServiceInfo();
- if (serviceInfo != null) {
- mInputMethodServices.add(serviceInfo.packageName);
- }
- }
-
- // TODO: Implements by JobScheduler with TriggerContentUri parameters.
- // Watch for related content URIs.
- mContentResolver.registerContentObserver(UserDictionary.Words.CONTENT_URI,
- true /* notifyForDescendants */, this /* observer */);
- // Watch for changing enabled IMEs.
- mContentResolver.registerContentObserver(ENABLED_INPUT_METHODS_CONTENT_URI,
- false /* notifyForDescendants */, this /* observer */);
- }
-
- private void buildIndex(Class<?> indexClass) {
- mIndexManager.updateFromClassNameResource(indexClass.getName(),
- true /* includeInSearchResults */);
- }
-
- synchronized void onPackageAvailable(String packageName) {
- if (mIndexManager == null) return;
- if (mInputMethodServices.contains(packageName)) return;
-
- final Intent intent = getIMEServiceIntent(packageName);
- final List<ResolveInfo> services = mPackageManager
- .queryIntentServices(intent, 0 /* flags */);
- if (services == null || services.isEmpty()) return;
- mInputMethodServices.add(packageName);
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
- }
-
- synchronized void onPackageUnavailable(String packageName) {
- if (mIndexManager == null) return;
- if (!mInputMethodServices.remove(packageName)) return;
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (ENABLED_INPUT_METHODS_CONTENT_URI.equals(uri)) {
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
- } else if (UserDictionary.Words.CONTENT_URI.equals(uri)) {
- buildIndex(LanguageAndInputSettings.class);
- }
- }
- }
-}
diff --git a/src/com/android/settings/search/InputDeviceResultLoader.java b/src/com/android/settings/search/InputDeviceResultLoader.java
new file mode 100644
index 0000000..61e1ad1
--- /dev/null
+++ b/src/com/android/settings/search/InputDeviceResultLoader.java
@@ -0,0 +1,200 @@
+/*
+ * 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.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.settings.utils.AsyncLoader;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Search result for input devices (physical/virtual keyboard, game controllers, etc)
+ */
+public class InputDeviceResultLoader extends AsyncLoader<Set<? extends SearchResult>> {
+ private static final int NAME_NO_MATCH = -1;
+
+ @VisibleForTesting
+ static final String PHYSICAL_KEYBOARD_FRAGMENT = PhysicalKeyboardFragment.class.getName();
+ @VisibleForTesting
+ static final String VIRTUAL_KEYBOARD_FRAGMENT =
+ AvailableVirtualKeyboardFragment.class.getName();
+
+ private final SiteMapManager mSiteMapManager;
+ private final InputManager mInputManager;
+ private final InputMethodManager mImm;
+ private final PackageManager mPackageManager;
+ @VisibleForTesting
+ final String mQuery;
+
+ private List<String> mPhysicalKeyboardBreadcrumb;
+ private List<String> mVirtualKeyboardBreadcrumb;
+
+ public InputDeviceResultLoader(Context context, String query, SiteMapManager mapManager) {
+ super(context);
+ mQuery = query;
+ mSiteMapManager = mapManager;
+ mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+ mImm = (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE);
+ mPackageManager = context.getPackageManager();
+ }
+
+ @Override
+ protected void onDiscardResult(Set<? extends SearchResult> result) {
+ }
+
+ @Override
+ public Set<? extends SearchResult> loadInBackground() {
+ final Set<SearchResult> results = new HashSet<>();
+ results.addAll(buildPhysicalKeyboardSearchResults());
+ results.addAll(buildVirtualKeyboardSearchResults());
+ return results;
+ }
+
+ private Set<SearchResult> buildPhysicalKeyboardSearchResults() {
+ final Set<SearchResult> results = new HashSet<>();
+ final Context context = getContext();
+ final String screenTitle = context.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()
+ : context.getString(R.string.keyboard_layout_default_label);
+ final String key = deviceName;
+
+ final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(context,
+ PHYSICAL_KEYBOARD_FRAGMENT, key, screenTitle);
+ results.add(new SearchResult.Builder()
+ .setTitle(deviceName)
+ .setPayload(new ResultPayload(intent))
+ .setStableId(Objects.hash(PHYSICAL_KEYBOARD_FRAGMENT, key))
+ .setSummary(summary)
+ .setRank(wordDiff)
+ .addBreadcrumbs(getPhysicalKeyboardBreadCrumb())
+ .build());
+ }
+ return results;
+ }
+
+ private Set<SearchResult> buildVirtualKeyboardSearchResults() {
+ final Set<SearchResult> results = new HashSet<>();
+ final Context context = getContext();
+ final String screenTitle = context.getString(R.string.add_virtual_keyboard);
+ final List<InputMethodInfo> inputMethods = mImm.getInputMethodList();
+ for (InputMethodInfo info : inputMethods) {
+ final String title = info.loadLabel(mPackageManager).toString();
+ final String summary = InputMethodAndSubtypeUtil
+ .getSubtypeLocaleNameListAsSentence(getAllSubtypesOf(info), context, 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.buildSubsettingIntent(context,
+ 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<String> getPhysicalKeyboardBreadCrumb() {
+ if (mPhysicalKeyboardBreadcrumb == null || mPhysicalKeyboardBreadcrumb.isEmpty()) {
+ final Context context = getContext();
+ mPhysicalKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb(
+ context, PHYSICAL_KEYBOARD_FRAGMENT,
+ context.getString(R.string.physical_keyboard_title));
+ }
+ return mPhysicalKeyboardBreadcrumb;
+ }
+
+
+ private List<String> getVirtualKeyboardBreadCrumb() {
+ if (mVirtualKeyboardBreadcrumb == null || mVirtualKeyboardBreadcrumb.isEmpty()) {
+ final Context context = getContext();
+ mVirtualKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb(
+ context, VIRTUAL_KEYBOARD_FRAGMENT,
+ context.getString(R.string.add_virtual_keyboard));
+ }
+ return mVirtualKeyboardBreadcrumb;
+ }
+
+ private List<InputDevice> getPhysicalFullKeyboards() {
+ final List<InputDevice> 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<InputMethodSubtype> getAllSubtypesOf(final InputMethodInfo imi) {
+ final int subtypeCount = imi.getSubtypeCount();
+ final List<InputMethodSubtype> 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/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 7e0e086..900cefc 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -49,6 +49,11 @@
String query);
/**
+ * Returns a new loader to search input devices.
+ */
+ InputDeviceResultLoader getInputDeviceResultLoader(Context context, String query);
+
+ /**
* Returns a new loader to get all recently saved queries search terms.
*/
SavedQueryLoader getSavedQueryLoader(Context context);
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index b90547e..400cf8f 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -62,6 +62,11 @@
}
@Override
+ public InputDeviceResultLoader getInputDeviceResultLoader(Context context, String query) {
+ return new InputDeviceResultLoader(context, cleanQuery(query), getSiteMapManager());
+ }
+
+ @Override
public SavedQueryLoader getSavedQueryLoader(Context context) {
return new SavedQueryLoader(context);
}
diff --git a/src/com/android/settings/search/SearchFragment.java b/src/com/android/settings/search/SearchFragment.java
index fb89d6e..ccc4d61 100644
--- a/src/com/android/settings/search/SearchFragment.java
+++ b/src/com/android/settings/search/SearchFragment.java
@@ -84,8 +84,10 @@
static final int LOADER_ID_INSTALLED_APPS = 2;
@VisibleForTesting
static final int LOADER_ID_ACCESSIBILITY_SERVICES = 3;
+ @VisibleForTesting
+ static final int LOADER_ID_INPUT_DEVICES = 4;
- private static final int NUM_QUERY_LOADERS = 3;
+ private static final int NUM_QUERY_LOADERS = 4;
@VisibleForTesting
AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);
@@ -284,6 +286,7 @@
loaderManager.destroyLoader(LOADER_ID_DATABASE);
loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
loaderManager.destroyLoader(LOADER_ID_ACCESSIBILITY_SERVICES);
+ loaderManager.destroyLoader(LOADER_ID_INPUT_DEVICES);
mShowingSavedQuery = true;
mSavedQueryController.loadSavedQueries();
mSearchFeatureProvider.hideFeedbackButton();
@@ -314,6 +317,8 @@
return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
case LOADER_ID_ACCESSIBILITY_SERVICES:
return mSearchFeatureProvider.getAccessibilityServiceResultLoader(activity, mQuery);
+ case LOADER_ID_INPUT_DEVICES:
+ return mSearchFeatureProvider.getInputDeviceResultLoader(activity, mQuery);
default:
return null;
}
@@ -351,6 +356,8 @@
LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
loaderManager.initLoader(
LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */, this /* callback */);
+ loaderManager.initLoader(
+ LOADER_ID_INPUT_DEVICES, null /* args */, this /* callback */);
}
requery();
@@ -392,6 +399,8 @@
loaderManager.restartLoader(LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
loaderManager.restartLoader(LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */,
this /* callback */);
+ loaderManager.restartLoader(LOADER_ID_INPUT_DEVICES, null /* args */,
+ this /* callback */);
}
public String getQuery() {
diff --git a/src/com/android/settings/search/SearchResultsAdapter.java b/src/com/android/settings/search/SearchResultsAdapter.java
index 6c58a0d..7b886a4 100644
--- a/src/com/android/settings/search/SearchResultsAdapter.java
+++ b/src/com/android/settings/search/SearchResultsAdapter.java
@@ -57,7 +57,9 @@
@VisibleForTesting
static final String APP_RESULTS_LOADER_KEY = InstalledAppResultLoader.class.getName();
@VisibleForTesting
- static final String ACCESSIBLITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
+ static final String ACCESSIBILITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
+ @VisibleForTesting
+ static final String INPUT_DEVICE_LOADER_KEY = InputDeviceResultLoader.class.getName();
@VisibleForTesting
static final int MSG_RANKING_TIMED_OUT = 1;
@@ -265,17 +267,21 @@
List<? extends SearchResult> installedAppResults =
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
List<? extends SearchResult> accessibilityResults =
- getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
+ getSortedLoadedResults(ACCESSIBILITY_LOADER_KEY);
+ List<? extends SearchResult> inputDeviceResults =
+ getSortedLoadedResults(INPUT_DEVICE_LOADER_KEY);
int dbSize = databaseResults.size();
int appSize = installedAppResults.size();
int a11ySize = accessibilityResults.size();
-
+ int inputDeviceSize = inputDeviceResults.size();
int dbIndex = 0;
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.
mStaticallyRankedSearchResults.clear();
while (rank <= SearchResult.BOTTOM_RANK) {
while ((dbIndex < dbSize) && (databaseResults.get(dbIndex).rank == rank)) {
@@ -287,6 +293,10 @@
while ((a11yIndex < a11ySize) && (accessibilityResults.get(a11yIndex).rank == rank)) {
mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
}
+ while (inputDeviceIndex < inputDeviceSize
+ && inputDeviceResults.get(inputDeviceIndex).rank == rank) {
+ mStaticallyRankedSearchResults.add(inputDeviceResults.get(inputDeviceIndex++));
+ }
rank++;
}
@@ -299,6 +309,9 @@
while(a11yIndex < a11ySize) {
mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
}
+ while (inputDeviceIndex < inputDeviceSize) {
+ mStaticallyRankedSearchResults.add(inputDeviceResults.get(inputDeviceIndex++));
+ }
}
private void updateSearchResults() {
@@ -332,12 +345,16 @@
List<? extends SearchResult> installedAppResults =
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
List<? extends SearchResult> accessibilityResults =
- getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
+ getSortedLoadedResults(ACCESSIBILITY_LOADER_KEY);
+ List<? extends SearchResult> inputDeviceResults =
+ getSortedLoadedResults(INPUT_DEVICE_LOADER_KEY);
int dbSize = databaseResults.size();
int appSize = installedAppResults.size();
int a11ySize = accessibilityResults.size();
+ int inputDeviceSize = inputDeviceResults.size();
- final List<SearchResult> asyncRankingResults = new ArrayList<>(dbSize + appSize + a11ySize);
+ final List<SearchResult> asyncRankingResults = new ArrayList<>(
+ dbSize + appSize + a11ySize + inputDeviceSize);
TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>(
new Comparator<SearchResult>() {
@Override
@@ -358,13 +375,13 @@
// Other results are not ranked by async ranking and appended at the end of the list.
asyncRankingResults.addAll(installedAppResults);
asyncRankingResults.addAll(accessibilityResults);
+ asyncRankingResults.addAll(inputDeviceResults);
return asyncRankingResults;
}
@VisibleForTesting
Set<? extends SearchResult> getUnsortedLoadedResults(String loaderKey) {
- return mResultsMap.containsKey(loaderKey) ?
- mResultsMap.get(loaderKey) : new HashSet<SearchResult>();
+ return mResultsMap.containsKey(loaderKey) ? mResultsMap.get(loaderKey) : new HashSet<>();
}
@VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
index 78bc7d1..69a1351 100644
--- a/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
@@ -30,7 +30,6 @@
import com.android.settings.password.SetupChooseLockPattern;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -49,7 +48,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
index 92aa675..8ed7284 100644
--- a/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
@@ -16,6 +16,17 @@
package com.android.settings.applications;
+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.eq;
+import static org.mockito.Mockito.doNothing;
+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.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -35,7 +46,6 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.widget.LoadingViewController;
import com.android.settingslib.applications.ApplicationsState;
@@ -53,17 +63,6 @@
import java.util.ArrayList;
-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.eq;
-import static org.mockito.Mockito.doNothing;
-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;
-
/**
* Tests for {@link ManageApplications}.
*/
@@ -74,7 +73,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class
})
public class ManageApplicationsTest {
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index 8a8a13d..6b56c29 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -15,6 +15,19 @@
*/
package com.android.settings.dashboard;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -38,7 +51,6 @@
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
@@ -56,26 +68,12 @@
import java.util.ArrayList;
import java.util.List;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class
})
public class DashboardAdapterTest {
diff --git a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
index 344914a..ad52bf6 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -36,7 +36,6 @@
import com.android.settings.password.IFingerprintManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -61,7 +60,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
index f1b7ee0..3b67851 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
@@ -30,7 +30,6 @@
import com.android.settings.password.IFingerprintManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -53,7 +52,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
index 013d379..e434bb3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
@@ -17,6 +17,15 @@
package com.android.settings.fuelgauge;
+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.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -27,11 +36,10 @@
import android.widget.TextView;
import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -45,23 +53,12 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-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.eq;
-import static org.mockito.Mockito.doReturn;
-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,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEntityHeaderController.class
})
public class BatteryHeaderPreferenceControllerTest {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
index e3a94d2..3a1fad0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
@@ -16,15 +16,17 @@
package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.ColorFilter;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import org.junit.Before;
import org.junit.Test;
@@ -34,10 +36,6 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
@RunWith(SettingsRobolectricTestRunner.class)
// TODO: Consider making the shadow class set global using a robolectric.properties file.
@Config(manifest = TestConfig.MANIFEST_PATH,
@@ -45,7 +43,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class
})
public class BatteryMeterViewTest {
private static final int BATTERY_LEVEL = 100;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 83e630d..48a48b1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -18,9 +18,7 @@
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
-
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.anyLong;
@@ -34,8 +32,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.List;
-
import android.app.LoaderManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -68,7 +64,6 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settingslib.core.AbstractPreferenceController;
import org.junit.Before;
@@ -95,7 +90,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class
})
public class PowerUsageSummaryTest {
private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
index 3b92ed1..d4fc014 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
@@ -129,46 +129,6 @@
assertThat(mController.isSwitchPrefEnabled()).isFalse();
}
- @Test
- public void testPreferenceController_ProperResultPayloadType() {
- when(mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_supportSystemNavigationKeys))
- .thenReturn(true);
-
- SwipeToNotificationPreferenceController controller =
- new SwipeToNotificationPreferenceController(mContext, null /* lifecycle */,
- SYSTEM_NAVIGATION_KEYS_ENABLED);
- ResultPayload payload = controller.getResultPayload();
- assertThat(payload).isInstanceOf(InlineSwitchPayload.class);
- }
-
- @Test
- @Config(shadows = ShadowSecureSettings.class)
- public void testSetValue_updatesCorrectly() {
- int newValue = 1;
- ContentResolver resolver = mContext.getContentResolver();
- Settings.Secure.putInt(resolver, Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0);
-
- ((InlinePayload) mController.getResultPayload()).setValue(mContext, newValue);
- int updatedValue = Settings.Secure.getInt(resolver,
- Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, -1);
-
- assertThat(updatedValue).isEqualTo(newValue);
- }
-
- @Test
- @Config(shadows = ShadowSecureSettings.class)
- public void testGetValue_correctValueReturned() {
- int currentValue = 1;
- ContentResolver resolver = mContext.getContentResolver();
- Settings.Secure.putInt(resolver,
- Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, currentValue);
-
- int newValue = ((InlinePayload) mController.getResultPayload()).getValue(mContext);
-
- assertThat(newValue).isEqualTo(currentValue);
- }
-
private void stubFingerprintSupported(boolean enabled) {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
.thenReturn(enabled);
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
index e115dad..66e357b 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
@@ -26,6 +26,7 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsWrapper;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -87,6 +88,7 @@
}
@Test
+ @Config(shadows = ShadowRestrictedLockUtilsWrapper.class)
public void wifiOnly_prefIsNotAvailable() {
when(mUserManager.isAdminUser()).thenReturn(true);
when(mUserManager.hasUserRestriction(anyString(), any(UserHandle.class)))
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
index 5fa731e..b8f0679 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -31,7 +31,6 @@
import com.android.settings.password.ChooseLockPassword.IntentBuilder;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.setupwizardlib.GlifLayout;
@@ -52,7 +51,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
index b238049..c74448b 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
@@ -29,7 +29,6 @@
import com.android.settings.password.ChooseLockPattern.IntentBuilder;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.setupwizardlib.GlifLayout;
@@ -48,7 +47,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
index 39a0fb6..1195a2c 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
@@ -34,7 +34,6 @@
import com.android.settings.password.SetupChooseLockPassword.SetupChooseLockPasswordFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -62,7 +61,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java b/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
index 639349d..0e6f28a 100644
--- a/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
@@ -27,7 +27,6 @@
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -40,13 +39,11 @@
import org.robolectric.shadows.ShadowAlertDialog;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(
- manifest = TestConfig.MANIFEST_PATH,
+@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java b/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java
deleted file mode 100644
index 26c89d5..0000000
--- a/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java
+++ /dev/null
@@ -1,563 +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.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.app.LoaderManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.print.PrintManager;
-import android.print.PrintServicesLoader;
-import android.printservice.PrintServiceInfo;
-import android.provider.Settings;
-import android.provider.UserDictionary;
-import android.view.inputmethod.InputMethodInfo;
-
-import com.android.internal.content.PackageMonitor;
-import com.android.settings.TestConfig;
-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 com.android.settings.testutils.shadow.ShadowInputMethodManagerWithMethodList;
-import com.android.settings.testutils.shadow.ShadowPackageMonitor;
-
-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.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.internal.ShadowExtractor;
-import org.robolectric.res.builder.RobolectricPackageManager;
-import org.robolectric.shadows.ShadowAccessibilityManager;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowContentResolver;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(
- manifest = TestConfig.MANIFEST_PATH,
- sdk = TestConfig.SDK_VERSION,
- shadows = {
- ShadowActivityWithLoadManager.class,
- ShadowContextImplWithRegisterReceiver.class,
- ShadowInputManager.class,
- ShadowInputMethodManagerWithMethodList.class,
- ShadowPackageMonitor.class,
- }
-)
-public class DynamicIndexableContentMonitorTest {
-
- private static final int LOADER_ID = 1234;
- private static final String A11Y_PACKAGE_1 = "a11y-1";
- private static final String A11Y_PACKAGE_2 = "a11y-2";
- private static final String IME_PACKAGE_1 = "ime-1";
- private static final String IME_PACKAGE_2 = "ime-2";
-
- @Mock
- private LoaderManager mLoaderManager;
- @Mock
- private DatabaseIndexingManager mIndexManager;
-
- private Activity mActivity;
- private InputManager mInputManager;
-
- private ShadowContextImplWithRegisterReceiver mShadowContextImpl;
- private ShadowActivityWithLoadManager mShadowActivity;
- private ShadowAccessibilityManager mShadowAccessibilityManager;
- private ShadowInputMethodManagerWithMethodList mShadowInputMethodManager;
- private RobolectricPackageManager mRobolectricPackageManager;
-
- private final DynamicIndexableContentMonitor mMonitor = new DynamicIndexableContentMonitor();
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mActivity = Robolectric.buildActivity(Activity.class).get();
- mInputManager = InputManager.getInstance();
-
- // Robolectric shadows.
- mShadowContextImpl = (ShadowContextImplWithRegisterReceiver) ShadowExtractor.extract(
- ((Application) ShadowApplication.getInstance().getApplicationContext())
- .getBaseContext());
- mShadowActivity = (ShadowActivityWithLoadManager) ShadowExtractor.extract(mActivity);
- mShadowAccessibilityManager = (ShadowAccessibilityManager) ShadowExtractor.extract(
- mActivity.getSystemService(Context.ACCESSIBILITY_SERVICE));
- mShadowInputMethodManager = (ShadowInputMethodManagerWithMethodList) ShadowExtractor
- .extract(mActivity.getSystemService(Context.INPUT_METHOD_SERVICE));
- mRobolectricPackageManager = RuntimeEnvironment.getRobolectricPackageManager();
-
- // Setup shadows.
- mShadowContextImpl.setSystemService(Context.PRINT_SERVICE, mock(PrintManager.class));
- mShadowContextImpl.setSystemService(Context.INPUT_SERVICE, mInputManager);
- mShadowActivity.setLoaderManager(mLoaderManager);
- mShadowAccessibilityManager.setInstalledAccessibilityServiceList(Collections.emptyList());
- mShadowInputMethodManager.setInputMethodList(Collections.emptyList());
- mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_PRINTING, true);
- mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_INPUT_METHODS, true);
- }
-
- @After
- public void shutDown() {
- mMonitor.unregister(mActivity, LOADER_ID);
- // BroadcastReceiver must be unregistered.
- assertThat(extractPackageMonitor()).isNull();
-
- DynamicIndexableContentMonitor.resetForTesting();
- mRobolectricPackageManager.reset();
-
- DatabaseTestUtils.clearDb(mActivity);
- }
-
- @Test
- public void testLockedUser() {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, false /* isUserUnlocked */);
-
- // No loader procedure happens.
- verify(mLoaderManager, never()).initLoader(
- anyInt(), any(Bundle.class), any(LoaderManager.LoaderCallbacks.class));
- // No indexing happens.
- verify(mIndexManager, never()).updateFromClassNameResource(
- anyString(), anyBoolean());
-
- mMonitor.unregister(mActivity, LOADER_ID);
-
- // No destroy loader should happen.
- verify(mLoaderManager, never()).destroyLoader(anyInt());
- }
-
- @Test
- public void testWithNoPrintingFeature() {
- mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_PRINTING, false);
-
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // No loader procedure happens.
- verify(mLoaderManager, never()).initLoader(
- anyInt(), any(Bundle.class), any(LoaderManager.LoaderCallbacks.class));
- verifyNoIndexing(PrintSettingsFragment.class);
-
- mMonitor.unregister(mActivity, LOADER_ID);
-
- // No destroy loader should happen.
- verify(mLoaderManager, never()).destroyLoader(anyInt());
- // BroadcastReceiver must be unregistered.
- assertThat(extractPackageMonitor()).isNull();
-
- // To suppress spurious test fail in {@link #shutDown()}.
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
- }
-
- @Test
- public void testPrinterServiceIndex() {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // Loader procedure happens.
- verify(mLoaderManager, only()).initLoader(LOADER_ID, null, mMonitor);
-
- // Loading print services happens.
- final Loader<List<PrintServiceInfo>> loader =
- mMonitor.onCreateLoader(LOADER_ID, null /* args */);
- assertThat(loader).isInstanceOf(PrintServicesLoader.class);
- verifyNoIndexing(PrintSettingsFragment.class);
-
- mMonitor.onLoadFinished(loader, Collections.emptyList());
-
- verifyIncrementalIndexing(PrintSettingsFragment.class);
- }
-
- @Test
- public void testInputDevicesMonitor() {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // Rebuild indexing should happen.
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
- // Input monitor should be registered to InputManager.
- final InputManager.InputDeviceListener listener = extactInputDeviceListener();
- assertThat(listener).isNotNull();
-
- /*
- * Nothing happens on successive register calls.
- */
- mMonitor.unregister(mActivity, LOADER_ID);
- reset(mIndexManager);
-
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- verifyNoIndexing(PhysicalKeyboardFragment.class);
- assertThat(extactInputDeviceListener()).isEqualTo(listener);
-
- /*
- * A device is added.
- */
- reset(mIndexManager);
-
- listener.onInputDeviceAdded(1 /* deviceId */);
-
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-
- /*
- * A device is removed.
- */
- reset(mIndexManager);
-
- listener.onInputDeviceRemoved(2 /* deviceId */);
-
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-
- /*
- * A device is changed.
- */
- reset(mIndexManager);
-
- listener.onInputDeviceChanged(3 /* deviceId */);
-
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
- }
-
- @Test
- public void testInputMethodServicesMonitor() throws Exception {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- final Uri enabledInputMethodsContentUri = Settings.Secure.getUriFor(
- Settings.Secure.ENABLED_INPUT_METHODS);
- // Content observer should be registered.
- final ContentObserver observer = extractContentObserver(enabledInputMethodsContentUri);
- assertThat(observer).isNotNull();
-
- /*
- * When an input method service package is installed, incremental indexing happen.
- */
- reset(mIndexManager);
-
- installInputMethodService(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When another input method service package is installed, incremental indexing happens.
- */
- reset(mIndexManager);
-
- installInputMethodService(IME_PACKAGE_2);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an input method service is disabled, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- disableInstalledPackage(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an input method service is enabled, incremental indexing happens.
- */
- reset(mIndexManager);
-
- enableInstalledPackage(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an input method service package is uninstalled, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- uninstallInputMethodService(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an accessibility service package is installed, nothing happens.
- */
- reset(mIndexManager);
-
- installAccessibilityService(A11Y_PACKAGE_1);
-
- verifyNoIndexing(VirtualKeyboardFragment.class);
- verifyNoIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When enabled IMEs list is changed, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- observer.onChange(false /* selfChange */, enabledInputMethodsContentUri);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
- }
-
- @Test
- public void testUserDictionaryChangeMonitor() throws Exception {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // Content observer should be registered.
- final ContentObserver observer = extractContentObserver(UserDictionary.Words.CONTENT_URI);
- assertThat(observer).isNotNull();
-
- verifyIncrementalIndexing(LanguageAndInputSettings.class);
-
- /*
- * When user dictionary content is changed, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- observer.onChange(false /* selfChange */, UserDictionary.Words.CONTENT_URI);
-
- verifyIncrementalIndexing(LanguageAndInputSettings.class);
- }
-
- /*
- * Verification helpers.
- */
-
- private void verifyNoIndexing(Class<?> indexingClass) {
- verify(mIndexManager, never()).updateFromClassNameResource(eq(indexingClass.getName()),
- anyBoolean());
- }
-
- private void verifyIncrementalIndexing(Class<?> indexingClass) {
- verify(mIndexManager, times(1)).updateFromClassNameResource(indexingClass.getName(),
- true /* includeInSearchResults */);
- verify(mIndexManager, never()).updateFromClassNameResource(indexingClass.getName(),
- false /* includeInSearchResults */);
- }
-
- /*
- * Testing helper methods.
- */
-
- private InputManager.InputDeviceListener extactInputDeviceListener() {
- List<InputManager.InputDeviceListener> listeners = ((ShadowInputManager) ShadowExtractor
- .extract(mInputManager))
- .getRegisteredInputDeviceListeners();
- InputManager.InputDeviceListener inputDeviceListener = null;
- for (InputManager.InputDeviceListener listener : listeners) {
- if (isUnderTest(listener)) {
- if (inputDeviceListener != null) {
- assertThat(listener).isEqualTo(inputDeviceListener);
- } else {
- inputDeviceListener = listener;
- }
- }
- }
- return inputDeviceListener;
- }
-
- private PackageMonitor extractPackageMonitor() {
- List<ShadowApplication.Wrapper> receivers = ShadowApplication.getInstance()
- .getRegisteredReceivers();
- PackageMonitor packageMonitor = null;
- for (ShadowApplication.Wrapper wrapper : receivers) {
- BroadcastReceiver receiver = wrapper.getBroadcastReceiver();
- if (isUnderTest(receiver) && receiver instanceof PackageMonitor) {
- if (packageMonitor != null) {
- assertThat(receiver).isEqualTo(packageMonitor);
- } else {
- packageMonitor = (PackageMonitor) receiver;
- }
- }
- }
- return packageMonitor;
- }
-
- private ContentObserver extractContentObserver(Uri uri) {
- ShadowContentResolver contentResolver = (ShadowContentResolver) ShadowExtractor
- .extract(mActivity.getContentResolver());
- Collection<ContentObserver> observers = contentResolver.getContentObservers(uri);
- ContentObserver contentObserver = null;
- for (ContentObserver observer : observers) {
- if (isUnderTest(observer)) {
- if (contentObserver != null) {
- assertThat(observer).isEqualTo(contentObserver);
- } else {
- contentObserver = observer;
- }
- }
- }
- return contentObserver;
- }
-
- private void enableInstalledPackage(String packageName) {
- ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
- packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
- extractPackageMonitor().onPackageModified(packageName);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void disableInstalledPackage(String packageName) {
- ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
- packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0 /* flags */);
- extractPackageMonitor().onPackageModified(packageName);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void installAccessibilityService(String packageName) throws Exception {
- final AccessibilityServiceInfo serviceToAdd = buildAccessibilityServiceInfo(packageName);
-
- final List<AccessibilityServiceInfo> services = new ArrayList<>();
- services.addAll(mShadowAccessibilityManager.getInstalledAccessibilityServiceList());
- services.add(serviceToAdd);
- mShadowAccessibilityManager.setInstalledAccessibilityServiceList(services);
-
- final Intent intent = DynamicIndexableContentMonitor
- .getAccessibilityServiceIntent(packageName);
- mRobolectricPackageManager.addResolveInfoForIntent(intent, serviceToAdd.getResolveInfo());
- mRobolectricPackageManager.addPackage(packageName);
-
- extractPackageMonitor()
- .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void uninstallAccessibilityService(String packageName) throws Exception {
- final AccessibilityServiceInfo serviceToRemove = buildAccessibilityServiceInfo(packageName);
-
- final List<AccessibilityServiceInfo> services = new ArrayList<>();
- services.addAll(mShadowAccessibilityManager.getInstalledAccessibilityServiceList());
- services.remove(serviceToRemove);
- mShadowAccessibilityManager.setInstalledAccessibilityServiceList(services);
-
- final Intent intent = DynamicIndexableContentMonitor
- .getAccessibilityServiceIntent(packageName);
- mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
- mRobolectricPackageManager.removePackage(packageName);
-
- extractPackageMonitor()
- .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void installInputMethodService(String packageName) throws Exception {
- final ResolveInfo resolveInfoToAdd = buildResolveInfo(packageName, "imeService");
- final InputMethodInfo serviceToAdd = buildInputMethodInfo(resolveInfoToAdd);
-
- final List<InputMethodInfo> services = new ArrayList<>();
- services.addAll(mShadowInputMethodManager.getInputMethodList());
- services.add(serviceToAdd);
- mShadowInputMethodManager.setInputMethodList(services);
-
- final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
- mRobolectricPackageManager.addResolveInfoForIntent(intent, resolveInfoToAdd);
- mRobolectricPackageManager.addPackage(packageName);
-
- extractPackageMonitor()
- .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void uninstallInputMethodService(String packageName) throws Exception {
- final ResolveInfo resolveInfoToRemove = buildResolveInfo(packageName, "imeService");
- final InputMethodInfo serviceToRemove = buildInputMethodInfo(resolveInfoToRemove);
-
- final List<InputMethodInfo> services = new ArrayList<>();
- services.addAll(mShadowInputMethodManager.getInputMethodList());
- services.remove(serviceToRemove);
- mShadowInputMethodManager.setInputMethodList(services);
-
- final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
- mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
- mRobolectricPackageManager.removePackage(packageName);
-
- extractPackageMonitor()
- .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private AccessibilityServiceInfo buildAccessibilityServiceInfo(String packageName)
- throws IOException, XmlPullParserException {
- return new AccessibilityServiceInfo(
- buildResolveInfo(packageName, "A11yService"), mActivity);
- }
-
- private static InputMethodInfo buildInputMethodInfo(ResolveInfo resolveInfo) {
- return new InputMethodInfo(resolveInfo, false /* isAuxIme */, "SettingsActivity",
- null /* subtypes */, 0 /* defaultResId */, false /* forceDefault */);
- }
-
- private static ResolveInfo buildResolveInfo(String packageName, String className) {
- final ResolveInfo resolveInfo = new ResolveInfo();
- resolveInfo.serviceInfo = new ServiceInfo();
- resolveInfo.serviceInfo.packageName = packageName;
- resolveInfo.serviceInfo.name = className;
- // To workaround that RobolectricPackageManager.removeResolveInfosForIntent() only works
- // for activity/broadcast resolver.
- resolveInfo.activityInfo = new ActivityInfo();
- resolveInfo.activityInfo.packageName = packageName;
- resolveInfo.activityInfo.name = className;
-
- return resolveInfo;
- }
-
- private static boolean isUnderTest(Object object) {
- return object.getClass().getName().startsWith(
- DynamicIndexableContentMonitor.class.getName());
- }
-}
diff --git a/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java b/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java
new file mode 100644
index 0000000..a955af1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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 InputDeviceResultLoaderTest {
+
+ private static final String QUERY = "test_query";
+ private static final List<String> PHYSICAL_KEYBOARD_BREADCRUMB;
+ private static final List<String> 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 mLoader;
+
+ @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]));
+ mLoader = new InputDeviceResultLoader(mContext, QUERY, mSiteMapManager);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowInputDevice.reset();
+ }
+
+ @Test
+ public void query_noKeyboard_shouldNotReturnAnything() {
+ assertThat(mLoader.loadInBackground()).isEmpty();
+ }
+
+ @Test
+ public void query_hasPhysicalKeyboard_match() {
+ addPhysicalKeyboard(QUERY);
+ when(mSiteMapManager.buildBreadCrumb(mContext, PHYSICAL_KEYBOARD_FRAGMENT,
+ RuntimeEnvironment.application.getString(R.string.physical_keyboard_title)))
+ .thenReturn(PHYSICAL_KEYBOARD_BREADCRUMB);
+
+ final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
+
+ 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() {
+ addVirtualKeyboard(QUERY);
+ when(mSiteMapManager.buildBreadCrumb(mContext, VIRTUAL_KEYBOARD_FRAGMENT,
+ RuntimeEnvironment.application.getString(R.string.add_virtual_keyboard)))
+ .thenReturn(VIRTUAL_KEYBOARD_BREADCRUMB);
+
+ final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
+ 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() {
+ addPhysicalKeyboard("abc");
+ addVirtualKeyboard("def");
+
+ assertThat(mLoader.loadInBackground()).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<InputMethodInfo> 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);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java b/tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
similarity index 88%
rename from tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
rename to tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
index aa9b778..0a06a35 100644
--- a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
+++ b/tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
@@ -21,9 +21,9 @@
import java.util.HashSet;
import java.util.Set;
-public class MockAccessiblityLoader extends AccessibilityServiceResultLoader {
+public class MockAccessibilityLoader extends AccessibilityServiceResultLoader {
- public MockAccessiblityLoader(Context context) {
+ public MockAccessibilityLoader(Context context) {
super(context, "test_query", null);
}
diff --git a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java b/tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
similarity index 88%
copy from tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
copy to tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
index aa9b778..2c16b14 100644
--- a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
+++ b/tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
@@ -21,9 +21,8 @@
import java.util.HashSet;
import java.util.Set;
-public class MockAccessiblityLoader extends AccessibilityServiceResultLoader {
-
- public MockAccessiblityLoader(Context context) {
+public class MockInputDeviceResultLoader extends InputDeviceResultLoader {
+ public MockInputDeviceResultLoader(Context context) {
super(context, "test_query", null);
}
diff --git a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java b/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
index 6588805..71c31aa 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
@@ -17,6 +17,20 @@
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.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.app.LoaderManager;
import android.content.Context;
import android.content.Intent;
@@ -28,10 +42,10 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
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;
@@ -52,20 +66,6 @@
import java.util.Set;
-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.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
@@ -83,6 +83,8 @@
private InstalledAppResultLoader mInstalledAppResultLoader;
@Mock
private AccessibilityServiceResultLoader mAccessibilityServiceResultLoader;
+ @Mock
+ private InputDeviceResultLoader mInputDeviceResultLoader;
@Mock
private SavedQueryLoader mSavedQueryLoader;
@@ -118,6 +120,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
@@ -178,6 +183,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
@@ -236,6 +244,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
ActivityController<SearchActivity> activityController =
@@ -270,6 +281,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
@@ -349,7 +363,10 @@
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
- .thenReturn(new MockAccessiblityLoader(RuntimeEnvironment.application));
+ .thenReturn(new MockAccessibilityLoader(RuntimeEnvironment.application));
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(new MockInputDeviceResultLoader(RuntimeEnvironment.application));
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
ActivityController<SearchActivity> activityController =
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
deleted file mode 100644
index de5d243..0000000
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.android.settings.testutils.shadow;
-
-import android.app.Activity;
-import android.os.UserManager;
-import com.android.settings.search.DynamicIndexableContentMonitor;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.RealObject;
-
-/**
- * A shadow class of {@link DynamicIndexableContentMonitor}. The real implementation of
- * {@link DynamicIndexableContentMonitor#register} calls {@link UserManager#isUserUnlocked()}, which
- * Robolectric has not yet been updated to support, so throws a NoSuchMethodError exception.
- */
-// TODO: Delete this once Robolectric is updated to the latest SDK.
-@Implements(DynamicIndexableContentMonitor.class)
-public class ShadowDynamicIndexableContentMonitor {
-
- @Implementation
- public void register(Activity activity, int loaderId) {
- }
-}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java
new file mode 100644
index 0000000..8d76063
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java
@@ -0,0 +1,28 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+import com.android.settings.network.MobileNetworkPreferenceController;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(MobileNetworkPreferenceController.class)
+public class ShadowMobileNetworkPreferenceController {
+ private static boolean mIsRestricted = false;
+
+ public void __constructor__(Context context) {
+ }
+
+ @Implementation
+ public boolean isAvailable() {
+ return mIsRestricted ? false : true;
+ }
+
+ @Implementation
+ public boolean isUserRestricted() {
+ return mIsRestricted;
+ }
+
+ public static void setRestricted(boolean restricted) {
+ mIsRestricted = restricted;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java
new file mode 100644
index 0000000..0e0adce
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java
@@ -0,0 +1,25 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+import com.android.settings.network.RestrictedLockUtilsWrapper;
+import org.robolectric.annotation.Implements;
+
+/**
+ * Shadow for the wrapper around RestrictedLockUtils. Should be removed/updated once robolectric is
+ * updated to allow usage of new UserManager API's. see
+ * {@link com.android.settingslib.RestrictedLockUtils} and
+ * {@link com.android.settings.network.RestrictedLockUtilsWrapper}
+ */
+@Implements(RestrictedLockUtilsWrapper.class)
+public class ShadowRestrictedLockUtilsWrapper {
+
+ private boolean isRestricted;
+
+ public boolean hasBaseUserRestriction(Context context, String userRestriction, int userId) {
+ return isRestricted;
+ }
+
+ public void setRestricted(boolean restricted) {
+ isRestricted = restricted;
+ }
+}