1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.settings.inputmethod; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyBoolean; 23 import static org.mockito.ArgumentMatchers.eq; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.app.admin.DevicePolicyManager; 30 import android.car.drivingstate.CarUxRestrictions; 31 import android.content.Context; 32 import android.content.DialogInterface; 33 import android.content.pm.PackageManager; 34 import android.content.pm.ServiceInfo; 35 import android.provider.Settings; 36 import android.view.inputmethod.InputMethodInfo; 37 import android.view.inputmethod.InputMethodManager; 38 import android.view.inputmethod.InputMethodSubtype; 39 40 import androidx.lifecycle.LifecycleOwner; 41 import androidx.preference.Preference; 42 import androidx.preference.PreferenceGroup; 43 import androidx.preference.PreferenceManager; 44 import androidx.preference.PreferenceScreen; 45 import androidx.preference.SwitchPreference; 46 import androidx.test.annotation.UiThreadTest; 47 import androidx.test.core.app.ApplicationProvider; 48 import androidx.test.ext.junit.runners.AndroidJUnit4; 49 50 import com.android.car.settings.common.ConfirmationDialogFragment; 51 import com.android.car.settings.common.FragmentController; 52 import com.android.car.settings.common.LogicalPreferenceGroup; 53 import com.android.car.settings.common.PreferenceControllerTestUtil; 54 import com.android.car.settings.testutils.TestLifecycleOwner; 55 56 import org.junit.After; 57 import org.junit.Before; 58 import org.junit.Test; 59 import org.junit.runner.RunWith; 60 import org.mockito.ArgumentCaptor; 61 import org.mockito.Mock; 62 import org.mockito.MockitoAnnotations; 63 import org.mockito.stubbing.Answer; 64 65 import java.util.ArrayList; 66 import java.util.Arrays; 67 import java.util.HashMap; 68 import java.util.List; 69 import java.util.Map; 70 import java.util.stream.Collectors; 71 72 @RunWith(AndroidJUnit4.class) 73 public class KeyboardManagementPreferenceControllerTest { 74 private static final String PLACEHOLDER_LABEL = "placeholder label"; 75 private static final String PLACEHOLDER_SETTINGS_ACTIVITY = "placeholder settings activity"; 76 private static final String PLACEHOLDER_PACKAGE_NAME = "placeholder package name"; 77 private static final String PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE = 78 "placeholder id defaultable direct boot aware"; 79 private static final String PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE = 80 "placeholder id defaultable not direct boot aware"; 81 private static final String PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE = 82 "placeholder id not defaultable direct boot aware"; 83 private static final String PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE = 84 "placeholder id not defaultable not direct boot aware"; 85 private static final String DISALLOWED_PACKAGE_NAME = "disallowed package name"; 86 private static final String ALLOWED_PACKAGE_NAME = "allowed package name"; 87 88 private Context mContext = spy(ApplicationProvider.getApplicationContext()); 89 private LifecycleOwner mLifecycleOwner; 90 private KeyboardManagementPreferenceController mPreferenceController; 91 private LogicalPreferenceGroup mPreferenceGroup; 92 private CarUxRestrictions mCarUxRestrictions; 93 private List<String> mPermittedList; 94 private Map<String, InputMethodInfo> mInputMethodMap; 95 private String mInitialInputMethods; 96 97 @Mock 98 private FragmentController mMockFragmentController; 99 @Mock 100 private DevicePolicyManager mDevicePolicyManager; 101 @Mock 102 private InputMethodManager mInputMethodManager; 103 104 @Before 105 @UiThreadTest setUp()106 public void setUp() { 107 MockitoAnnotations.initMocks(this); 108 mLifecycleOwner = new TestLifecycleOwner(); 109 110 mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true, 111 CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build(); 112 mInputMethodMap = new HashMap<>(); 113 mPermittedList = new ArrayList<>(); 114 mPermittedList.add(PLACEHOLDER_PACKAGE_NAME); 115 mPermittedList.add(ALLOWED_PACKAGE_NAME); 116 mInitialInputMethods = Settings.Secure.getString(mContext.getContentResolver(), 117 Settings.Secure.ENABLED_INPUT_METHODS); 118 119 when(mContext.getSystemService(DevicePolicyManager.class)).thenReturn(mDevicePolicyManager); 120 when(mContext.getSystemService(InputMethodManager.class)).thenReturn(mInputMethodManager); 121 when(mInputMethodManager.getInputMethodList()).thenReturn(new ArrayList<>()); 122 123 mPreferenceController = new KeyboardManagementPreferenceController(mContext, 124 /* preferenceKey= */ "key", mMockFragmentController, 125 mCarUxRestrictions); 126 PreferenceManager preferenceManager = new PreferenceManager(mContext); 127 PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); 128 mPreferenceGroup = new LogicalPreferenceGroup(mContext); 129 screen.addPreference(mPreferenceGroup); 130 PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup); 131 mPreferenceController.onCreate(mLifecycleOwner); 132 } 133 134 @After tearDown()135 public void tearDown() { 136 Settings.Secure.putString(mContext.getContentResolver(), 137 Settings.Secure.ENABLED_INPUT_METHODS, mInitialInputMethods); 138 } 139 140 @Test 141 @UiThreadTest refreshUi_permitAllInputMethods_preferenceCountIs4()142 public void refreshUi_permitAllInputMethods_preferenceCountIs4() { 143 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 144 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 145 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 146 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 147 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 148 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 149 setInputMethodList(infos); 150 setEnabledInputMethodList(infos); 151 152 mPreferenceController.refreshUi(); 153 154 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(4); 155 } 156 157 @Test 158 @UiThreadTest refreshUi_multiplteAllowedImeByOrganization_allPreferencesVisible()159 public void refreshUi_multiplteAllowedImeByOrganization_allPreferencesVisible() { 160 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 161 mPermittedList); 162 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 163 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 164 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 165 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 166 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 167 setInputMethodList(infos); 168 setEnabledInputMethodList(infos); 169 170 mPreferenceController.refreshUi(); 171 172 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 173 assertThat(mPreferenceGroup.getPreference(i).isVisible()).isTrue(); 174 } 175 } 176 177 @Test 178 @UiThreadTest refreshUi_multipleEnabledInputMethods_allPreferencesEnabled()179 public void refreshUi_multipleEnabledInputMethods_allPreferencesEnabled() { 180 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 181 mPermittedList); 182 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 183 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 184 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 185 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 186 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 187 setInputMethodList(infos); 188 setEnabledInputMethodList(infos); 189 190 mPreferenceController.refreshUi(); 191 192 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 193 assertThat(mPreferenceGroup.getPreference(i).isEnabled()).isTrue(); 194 } 195 } 196 197 @Test 198 @UiThreadTest refreshUi_multipleEnabledInputMethods_allPreferencesChecked()199 public void refreshUi_multipleEnabledInputMethods_allPreferencesChecked() { 200 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 201 mPermittedList); 202 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 203 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 204 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 205 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 206 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 207 setInputMethodList(infos); 208 setEnabledInputMethodList(infos); 209 210 mPreferenceController.refreshUi(); 211 212 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 213 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(i)).isChecked()) 214 .isTrue(); 215 } 216 } 217 218 @Test 219 @UiThreadTest refreshUi_disallowedByOrganization_preferenceShownDisabled()220 public void refreshUi_disallowedByOrganization_preferenceShownDisabled() { 221 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 222 mPermittedList); 223 List<InputMethodInfo> infos = createInputMethodInfoList(DISALLOWED_PACKAGE_NAME, 224 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 225 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 226 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 227 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 228 setInputMethodList(infos); 229 setEnabledInputMethodList(infos); 230 231 mPreferenceController.refreshUi(); 232 233 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(infos.size()); 234 235 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 236 SwitchPreference pref = (SwitchPreference) mPreferenceGroup.getPreference(i); 237 assertThat(pref.isVisible()).isTrue(); 238 assertThat(pref.isEnabled()).isTrue(); 239 } 240 } 241 242 @Test 243 @UiThreadTest refreshUi_skipVoiceTyping()244 public void refreshUi_skipVoiceTyping() { 245 // TODO: b/236143731 Add Sufficient Testing to Prevent "Google Voice Typing" Regression 246 for (String gvtPackageName : InputMethodUtil.GVT_PACKAGE_NAMES) { 247 List<InputMethodInfo> infos = 248 createInputMethodInfoList(gvtPackageName); 249 setInputMethodList(infos); 250 251 mPreferenceController.refreshUi(); 252 253 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0); 254 } 255 } 256 257 @Test 258 @UiThreadTest refreshUi_verifyPreferenceIcon()259 public void refreshUi_verifyPreferenceIcon() { 260 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 261 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 262 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 263 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 264 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 265 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 266 setInputMethodList(infos); 267 setEnabledInputMethodList(infos); 268 269 mPreferenceController.refreshUi(); 270 271 Preference preference = mPreferenceGroup.getPreference(0); 272 assertThat(preference.getIcon()).isEqualTo( 273 InputMethodUtil.getPackageIcon(mContext.getPackageManager(), infos.get(0))); 274 } 275 276 @Test 277 @UiThreadTest refreshUi_verifyPreferenceTitle()278 public void refreshUi_verifyPreferenceTitle() { 279 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 280 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 281 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 282 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 283 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 284 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 285 setInputMethodList(infos); 286 setEnabledInputMethodList(infos); 287 288 mPreferenceController.refreshUi(); 289 290 Preference preference = mPreferenceGroup.getPreference(0); 291 assertThat(preference.getTitle()).isEqualTo( 292 InputMethodUtil.getPackageLabel(mContext.getPackageManager(), infos.get(0))); 293 } 294 295 @Test 296 @UiThreadTest refreshUi_verifyPreferenceSummary()297 public void refreshUi_verifyPreferenceSummary() { 298 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 299 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 300 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 301 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 302 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 303 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 304 setInputMethodList(infos); 305 setEnabledInputMethodList(infos); 306 307 mPreferenceController.refreshUi(); 308 309 Preference preference = mPreferenceGroup.getPreference(0); 310 assertThat(preference.getSummary()).isEqualTo( 311 InputMethodUtil.getSummaryString(mContext, mInputMethodManager, infos.get(0))); 312 } 313 314 @Test 315 @UiThreadTest refreshUi_oneInputMethod_noneEnabled_oneInputMethodPreferenceInView()316 public void refreshUi_oneInputMethod_noneEnabled_oneInputMethodPreferenceInView() { 317 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 318 List<InputMethodInfo> infos = createInputMethodInfoList( 319 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 320 setInputMethodList(infos); 321 setEnabledInputMethodList(new ArrayList<>()); 322 323 mPreferenceController.refreshUi(); 324 325 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 326 } 327 328 @Test 329 @UiThreadTest refreshUi_oneInputMethod_noneEnabled_preferenceEnabled()330 public void refreshUi_oneInputMethod_noneEnabled_preferenceEnabled() { 331 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 332 List<InputMethodInfo> infos = createInputMethodInfoList( 333 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 334 setInputMethodList(infos); 335 setEnabledInputMethodList(new ArrayList<>()); 336 337 mPreferenceController.refreshUi(); 338 339 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 340 } 341 342 @Test 343 @UiThreadTest refreshUi_oneInputMethod_noneEnabled_preferenceNotChecked()344 public void refreshUi_oneInputMethod_noneEnabled_preferenceNotChecked() { 345 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 346 List<InputMethodInfo> infos = createInputMethodInfoList( 347 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 348 setInputMethodList(infos); 349 setEnabledInputMethodList(new ArrayList<>()); 350 351 mPreferenceController.refreshUi(); 352 353 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 354 .isFalse(); 355 } 356 357 @Test 358 @UiThreadTest refreshUi_oneInputMethod_defaultable_notChecked_preferenceEnabled()359 public void refreshUi_oneInputMethod_defaultable_notChecked_preferenceEnabled() { 360 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 361 List<InputMethodInfo> infos = createInputMethodInfoList( 362 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 363 setInputMethodList(infos); 364 setEnabledInputMethodList(new ArrayList<>()); 365 366 mPreferenceController.refreshUi(); 367 368 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 369 } 370 371 @Test 372 @UiThreadTest performClick_toggleTrue_securityDialogShown()373 public void performClick_toggleTrue_securityDialogShown() { 374 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 375 List<InputMethodInfo> infos = createInputMethodInfoList( 376 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 377 setInputMethodList(infos); 378 setEnabledInputMethodList(new ArrayList<>()); 379 380 mPreferenceController.refreshUi(); 381 382 mPreferenceGroup.getPreference(0).performClick(); 383 384 verify(mMockFragmentController).showDialog( 385 any(ConfirmationDialogFragment.class), 386 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 387 } 388 389 @Test 390 @UiThreadTest performClick_toggleTrue_showSecurityDialog_positive_noOtherPreferenceAdded()391 public void performClick_toggleTrue_showSecurityDialog_positive_noOtherPreferenceAdded() { 392 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 393 List<InputMethodInfo> infos = createInputMethodInfoList( 394 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 395 setInputMethodList(infos); 396 setEnabledInputMethodList(new ArrayList<>()); 397 398 mPreferenceController.refreshUi(); 399 400 mPreferenceGroup.getPreference(0).performClick(); 401 402 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 403 ConfirmationDialogFragment.class); 404 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 405 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 406 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 407 408 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 409 410 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 411 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 412 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 413 } 414 415 @Test 416 @UiThreadTest performClick_toggleTrue_showSecurityDialog_positive_preferenceChecked()417 public void performClick_toggleTrue_showSecurityDialog_positive_preferenceChecked() { 418 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 419 List<InputMethodInfo> infos = createInputMethodInfoList( 420 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 421 setInputMethodList(infos); 422 setEnabledInputMethodList(new ArrayList<>()); 423 424 mPreferenceController.refreshUi(); 425 426 mPreferenceGroup.getPreference(0).performClick(); 427 428 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 429 ConfirmationDialogFragment.class); 430 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 431 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 432 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 433 434 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 435 436 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 437 .isTrue(); 438 } 439 440 @Test 441 @UiThreadTest performClick_toggleTrue_showSecurityDialog_positive_preferenceEnabled()442 public void performClick_toggleTrue_showSecurityDialog_positive_preferenceEnabled() { 443 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 444 List<InputMethodInfo> infos = createInputMethodInfoList( 445 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 446 setInputMethodList(infos); 447 setEnabledInputMethodList(new ArrayList<>()); 448 449 mPreferenceController.refreshUi(); 450 451 mPreferenceGroup.getPreference(0).performClick(); 452 453 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 454 ConfirmationDialogFragment.class); 455 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 456 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 457 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 458 459 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 460 461 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 462 } 463 464 @Test 465 @UiThreadTest performClick_toggleTrue_showSecurityDialog_positive_inputMethodEnabled()466 public void performClick_toggleTrue_showSecurityDialog_positive_inputMethodEnabled() { 467 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 468 List<InputMethodInfo> infos = createInputMethodInfoList( 469 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 470 setInputMethodList(infos); 471 setEnabledInputMethodList(new ArrayList<>()); 472 473 mPreferenceController.refreshUi(); 474 475 mPreferenceGroup.getPreference(0).performClick(); 476 477 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 478 ConfirmationDialogFragment.class); 479 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 480 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 481 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 482 483 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 484 485 assertThat(getEnabledInputMethodList().get(0).getId()) 486 .isEqualTo(PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 487 } 488 489 @Test 490 @UiThreadTest performClick_toggleTrue_showSecurityDialog_negative_noOtherPreferenceAdded()491 public void performClick_toggleTrue_showSecurityDialog_negative_noOtherPreferenceAdded() { 492 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 493 List<InputMethodInfo> infos = createInputMethodInfoList( 494 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 495 setInputMethodList(infos); 496 setEnabledInputMethodList(new ArrayList<>()); 497 498 mPreferenceController.refreshUi(); 499 500 mPreferenceGroup.getPreference(0).performClick(); 501 502 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 503 ConfirmationDialogFragment.class); 504 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 505 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 506 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 507 508 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 509 510 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 511 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 512 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 513 } 514 515 @Test 516 @UiThreadTest performClick_toggleTrue_showSecurityDialog_negative_preferenceEnabled()517 public void performClick_toggleTrue_showSecurityDialog_negative_preferenceEnabled() { 518 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 519 List<InputMethodInfo> infos = createInputMethodInfoList( 520 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 521 setInputMethodList(infos); 522 setEnabledInputMethodList(new ArrayList<>()); 523 524 mPreferenceController.refreshUi(); 525 526 mPreferenceGroup.getPreference(0).performClick(); 527 528 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 529 ConfirmationDialogFragment.class); 530 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 531 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 532 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 533 534 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 535 536 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 537 } 538 539 @Test 540 @UiThreadTest performClick_toggleTrue_showSecurityDialog_negative_inputMethodDisabled()541 public void performClick_toggleTrue_showSecurityDialog_negative_inputMethodDisabled() { 542 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 543 List<InputMethodInfo> infos = createInputMethodInfoList( 544 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 545 setInputMethodList(infos); 546 setEnabledInputMethodList(new ArrayList<>()); 547 548 mPreferenceController.refreshUi(); 549 550 mPreferenceGroup.getPreference(0).performClick(); 551 552 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 553 ConfirmationDialogFragment.class); 554 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 555 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 556 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 557 558 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 559 560 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 561 .isFalse(); 562 } 563 564 @Test 565 @UiThreadTest performClick_toggleTrue_directBootWarningShown()566 public void performClick_toggleTrue_directBootWarningShown() { 567 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 568 List<InputMethodInfo> infos = createInputMethodInfoList( 569 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 570 setInputMethodList(infos); 571 setEnabledInputMethodList(new ArrayList<>()); 572 573 mPreferenceController.refreshUi(); 574 575 mPreferenceGroup.getPreference(0).performClick(); 576 577 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 578 ConfirmationDialogFragment.class); 579 verify(mMockFragmentController).showDialog( 580 securityDialogCaptor.capture(), 581 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 582 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 583 584 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 585 586 587 verify(mMockFragmentController).showDialog( 588 any(ConfirmationDialogFragment.class), 589 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 590 } 591 592 @Test 593 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_positive_noOtherPreferenceAdded()594 public void performClick_toggleTrue_showDirectBootDialog_positive_noOtherPreferenceAdded() { 595 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 596 List<InputMethodInfo> infos = createInputMethodInfoList( 597 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 598 setInputMethodList(infos); 599 setEnabledInputMethodList(new ArrayList<>()); 600 601 mPreferenceController.refreshUi(); 602 603 mPreferenceGroup.getPreference(0).performClick(); 604 605 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 606 ConfirmationDialogFragment.class); 607 verify(mMockFragmentController).showDialog( 608 securityDialogCaptor.capture(), 609 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 610 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 611 612 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 613 614 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 615 ConfirmationDialogFragment.class); 616 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 617 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 618 dialogFragment = bootDialogCaptor.getValue(); 619 620 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 621 622 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 623 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 624 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 625 } 626 627 @Test 628 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_positive_preferenceChecked()629 public void performClick_toggleTrue_showDirectBootDialog_positive_preferenceChecked() { 630 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 631 List<InputMethodInfo> infos = createInputMethodInfoList( 632 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 633 setInputMethodList(infos); 634 setEnabledInputMethodList(new ArrayList<>()); 635 636 mPreferenceController.refreshUi(); 637 638 mPreferenceGroup.getPreference(0).performClick(); 639 640 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 641 ConfirmationDialogFragment.class); 642 verify(mMockFragmentController).showDialog( 643 securityDialogCaptor.capture(), 644 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 645 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 646 647 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 648 649 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 650 ConfirmationDialogFragment.class); 651 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 652 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 653 dialogFragment = bootDialogCaptor.getValue(); 654 655 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 656 657 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 658 .isTrue(); 659 } 660 661 @Test 662 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_positive_preferenceEnabled()663 public void performClick_toggleTrue_showDirectBootDialog_positive_preferenceEnabled() { 664 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 665 List<InputMethodInfo> infos = createInputMethodInfoList( 666 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 667 setInputMethodList(infos); 668 setEnabledInputMethodList(new ArrayList<>()); 669 670 mPreferenceController.refreshUi(); 671 672 mPreferenceGroup.getPreference(0).performClick(); 673 674 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 675 ConfirmationDialogFragment.class); 676 verify(mMockFragmentController).showDialog( 677 securityDialogCaptor.capture(), 678 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 679 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 680 681 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 682 683 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 684 ConfirmationDialogFragment.class); 685 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 686 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 687 dialogFragment = bootDialogCaptor.getValue(); 688 689 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 690 691 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 692 } 693 694 @Test 695 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_positive_inputMethodEnabled()696 public void performClick_toggleTrue_showDirectBootDialog_positive_inputMethodEnabled() { 697 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 698 List<InputMethodInfo> infos = createInputMethodInfoList( 699 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 700 setInputMethodList(infos); 701 setEnabledInputMethodList(new ArrayList<>()); 702 703 mPreferenceController.refreshUi(); 704 705 mPreferenceGroup.getPreference(0).performClick(); 706 707 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 708 ConfirmationDialogFragment.class); 709 verify(mMockFragmentController).showDialog( 710 securityDialogCaptor.capture(), 711 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 712 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 713 714 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 715 716 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 717 ConfirmationDialogFragment.class); 718 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 719 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 720 dialogFragment = bootDialogCaptor.getValue(); 721 722 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 723 724 assertThat(getEnabledInputMethodList().get(0).getId()) 725 .isEqualTo(PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 726 } 727 728 @Test 729 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_negative_noOtherPreferenceAdded()730 public void performClick_toggleTrue_showDirectBootDialog_negative_noOtherPreferenceAdded() { 731 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 732 List<InputMethodInfo> infos = createInputMethodInfoList( 733 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 734 setInputMethodList(infos); 735 setEnabledInputMethodList(new ArrayList<>()); 736 737 mPreferenceController.refreshUi(); 738 739 mPreferenceGroup.getPreference(0).performClick(); 740 741 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 742 ConfirmationDialogFragment.class); 743 verify(mMockFragmentController).showDialog( 744 securityDialogCaptor.capture(), 745 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 746 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 747 748 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 749 750 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 751 ConfirmationDialogFragment.class); 752 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 753 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 754 dialogFragment = bootDialogCaptor.getValue(); 755 756 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 757 758 759 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 760 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 761 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 762 } 763 764 @Test 765 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_negative_preferenceNotChecked()766 public void performClick_toggleTrue_showDirectBootDialog_negative_preferenceNotChecked() { 767 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 768 List<InputMethodInfo> infos = createInputMethodInfoList( 769 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 770 setInputMethodList(infos); 771 setEnabledInputMethodList(new ArrayList<>()); 772 773 mPreferenceController.refreshUi(); 774 775 mPreferenceGroup.getPreference(0).performClick(); 776 777 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 778 ConfirmationDialogFragment.class); 779 verify(mMockFragmentController).showDialog( 780 securityDialogCaptor.capture(), 781 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 782 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 783 784 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 785 786 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 787 ConfirmationDialogFragment.class); 788 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 789 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 790 dialogFragment = bootDialogCaptor.getValue(); 791 792 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 793 794 795 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 796 .isFalse(); 797 } 798 799 @Test 800 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_negative_preferenceEnabled()801 public void performClick_toggleTrue_showDirectBootDialog_negative_preferenceEnabled() { 802 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 803 List<InputMethodInfo> infos = createInputMethodInfoList( 804 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 805 setInputMethodList(infos); 806 setEnabledInputMethodList(new ArrayList<>()); 807 808 mPreferenceController.refreshUi(); 809 810 mPreferenceGroup.getPreference(0).performClick(); 811 812 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 813 ConfirmationDialogFragment.class); 814 verify(mMockFragmentController).showDialog( 815 securityDialogCaptor.capture(), 816 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 817 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 818 819 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 820 821 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 822 ConfirmationDialogFragment.class); 823 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 824 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 825 dialogFragment = bootDialogCaptor.getValue(); 826 827 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 828 829 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 830 } 831 832 @Test 833 @UiThreadTest performClick_toggleTrue_showDirectBootDialog_negative_inputMethodDisabled()834 public void performClick_toggleTrue_showDirectBootDialog_negative_inputMethodDisabled() { 835 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 836 List<InputMethodInfo> infos = createInputMethodInfoList( 837 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 838 setInputMethodList(infos); 839 setEnabledInputMethodList(new ArrayList<>()); 840 841 mPreferenceController.refreshUi(); 842 843 mPreferenceGroup.getPreference(0).performClick(); 844 845 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 846 ConfirmationDialogFragment.class); 847 verify(mMockFragmentController).showDialog( 848 securityDialogCaptor.capture(), 849 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 850 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 851 852 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 853 854 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 855 ConfirmationDialogFragment.class); 856 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 857 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 858 dialogFragment = bootDialogCaptor.getValue(); 859 860 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 861 862 assertThat(mInputMethodManager.getEnabledInputMethodList().size()) 863 .isEqualTo(0); 864 } 865 866 @Test 867 @UiThreadTest performClick_toggleFalse_noOtherPreferenceAdded()868 public void performClick_toggleFalse_noOtherPreferenceAdded() { 869 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 870 List<InputMethodInfo> infos = createInputMethodInfoList( 871 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 872 setInputMethodList(infos); 873 setEnabledInputMethodList(infos); 874 875 mPreferenceController.refreshUi(); 876 877 mPreferenceGroup.getPreference(0).performClick(); 878 879 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 880 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 881 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 882 } 883 884 @Test 885 @UiThreadTest performClick_toggleFalse_preferenceNotChecked()886 public void performClick_toggleFalse_preferenceNotChecked() { 887 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 888 List<InputMethodInfo> infos = createInputMethodInfoList( 889 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 890 setInputMethodList(infos); 891 setEnabledInputMethodList(infos); 892 893 mPreferenceController.refreshUi(); 894 895 mPreferenceGroup.getPreference(0).performClick(); 896 897 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 898 .isFalse(); 899 } 900 901 @Test 902 @UiThreadTest performClick_toggleFalse_preferenceEnabled()903 public void performClick_toggleFalse_preferenceEnabled() { 904 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 905 List<InputMethodInfo> infos = createInputMethodInfoList( 906 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 907 setInputMethodList(infos); 908 setEnabledInputMethodList(infos); 909 910 mPreferenceController.refreshUi(); 911 912 mPreferenceGroup.getPreference(0).performClick(); 913 914 assertThat((mPreferenceGroup.getPreference(0)).isEnabled()) 915 .isTrue(); 916 } 917 918 @Test 919 @UiThreadTest performClick_toggleFalse_inputMethodDisabled()920 public void performClick_toggleFalse_inputMethodDisabled() { 921 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 922 List<InputMethodInfo> infos = createInputMethodInfoList( 923 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 924 setInputMethodList(infos); 925 setEnabledInputMethodList(infos); 926 927 mPreferenceController.refreshUi(); 928 929 mPreferenceGroup.getPreference(0).performClick(); 930 931 assertThat(mInputMethodManager.getEnabledInputMethodList().size()) 932 .isEqualTo(0); 933 } 934 935 @Test 936 @UiThreadTest performClick_toggleFalse_twoDefaultable_notClickDefaultablePreferenceDisabled()937 public void performClick_toggleFalse_twoDefaultable_notClickDefaultablePreferenceDisabled() { 938 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 939 List<InputMethodInfo> infos = createInputMethodInfoList( 940 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 941 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 942 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 943 setInputMethodList(infos); 944 setEnabledInputMethodList(infos); 945 946 mPreferenceController.refreshUi(); 947 948 getPreferenceFromGroupByKey(mPreferenceGroup, PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE) 949 .performClick(); 950 951 assertThat(getPreferenceFromGroupByKey(mPreferenceGroup, 952 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE).isEnabled()).isFalse(); 953 } 954 955 @Test 956 @UiThreadTest performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceEnabled()957 public void performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceEnabled() { 958 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 959 List<InputMethodInfo> infos = createInputMethodInfoList( 960 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 961 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 962 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 963 setInputMethodList(infos); 964 setEnabledInputMethodList(infos); 965 966 mPreferenceController.refreshUi(); 967 968 getPreferenceFromGroupByKey(mPreferenceGroup, 969 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 970 971 assertThat(getPreferenceFromGroupByKey(mPreferenceGroup, 972 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).isEnabled()).isTrue(); 973 } 974 975 @Test 976 @UiThreadTest performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceEnabled()977 public void performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceEnabled() { 978 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 979 List<InputMethodInfo> infos = createInputMethodInfoList( 980 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 981 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 982 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 983 setInputMethodList(infos); 984 setEnabledInputMethodList(infos); 985 986 mPreferenceController.refreshUi(); 987 988 getPreferenceFromGroupByKey(mPreferenceGroup, 989 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 990 991 assertThat(getPreferenceFromGroupByKey(mPreferenceGroup, 992 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE).isEnabled()).isTrue(); 993 } 994 995 @Test 996 @UiThreadTest performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceNotChecked()997 public void performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceNotChecked() { 998 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 999 List<InputMethodInfo> infos = createInputMethodInfoList( 1000 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1001 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 1002 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1003 setInputMethodList(infos); 1004 setEnabledInputMethodList(infos); 1005 1006 mPreferenceController.refreshUi(); 1007 1008 getPreferenceFromGroupByKey(mPreferenceGroup, 1009 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1010 1011 assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup, 1012 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE)).isChecked()).isFalse(); 1013 } 1014 1015 @Test 1016 @UiThreadTest performClick_toggleFalse_twoDefaultable_notClickedDefaultablePreferenceChecked()1017 public void performClick_toggleFalse_twoDefaultable_notClickedDefaultablePreferenceChecked() { 1018 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 1019 List<InputMethodInfo> infos = createInputMethodInfoList( 1020 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1021 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 1022 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1023 setInputMethodList(infos); 1024 setEnabledInputMethodList(infos); 1025 1026 mPreferenceController.refreshUi(); 1027 1028 getPreferenceFromGroupByKey(mPreferenceGroup, 1029 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1030 1031 assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup, 1032 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)).isChecked()).isTrue(); 1033 } 1034 1035 @Test 1036 @UiThreadTest performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceChecked()1037 public void performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceChecked() { 1038 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 1039 List<InputMethodInfo> infos = createInputMethodInfoList( 1040 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1041 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 1042 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1043 setInputMethodList(infos); 1044 setEnabledInputMethodList(infos); 1045 1046 mPreferenceController.refreshUi(); 1047 1048 getPreferenceFromGroupByKey(mPreferenceGroup, 1049 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1050 1051 assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup, 1052 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)).isChecked()).isTrue(); 1053 } 1054 1055 @Test 1056 @UiThreadTest performClick_toggleTrue_twoDefaultable_allPreferencesEnabled()1057 public void performClick_toggleTrue_twoDefaultable_allPreferencesEnabled() { 1058 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 1059 List<InputMethodInfo> infos = createInputMethodInfoList( 1060 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1061 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 1062 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1063 setInputMethodList(infos); 1064 List<InputMethodInfo> infos2 = createInputMethodInfoList( 1065 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1066 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1067 setEnabledInputMethodList(infos2); 1068 1069 mPreferenceController.refreshUi(); 1070 1071 getPreferenceFromGroupByKey(mPreferenceGroup, 1072 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1073 1074 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 1075 ConfirmationDialogFragment.class); 1076 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 1077 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 1078 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 1079 1080 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 1081 1082 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 1083 assertThat(mPreferenceGroup.getPreference(i).isEnabled()).isTrue(); 1084 } 1085 } 1086 1087 @Test 1088 @UiThreadTest performClick_toggleTrue_twoDefaultable_allPreferencesChecked()1089 public void performClick_toggleTrue_twoDefaultable_allPreferencesChecked() { 1090 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 1091 List<InputMethodInfo> infos = createInputMethodInfoList( 1092 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1093 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 1094 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1095 setInputMethodList(infos); 1096 List<InputMethodInfo> infos2 = createInputMethodInfoList( 1097 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1098 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1099 setEnabledInputMethodList(infos2); 1100 1101 mPreferenceController.refreshUi(); 1102 1103 getPreferenceFromGroupByKey(mPreferenceGroup, 1104 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1105 1106 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 1107 ConfirmationDialogFragment.class); 1108 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 1109 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 1110 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 1111 1112 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 1113 1114 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 1115 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(i)).isChecked()) 1116 .isTrue(); 1117 } 1118 } 1119 createMockInputMethodInfo( Context context, PackageManager packageManager, String packageName, String id, boolean isDefaultable, boolean directBootAware)1120 private InputMethodInfo createMockInputMethodInfo( 1121 Context context, PackageManager packageManager, 1122 String packageName, String id, boolean isDefaultable, boolean directBootAware) { 1123 ServiceInfo mockServiceInfo = mock(ServiceInfo.class); 1124 mockServiceInfo.directBootAware = directBootAware; 1125 1126 InputMethodInfo mockInfo = mock(InputMethodInfo.class); 1127 when(mockInfo.getPackageName()).thenReturn(packageName); 1128 when(mockInfo.loadLabel(packageManager)).thenReturn(PLACEHOLDER_LABEL); 1129 when(mockInfo.getServiceInfo()).thenReturn(mockServiceInfo); 1130 when(mockInfo.getSettingsActivity()).thenReturn(PLACEHOLDER_SETTINGS_ACTIVITY); 1131 when(mockInfo.getId()).thenReturn(id); 1132 when(mockInfo.isDefault(context)).thenReturn(isDefaultable); 1133 List<InputMethodSubtype> subtypes = createSubtypes(); 1134 when(mInputMethodManager.getEnabledInputMethodSubtypeList(any(), anyBoolean())) 1135 .thenReturn(subtypes); 1136 return mockInfo; 1137 } 1138 getPreferenceFromGroupByKey(PreferenceGroup prefGroup, String key)1139 private static Preference getPreferenceFromGroupByKey(PreferenceGroup prefGroup, String key) { 1140 for (int i = 0; i < prefGroup.getPreferenceCount(); i++) { 1141 Preference pref = prefGroup.getPreference(i); 1142 if (pref.getKey().equals(key)) { 1143 return pref; 1144 } 1145 } 1146 return null; 1147 } 1148 createSubtypes()1149 private static List<InputMethodSubtype> createSubtypes() { 1150 List<InputMethodSubtype> subtypes = new ArrayList<>(); 1151 subtypes.add(createSubtype(1, "en_US")); 1152 subtypes.add(createSubtype(2, "de_BE")); 1153 subtypes.add(createSubtype(3, "oc-FR")); 1154 return subtypes; 1155 } 1156 createSubtype(int id, String locale)1157 private static InputMethodSubtype createSubtype(int id, String locale) { 1158 return new InputMethodSubtype.InputMethodSubtypeBuilder().setSubtypeId(id) 1159 .setSubtypeLocale(locale).setIsAuxiliary(false).setIsAsciiCapable(true).build(); 1160 } 1161 createInputMethodInfoList(String packageName, String... ids)1162 private List<InputMethodInfo> createInputMethodInfoList(String packageName, String... ids) { 1163 List<InputMethodInfo> infos = new ArrayList<>(); 1164 PackageManager packageManager = mContext.getPackageManager(); 1165 List<String> idsList = Arrays.asList(ids); 1166 idsList.forEach(id -> { 1167 boolean defaultable; 1168 boolean directBootAware; 1169 switch (id) { 1170 case PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE: 1171 defaultable = true; 1172 directBootAware = true; 1173 break; 1174 case PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE: 1175 defaultable = true; 1176 directBootAware = false; 1177 break; 1178 case PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE: 1179 defaultable = false; 1180 directBootAware = true; 1181 break; 1182 default: //case PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE: 1183 defaultable = false; 1184 directBootAware = false; 1185 break; 1186 } 1187 infos.add(createMockInputMethodInfo(mContext, packageManager, packageName, id, 1188 defaultable, directBootAware)); 1189 }); 1190 return infos; 1191 } 1192 setInputMethodList(List<InputMethodInfo> list)1193 private void setInputMethodList(List<InputMethodInfo> list) { 1194 when(mInputMethodManager.getInputMethodList()).thenReturn(list); 1195 if (list != null && list.size() > 0) { 1196 addInputMethodInfosToMap(list); 1197 } 1198 } 1199 setEnabledInputMethodList(List<InputMethodInfo> list)1200 private void setEnabledInputMethodList(List<InputMethodInfo> list) { 1201 if (list == null || list.size() == 0) { 1202 Settings.Secure.putString(mContext.getContentResolver(), 1203 Settings.Secure.ENABLED_INPUT_METHODS, ""); 1204 return; 1205 } 1206 1207 String concatenatedInputMethodIds = createInputMethodIdString(list.stream().map( 1208 imi -> imi.getId()).collect(Collectors.toList()).toArray(new String[list.size()])); 1209 Settings.Secure.putString(mContext.getContentResolver(), 1210 Settings.Secure.ENABLED_INPUT_METHODS, concatenatedInputMethodIds); 1211 addInputMethodInfosToMap(list); 1212 when(mInputMethodManager.getEnabledInputMethodList()).thenAnswer( 1213 (Answer<List<InputMethodInfo>>) invocation -> getEnabledInputMethodList()); 1214 } 1215 getEnabledInputMethodList()1216 private List<InputMethodInfo> getEnabledInputMethodList() { 1217 List<InputMethodInfo> enabledInputMethodList = new ArrayList<>(); 1218 1219 String inputMethodIdString = Settings.Secure.getString( 1220 mContext.getContentResolver(), 1221 Settings.Secure.ENABLED_INPUT_METHODS); 1222 if (inputMethodIdString == null || inputMethodIdString.isEmpty()) { 1223 return enabledInputMethodList; 1224 } 1225 1226 InputMethodUtil.sInputMethodSplitter.setString(inputMethodIdString); 1227 while (InputMethodUtil.sInputMethodSplitter.hasNext()) { 1228 enabledInputMethodList.add(mInputMethodMap.get(InputMethodUtil.sInputMethodSplitter 1229 .next())); 1230 } 1231 return enabledInputMethodList; 1232 } 1233 createInputMethodIdString(String... ids)1234 private String createInputMethodIdString(String... ids) { 1235 int size = ids == null ? 0 : ids.length; 1236 1237 if (size == 1) { 1238 return ids[0]; 1239 } 1240 1241 StringBuilder builder = new StringBuilder(); 1242 for (int i = 0; i < size; i++) { 1243 builder.append(ids[i]); 1244 if (i != size - 1) { 1245 builder.append(InputMethodUtil.INPUT_METHOD_DELIMITER); 1246 } 1247 } 1248 return builder.toString(); 1249 } 1250 addInputMethodInfosToMap(List<InputMethodInfo> inputMethodInfos)1251 private void addInputMethodInfosToMap(List<InputMethodInfo> inputMethodInfos) { 1252 if (mInputMethodMap == null || mInputMethodMap.size() == 0) { 1253 mInputMethodMap = inputMethodInfos.stream().collect(Collectors.toMap( 1254 InputMethodInfo::getId, imi -> imi)); 1255 return; 1256 } 1257 1258 inputMethodInfos.forEach(imi -> { 1259 mInputMethodMap.put(imi.getId(), imi); 1260 }); 1261 } 1262 } 1263