1 /* 2 * Copyright (C) 2020 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.settings.accessibility; 18 19 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE; 20 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE; 21 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS; 22 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; 23 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TRIPLETAP; 24 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TWOFINGER_DOUBLETAP; 25 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.createAccessibilityTutorialDialog; 26 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.createAccessibilityTutorialDialogForSetupWizard; 27 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.createShortcutTutorialPages; 28 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.showGestureNavigationTutorialDialog; 29 30 import static com.google.common.truth.Truth.assertThat; 31 32 import static org.mockito.Mockito.verify; 33 import static org.robolectric.Shadows.shadowOf; 34 35 import android.app.Activity; 36 import android.app.settings.SettingsEnums; 37 import android.content.Context; 38 import android.content.DialogInterface; 39 import android.content.Intent; 40 import android.platform.test.annotations.DisableFlags; 41 import android.platform.test.annotations.EnableFlags; 42 import android.platform.test.flag.junit.SetFlagsRule; 43 import android.text.SpannableStringBuilder; 44 import android.util.ArrayMap; 45 import android.view.View; 46 import android.view.accessibility.AccessibilityManager; 47 import android.widget.Button; 48 import android.widget.TextSwitcher; 49 import android.widget.TextView; 50 51 import androidx.appcompat.app.AlertDialog; 52 import androidx.test.core.app.ApplicationProvider; 53 54 import com.android.server.accessibility.Flags; 55 import com.android.settings.R; 56 import com.android.settings.SettingsActivity; 57 import com.android.settings.SubSettings; 58 import com.android.settings.testutils.AccessibilityTestUtils; 59 import com.android.settings.testutils.shadow.SettingsShadowResources; 60 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 61 import com.android.settingslib.utils.StringUtil; 62 63 import org.junit.Before; 64 import org.junit.Rule; 65 import org.junit.Test; 66 import org.junit.runner.RunWith; 67 import org.mockito.Mock; 68 import org.mockito.junit.MockitoJUnit; 69 import org.mockito.junit.MockitoRule; 70 import org.robolectric.Robolectric; 71 import org.robolectric.RobolectricTestRunner; 72 import org.robolectric.annotation.Config; 73 import org.robolectric.shadows.ShadowAccessibilityManager; 74 import org.robolectric.shadows.ShadowLooper; 75 76 import java.util.Map; 77 78 /** Tests for {@link AccessibilityShortcutsTutorial}. */ 79 @Config(shadows = SettingsShadowResources.class) 80 @RunWith(RobolectricTestRunner.class) 81 public final class AccessibilityShortcutsTutorialTest { 82 private static final String FAKE_FEATURE_NAME = "Fake Feature Name"; 83 84 @Rule 85 public final MockitoRule mMockitoRule = MockitoJUnit.rule(); 86 @Rule 87 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 88 @Mock 89 private DialogInterface.OnClickListener mOnClickListener; 90 @Mock 91 private DialogInterface.OnDismissListener mOnDismissListener; 92 private final Context mContext = ApplicationProvider.getApplicationContext(); 93 private int mShortcutTypes; 94 95 @Before setUp()96 public void setUp() { 97 mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat); 98 mShortcutTypes = /* initial */ 0; 99 } 100 101 @Test(expected = IllegalArgumentException.class) createTutorialPages_shortcutListIsEmpty_throwsException()102 public void createTutorialPages_shortcutListIsEmpty_throwsException() { 103 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 104 } 105 106 @Test createTutorialPages_turnOnTripleTapShortcut_hasOnePage()107 public void createTutorialPages_turnOnTripleTapShortcut_hasOnePage() { 108 mShortcutTypes |= TRIPLETAP; 109 110 final AlertDialog alertDialog = 111 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 112 113 assertThat( 114 createShortcutTutorialPages( 115 mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false) 116 ).hasSize(/* expectedSize= */ 1); 117 assertThat(alertDialog).isNotNull(); 118 } 119 120 @Test 121 @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE) createTutorialPages_turnOnTwoFingerTripleTapShortcut_hasOnePage()122 public void createTutorialPages_turnOnTwoFingerTripleTapShortcut_hasOnePage() { 123 mShortcutTypes |= TWOFINGER_DOUBLETAP; 124 125 final AlertDialog alertDialog = 126 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 127 128 assertThat( 129 createShortcutTutorialPages( 130 mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false) 131 ).hasSize(/* expectedSize= */ 1); 132 assertThat(alertDialog).isNotNull(); 133 } 134 135 @Test createTutorialPages_turnOnQuickSettingShortcut_hasOnePage()136 public void createTutorialPages_turnOnQuickSettingShortcut_hasOnePage() { 137 mShortcutTypes |= QUICK_SETTINGS; 138 139 final AlertDialog alertDialog = 140 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 141 142 assertThat( 143 createShortcutTutorialPages( 144 mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false) 145 ).hasSize(/* expectedSize= */ 1); 146 assertThat(alertDialog).isNotNull(); 147 } 148 149 @Test createTutorialPages_turnOnSoftwareShortcut_hasOnePage()150 public void createTutorialPages_turnOnSoftwareShortcut_hasOnePage() { 151 mShortcutTypes |= SOFTWARE; 152 153 final AlertDialog alertDialog = 154 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 155 156 assertThat( 157 createShortcutTutorialPages( 158 mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false) 159 ).hasSize(/* expectedSize= */ 1); 160 assertThat(alertDialog).isNotNull(); 161 } 162 163 @Test createTutorialPages_turnOnSoftwareAndHardwareShortcuts_hasTwoPages()164 public void createTutorialPages_turnOnSoftwareAndHardwareShortcuts_hasTwoPages() { 165 mShortcutTypes |= SOFTWARE; 166 mShortcutTypes |= HARDWARE; 167 168 final AlertDialog alertDialog = 169 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 170 171 assertThat( 172 createShortcutTutorialPages( 173 mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false) 174 ).hasSize(/* expectedSize= */ 2); 175 assertThat(alertDialog).isNotNull(); 176 } 177 178 @Test createTutorialPages_turnOnA11yGestureShortcut_linkButtonShownWithText()179 public void createTutorialPages_turnOnA11yGestureShortcut_linkButtonShownWithText() { 180 mShortcutTypes |= SOFTWARE; 181 AccessibilityTestUtils.setSoftwareShortcutMode( 182 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false); 183 184 final AlertDialog alertDialog = 185 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 186 alertDialog.show(); 187 ShadowLooper.idleMainLooper(); 188 189 Button btn = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE); 190 assertThat(btn).isNotNull(); 191 assertThat(btn.getVisibility()).isEqualTo(View.VISIBLE); 192 assertThat(btn.getText().toString()).isEqualTo( 193 mContext.getString( 194 R.string.accessibility_tutorial_dialog_configure_software_shortcut_type)); 195 } 196 197 @Test createTutorialPages_turnOnA11yNavButtonShortcut_linkButtonShownWithText()198 public void createTutorialPages_turnOnA11yNavButtonShortcut_linkButtonShownWithText() { 199 mShortcutTypes |= SOFTWARE; 200 AccessibilityTestUtils.setSoftwareShortcutMode( 201 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false); 202 203 final AlertDialog alertDialog = 204 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 205 alertDialog.show(); 206 ShadowLooper.idleMainLooper(); 207 208 Button btn = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE); 209 assertThat(btn).isNotNull(); 210 assertThat(btn.getVisibility()).isEqualTo(View.VISIBLE); 211 assertThat(btn.getText().toString()).isEqualTo( 212 mContext.getString( 213 R.string.accessibility_tutorial_dialog_configure_software_shortcut_type)); 214 } 215 216 @Test createTutorialPages_turnOnFloatingButtonShortcut_linkButtonShownWithText()217 public void createTutorialPages_turnOnFloatingButtonShortcut_linkButtonShownWithText() { 218 mShortcutTypes |= SOFTWARE; 219 AccessibilityTestUtils.setSoftwareShortcutMode( 220 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true); 221 222 final AlertDialog alertDialog = 223 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 224 alertDialog.show(); 225 ShadowLooper.idleMainLooper(); 226 227 Button btn = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE); 228 assertThat(btn).isNotNull(); 229 assertThat(btn.getVisibility()).isEqualTo(View.VISIBLE); 230 assertThat(btn.getText().toString()).isEqualTo( 231 mContext.getString(R.string.accessibility_tutorial_dialog_link_button)); 232 } 233 234 @Test createTutorialPages_turnOnHardwareShortcut_linkButtonGone()235 public void createTutorialPages_turnOnHardwareShortcut_linkButtonGone() { 236 mShortcutTypes |= HARDWARE; 237 238 final AlertDialog alertDialog = 239 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 240 alertDialog.show(); 241 ShadowLooper.idleMainLooper(); 242 243 assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility()) 244 .isEqualTo(View.GONE); 245 } 246 247 @Test createTutorialPages_turnOnSoftwareShortcut_showFromSuW_linkButtonGone()248 public void createTutorialPages_turnOnSoftwareShortcut_showFromSuW_linkButtonGone() { 249 mShortcutTypes |= SOFTWARE; 250 251 final AlertDialog alertDialog = 252 createAccessibilityTutorialDialogForSetupWizard( 253 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 254 alertDialog.show(); 255 ShadowLooper.idleMainLooper(); 256 257 assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility()) 258 .isEqualTo(View.GONE); 259 } 260 261 @Test createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOn_verifyText()262 public void createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOn_verifyText() { 263 mShortcutTypes |= QUICK_SETTINGS; 264 setTouchExplorationEnabled(true); 265 final String expectedTitle = mContext.getString( 266 R.string.accessibility_tutorial_dialog_title_quick_setting); 267 Map<String, Object> arguments = new ArrayMap<>(); 268 arguments.put("count", 2); 269 arguments.put("featureName", FAKE_FEATURE_NAME); 270 final CharSequence instruction = StringUtil.getIcuPluralsString(mContext, 271 arguments, 272 R.string.accessibility_tutorial_dialog_message_quick_setting); 273 final SpannableStringBuilder expectedInstruction = new SpannableStringBuilder(); 274 expectedInstruction 275 .append(mContext.getText( 276 R.string.accessibility_tutorial_dialog_shortcut_unavailable_in_suw)) 277 .append("\n\n"); 278 expectedInstruction.append(instruction); 279 280 final AlertDialog alertDialog = 281 createAccessibilityTutorialDialogForSetupWizard( 282 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 283 alertDialog.show(); 284 ShadowLooper.idleMainLooper(); 285 286 verifyTutorialTitleAndInstruction( 287 alertDialog, 288 expectedTitle, 289 expectedInstruction.toString()); 290 } 291 292 @Test createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOn_verifyText()293 public void createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOn_verifyText() { 294 mShortcutTypes |= QUICK_SETTINGS; 295 setTouchExplorationEnabled(true); 296 final String expectedTitle = mContext.getString( 297 R.string.accessibility_tutorial_dialog_title_quick_setting); 298 Map<String, Object> arguments = new ArrayMap<>(); 299 arguments.put("count", 2); 300 arguments.put("featureName", FAKE_FEATURE_NAME); 301 final CharSequence expectedInstruction = StringUtil.getIcuPluralsString(mContext, 302 arguments, 303 R.string.accessibility_tutorial_dialog_message_quick_setting); 304 305 final AlertDialog alertDialog = 306 createAccessibilityTutorialDialog( 307 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 308 alertDialog.show(); 309 ShadowLooper.idleMainLooper(); 310 311 verifyTutorialTitleAndInstruction( 312 alertDialog, 313 expectedTitle, 314 expectedInstruction.toString()); 315 } 316 317 @Test createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOff_verifyText()318 public void createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOff_verifyText() { 319 mShortcutTypes |= QUICK_SETTINGS; 320 setTouchExplorationEnabled(false); 321 final String expectedTitle = mContext.getString( 322 R.string.accessibility_tutorial_dialog_title_quick_setting); 323 Map<String, Object> arguments = new ArrayMap<>(); 324 arguments.put("count", 1); 325 arguments.put("featureName", FAKE_FEATURE_NAME); 326 final CharSequence instruction = StringUtil.getIcuPluralsString(mContext, 327 arguments, 328 R.string.accessibility_tutorial_dialog_message_quick_setting); 329 final SpannableStringBuilder expectedInstruction = new SpannableStringBuilder(); 330 expectedInstruction.append(mContext.getText( 331 R.string.accessibility_tutorial_dialog_shortcut_unavailable_in_suw)) 332 .append("\n\n"); 333 expectedInstruction.append(instruction); 334 335 final AlertDialog alertDialog = 336 createAccessibilityTutorialDialogForSetupWizard( 337 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 338 alertDialog.show(); 339 ShadowLooper.idleMainLooper(); 340 341 verifyTutorialTitleAndInstruction( 342 alertDialog, 343 expectedTitle, 344 expectedInstruction.toString()); 345 } 346 347 @Test createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOff_verifyText()348 public void createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOff_verifyText() { 349 mShortcutTypes |= QUICK_SETTINGS; 350 setTouchExplorationEnabled(false); 351 final String expectedTitle = mContext.getString( 352 R.string.accessibility_tutorial_dialog_title_quick_setting); 353 Map<String, Object> arguments = new ArrayMap<>(); 354 arguments.put("count", 1); 355 arguments.put("featureName", FAKE_FEATURE_NAME); 356 final CharSequence expectedInstruction = StringUtil.getIcuPluralsString(mContext, 357 arguments, 358 R.string.accessibility_tutorial_dialog_message_quick_setting); 359 360 final AlertDialog alertDialog = 361 createAccessibilityTutorialDialog( 362 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 363 alertDialog.show(); 364 ShadowLooper.idleMainLooper(); 365 366 verifyTutorialTitleAndInstruction( 367 alertDialog, 368 expectedTitle, 369 expectedInstruction.toString()); 370 } 371 372 @Test createAccessibilityTutorialDialog_volumeKeysShortcut_verifyText()373 public void createAccessibilityTutorialDialog_volumeKeysShortcut_verifyText() { 374 mShortcutTypes |= HARDWARE; 375 final String expectedTitle = mContext.getString( 376 R.string.accessibility_tutorial_dialog_title_volume); 377 final CharSequence expectedInstruction = mContext.getString( 378 R.string.accessibility_tutorial_dialog_message_volume); 379 380 final AlertDialog alertDialog = 381 createAccessibilityTutorialDialog( 382 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 383 alertDialog.show(); 384 ShadowLooper.idleMainLooper(); 385 386 verifyTutorialTitleAndInstruction( 387 alertDialog, 388 expectedTitle, 389 expectedInstruction.toString()); 390 } 391 392 @Test createAccessibilityTutorialDialog_tripleTapShortcut_verifyText()393 public void createAccessibilityTutorialDialog_tripleTapShortcut_verifyText() { 394 mShortcutTypes |= TRIPLETAP; 395 final String expectedTitle = mContext.getString( 396 R.string.accessibility_tutorial_dialog_title_triple); 397 final CharSequence expectedInstruction = mContext.getString( 398 R.string.accessibility_tutorial_dialog_tripletap_instruction, 3); 399 400 final AlertDialog alertDialog = 401 createAccessibilityTutorialDialog( 402 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 403 alertDialog.show(); 404 ShadowLooper.idleMainLooper(); 405 406 verifyTutorialTitleAndInstruction( 407 alertDialog, 408 expectedTitle, 409 expectedInstruction.toString()); 410 } 411 412 @Test 413 @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE) createAccessibilityTutorialDialog_twoFingerDoubleTapShortcut_verifyText()414 public void createAccessibilityTutorialDialog_twoFingerDoubleTapShortcut_verifyText() { 415 mShortcutTypes |= TWOFINGER_DOUBLETAP; 416 final int numFingers = 2; 417 final String expectedTitle = mContext.getString( 418 R.string.accessibility_tutorial_dialog_title_two_finger_double, numFingers); 419 final String expectedInstruction = mContext.getString( 420 R.string.accessibility_tutorial_dialog_twofinger_doubletap_instruction, numFingers); 421 422 final AlertDialog alertDialog = 423 createAccessibilityTutorialDialog( 424 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 425 alertDialog.show(); 426 ShadowLooper.idleMainLooper(); 427 428 verifyTutorialTitleAndInstruction( 429 alertDialog, 430 expectedTitle, 431 expectedInstruction); 432 } 433 434 @Test createAccessibilityTutorialDialog_floatingButtonShortcut_verifyText()435 public void createAccessibilityTutorialDialog_floatingButtonShortcut_verifyText() { 436 mShortcutTypes |= SOFTWARE; 437 AccessibilityTestUtils.setSoftwareShortcutMode( 438 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true); 439 final String expectedTitle = mContext.getString( 440 R.string.accessibility_tutorial_dialog_title_button); 441 final String expectedInstruction = mContext.getString( 442 R.string.accessibility_tutorial_dialog_message_floating_button); 443 444 final AlertDialog alertDialog = 445 createAccessibilityTutorialDialog( 446 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 447 alertDialog.show(); 448 ShadowLooper.idleMainLooper(); 449 450 verifyTutorialTitleAndInstruction( 451 alertDialog, 452 expectedTitle, 453 expectedInstruction); 454 } 455 456 @Test createAccessibilityTutorialDialog_navA11yButtonShortcut_verifyText()457 public void createAccessibilityTutorialDialog_navA11yButtonShortcut_verifyText() { 458 mShortcutTypes |= SOFTWARE; 459 AccessibilityTestUtils.setSoftwareShortcutMode( 460 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false); 461 final String expectedTitle = mContext.getString( 462 R.string.accessibility_tutorial_dialog_title_button); 463 final String expectedInstruction = mContext.getString( 464 R.string.accessibility_tutorial_dialog_message_button); 465 466 final AlertDialog alertDialog = 467 createAccessibilityTutorialDialog( 468 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 469 alertDialog.show(); 470 ShadowLooper.idleMainLooper(); 471 472 verifyTutorialTitleAndInstruction( 473 alertDialog, 474 expectedTitle, 475 expectedInstruction); 476 } 477 478 @Test 479 @DisableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED) createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_verifyText()480 public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_verifyText() { 481 mShortcutTypes |= SOFTWARE; 482 setTouchExplorationEnabled(true); 483 AccessibilityTestUtils.setSoftwareShortcutMode( 484 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false); 485 486 final String expectedTitle = mContext.getString( 487 R.string.accessibility_tutorial_dialog_title_gesture); 488 final String expectedInstruction = StringUtil.getIcuPluralsString( 489 mContext, 490 /* count= */ 3, 491 R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction); 492 493 final AlertDialog alertDialog = 494 createAccessibilityTutorialDialog( 495 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 496 alertDialog.show(); 497 ShadowLooper.idleMainLooper(); 498 499 verifyTutorialTitleAndInstruction( 500 alertDialog, 501 expectedTitle, 502 expectedInstruction); 503 } 504 505 @Test 506 @EnableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED) createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_flag_verifyText()507 public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_flag_verifyText() { 508 mShortcutTypes |= GESTURE; 509 setTouchExplorationEnabled(true); 510 AccessibilityTestUtils.setSoftwareShortcutMode( 511 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false); 512 final String expectedTitle = mContext.getString( 513 R.string.accessibility_tutorial_dialog_title_gesture); 514 final String expectedInstruction = StringUtil.getIcuPluralsString( 515 mContext, 516 /* count= */ 3, 517 R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction); 518 519 final AlertDialog alertDialog = 520 createAccessibilityTutorialDialog( 521 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 522 alertDialog.show(); 523 ShadowLooper.idleMainLooper(); 524 525 verifyTutorialTitleAndInstruction( 526 alertDialog, 527 expectedTitle, 528 expectedInstruction); 529 } 530 531 @Test 532 @DisableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED) createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_verifyText()533 public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_verifyText() { 534 mShortcutTypes |= SOFTWARE; 535 setTouchExplorationEnabled(false); 536 AccessibilityTestUtils.setSoftwareShortcutMode( 537 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false); 538 final String expectedTitle = mContext.getString( 539 R.string.accessibility_tutorial_dialog_title_gesture); 540 final String expectedInstruction = StringUtil.getIcuPluralsString( 541 mContext, 542 /* count= */ 2, 543 R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction); 544 545 final AlertDialog alertDialog = 546 createAccessibilityTutorialDialog( 547 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 548 alertDialog.show(); 549 ShadowLooper.idleMainLooper(); 550 551 verifyTutorialTitleAndInstruction( 552 alertDialog, 553 expectedTitle, 554 expectedInstruction); 555 } 556 557 @Test 558 @EnableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED) createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_flag_verifyText()559 public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_flag_verifyText() { 560 mShortcutTypes |= GESTURE; 561 setTouchExplorationEnabled(false); 562 AccessibilityTestUtils.setSoftwareShortcutMode( 563 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false); 564 final String expectedTitle = mContext.getString( 565 R.string.accessibility_tutorial_dialog_title_gesture); 566 final String expectedInstruction = StringUtil.getIcuPluralsString( 567 mContext, 568 /* count= */ 2, 569 R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction); 570 571 final AlertDialog alertDialog = 572 createAccessibilityTutorialDialog( 573 mContext, mShortcutTypes, FAKE_FEATURE_NAME); 574 alertDialog.show(); 575 ShadowLooper.idleMainLooper(); 576 577 verifyTutorialTitleAndInstruction( 578 alertDialog, 579 expectedTitle, 580 expectedInstruction); 581 } 582 583 @Test performClickOnPositiveButton_turnOnSoftwareShortcut_dismiss()584 public void performClickOnPositiveButton_turnOnSoftwareShortcut_dismiss() { 585 mShortcutTypes |= SOFTWARE; 586 final AlertDialog alertDialog = 587 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME); 588 alertDialog.show(); 589 ShadowLooper.idleMainLooper(); 590 591 alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick(); 592 ShadowLooper.idleMainLooper(); 593 594 assertThat(alertDialog.isShowing()).isFalse(); 595 } 596 597 @Test performClickOnPositiveButton_turnOnSoftwareShortcut_callOnClickListener()598 public void performClickOnPositiveButton_turnOnSoftwareShortcut_callOnClickListener() { 599 mShortcutTypes |= SOFTWARE; 600 final AlertDialog alertDialog = 601 createAccessibilityTutorialDialog( 602 mContext, mShortcutTypes, mOnClickListener, FAKE_FEATURE_NAME); 603 alertDialog.show(); 604 ShadowLooper.idleMainLooper(); 605 606 alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick(); 607 ShadowLooper.idleMainLooper(); 608 609 verify(mOnClickListener).onClick(alertDialog, DialogInterface.BUTTON_POSITIVE); 610 } 611 612 @Test performClickOnNegativeButton_turnOnSoftwareShortcut_directToSettingsPage()613 public void performClickOnNegativeButton_turnOnSoftwareShortcut_directToSettingsPage() { 614 mShortcutTypes |= SOFTWARE; 615 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 616 final AlertDialog alertDialog = 617 createAccessibilityTutorialDialog(activity, mShortcutTypes, FAKE_FEATURE_NAME); 618 alertDialog.show(); 619 620 alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick(); 621 ShadowLooper.idleMainLooper(); 622 623 final Intent intent = shadowOf(activity).peekNextStartedActivity(); 624 assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName()); 625 assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) 626 .isEqualTo(AccessibilityButtonFragment.class.getName()); 627 assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1)) 628 .isEqualTo(SettingsEnums.SWITCH_SHORTCUT_DIALOG_ACCESSIBILITY_BUTTON_SETTINGS); 629 } 630 631 @Test performClickOnPositiveButton_turnOnGestureShortcut_callOnDismissListener()632 public void performClickOnPositiveButton_turnOnGestureShortcut_callOnDismissListener() { 633 final AlertDialog alertDialog = 634 showGestureNavigationTutorialDialog(mContext, mOnDismissListener); 635 636 alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick(); 637 ShadowLooper.idleMainLooper(); 638 639 assertThat(alertDialog.isShowing()).isFalse(); 640 verify(mOnDismissListener).onDismiss(alertDialog); 641 } 642 setTouchExplorationEnabled(boolean enable)643 private void setTouchExplorationEnabled(boolean enable) { 644 ShadowAccessibilityManager am = shadowOf( 645 mContext.getSystemService(AccessibilityManager.class)); 646 am.setTouchExplorationEnabled(enable); 647 } 648 verifyTutorialTitleAndInstruction(AlertDialog alertDialog, String expectedTitle, String expectedInstruction)649 private void verifyTutorialTitleAndInstruction(AlertDialog alertDialog, String expectedTitle, 650 String expectedInstruction) { 651 TextSwitcher titleView = alertDialog.findViewById(R.id.title); 652 assertThat(titleView).isNotNull(); 653 assertThat(((TextView) titleView.getCurrentView()).getText().toString()).isEqualTo( 654 expectedTitle); 655 TextSwitcher instructionView = alertDialog.findViewById(R.id.instruction); 656 assertThat(instructionView).isNotNull(); 657 assertThat(((TextView) instructionView.getCurrentView()).getText().toString()).isEqualTo( 658 expectedInstruction); 659 } 660 } 661