• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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