diff --git a/res/values/strings.xml b/res/values/strings.xml
index 88f57001419..73795e2c9de 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5395,6 +5395,8 @@
To use an accessibility feature, swipe up from the bottom of the screen with 3 fingers.\n\nTo switch between features, swipe up with 3 fingers and hold.
Got it
+
+ Accessibility button settings
%1$s shortcut
diff --git a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
index 773c9878e9d..95469d4bc2f 100644
--- a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
+++ b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
@@ -21,6 +21,7 @@ import static android.view.View.VISIBLE;
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
@@ -57,6 +58,7 @@ import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieDrawable;
@@ -130,12 +132,29 @@ public final class AccessibilityGestureNavigationTutorial {
}
static AlertDialog createAccessibilityTutorialDialog(Context context, int shortcutTypes,
- @Nullable DialogInterface.OnClickListener negativeButtonListener) {
- return new AlertDialog.Builder(context)
- .setView(createShortcutNavigationContentView(context, shortcutTypes))
- .setNegativeButton(R.string.accessibility_tutorial_dialog_button,
- negativeButtonListener)
+ @Nullable DialogInterface.OnClickListener actionButtonListener) {
+
+ final int category = SettingsEnums.SWITCH_SHORTCUT_DIALOG_ACCESSIBILITY_BUTTON_SETTINGS;
+ final DialogInterface.OnClickListener linkButtonListener =
+ (dialog, which) -> new SubSettingLauncher(context)
+ .setDestination(AccessibilityButtonFragment.class.getName())
+ .setSourceMetricsCategory(category)
+ .launch();
+
+ final AlertDialog alertDialog = new AlertDialog.Builder(context)
+ .setNegativeButton(R.string.accessibility_tutorial_dialog_link_button,
+ linkButtonListener)
+ .setPositiveButton(R.string.accessibility_tutorial_dialog_button,
+ actionButtonListener)
.create();
+
+ final TutorialPageChangeListener.OnPageSelectedCallback callback =
+ type -> alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(
+ type == UserShortcutType.SOFTWARE ? VISIBLE : GONE);
+
+ alertDialog.setView(createShortcutNavigationContentView(context, shortcutTypes, callback));
+
+ return alertDialog;
}
/**
@@ -311,7 +330,9 @@ public final class AccessibilityGestureNavigationTutorial {
return inflater.inflate(R.layout.accessibility_lottie_animation_view, /* root= */ null);
}
- private static View createShortcutNavigationContentView(Context context, int shortcutTypes) {
+ private static View createShortcutNavigationContentView(Context context, int shortcutTypes,
+ TutorialPageChangeListener.OnPageSelectedCallback onPageSelectedCallback) {
+
final LayoutInflater inflater = context.getSystemService(LayoutInflater.class);
final View contentView = inflater.inflate(
R.layout.accessibility_shortcut_tutorial_dialog, /* root= */ null);
@@ -342,9 +363,10 @@ public final class AccessibilityGestureNavigationTutorial {
viewPager.setImportantForAccessibility(tutorialPages.size() > 1
? View.IMPORTANT_FOR_ACCESSIBILITY_YES
: View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
- viewPager.addOnPageChangeListener(
- new TutorialPageChangeListener(context, viewPager, title, instruction,
- tutorialPages));
+
+ TutorialPageChangeListener listener = new TutorialPageChangeListener(context, viewPager,
+ title, instruction, tutorialPages);
+ listener.setOnPageSelectedCallback(onPageSelectedCallback);
return contentView;
}
@@ -365,6 +387,7 @@ public final class AccessibilityGestureNavigationTutorial {
}
private static TutorialPage createSoftwareTutorialPage(@NonNull Context context) {
+ final int type = UserShortcutType.SOFTWARE;
final CharSequence title = getSoftwareTitle(context);
final View image = createSoftwareImage(context);
final CharSequence instruction = getSoftwareInstruction(context);
@@ -372,10 +395,11 @@ public final class AccessibilityGestureNavigationTutorial {
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
- return new TutorialPage(title, image, indicatorIcon, instruction);
+ return new TutorialPage(type, title, image, indicatorIcon, instruction);
}
private static TutorialPage createHardwareTutorialPage(@NonNull Context context) {
+ final int type = UserShortcutType.HARDWARE;
final CharSequence title =
context.getText(R.string.accessibility_tutorial_dialog_title_volume);
final View image =
@@ -386,10 +410,11 @@ public final class AccessibilityGestureNavigationTutorial {
context.getText(R.string.accessibility_tutorial_dialog_message_volume);
indicatorIcon.setEnabled(false);
- return new TutorialPage(title, image, indicatorIcon, instruction);
+ return new TutorialPage(type, title, image, indicatorIcon, instruction);
}
private static TutorialPage createTripleTapTutorialPage(@NonNull Context context) {
+ final int type = UserShortcutType.TRIPLETAP;
final CharSequence title =
context.getText(R.string.accessibility_tutorial_dialog_title_triple);
final View image =
@@ -401,7 +426,7 @@ public final class AccessibilityGestureNavigationTutorial {
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
- return new TutorialPage(title, image, indicatorIcon, instruction);
+ return new TutorialPage(type, title, image, indicatorIcon, instruction);
}
@VisibleForTesting
@@ -485,13 +510,15 @@ public final class AccessibilityGestureNavigationTutorial {
}
private static class TutorialPage {
+ private final int mType;
private final CharSequence mTitle;
private final View mIllustrationView;
private final ImageView mIndicatorIcon;
private final CharSequence mInstruction;
- TutorialPage(CharSequence title, View illustrationView, ImageView indicatorIcon,
+ TutorialPage(int type, CharSequence title, View illustrationView, ImageView indicatorIcon,
CharSequence instruction) {
+ this.mType = type;
this.mTitle = title;
this.mIllustrationView = illustrationView;
this.mIndicatorIcon = indicatorIcon;
@@ -500,6 +527,10 @@ public final class AccessibilityGestureNavigationTutorial {
setupIllustrationChildViewsGravity();
}
+ public int getType() {
+ return mType;
+ }
+
public CharSequence getTitle() {
return mTitle;
}
@@ -541,6 +572,7 @@ public final class AccessibilityGestureNavigationTutorial {
private final TextSwitcher mInstruction;
private final List mTutorialPages;
private final ViewPager mViewPager;
+ private OnPageSelectedCallback mOnPageSelectedCallback;
TutorialPageChangeListener(Context context, ViewPager viewPager, ViewGroup title,
ViewGroup instruction, List tutorialPages) {
@@ -549,6 +581,14 @@ public final class AccessibilityGestureNavigationTutorial {
this.mTitle = (TextSwitcher) title;
this.mInstruction = (TextSwitcher) instruction;
this.mTutorialPages = tutorialPages;
+ this.mOnPageSelectedCallback = null;
+
+ this.mViewPager.addOnPageChangeListener(this);
+ }
+
+ public void setOnPageSelectedCallback(
+ OnPageSelectedCallback callback) {
+ this.mOnPageSelectedCallback = callback;
}
@Override
@@ -589,11 +629,22 @@ public final class AccessibilityGestureNavigationTutorial {
mViewPager.setContentDescription(
mContext.getString(R.string.accessibility_tutorial_pager,
currentPageNumber, mTutorialPages.size()));
+
+ if (mOnPageSelectedCallback != null) {
+ mOnPageSelectedCallback.onPageSelected(mTutorialPages.get(position).getType());
+ }
}
@Override
public void onPageScrollStateChanged(int state) {
// Do nothing.
}
+
+ /** The interface that provides a callback method after tutorial page is selected. */
+ private interface OnPageSelectedCallback {
+
+ /** The callback method after tutorial page is selected. */
+ void onPageSelected(int type);
+ }
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
index 6efdcf7a7e2..ceb630c6d3b 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
@@ -23,14 +23,21 @@ import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutT
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
+import static org.robolectric.Shadows.shadowOf;
+import android.app.Activity;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import androidx.appcompat.app.AlertDialog;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SubSettings;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Rule;
@@ -39,6 +46,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AccessibilityGestureNavigationTutorial}. */
@@ -103,26 +111,44 @@ public final class AccessibilityGestureNavigationTutorialTest {
}
@Test
- public void performClickOnNegativeButton_turnOnSoftwareShortcut_dismiss() {
+ public void performClickOnPositiveButton_turnOnSoftwareShortcut_dismiss() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
alertDialog.show();
- alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
assertThat(alertDialog.isShowing()).isFalse();
}
@Test
- public void performClickOnNegativeButton_turnOnSoftwareShortcut_callOnClickListener() {
+ public void performClickOnPositiveButton_turnOnSoftwareShortcut_callOnClickListener() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes, mMockOnClickListener);
alertDialog.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
+
+ verify(mMockOnClickListener).onClick(alertDialog, DialogInterface.BUTTON_POSITIVE);
+ }
+
+ @Test
+ public void performClickOnNegativeButton_turnOnSoftwareShortcut_directToSettingsPage() {
+ mShortcutTypes |= UserShortcutType.SOFTWARE;
+ Activity activity = Robolectric.buildActivity(Activity.class).create().get();
+ final AlertDialog alertDialog =
+ createAccessibilityTutorialDialog(activity, mShortcutTypes, mMockOnClickListener);
+ alertDialog.show();
+
alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();
- verify(mMockOnClickListener).onClick(alertDialog, DialogInterface.BUTTON_NEGATIVE);
+ final Intent intent = shadowOf(activity).peekNextStartedActivity();
+ assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
+ assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(AccessibilityButtonFragment.class.getName());
+ assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
+ .isEqualTo(SettingsEnums.SWITCH_SHORTCUT_DIALOG_ACCESSIBILITY_BUTTON_SETTINGS);
}
}