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 refreshUi_permitAllInputMethods_preferenceCountIs4()141 public void refreshUi_permitAllInputMethods_preferenceCountIs4() { 142 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 143 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 144 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 145 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 146 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 147 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 148 setInputMethodList(infos); 149 setEnabledInputMethodList(infos); 150 151 mPreferenceController.refreshUi(); 152 153 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(4); 154 } 155 156 @Test refreshUi_multiplteAllowedImeByOrganization_allPreferencesVisible()157 public void refreshUi_multiplteAllowedImeByOrganization_allPreferencesVisible() { 158 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 159 mPermittedList); 160 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 161 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 162 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 163 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 164 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 165 setInputMethodList(infos); 166 setEnabledInputMethodList(infos); 167 168 mPreferenceController.refreshUi(); 169 170 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 171 assertThat(mPreferenceGroup.getPreference(i).isVisible()).isTrue(); 172 } 173 } 174 175 @Test refreshUi_multipleEnabledInputMethods_allPreferencesEnabled()176 public void refreshUi_multipleEnabledInputMethods_allPreferencesEnabled() { 177 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 178 mPermittedList); 179 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 180 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 181 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 182 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 183 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 184 setInputMethodList(infos); 185 setEnabledInputMethodList(infos); 186 187 mPreferenceController.refreshUi(); 188 189 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 190 assertThat(mPreferenceGroup.getPreference(i).isEnabled()).isTrue(); 191 } 192 } 193 194 @Test refreshUi_multipleEnabledInputMethods_allPreferencesChecked()195 public void refreshUi_multipleEnabledInputMethods_allPreferencesChecked() { 196 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 197 mPermittedList); 198 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 199 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 200 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 201 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 202 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 203 setInputMethodList(infos); 204 setEnabledInputMethodList(infos); 205 206 mPreferenceController.refreshUi(); 207 208 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 209 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(i)).isChecked()) 210 .isTrue(); 211 } 212 } 213 214 @Test refreshUi_disallowedByOrganization_noPreferencesShown()215 public void refreshUi_disallowedByOrganization_noPreferencesShown() { 216 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn( 217 mPermittedList); 218 List<InputMethodInfo> infos = createInputMethodInfoList(DISALLOWED_PACKAGE_NAME, 219 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 220 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 221 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 222 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 223 setInputMethodList(infos); 224 setEnabledInputMethodList(infos); 225 226 mPreferenceController.refreshUi(); 227 228 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0); 229 } 230 231 @Test refreshUi_skipVoiceTyping()232 public void refreshUi_skipVoiceTyping() { 233 List<InputMethodInfo> infos = 234 createInputMethodInfoList(InputMethodUtil.GOOGLE_VOICE_TYPING); 235 setInputMethodList(infos); 236 237 mPreferenceController.refreshUi(); 238 239 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0); 240 } 241 242 @Test refreshUi_verifyPreferenceIcon()243 public void refreshUi_verifyPreferenceIcon() { 244 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 245 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 246 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 247 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 248 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 249 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 250 setInputMethodList(infos); 251 setEnabledInputMethodList(infos); 252 253 mPreferenceController.refreshUi(); 254 255 Preference preference = mPreferenceGroup.getPreference(0); 256 assertThat(preference.getIcon()).isEqualTo( 257 InputMethodUtil.getPackageIcon(mContext.getPackageManager(), infos.get(0))); 258 } 259 260 @Test refreshUi_verifyPreferenceTitle()261 public void refreshUi_verifyPreferenceTitle() { 262 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 263 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 264 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 265 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 266 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 267 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 268 setInputMethodList(infos); 269 setEnabledInputMethodList(infos); 270 271 mPreferenceController.refreshUi(); 272 273 Preference preference = mPreferenceGroup.getPreference(0); 274 assertThat(preference.getTitle()).isEqualTo( 275 InputMethodUtil.getPackageLabel(mContext.getPackageManager(), infos.get(0))); 276 } 277 278 @Test refreshUi_verifyPreferenceSummary()279 public void refreshUi_verifyPreferenceSummary() { 280 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 281 List<InputMethodInfo> infos = createInputMethodInfoList(ALLOWED_PACKAGE_NAME, 282 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 283 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 284 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE, 285 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 286 setInputMethodList(infos); 287 setEnabledInputMethodList(infos); 288 289 mPreferenceController.refreshUi(); 290 291 Preference preference = mPreferenceGroup.getPreference(0); 292 assertThat(preference.getSummary()).isEqualTo( 293 InputMethodUtil.getSummaryString(mContext, mInputMethodManager, infos.get(0))); 294 } 295 296 @Test refreshUi_oneInputMethod_noneEnabled_oneInputMethodPreferenceInView()297 public void refreshUi_oneInputMethod_noneEnabled_oneInputMethodPreferenceInView() { 298 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 299 List<InputMethodInfo> infos = createInputMethodInfoList( 300 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 301 setInputMethodList(infos); 302 setEnabledInputMethodList(new ArrayList<>()); 303 304 mPreferenceController.refreshUi(); 305 306 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 307 } 308 309 @Test refreshUi_oneInputMethod_noneEnabled_preferenceEnabled()310 public void refreshUi_oneInputMethod_noneEnabled_preferenceEnabled() { 311 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 312 List<InputMethodInfo> infos = createInputMethodInfoList( 313 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 314 setInputMethodList(infos); 315 setEnabledInputMethodList(new ArrayList<>()); 316 317 mPreferenceController.refreshUi(); 318 319 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 320 } 321 322 @Test refreshUi_oneInputMethod_noneEnabled_preferenceNotChecked()323 public void refreshUi_oneInputMethod_noneEnabled_preferenceNotChecked() { 324 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 325 List<InputMethodInfo> infos = createInputMethodInfoList( 326 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 327 setInputMethodList(infos); 328 setEnabledInputMethodList(new ArrayList<>()); 329 330 mPreferenceController.refreshUi(); 331 332 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 333 .isFalse(); 334 } 335 336 @Test refreshUi_oneInputMethod_defaultable_notChecked_preferenceEnabled()337 public void refreshUi_oneInputMethod_defaultable_notChecked_preferenceEnabled() { 338 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 339 List<InputMethodInfo> infos = createInputMethodInfoList( 340 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 341 setInputMethodList(infos); 342 setEnabledInputMethodList(new ArrayList<>()); 343 344 mPreferenceController.refreshUi(); 345 346 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 347 } 348 349 @Test performClick_toggleTrue_securityDialogShown()350 public void performClick_toggleTrue_securityDialogShown() { 351 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 352 List<InputMethodInfo> infos = createInputMethodInfoList( 353 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 354 setInputMethodList(infos); 355 setEnabledInputMethodList(new ArrayList<>()); 356 357 mPreferenceController.refreshUi(); 358 359 mPreferenceGroup.getPreference(0).performClick(); 360 361 verify(mMockFragmentController).showDialog( 362 any(ConfirmationDialogFragment.class), 363 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 364 } 365 366 @Test performClick_toggleTrue_showSecurityDialog_positive_noOtherPreferenceAdded()367 public void performClick_toggleTrue_showSecurityDialog_positive_noOtherPreferenceAdded() { 368 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 369 List<InputMethodInfo> infos = createInputMethodInfoList( 370 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 371 setInputMethodList(infos); 372 setEnabledInputMethodList(new ArrayList<>()); 373 374 mPreferenceController.refreshUi(); 375 376 mPreferenceGroup.getPreference(0).performClick(); 377 378 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 379 ConfirmationDialogFragment.class); 380 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 381 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 382 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 383 384 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 385 386 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 387 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 388 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 389 } 390 391 @Test performClick_toggleTrue_showSecurityDialog_positive_preferenceChecked()392 public void performClick_toggleTrue_showSecurityDialog_positive_preferenceChecked() { 393 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 394 List<InputMethodInfo> infos = createInputMethodInfoList( 395 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 396 setInputMethodList(infos); 397 setEnabledInputMethodList(new ArrayList<>()); 398 399 mPreferenceController.refreshUi(); 400 401 mPreferenceGroup.getPreference(0).performClick(); 402 403 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 404 ConfirmationDialogFragment.class); 405 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 406 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 407 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 408 409 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 410 411 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 412 .isTrue(); 413 } 414 415 @Test performClick_toggleTrue_showSecurityDialog_positive_preferenceEnabled()416 public void performClick_toggleTrue_showSecurityDialog_positive_preferenceEnabled() { 417 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 418 List<InputMethodInfo> infos = createInputMethodInfoList( 419 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 420 setInputMethodList(infos); 421 setEnabledInputMethodList(new ArrayList<>()); 422 423 mPreferenceController.refreshUi(); 424 425 mPreferenceGroup.getPreference(0).performClick(); 426 427 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 428 ConfirmationDialogFragment.class); 429 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 430 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 431 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 432 433 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 434 435 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 436 } 437 438 @Test performClick_toggleTrue_showSecurityDialog_positive_inputMethodEnabled()439 public void performClick_toggleTrue_showSecurityDialog_positive_inputMethodEnabled() { 440 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 441 List<InputMethodInfo> infos = createInputMethodInfoList( 442 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 443 setInputMethodList(infos); 444 setEnabledInputMethodList(new ArrayList<>()); 445 446 mPreferenceController.refreshUi(); 447 448 mPreferenceGroup.getPreference(0).performClick(); 449 450 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 451 ConfirmationDialogFragment.class); 452 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 453 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 454 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 455 456 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 457 458 assertThat(getEnabledInputMethodList().get(0).getId()) 459 .isEqualTo(PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 460 } 461 462 @Test performClick_toggleTrue_showSecurityDialog_negative_noOtherPreferenceAdded()463 public void performClick_toggleTrue_showSecurityDialog_negative_noOtherPreferenceAdded() { 464 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 465 List<InputMethodInfo> infos = createInputMethodInfoList( 466 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 467 setInputMethodList(infos); 468 setEnabledInputMethodList(new ArrayList<>()); 469 470 mPreferenceController.refreshUi(); 471 472 mPreferenceGroup.getPreference(0).performClick(); 473 474 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 475 ConfirmationDialogFragment.class); 476 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 477 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 478 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 479 480 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 481 482 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 483 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 484 PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 485 } 486 487 @Test performClick_toggleTrue_showSecurityDialog_negative_preferenceEnabled()488 public void performClick_toggleTrue_showSecurityDialog_negative_preferenceEnabled() { 489 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 490 List<InputMethodInfo> infos = createInputMethodInfoList( 491 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 492 setInputMethodList(infos); 493 setEnabledInputMethodList(new ArrayList<>()); 494 495 mPreferenceController.refreshUi(); 496 497 mPreferenceGroup.getPreference(0).performClick(); 498 499 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 500 ConfirmationDialogFragment.class); 501 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 502 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 503 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 504 505 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 506 507 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 508 } 509 510 @Test performClick_toggleTrue_showSecurityDialog_negative_inputMethodDisabled()511 public void performClick_toggleTrue_showSecurityDialog_negative_inputMethodDisabled() { 512 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 513 List<InputMethodInfo> infos = createInputMethodInfoList( 514 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE); 515 setInputMethodList(infos); 516 setEnabledInputMethodList(new ArrayList<>()); 517 518 mPreferenceController.refreshUi(); 519 520 mPreferenceGroup.getPreference(0).performClick(); 521 522 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 523 ConfirmationDialogFragment.class); 524 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 525 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 526 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 527 528 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 529 530 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 531 .isFalse(); 532 } 533 534 @Test performClick_toggleTrue_directBootWarningShown()535 public void performClick_toggleTrue_directBootWarningShown() { 536 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 537 List<InputMethodInfo> infos = createInputMethodInfoList( 538 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 539 setInputMethodList(infos); 540 setEnabledInputMethodList(new ArrayList<>()); 541 542 mPreferenceController.refreshUi(); 543 544 mPreferenceGroup.getPreference(0).performClick(); 545 546 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 547 ConfirmationDialogFragment.class); 548 verify(mMockFragmentController).showDialog( 549 securityDialogCaptor.capture(), 550 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 551 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 552 553 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 554 555 556 verify(mMockFragmentController).showDialog( 557 any(ConfirmationDialogFragment.class), 558 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 559 } 560 561 @Test performClick_toggleTrue_showDirectBootDialog_positive_noOtherPreferenceAdded()562 public void performClick_toggleTrue_showDirectBootDialog_positive_noOtherPreferenceAdded() { 563 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 564 List<InputMethodInfo> infos = createInputMethodInfoList( 565 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 566 setInputMethodList(infos); 567 setEnabledInputMethodList(new ArrayList<>()); 568 569 mPreferenceController.refreshUi(); 570 571 mPreferenceGroup.getPreference(0).performClick(); 572 573 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 574 ConfirmationDialogFragment.class); 575 verify(mMockFragmentController).showDialog( 576 securityDialogCaptor.capture(), 577 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 578 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 579 580 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 581 582 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 583 ConfirmationDialogFragment.class); 584 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 585 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 586 dialogFragment = bootDialogCaptor.getValue(); 587 588 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 589 590 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 591 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 592 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 593 } 594 595 @Test performClick_toggleTrue_showDirectBootDialog_positive_preferenceChecked()596 public void performClick_toggleTrue_showDirectBootDialog_positive_preferenceChecked() { 597 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 598 List<InputMethodInfo> infos = createInputMethodInfoList( 599 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 600 setInputMethodList(infos); 601 setEnabledInputMethodList(new ArrayList<>()); 602 603 mPreferenceController.refreshUi(); 604 605 mPreferenceGroup.getPreference(0).performClick(); 606 607 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 608 ConfirmationDialogFragment.class); 609 verify(mMockFragmentController).showDialog( 610 securityDialogCaptor.capture(), 611 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 612 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 613 614 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 615 616 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 617 ConfirmationDialogFragment.class); 618 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 619 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 620 dialogFragment = bootDialogCaptor.getValue(); 621 622 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 623 624 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 625 .isTrue(); 626 } 627 628 @Test performClick_toggleTrue_showDirectBootDialog_positive_preferenceEnabled()629 public void performClick_toggleTrue_showDirectBootDialog_positive_preferenceEnabled() { 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(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 658 } 659 660 @Test performClick_toggleTrue_showDirectBootDialog_positive_inputMethodEnabled()661 public void performClick_toggleTrue_showDirectBootDialog_positive_inputMethodEnabled() { 662 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 663 List<InputMethodInfo> infos = createInputMethodInfoList( 664 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 665 setInputMethodList(infos); 666 setEnabledInputMethodList(new ArrayList<>()); 667 668 mPreferenceController.refreshUi(); 669 670 mPreferenceGroup.getPreference(0).performClick(); 671 672 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 673 ConfirmationDialogFragment.class); 674 verify(mMockFragmentController).showDialog( 675 securityDialogCaptor.capture(), 676 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 677 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 678 679 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 680 681 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 682 ConfirmationDialogFragment.class); 683 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 684 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 685 dialogFragment = bootDialogCaptor.getValue(); 686 687 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 688 689 assertThat(getEnabledInputMethodList().get(0).getId()) 690 .isEqualTo(PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 691 } 692 693 @Test performClick_toggleTrue_showDirectBootDialog_negative_noOtherPreferenceAdded()694 public void performClick_toggleTrue_showDirectBootDialog_negative_noOtherPreferenceAdded() { 695 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 696 List<InputMethodInfo> infos = createInputMethodInfoList( 697 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 698 setInputMethodList(infos); 699 setEnabledInputMethodList(new ArrayList<>()); 700 701 mPreferenceController.refreshUi(); 702 703 mPreferenceGroup.getPreference(0).performClick(); 704 705 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 706 ConfirmationDialogFragment.class); 707 verify(mMockFragmentController).showDialog( 708 securityDialogCaptor.capture(), 709 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 710 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 711 712 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 713 714 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 715 ConfirmationDialogFragment.class); 716 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 717 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 718 dialogFragment = bootDialogCaptor.getValue(); 719 720 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 721 722 723 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 724 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 725 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 726 } 727 728 @Test performClick_toggleTrue_showDirectBootDialog_negative_preferenceNotChecked()729 public void performClick_toggleTrue_showDirectBootDialog_negative_preferenceNotChecked() { 730 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 731 List<InputMethodInfo> infos = createInputMethodInfoList( 732 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 733 setInputMethodList(infos); 734 setEnabledInputMethodList(new ArrayList<>()); 735 736 mPreferenceController.refreshUi(); 737 738 mPreferenceGroup.getPreference(0).performClick(); 739 740 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 741 ConfirmationDialogFragment.class); 742 verify(mMockFragmentController).showDialog( 743 securityDialogCaptor.capture(), 744 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 745 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 746 747 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 748 749 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 750 ConfirmationDialogFragment.class); 751 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 752 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 753 dialogFragment = bootDialogCaptor.getValue(); 754 755 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 756 757 758 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 759 .isFalse(); 760 } 761 762 @Test performClick_toggleTrue_showDirectBootDialog_negative_preferenceEnabled()763 public void performClick_toggleTrue_showDirectBootDialog_negative_preferenceEnabled() { 764 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 765 List<InputMethodInfo> infos = createInputMethodInfoList( 766 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 767 setInputMethodList(infos); 768 setEnabledInputMethodList(new ArrayList<>()); 769 770 mPreferenceController.refreshUi(); 771 772 mPreferenceGroup.getPreference(0).performClick(); 773 774 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 775 ConfirmationDialogFragment.class); 776 verify(mMockFragmentController).showDialog( 777 securityDialogCaptor.capture(), 778 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 779 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 780 781 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 782 783 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 784 ConfirmationDialogFragment.class); 785 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 786 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 787 dialogFragment = bootDialogCaptor.getValue(); 788 789 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 790 791 assertThat(mPreferenceGroup.getPreference(0).isEnabled()).isTrue(); 792 } 793 794 @Test performClick_toggleTrue_showDirectBootDialog_negative_inputMethodDisabled()795 public void performClick_toggleTrue_showDirectBootDialog_negative_inputMethodDisabled() { 796 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 797 List<InputMethodInfo> infos = createInputMethodInfoList( 798 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 799 setInputMethodList(infos); 800 setEnabledInputMethodList(new ArrayList<>()); 801 802 mPreferenceController.refreshUi(); 803 804 mPreferenceGroup.getPreference(0).performClick(); 805 806 ArgumentCaptor<ConfirmationDialogFragment> securityDialogCaptor = ArgumentCaptor.forClass( 807 ConfirmationDialogFragment.class); 808 verify(mMockFragmentController).showDialog( 809 securityDialogCaptor.capture(), 810 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 811 ConfirmationDialogFragment dialogFragment = securityDialogCaptor.getValue(); 812 813 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 814 815 ArgumentCaptor<ConfirmationDialogFragment> bootDialogCaptor = ArgumentCaptor.forClass( 816 ConfirmationDialogFragment.class); 817 verify(mMockFragmentController).showDialog(bootDialogCaptor.capture(), 818 eq(KeyboardManagementPreferenceController.DIRECT_BOOT_WARN_DIALOG_TAG)); 819 dialogFragment = bootDialogCaptor.getValue(); 820 821 dialogFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE); 822 823 assertThat(mInputMethodManager.getEnabledInputMethodList().size()) 824 .isEqualTo(0); 825 } 826 827 @Test performClick_toggleFalse_noOtherPreferenceAdded()828 public void performClick_toggleFalse_noOtherPreferenceAdded() { 829 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 830 List<InputMethodInfo> infos = createInputMethodInfoList( 831 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 832 setInputMethodList(infos); 833 setEnabledInputMethodList(infos); 834 835 mPreferenceController.refreshUi(); 836 837 mPreferenceGroup.getPreference(0).performClick(); 838 839 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 840 assertThat(mPreferenceGroup.getPreference(0).getKey()).isEqualTo( 841 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 842 } 843 844 @Test performClick_toggleFalse_preferenceNotChecked()845 public void performClick_toggleFalse_preferenceNotChecked() { 846 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 847 List<InputMethodInfo> infos = createInputMethodInfoList( 848 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 849 setInputMethodList(infos); 850 setEnabledInputMethodList(infos); 851 852 mPreferenceController.refreshUi(); 853 854 mPreferenceGroup.getPreference(0).performClick(); 855 856 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(0)).isChecked()) 857 .isFalse(); 858 } 859 860 @Test performClick_toggleFalse_preferenceEnabled()861 public void performClick_toggleFalse_preferenceEnabled() { 862 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 863 List<InputMethodInfo> infos = createInputMethodInfoList( 864 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 865 setInputMethodList(infos); 866 setEnabledInputMethodList(infos); 867 868 mPreferenceController.refreshUi(); 869 870 mPreferenceGroup.getPreference(0).performClick(); 871 872 assertThat((mPreferenceGroup.getPreference(0)).isEnabled()) 873 .isTrue(); 874 } 875 876 @Test performClick_toggleFalse_inputMethodDisabled()877 public void performClick_toggleFalse_inputMethodDisabled() { 878 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 879 List<InputMethodInfo> infos = createInputMethodInfoList( 880 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 881 setInputMethodList(infos); 882 setEnabledInputMethodList(infos); 883 884 mPreferenceController.refreshUi(); 885 886 mPreferenceGroup.getPreference(0).performClick(); 887 888 assertThat(mInputMethodManager.getEnabledInputMethodList().size()) 889 .isEqualTo(0); 890 } 891 892 @Test performClick_toggleFalse_twoDefaultable_notClickDefaultablePreferenceDisabled()893 public void performClick_toggleFalse_twoDefaultable_notClickDefaultablePreferenceDisabled() { 894 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 895 List<InputMethodInfo> infos = createInputMethodInfoList( 896 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 897 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 898 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 899 setInputMethodList(infos); 900 setEnabledInputMethodList(infos); 901 902 mPreferenceController.refreshUi(); 903 904 getPreferenceFromGroupByKey(mPreferenceGroup, PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE) 905 .performClick(); 906 907 assertThat(getPreferenceFromGroupByKey(mPreferenceGroup, 908 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE).isEnabled()).isFalse(); 909 } 910 911 @Test performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceEnabled()912 public void performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceEnabled() { 913 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 914 List<InputMethodInfo> infos = createInputMethodInfoList( 915 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 916 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 917 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 918 setInputMethodList(infos); 919 setEnabledInputMethodList(infos); 920 921 mPreferenceController.refreshUi(); 922 923 getPreferenceFromGroupByKey(mPreferenceGroup, 924 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 925 926 assertThat(getPreferenceFromGroupByKey(mPreferenceGroup, 927 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).isEnabled()).isTrue(); 928 } 929 930 @Test performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceEnabled()931 public void performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceEnabled() { 932 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 933 List<InputMethodInfo> infos = createInputMethodInfoList( 934 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 935 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 936 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 937 setInputMethodList(infos); 938 setEnabledInputMethodList(infos); 939 940 mPreferenceController.refreshUi(); 941 942 getPreferenceFromGroupByKey(mPreferenceGroup, 943 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 944 945 assertThat(getPreferenceFromGroupByKey(mPreferenceGroup, 946 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE).isEnabled()).isTrue(); 947 } 948 949 @Test performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceNotChecked()950 public void performClick_toggleFalse_twoDefaultable_clickedDefaultablePreferenceNotChecked() { 951 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 952 List<InputMethodInfo> infos = createInputMethodInfoList( 953 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 954 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 955 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 956 setInputMethodList(infos); 957 setEnabledInputMethodList(infos); 958 959 mPreferenceController.refreshUi(); 960 961 getPreferenceFromGroupByKey(mPreferenceGroup, 962 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 963 964 assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup, 965 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE)).isChecked()).isFalse(); 966 } 967 968 @Test performClick_toggleFalse_twoDefaultable_notClickedDefaultablePreferenceChecked()969 public void performClick_toggleFalse_twoDefaultable_notClickedDefaultablePreferenceChecked() { 970 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 971 List<InputMethodInfo> infos = createInputMethodInfoList( 972 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 973 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 974 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 975 setInputMethodList(infos); 976 setEnabledInputMethodList(infos); 977 978 mPreferenceController.refreshUi(); 979 980 getPreferenceFromGroupByKey(mPreferenceGroup, 981 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 982 983 assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup, 984 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)).isChecked()).isTrue(); 985 } 986 987 @Test performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceChecked()988 public void performClick_toggleFalse_twoDefaultable_nonDefaultablePreferenceChecked() { 989 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 990 List<InputMethodInfo> infos = createInputMethodInfoList( 991 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 992 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 993 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 994 setInputMethodList(infos); 995 setEnabledInputMethodList(infos); 996 997 mPreferenceController.refreshUi(); 998 999 getPreferenceFromGroupByKey(mPreferenceGroup, 1000 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1001 1002 assertThat(((SwitchPreference) getPreferenceFromGroupByKey(mPreferenceGroup, 1003 PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE)).isChecked()).isTrue(); 1004 } 1005 1006 @Test performClick_toggleTrue_twoDefaultable_allPreferencesEnabled()1007 public void performClick_toggleTrue_twoDefaultable_allPreferencesEnabled() { 1008 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 1009 List<InputMethodInfo> infos = createInputMethodInfoList( 1010 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1011 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 1012 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1013 setInputMethodList(infos); 1014 List<InputMethodInfo> infos2 = createInputMethodInfoList( 1015 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1016 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1017 setEnabledInputMethodList(infos2); 1018 1019 mPreferenceController.refreshUi(); 1020 1021 getPreferenceFromGroupByKey(mPreferenceGroup, 1022 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1023 1024 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 1025 ConfirmationDialogFragment.class); 1026 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 1027 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 1028 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 1029 1030 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 1031 1032 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 1033 assertThat(mPreferenceGroup.getPreference(i).isEnabled()).isTrue(); 1034 } 1035 } 1036 1037 @Test performClick_toggleTrue_twoDefaultable_allPreferencesChecked()1038 public void performClick_toggleTrue_twoDefaultable_allPreferencesChecked() { 1039 when(mDevicePolicyManager.getPermittedInputMethodsForCurrentUser()).thenReturn(null); 1040 List<InputMethodInfo> infos = createInputMethodInfoList( 1041 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1042 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE, 1043 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1044 setInputMethodList(infos); 1045 List<InputMethodInfo> infos2 = createInputMethodInfoList( 1046 ALLOWED_PACKAGE_NAME, PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE, 1047 PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE); 1048 setEnabledInputMethodList(infos2); 1049 1050 mPreferenceController.refreshUi(); 1051 1052 getPreferenceFromGroupByKey(mPreferenceGroup, 1053 PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE).performClick(); 1054 1055 ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass( 1056 ConfirmationDialogFragment.class); 1057 verify(mMockFragmentController).showDialog(dialogCaptor.capture(), 1058 eq(KeyboardManagementPreferenceController.SECURITY_WARN_DIALOG_TAG)); 1059 ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue(); 1060 1061 dialogFragment.onClick(null, DialogInterface.BUTTON_POSITIVE); 1062 1063 for (int i = 0; i < mPreferenceGroup.getPreferenceCount(); i++) { 1064 assertThat(((SwitchPreference) mPreferenceGroup.getPreference(i)).isChecked()) 1065 .isTrue(); 1066 } 1067 } 1068 createMockInputMethodInfo( Context context, PackageManager packageManager, String packageName, String id, boolean isDefaultable, boolean directBootAware)1069 private InputMethodInfo createMockInputMethodInfo( 1070 Context context, PackageManager packageManager, 1071 String packageName, String id, boolean isDefaultable, boolean directBootAware) { 1072 ServiceInfo mockServiceInfo = mock(ServiceInfo.class); 1073 mockServiceInfo.directBootAware = directBootAware; 1074 1075 InputMethodInfo mockInfo = mock(InputMethodInfo.class); 1076 when(mockInfo.getPackageName()).thenReturn(packageName); 1077 when(mockInfo.loadLabel(packageManager)).thenReturn(PLACEHOLDER_LABEL); 1078 when(mockInfo.getServiceInfo()).thenReturn(mockServiceInfo); 1079 when(mockInfo.getSettingsActivity()).thenReturn(PLACEHOLDER_SETTINGS_ACTIVITY); 1080 when(mockInfo.getId()).thenReturn(id); 1081 when(mockInfo.isDefault(context)).thenReturn(isDefaultable); 1082 List<InputMethodSubtype> subtypes = createSubtypes(); 1083 when(mInputMethodManager.getEnabledInputMethodSubtypeList(any(), anyBoolean())) 1084 .thenReturn(subtypes); 1085 return mockInfo; 1086 } 1087 getPreferenceFromGroupByKey(PreferenceGroup prefGroup, String key)1088 private static Preference getPreferenceFromGroupByKey(PreferenceGroup prefGroup, String key) { 1089 for (int i = 0; i < prefGroup.getPreferenceCount(); i++) { 1090 Preference pref = prefGroup.getPreference(i); 1091 if (pref.getKey().equals(key)) { 1092 return pref; 1093 } 1094 } 1095 return null; 1096 } 1097 createSubtypes()1098 private static List<InputMethodSubtype> createSubtypes() { 1099 List<InputMethodSubtype> subtypes = new ArrayList<>(); 1100 subtypes.add(createSubtype(1, "en_US")); 1101 subtypes.add(createSubtype(2, "de_BE")); 1102 subtypes.add(createSubtype(3, "oc-FR")); 1103 return subtypes; 1104 } 1105 createSubtype(int id, String locale)1106 private static InputMethodSubtype createSubtype(int id, String locale) { 1107 return new InputMethodSubtype.InputMethodSubtypeBuilder().setSubtypeId(id) 1108 .setSubtypeLocale(locale).setIsAuxiliary(false).setIsAsciiCapable(true).build(); 1109 } 1110 createInputMethodInfoList(String packageName, String... ids)1111 private List<InputMethodInfo> createInputMethodInfoList(String packageName, String... ids) { 1112 List<InputMethodInfo> infos = new ArrayList<>(); 1113 PackageManager packageManager = mContext.getPackageManager(); 1114 List<String> idsList = Arrays.asList(ids); 1115 idsList.forEach(id -> { 1116 boolean defaultable; 1117 boolean directBootAware; 1118 switch (id) { 1119 case PLACEHOLDER_ID_DEFAULTABLE_DIRECT_BOOT_AWARE: 1120 defaultable = true; 1121 directBootAware = true; 1122 break; 1123 case PLACEHOLDER_ID_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE: 1124 defaultable = true; 1125 directBootAware = false; 1126 break; 1127 case PLACEHOLDER_ID_NOT_DEFAULTABLE_DIRECT_BOOT_AWARE: 1128 defaultable = false; 1129 directBootAware = true; 1130 break; 1131 default: //case PLACEHOLDER_ID_NOT_DEFAULTABLE_NOT_DIRECT_BOOT_AWARE: 1132 defaultable = false; 1133 directBootAware = false; 1134 break; 1135 } 1136 infos.add(createMockInputMethodInfo(mContext, packageManager, packageName, id, 1137 defaultable, directBootAware)); 1138 }); 1139 return infos; 1140 } 1141 setInputMethodList(List<InputMethodInfo> list)1142 private void setInputMethodList(List<InputMethodInfo> list) { 1143 when(mInputMethodManager.getInputMethodList()).thenReturn(list); 1144 if (list != null && list.size() > 0) { 1145 addInputMethodInfosToMap(list); 1146 } 1147 } 1148 setEnabledInputMethodList(List<InputMethodInfo> list)1149 private void setEnabledInputMethodList(List<InputMethodInfo> list) { 1150 if (list == null || list.size() == 0) { 1151 Settings.Secure.putString(mContext.getContentResolver(), 1152 Settings.Secure.ENABLED_INPUT_METHODS, ""); 1153 return; 1154 } 1155 1156 String concatenatedInputMethodIds = createInputMethodIdString(list.stream().map( 1157 imi -> imi.getId()).collect(Collectors.toList()).toArray(new String[list.size()])); 1158 Settings.Secure.putString(mContext.getContentResolver(), 1159 Settings.Secure.ENABLED_INPUT_METHODS, concatenatedInputMethodIds); 1160 addInputMethodInfosToMap(list); 1161 when(mInputMethodManager.getEnabledInputMethodList()).thenAnswer( 1162 (Answer<List<InputMethodInfo>>) invocation -> getEnabledInputMethodList()); 1163 } 1164 getEnabledInputMethodList()1165 private List<InputMethodInfo> getEnabledInputMethodList() { 1166 List<InputMethodInfo> enabledInputMethodList = new ArrayList<>(); 1167 1168 String inputMethodIdString = Settings.Secure.getString( 1169 mContext.getContentResolver(), 1170 Settings.Secure.ENABLED_INPUT_METHODS); 1171 if (inputMethodIdString == null || inputMethodIdString.isEmpty()) { 1172 return enabledInputMethodList; 1173 } 1174 1175 InputMethodUtil.sInputMethodSplitter.setString(inputMethodIdString); 1176 while (InputMethodUtil.sInputMethodSplitter.hasNext()) { 1177 enabledInputMethodList.add(mInputMethodMap.get(InputMethodUtil.sInputMethodSplitter 1178 .next())); 1179 } 1180 return enabledInputMethodList; 1181 } 1182 createInputMethodIdString(String... ids)1183 private String createInputMethodIdString(String... ids) { 1184 int size = ids == null ? 0 : ids.length; 1185 1186 if (size == 1) { 1187 return ids[0]; 1188 } 1189 1190 StringBuilder builder = new StringBuilder(); 1191 for (int i = 0; i < size; i++) { 1192 builder.append(ids[i]); 1193 if (i != size - 1) { 1194 builder.append(InputMethodUtil.INPUT_METHOD_DELIMITER); 1195 } 1196 } 1197 return builder.toString(); 1198 } 1199 addInputMethodInfosToMap(List<InputMethodInfo> inputMethodInfos)1200 private void addInputMethodInfosToMap(List<InputMethodInfo> inputMethodInfos) { 1201 if (mInputMethodMap == null || mInputMethodMap.size() == 0) { 1202 mInputMethodMap = inputMethodInfos.stream().collect(Collectors.toMap( 1203 InputMethodInfo::getId, imi -> imi)); 1204 return; 1205 } 1206 1207 inputMethodInfos.forEach(imi -> { 1208 mInputMethodMap.put(imi.getId(), imi); 1209 }); 1210 } 1211 } 1212