Merge "DO NOT MERGE Extract Bluetooth device scanning logic into abstract superclass." into pi-car-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a0491db..a890aed 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -412,6 +412,8 @@
<item quantity="one"><xliff:g example="1" id="count">%d</xliff:g> additional permission</item>
<item quantity="other"><xliff:g example="10" id="count">%d</xliff:g> additional permissions</item>
</plurals>
+ <!-- Dialog body explaining that the app just selected by the user will not work after a reboot until after the user enters their credentials, such as a PIN or password. [CHAR LIMIT=NONE] -->
+ <string name="direct_boot_unaware_dialog_message_car">Note: After a reboot, this app can\'t start until you unlock your vehicle.</string>
<!-- Assistant and voice input settings title. This setting goes into the manage assistant settings page. [CHAR LIMIT=40] -->
<string name="assist_and_voice_input_settings">Assist & voice input</string>
<!-- Default assistant settings title. This setting allows users to select the default assistant for the device. [CHAR LIMIT=40] -->
diff --git a/src/com/android/car/settings/inputmethod/InputMethodUtil.java b/src/com/android/car/settings/inputmethod/InputMethodUtil.java
index 585ee2c..8100b02 100644
--- a/src/com/android/car/settings/inputmethod/InputMethodUtil.java
+++ b/src/com/android/car/settings/inputmethod/InputMethodUtil.java
@@ -16,12 +16,15 @@
package com.android.car.settings.inputmethod;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.provider.Settings;
+import android.text.TextUtils;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
@@ -35,9 +38,21 @@
/** Keyboard utility class. */
public final class InputMethodUtil {
+ /**
+ * Delimiter for Enabled Input Methods' concatenated string.
+ */
+ public static final char INPUT_METHOD_DELIMITER = ':';
+ /**
+ * Splitter for Enabled Input Methods' concatenated string.
+ */
+ public static final TextUtils.SimpleStringSplitter sInputMethodSplitter =
+ new TextUtils.SimpleStringSplitter(INPUT_METHOD_DELIMITER);
@VisibleForTesting
static final Drawable NO_ICON = new ColorDrawable(Color.TRANSPARENT);
+ private InputMethodUtil() {
+ }
+
/** Returns package icon. */
public static Drawable getPackageIcon(@NonNull PackageManager packageManager,
@NonNull InputMethodInfo inputMethodInfo) {
@@ -68,5 +83,104 @@
subtypes, context, inputMethodInfo);
}
- private InputMethodUtil() {}
+ /**
+ * Check if input method is enabled.
+ *
+ * @return {@code true} if the input method is enabled.
+ */
+ public static boolean isInputMethodEnabled(ContentResolver resolver,
+ InputMethodInfo inputMethodInfo) {
+ sInputMethodSplitter.setString(getEnabledInputMethodsConcatenatedIds(resolver));
+ while (sInputMethodSplitter.hasNext()) {
+ String inputMethodId = sInputMethodSplitter.next();
+ if (inputMethodId.equals(inputMethodInfo.getId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Enable an input method using its InputMethodInfo.
+ */
+ public static void enableInputMethod(ContentResolver resolver,
+ InputMethodInfo inputMethodInfo) {
+ if (isInputMethodEnabled(resolver, inputMethodInfo)) {
+ return;
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append(getEnabledInputMethodsConcatenatedIds(resolver));
+
+ if (!builder.toString().isEmpty()) {
+ builder.append(INPUT_METHOD_DELIMITER);
+ }
+
+ builder.append(inputMethodInfo.getId());
+
+ setEnabledInputMethodsConcatenatedIds(resolver, builder.toString());
+ }
+
+ /**
+ * Disable an input method if its not the default system input method or if there exists another
+ * enabled input method that can also be set as the default system input method.
+ */
+ public static void disableInputMethod(Context context, InputMethodManager inputMethodManager,
+ InputMethodInfo inputMethodInfo) {
+ List<InputMethodInfo> enabledInputMethodInfos = inputMethodManager
+ .getEnabledInputMethodList();
+ StringBuilder builder = new StringBuilder();
+
+ boolean foundAnotherEnabledDefaultInputMethod = false;
+ boolean isSystemDefault = isDefaultInputMethod(context.getContentResolver(),
+ inputMethodInfo);
+ for (InputMethodInfo enabledInputMethodInfo : enabledInputMethodInfos) {
+ if (enabledInputMethodInfo.getId().equals(inputMethodInfo.getId())) {
+ continue;
+ }
+
+ if (builder.length() > 0) {
+ builder.append(INPUT_METHOD_DELIMITER);
+ }
+
+ builder.append(enabledInputMethodInfo.getId());
+
+ if (isSystemDefault && enabledInputMethodInfo.isDefault(context)) {
+ foundAnotherEnabledDefaultInputMethod = true;
+ setDefaultInputMethodId(context.getContentResolver(),
+ enabledInputMethodInfo.getId());
+ }
+ }
+
+ if (isSystemDefault && !foundAnotherEnabledDefaultInputMethod) {
+ return;
+ }
+
+ setEnabledInputMethodsConcatenatedIds(context.getContentResolver(), builder.toString());
+ }
+
+ private static String getEnabledInputMethodsConcatenatedIds(ContentResolver resolver) {
+ return Settings.Secure.getString(resolver, Settings.Secure.ENABLED_INPUT_METHODS);
+ }
+
+ private static String getDefaultInputMethodId(ContentResolver resolver) {
+ return Settings.Secure.getString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD);
+ }
+
+ private static boolean isDefaultInputMethod(ContentResolver resolver,
+ InputMethodInfo inputMethodInfo) {
+ return inputMethodInfo.getId().equals(getDefaultInputMethodId(resolver));
+ }
+
+ private static void setEnabledInputMethodsConcatenatedIds(ContentResolver resolver,
+ String enabledInputMethodIds) {
+ Settings.Secure.putString(resolver, Settings.Secure.ENABLED_INPUT_METHODS,
+ enabledInputMethodIds);
+ }
+
+ private static void setDefaultInputMethodId(ContentResolver resolver,
+ String defaultInputMethodId) {
+ Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD,
+ defaultInputMethodId);
+ }
}
diff --git a/src/com/android/car/settings/inputmethod/KeyboardManagementPreferenceController.java b/src/com/android/car/settings/inputmethod/KeyboardManagementPreferenceController.java
index 8f6da1b..e643867 100644
--- a/src/com/android/car/settings/inputmethod/KeyboardManagementPreferenceController.java
+++ b/src/com/android/car/settings/inputmethod/KeyboardManagementPreferenceController.java
@@ -16,21 +16,89 @@
package com.android.car.settings.inputmethod;
+import android.app.admin.DevicePolicyManager;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
+import androidx.preference.SwitchPreference;
+import com.android.car.settings.R;
+import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceController;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
/** Updates the available keyboard list. */
public class KeyboardManagementPreferenceController extends
PreferenceController<PreferenceGroup> {
+ @VisibleForTesting
+ static final String DIRECT_BOOT_WARN_DIALOG_TAG = "DirectBootWarnDialog";
+ @VisibleForTesting
+ static final String SECURITY_WARN_DIALOG_TAG = "SecurityWarnDialog";
+ private static final String KEY_INPUT_METHOD_INFO = "INPUT_METHOD_INFO";
+ private final InputMethodManager mInputMethodManager;
+ private final DevicePolicyManager mDevicePolicyManager;
+ private final PackageManager mPackageManager;
+ private final ConfirmationDialogFragment.ConfirmListener mDirectBootWarnConfirmListener =
+ args -> {
+ InputMethodInfo inputMethodInfo = args.getParcelable(KEY_INPUT_METHOD_INFO);
+ InputMethodUtil.enableInputMethod(getContext().getContentResolver(),
+ inputMethodInfo);
+ refreshUi();
+ };
+ private final ConfirmationDialogFragment.RejectListener mRejectListener = args ->
+ refreshUi();
+ private final ConfirmationDialogFragment.ConfirmListener mSecurityWarnDialogConfirmListener =
+ args -> {
+ InputMethodInfo inputMethodInfo = args.getParcelable(KEY_INPUT_METHOD_INFO);
+ // The user confirmed to enable a 3rd party IME, but we might need to prompt if
+ // it's not
+ // Direct Boot aware.
+ if (inputMethodInfo.getServiceInfo().directBootAware) {
+ InputMethodUtil.enableInputMethod(getContext().getContentResolver(),
+ inputMethodInfo);
+ refreshUi();
+ } else {
+ showDirectBootWarnDialog(inputMethodInfo);
+ }
+ };
public KeyboardManagementPreferenceController(Context context, String preferenceKey,
FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
+ mPackageManager = context.getPackageManager();
+ mDevicePolicyManager =
+ (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ mInputMethodManager =
+ (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ }
+
+ @Override
+ protected void onCreateInternal() {
+ super.onCreateInternal();
+
+ ConfirmationDialogFragment dialogFragment = (ConfirmationDialogFragment)
+ getFragmentController().findDialogByTag(DIRECT_BOOT_WARN_DIALOG_TAG);
+ ConfirmationDialogFragment.resetListeners(dialogFragment,
+ mDirectBootWarnConfirmListener,
+ mRejectListener);
+
+ dialogFragment = (ConfirmationDialogFragment) getFragmentController()
+ .findDialogByTag(SECURITY_WARN_DIALOG_TAG);
+ ConfirmationDialogFragment.resetListeners(dialogFragment,
+ mSecurityWarnDialogConfirmListener,
+ mRejectListener);
}
@Override
@@ -39,8 +107,122 @@
}
@Override
- protected void onCreateInternal() {
- // TODO: create preference for each available keyboard and add those preferences to the
- // preference group.
+ protected void updateState(PreferenceGroup preferenceGroup) {
+ List<String> permittedInputMethods = mDevicePolicyManager
+ .getPermittedInputMethodsForCurrentUser();
+ Set<String> permittedInputMethodsSet = permittedInputMethods == null ? null : new HashSet<>(
+ permittedInputMethods);
+
+ preferenceGroup.removeAll();
+
+ List<InputMethodInfo> inputMethodInfos = mInputMethodManager.getInputMethodList();
+ if (inputMethodInfos == null || inputMethodInfos.size() == 0) {
+ return;
+ }
+
+ Collections.sort(inputMethodInfos, Comparator.comparing(
+ (InputMethodInfo a) -> InputMethodUtil.getPackageLabel(mPackageManager, a))
+ .thenComparing((InputMethodInfo a) -> InputMethodUtil.getSummaryString(getContext(),
+ mInputMethodManager, a)));
+
+ for (InputMethodInfo inputMethodInfo : inputMethodInfos) {
+ if (!isInputMethodAllowedByOrganization(permittedInputMethodsSet, inputMethodInfo)) {
+ continue;
+ }
+
+ Preference preference = createSwitchPreference(inputMethodInfo);
+
+ preference.setEnabled(!isOnlyEnabledDefaultInputMethod(inputMethodInfo));
+
+ preferenceGroup.addPreference(preference);
+ }
+ }
+
+ private boolean isInputMethodAllowedByOrganization(Set<String> permittedList,
+ InputMethodInfo inputMethodInfo) {
+ // permittedList is null means that all input methods are allowed.
+ return (permittedList == null) || permittedList.contains(inputMethodInfo.getPackageName());
+ }
+
+ /**
+ * Check if given input method is the only enabled input method that can be a default system
+ * input method.
+ *
+ * @return {@code true} if input method is the only input method that can be a default system
+ * input method.
+ */
+ private boolean isOnlyEnabledDefaultInputMethod(InputMethodInfo inputMethodInfo) {
+ if (!inputMethodInfo.isDefault(getContext())) {
+ return false;
+ }
+
+ List<InputMethodInfo> inputMethodInfos = mInputMethodManager.getEnabledInputMethodList();
+
+ for (InputMethodInfo imi : inputMethodInfos) {
+ if (!imi.isDefault(getContext())) {
+ continue;
+ }
+
+ if (!imi.getId().equals(inputMethodInfo.getId())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Create a SwitchPreference to enable/disable an input method.
+ *
+ * @return {@code SwitchPreference} which allows a user to enable/disable an input method.
+ */
+ private SwitchPreference createSwitchPreference(InputMethodInfo inputMethodInfo) {
+ SwitchPreference switchPreference = new SwitchPreference(getContext());
+ switchPreference.setKey(String.valueOf(inputMethodInfo.getId()));
+ switchPreference.setIcon(InputMethodUtil.getPackageIcon(mPackageManager, inputMethodInfo));
+ switchPreference.setTitle(InputMethodUtil.getPackageLabel(mPackageManager,
+ inputMethodInfo));
+ switchPreference.setChecked(InputMethodUtil.isInputMethodEnabled(getContext()
+ .getContentResolver(), inputMethodInfo));
+ switchPreference.setSummary(InputMethodUtil.getSummaryString(getContext(),
+ mInputMethodManager, inputMethodInfo));
+
+ switchPreference.setOnPreferenceChangeListener((switchPref, newValue) -> {
+ boolean enable = (boolean) newValue;
+ if (enable) {
+ showSecurityWarnDialog(inputMethodInfo);
+ } else {
+ InputMethodUtil.disableInputMethod(getContext(), mInputMethodManager,
+ inputMethodInfo);
+ refreshUi();
+ }
+ return false;
+ });
+ return switchPreference;
+ }
+
+ private void showDirectBootWarnDialog(InputMethodInfo inputMethodInfo) {
+ ConfirmationDialogFragment dialog = new ConfirmationDialogFragment.Builder(getContext())
+ .setMessage(getContext().getString(R.string.direct_boot_unaware_dialog_message_car))
+ .setPositiveButton(android.R.string.ok, mDirectBootWarnConfirmListener)
+ .setNegativeButton(android.R.string.cancel, mRejectListener)
+ .addArgumentParcelable(KEY_INPUT_METHOD_INFO, inputMethodInfo)
+ .build();
+
+ getFragmentController().showDialog(dialog, DIRECT_BOOT_WARN_DIALOG_TAG);
+ }
+
+ private void showSecurityWarnDialog(InputMethodInfo inputMethodInfo) {
+ CharSequence label = inputMethodInfo.loadLabel(mPackageManager);
+
+ ConfirmationDialogFragment dialog = new ConfirmationDialogFragment.Builder(getContext())
+ .setTitle(android.R.string.dialog_alert_title)
+ .setMessage(getContext().getString(R.string.ime_security_warning, label))
+ .setPositiveButton(android.R.string.ok, mSecurityWarnDialogConfirmListener)
+ .setNegativeButton(android.R.string.cancel, mRejectListener)
+ .addArgumentParcelable(KEY_INPUT_METHOD_INFO, inputMethodInfo)
+ .build();
+
+ getFragmentController().showDialog(dialog, SECURITY_WARN_DIALOG_TAG);
}
}
diff --git a/tests/robotests/src/com/android/car/settings/inputmethod/EnabledKeyboardPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/inputmethod/EnabledKeyboardPreferenceControllerTest.java
index 57b4d9c..8cc7aad 100644
--- a/tests/robotests/src/com/android/car/settings/inputmethod/EnabledKeyboardPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/car/settings/inputmethod/EnabledKeyboardPreferenceControllerTest.java
@@ -57,6 +57,7 @@
@Config(shadows = {ShadowInputMethodManager.class, ShadowDevicePolicyManager.class})
public class EnabledKeyboardPreferenceControllerTest {
private static final String DUMMY_LABEL = "dummy label";
+ private static final String DUMMY_ID = "dummy id";
private static final String DUMMY_SETTINGS_ACTIVITY = "dummy settings activity";
private static final String DUMMY_PACKAGE_NAME = "dummy package name";
private static final String ALLOWED_PACKAGE_NAME = "allowed package name";
@@ -218,6 +219,7 @@
PackageManager packageManager, String packageName) {
InputMethodInfo mockInfo = mock(InputMethodInfo.class);
when(mockInfo.getPackageName()).thenReturn(packageName);
+ when(mockInfo.getId()).thenReturn(DUMMY_ID);
when(mockInfo.loadLabel(packageManager)).thenReturn(DUMMY_LABEL);
when(mockInfo.getServiceInfo()).thenReturn(new ServiceInfo());
when(mockInfo.getSettingsActivity()).thenReturn(DUMMY_SETTINGS_ACTIVITY);
diff --git a/tests/robotests/src/com/android/car/settings/inputmethod/InputMethodUtilTest.java b/tests/robotests/src/com/android/car/settings/inputmethod/InputMethodUtilTest.java
index 2e995ad..2067089 100644
--- a/tests/robotests/src/com/android/car/settings/inputmethod/InputMethodUtilTest.java
+++ b/tests/robotests/src/com/android/car/settings/inputmethod/InputMethodUtilTest.java
@@ -28,6 +28,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
+import android.provider.Settings;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
@@ -43,7 +44,11 @@
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
@RunWith(CarSettingsRobolectricTestRunner.class)
public class InputMethodUtilTest {
@@ -52,8 +57,19 @@
private static final String DUMMY_SETTINGS_ACTIVITY = "dummy settings activity";
private static final String SUBTYPES_STRING =
"English (United States), German (Belgium), and Occitan (France)";
-
+ private static final String DUMMY_ENABLED_INPUT_METHODS =
+ "com.google.android.googlequicksearchbox/com.google.android.voicesearch.ime"
+ + ".VoiceInputMethodService:com.google.android.apps.automotive.inputmethod/"
+ + ".InputMethodService";
+ private static final String DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT =
+ "com.google.android.apps.automotive.inputmethod/.InputMethodService";
+ private static final String DUMMY_ENABLED_INPUT_METHOD_ID =
+ "com.google.android.googlequicksearchbox/com.google.android.voicesearch.ime"
+ + ".VoiceInputMethodService";
+ private static final String DUMMY_DISABLED_INPUT_METHOD_ID = "disabled input method id";
private Context mContext;
+ private List<InputMethodInfo> mDummyEnabledInputMethodsListAllDefaultable;
+ private List<InputMethodInfo> mDummyEnabledInputMethodsListOneDefaultable;
@Mock
private PackageManager mPackageManager;
@@ -62,6 +78,197 @@
@Mock
private Drawable mIcon;
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS, DUMMY_ENABLED_INPUT_METHODS);
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD, DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+
+ mDummyEnabledInputMethodsListOneDefaultable = Arrays
+ .stream(DUMMY_ENABLED_INPUT_METHODS.split(String.valueOf(InputMethodUtil
+ .INPUT_METHOD_DELIMITER))).collect(Collectors.toList()).stream().map(
+ result -> {
+ InputMethodInfo info = createMockInputMethodInfo(
+ mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(result);
+ when(info.isDefault(mContext)).thenReturn(result.equals(
+ DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT));
+ return info;
+ }).collect(Collectors.toList());
+ mDummyEnabledInputMethodsListAllDefaultable = Arrays
+ .stream(DUMMY_ENABLED_INPUT_METHODS.split(String.valueOf(InputMethodUtil
+ .INPUT_METHOD_DELIMITER))).collect(Collectors.toList()).stream().map(
+ result -> {
+ InputMethodInfo info = createMockInputMethodInfo(
+ mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(result);
+ when(info.isDefault(mContext)).thenReturn(true);
+ return info;
+ }).collect(Collectors.toList());
+ }
+
+ @Test
+ public void getPackageIcon_hasApplicationIcon() throws NameNotFoundException {
+ InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
+ mInputMethodManager, DUMMY_PACKAGE_NAME);
+ when(mPackageManager.getApplicationIcon(eq(info.getPackageName()))).thenReturn(mIcon);
+ assertThat(InputMethodUtil.getPackageIcon(mPackageManager, info)).isEqualTo(mIcon);
+ }
+
+ @Test
+ public void getPackageIcon_noApplicationIcon() throws NameNotFoundException {
+ InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
+ mInputMethodManager, DUMMY_PACKAGE_NAME);
+ when(mPackageManager.getApplicationIcon(DUMMY_PACKAGE_NAME)).thenThrow(
+ new NameNotFoundException());
+ assertThat(InputMethodUtil.getPackageIcon(mPackageManager, info)).isEqualTo(
+ InputMethodUtil.NO_ICON);
+ }
+
+ @Test
+ public void getPackageLabel() {
+ InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
+ mInputMethodManager, DUMMY_PACKAGE_NAME);
+ assertThat(InputMethodUtil.getPackageLabel(mPackageManager, info)).isEqualTo(
+ DUMMY_LABEL);
+ }
+
+ @Test
+ public void getSummaryString() {
+ InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
+ mInputMethodManager, DUMMY_PACKAGE_NAME);
+ assertThat(InputMethodUtil.getSummaryString(mContext, mInputMethodManager, info)).isEqualTo(
+ SUBTYPES_STRING);
+ }
+
+ @Test
+ public void isInputMethodEnabled_isDisabled_returnsFalse() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_DISABLED_INPUT_METHOD_ID);
+
+ assertThat(InputMethodUtil.isInputMethodEnabled(mContext.getContentResolver(), info))
+ .isFalse();
+ }
+
+ @Test
+ public void isInputMethodEnabled_isEnabled_returnsTrue() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+
+ assertThat(InputMethodUtil.isInputMethodEnabled(mContext.getContentResolver(), info))
+ .isTrue();
+ }
+
+ @Test
+ public void enableInputMethod_alreadyEnabled_remainsUnchanged() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+
+ InputMethodUtil.enableInputMethod(mContext.getContentResolver(), info);
+
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS)).isEqualTo(DUMMY_ENABLED_INPUT_METHODS);
+ }
+
+ @Test
+ public void enableInputMethod_noEnabledInputMethods_addsIME() {
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS, "");
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+
+ InputMethodUtil.enableInputMethod(mContext.getContentResolver(), info);
+
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS)).isEqualTo(
+ DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+ }
+
+ @Test
+ public void enableInputMethod_someEnabledInputMethods_addsIME() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_DISABLED_INPUT_METHOD_ID);
+
+ InputMethodUtil.enableInputMethod(mContext.getContentResolver(), info);
+
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS)).isEqualTo(
+ DUMMY_ENABLED_INPUT_METHODS + ":"
+ + DUMMY_DISABLED_INPUT_METHOD_ID);
+ }
+
+ @Test
+ public void disableInputMethod_notEnabled_remainsUnchanged() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_DISABLED_INPUT_METHOD_ID);
+ when(mInputMethodManager.getEnabledInputMethodList())
+ .thenReturn(mDummyEnabledInputMethodsListAllDefaultable);
+
+ InputMethodUtil.disableInputMethod(mContext, mInputMethodManager, info);
+
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS)).isEqualTo(DUMMY_ENABLED_INPUT_METHODS);
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD)).isEqualTo(
+ DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+ }
+
+ @Test
+ public void disableInputMethod_notDefault_removesIMEWhileDefaultRemainsSame() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_ENABLED_INPUT_METHOD_ID);
+ when(mInputMethodManager.getEnabledInputMethodList())
+ .thenReturn(mDummyEnabledInputMethodsListAllDefaultable);
+
+ InputMethodUtil.disableInputMethod(mContext, mInputMethodManager, info);
+
+ assertThat(splitConcatenatedIdsIntoSet(Settings.Secure.getString(mContext
+ .getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS))).isEqualTo(
+ splitConcatenatedIdsIntoSet(DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT));
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD)).isEqualTo(
+ DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+ }
+
+ @Test
+ public void disableInputMethod_twoDefaultableIMEsEnabled_removesIMEAndChangesDefault() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+ when(mInputMethodManager.getEnabledInputMethodList())
+ .thenReturn(mDummyEnabledInputMethodsListAllDefaultable);
+
+ InputMethodUtil.disableInputMethod(mContext, mInputMethodManager, info);
+
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS)).isEqualTo(
+ DUMMY_ENABLED_INPUT_METHOD_ID);
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD)).isEqualTo(
+ DUMMY_ENABLED_INPUT_METHOD_ID);
+ }
+
+ @Test
+ public void disableInputMethod_isDefaultWithNoOtherDefaultableEnabled_remainsUnchanged() {
+ InputMethodInfo info = createMockInputMethodInfo(mPackageManager, DUMMY_PACKAGE_NAME);
+ when(info.getId()).thenReturn(DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+ when(mInputMethodManager.getEnabledInputMethodList())
+ .thenReturn(mDummyEnabledInputMethodsListOneDefaultable);
+
+ InputMethodUtil.disableInputMethod(mContext, mInputMethodManager, info);
+
+ assertThat(splitConcatenatedIdsIntoSet(Settings.Secure.getString(mContext
+ .getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS))).isEqualTo(
+ splitConcatenatedIdsIntoSet(DUMMY_ENABLED_INPUT_METHODS));
+ assertThat(Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD)).isEqualTo(
+ DUMMY_ENABLED_INPUT_METHOD_ID_DEFAULT);
+ }
+
private static InputMethodInfo createMockInputMethodInfoWithSubtypes(
PackageManager packageManager, InputMethodManager inputMethodManager,
String packageName) {
@@ -69,7 +276,6 @@
List<InputMethodSubtype> subtypes = createSubtypes();
when(inputMethodManager.getEnabledInputMethodSubtypeList(
eq(mockInfo), anyBoolean())).thenReturn(subtypes);
-
return mockInfo;
}
@@ -96,43 +302,18 @@
.setIsAuxiliary(false).setIsAsciiCapable(true).build();
}
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- }
+ private Set<String> splitConcatenatedIdsIntoSet(String ids) {
+ Set<String> result = new HashSet<>();
- @Test
- public void testGetPackageIcon_hasApplicationIcon() throws NameNotFoundException {
- InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
- mInputMethodManager, DUMMY_PACKAGE_NAME);
- when(mPackageManager.getApplicationIcon(eq(info.getPackageName()))).thenReturn(mIcon);
- assertThat(InputMethodUtil.getPackageIcon(mPackageManager, info)).isEqualTo(mIcon);
- }
+ if (ids == null || ids.isEmpty()) {
+ return result;
+ }
- @Test
- public void testGetPackageIcon_noApplicationIcon() throws NameNotFoundException {
- InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
- mInputMethodManager, DUMMY_PACKAGE_NAME);
- when(mPackageManager.getApplicationIcon(DUMMY_PACKAGE_NAME)).thenThrow(
- new NameNotFoundException());
- assertThat(InputMethodUtil.getPackageIcon(mPackageManager, info)).isEqualTo(
- InputMethodUtil.NO_ICON);
- }
+ InputMethodUtil.sInputMethodSplitter.setString(ids);
+ while (InputMethodUtil.sInputMethodSplitter.hasNext()) {
+ result.add(InputMethodUtil.sInputMethodSplitter.next());
+ }
- @Test
- public void testGetPackageLabel() {
- InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
- mInputMethodManager, DUMMY_PACKAGE_NAME);
- assertThat(InputMethodUtil.getPackageLabel(mPackageManager, info)).isEqualTo(
- DUMMY_LABEL);
- }
-
- @Test
- public void testGetSummaryString() {
- InputMethodInfo info = createMockInputMethodInfoWithSubtypes(mPackageManager,
- mInputMethodManager, DUMMY_PACKAGE_NAME);
- assertThat(InputMethodUtil.getSummaryString(mContext, mInputMethodManager, info)).isEqualTo(
- SUBTYPES_STRING);
+ return result;
}
}
diff --git a/tests/robotests/src/com/android/car/settings/inputmethod/KeyboardManagementPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/inputmethod/KeyboardManagementPreferenceControllerTest.java
new file mode 100644
index 0000000..0bc50ef
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/inputmethod/KeyboardManagementPreferenceControllerTest.java
@@ -0,0 +1,1066 @@
+/*
+ * Copyright (C) 2019 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.car.settings.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.SwitchPreference;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.common.ConfirmationDialogFragment;
+import com.android.car.settings.common.LogicalPreferenceGroup;
+import com.android.car.settings.common.PreferenceControllerTestHelper;
+import com.android.car.settings.testutils.ShadowDevicePolicyManager;
+import com.android.car.settings.testutils.ShadowInputMethodManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowInputMethodManager.class, ShadowDevicePolicyManager.class})
+public class KeyboardManagementPreferenceControllerTest {
+ private static final String DUMMY_LABEL = "dummy label";
+ private static final String DUMMY_SETTINGS_ACTIVITY = "dummy settings activity";
+ private static final String DUMMY_PACKAGE_NAME = "dummy package name";
+ private static final String DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE =
+ "dummy id defaultable direct boot aware";
+ private static final String DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE =
+ "dummy id defaultable not direct boot aware";
+ private static final String DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE =
+ "dummy id not defaultable direct boot aware";
+ private static final String DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE =
+ "dummy id not defaultable not direct boot aware";
+ private static final String DISALLOWED_PACKAGE_NAME = "disallowed package name";
+ private static final String ALLOWED_PACKAGE_NAME = "allowed package name";
+ private List<String> mPermittedList;
+ private PreferenceControllerTestHelper<KeyboardManagementPreferenceController>
+ mControllerHelper;
+ private PreferenceGroup mPreferenceGroup;
+ private Context mContext;
+ private InputMethodManager mInputMethodManager;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+
+ mPreferenceGroup = new LogicalPreferenceGroup(mContext);
+ mControllerHelper = new PreferenceControllerTestHelper<>(mContext,
+ KeyboardManagementPreferenceController.class, mPreferenceGroup);
+ mInputMethodManager = (InputMethodManager) mContext.getSystemService(Context
+ .INPUT_METHOD_SERVICE);
+
+ mPermittedList = new ArrayList<>();
+ mPermittedList.add(DUMMY_PACKAGE_NAME);
+ mPermittedList.add(ALLOWED_PACKAGE_NAME);
+ mControllerHelper.markState(Lifecycle.State.CREATED);
+ }
+
+ @Test
+ public void refreshUi_permitAllInputMethods_preferenceCountIs4() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(4);
+ }
+
+ @Test
+ public void refreshUi_multiplteAllowedImeByOrganization_allPreferencesVisible() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(
+ mPermittedList);
+ List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) {
+ assertThat(mPreferenceGroup.getPreference(i).isVisible()).isTrue();
+ }
+ }
+
+ @Test
+ public void refreshUi_multipleEnabledInputMethods_allPreferencesEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(
+ mPermittedList);
+ List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) {
+ assertThat(mPreferenceGroup.getPreference(i).isEnabled()).isTrue();
+ }
+ }
+
+ @Test
+ public void refreshUi_multipleEnabledInputMethods_allPreferencesChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(
+ mPermittedList);
+ List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) {
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(i)).isChecked())
+ .isTrue();
+ }
+ }
+
+ @Test
+ public void refreshUi_disallowedByOrganization_noPreferencesShown() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(
+ mPermittedList);
+ List<InputMethodInfo> infos = createInputMethodInfoList(DISALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void refreshUi_verifyPreferenceIcon() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ Preference preference = mPreferenceGroup.getPreference(0);
+ assertThat(preference.getIcon()).isEqualTo(
+ InputMethodUtil.getPackageIcon(mContext.getPackageManager(), infos.get(0)));
+ }
+
+ @Test
+ public void refreshUi_verifyPreferenceTitle() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ Preference preference = mPreferenceGroup.getPreference(0);
+ assertThat(preference.getTitle()).isEqualTo(
+ InputMethodUtil.getPackageLabel(mContext.getPackageManager(), infos.get(0)));
+ }
+
+ @Test
+ public void refreshUi_verifyPreferenceSummary() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ getShadowInputMethodManager(mContext).setInputMethodList(infos);
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(infos);
+
+ mControllerHelper.getController().refreshUi();
+
+ InputMethodManager inputMethodManager =
+ (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ Preference preference = mPreferenceGroup.getPreference(0);
+ assertThat(preference.getSummary()).isEqualTo(
+ InputMethodUtil.getSummaryString(mContext, inputMethodManager, infos.get(0)));
+ }
+
+ @Test
+ public void refreshUi_oneInputMethod_noneEnabled_oneInputMethodPreferenceInView() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void refreshUi_oneInputMethod_noneEnabled_preferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue();
+ }
+
+ @Test
+ public void refreshUi_oneInputMethod_noneEnabled_preferenceNotChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked())
+ .isFalse();
+ }
+
+ @Test
+ public void performClick_toggleTrue_securityDialogShown() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ any(ConfirmationDialogFragment.class),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ }
+
+ @Test
+ public void performClick_toggleTrue_showSecurityDialog_positive_noOtherPreferenceAdded() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+ assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo(
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE);
+ }
+
+ @Test
+ public void performClick_toggleTrue_showSecurityDialog_positive_preferenceChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked())
+ .isTrue();
+ }
+
+ @Test
+ public void performClick_toggleTrue_showSecurityDialog_positive_preferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleTrue_showSecurityDialog_positive_inputMethodEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(mInputMethodManager.getEnabledInputMethodList().get(0).getId())
+ .isEqualTo(DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE);
+ }
+
+ @Test
+ public void performClick_toggleTrue_showSecurityDialog_negative_noOtherPreferenceAdded() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+ assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo(
+ DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE);
+ }
+
+ @Test
+ public void performClick_toggleTrue_showSecurityDialog_negative_preferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+ assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleTrue_showSecurityDialog_negative_inputMethodDisabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked())
+ .isFalse();
+ }
+
+ @Test
+ public void performClick_toggleTrue_directBootWarningShown() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ any(ConfirmationDialogFragment.class),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_positive_noOtherPreferenceAdded() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+ assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo(
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_positive_preferenceChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked())
+ .isTrue();
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_positive_preferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_positive_inputMethodEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ assertThat(mInputMethodManager.getEnabledInputMethodList().get(0).getId())
+ .isEqualTo(DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_negative_noOtherPreferenceAdded() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+ assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo(
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_negative_preferenceNotChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked())
+ .isFalse();
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_negative_preferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+ assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleTrue_showDirectBootDialog_negative_inputMethodDisabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(new ArrayList<>());
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(
+ securityDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(bootDialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG));
+ dialogFragment = bootDialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+ assertThat(mInputMethodManager.getEnabledInputMethodList().size())
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void performClick_toggleFalse_noOtherPreferenceAdded() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+ assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo(
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE);
+ }
+
+ @Test
+ public void performClick_toggleFalse_preferenceNotChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked())
+ .isFalse();
+ }
+
+ @Test
+ public void performClick_toggleFalse_preferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ assertThat((mPreferenceGroup.getPreference(0)).isEnabled())
+ .isTrue();
+ }
+
+ @Test
+ public void performClick_toggleFalse_inputMethodDisabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+
+ mControllerHelper.getController().refreshUi();
+
+ mPreferenceGroup.getPreference(0).performClick();
+
+ assertThat(mInputMethodManager.getEnabledInputMethodList().size())
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void performClick_toggleFalse_twoDefaultable_notClickDefaultablePreferenceDisabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup, DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE)
+ .performClick();
+
+ assertThat(getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE).isEnabled()).isFalse();
+ }
+
+ @Test
+ public void performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick();
+
+ assertThat(getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).isEnabled()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick();
+
+ assertThat(getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE).isEnabled()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceNotChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick();
+
+ assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE)).isChecked()).isFalse();
+ }
+
+ @Test
+ public void performClick_toggleFalse_twoDefaultable_notClickedDefaultablePreferenceChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick();
+
+ assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)).isChecked()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick();
+
+ assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)).isChecked()).isTrue();
+ }
+
+ @Test
+ public void performClick_toggleTrue_twoDefaultable_allPreferencesEnabled() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) {
+ assertThat(mPreferenceGroup.getPreference(i).isEnabled()).isTrue();
+ }
+ }
+
+ @Test
+ public void performClick_toggleTrue_twoDefaultable_allPreferencesChecked() {
+ getShadowDevicePolicyManager(mContext).setPermittedInputMethodsForCurrentUser(null);
+ getShadowInputMethodManager(mContext).setInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)
+ );
+ getShadowInputMethodManager(mContext).setEnabledInputMethodList(createInputMethodInfoList(
+ ALLOWED_PACKAGE_NAME, DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE,
+ DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE));
+
+ mControllerHelper.getController().refreshUi();
+
+ getPreferenceFromGroupByKey(mPreferenceGroup,
+ DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick();
+
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mControllerHelper.getMockFragmentController()).showDialog(dialogCaptor.capture(),
+ eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG));
+ ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
+
+ dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+ for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) {
+ assertThat(((SwitchPreference) mPreferenceGroup.getPreference(i)).isChecked())
+ .isTrue();
+ }
+ }
+
+ private static InputMethodInfo createMockInputMethodInfo(
+ Context context, PackageManager packageManager,
+ ShadowInputMethodManager inputMethodManager, String packageName, String id,
+ boolean isDefaultable, boolean directBootAware) {
+ ServiceInfo mockServiceInfo = mock(ServiceInfo.class);
+ mockServiceInfo.directBootAware = directBootAware;
+
+ InputMethodInfo mockInfo = mock(InputMethodInfo.class);
+ when(mockInfo.getPackageName()).thenReturn(packageName);
+ when(mockInfo.loadLabel(packageManager)).thenReturn(DUMMY_LABEL);
+ when(mockInfo.getServiceInfo()).thenReturn(mockServiceInfo);
+ when(mockInfo.getSettingsActivity()).thenReturn(DUMMY_SETTINGS_ACTIVITY);
+ when(mockInfo.getId()).thenReturn(id);
+ when(mockInfo.isDefault(context)).thenReturn(isDefaultable);
+ List<InputMethodSubtype> subtypes = createSubtypes();
+ inputMethodManager.setEnabledInputMethodSubtypeList(subtypes);
+ return mockInfo;
+ }
+
+ private static Preference getPreferenceFromGroupByKey(PreferenceGroup prefGroup, String key) {
+ for (int i = 0; i < prefGroup.getPreferenceCount(); i++) {
+ Preference pref = prefGroup.getPreference(i);
+ if (pref.getKey().equals(key)) {
+ return pref;
+ }
+ }
+ return null;
+ }
+
+ private static List<InputMethodSubtype> createSubtypes() {
+ List<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(createSubtype(1, "en_US"));
+ subtypes.add(createSubtype(2, "de_BE"));
+ subtypes.add(createSubtype(3, "oc-FR"));
+ return subtypes;
+ }
+
+ private static InputMethodSubtype createSubtype(int id, String locale) {
+ return new InputMethodSubtype.InputMethodSubtypeBuilder().setSubtypeId(id)
+ .setSubtypeLocale(locale).setIsAuxiliary(false).setIsAsciiCapable(true).build();
+ }
+
+ private static ShadowInputMethodManager getShadowInputMethodManager(Context context) {
+ return Shadow.extract(context.getSystemService(Context.INPUT_METHOD_SERVICE));
+ }
+
+ private static ShadowDevicePolicyManager getShadowDevicePolicyManager(Context context) {
+ return Shadow.extract(context.getSystemService(Context.DEVICE_POLICY_SERVICE));
+ }
+
+ private List<InputMethodInfo> createInputMethodInfoList(String packageName, String... ids) {
+ List<InputMethodInfo> infos = new ArrayList<>();
+ PackageManager packageManager = mContext.getPackageManager();
+ List<String> idsList = Arrays.asList(ids);
+ idsList.forEach(id -> {
+ boolean defaultable;
+ boolean directBootAware;
+ switch (id) {
+ case DUMMY_ID_DEFAULTABLE_DIRECT_BOOT_AWARE:
+ defaultable = true;
+ directBootAware = true;
+ break;
+ case DUMMY_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE:
+ defaultable = true;
+ directBootAware = false;
+ break;
+ case DUMMY_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE:
+ defaultable = false;
+ directBootAware = true;
+ break;
+ default: //case DUMMY_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE:
+ defaultable = false;
+ directBootAware = false;
+ break;
+ }
+ infos.add(createMockInputMethodInfo(mContext, packageManager,
+ getShadowInputMethodManager(mContext), packageName, id, defaultable,
+ directBootAware));
+ });
+ return infos;
+ }
+}
diff --git a/tests/robotests/src/com/android/car/settings/testutils/ShadowInputMethodManager.java b/tests/robotests/src/com/android/car/settings/testutils/ShadowInputMethodManager.java
index fc2e6e4..f6ccbc0 100644
--- a/tests/robotests/src/com/android/car/settings/testutils/ShadowInputMethodManager.java
+++ b/tests/robotests/src/com/android/car/settings/testutils/ShadowInputMethodManager.java
@@ -16,29 +16,56 @@
package com.android.car.settings.testutils;
+import android.provider.Settings;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import androidx.annotation.Nullable;
+import com.android.car.settings.inputmethod.InputMethodUtil;
+
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
@Implements(value = InputMethodManager.class)
public class ShadowInputMethodManager extends org.robolectric.shadows.ShadowInputMethodManager {
- private List<InputMethodInfo> mEnabledInputMethodList;
+ private List<InputMethodInfo> mInputMethodList;
+ private Map<String, InputMethodInfo> mInputMethodMap;
private List<InputMethodSubtype> mInputMethodSubtypes;
- public void setEnabledInputMethodList(@Nullable List<InputMethodInfo> list) {
- mEnabledInputMethodList = list;
+ public void setEnabledInputMethodList(@Nullable List<InputMethodInfo> inputMethodInfos) {
+ String concatenatedInputMethodIds = createInputMethodIdString(inputMethodInfos.stream().map(
+ imi -> imi.getId()).collect(Collectors.toList()).toArray(
+ new String[inputMethodInfos.size()]));
+ Settings.Secure.putString(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS, concatenatedInputMethodIds);
+ addInputMethodInfosToMap(inputMethodInfos);
}
@Implementation
- public List<InputMethodInfo> getEnabledInputMethodList() {
- return mEnabledInputMethodList;
+ protected List<InputMethodInfo> getEnabledInputMethodList() {
+ List<InputMethodInfo> enabledInputMethodList = new ArrayList<>();
+
+ String inputMethodIdString = Settings.Secure.getString(
+ RuntimeEnvironment.application.getContentResolver(),
+ Settings.Secure.ENABLED_INPUT_METHODS);
+ if (inputMethodIdString == null || inputMethodIdString.isEmpty()) {
+ return enabledInputMethodList;
+ }
+
+ InputMethodUtil.sInputMethodSplitter.setString(inputMethodIdString);
+ while (InputMethodUtil.sInputMethodSplitter.hasNext()) {
+ enabledInputMethodList.add(mInputMethodMap.get(InputMethodUtil.sInputMethodSplitter
+ .next()));
+ }
+ return enabledInputMethodList;
}
public void setEnabledInputMethodSubtypeList(List<InputMethodSubtype> list) {
@@ -46,8 +73,51 @@
}
@Implementation
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
+ protected List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
boolean allowsImplicitlySelectedSubtypes) {
return mInputMethodSubtypes;
}
+
+ public void setInputMethodList(List<InputMethodInfo> inputMethodInfos) {
+ mInputMethodList = inputMethodInfos;
+ if (inputMethodInfos == null) {
+ return;
+ }
+
+ addInputMethodInfosToMap(inputMethodInfos);
+ }
+
+ @Implementation
+ protected List<InputMethodInfo> getInputMethodList() {
+ return mInputMethodList;
+ }
+
+ private static String createInputMethodIdString(String... ids) {
+ int size = ids == null ? 0 : ids.length;
+
+ if (size == 1) {
+ return ids[0];
+ }
+
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < size; i++) {
+ builder.append(ids[i]);
+ if (i != size - 1) {
+ builder.append(InputMethodUtil.INPUT_METHOD_DELIMITER);
+ }
+ }
+ return builder.toString();
+ }
+
+ private void addInputMethodInfosToMap(List<InputMethodInfo> inputMethodInfos) {
+ if (mInputMethodMap == null || mInputMethodMap.size() == 0) {
+ mInputMethodMap = inputMethodInfos.stream().collect(Collectors.toMap(
+ InputMethodInfo::getId, imi -> imi));
+ return;
+ }
+
+ inputMethodInfos.forEach(imi -> {
+ mInputMethodMap.put(imi.getId(), imi);
+ });
+ }
}