Merge "Refactoring A11y shortcut functions in Settings to use GESTURE" into main

This commit is contained in:
Riley Jones
2024-09-30 19:38:10 +00:00
committed by Android (Google) Code Review
15 changed files with 515 additions and 414 deletions

View File

@@ -49,9 +49,14 @@ public class AccessibilityButtonFooterPreferenceController extends
public void displayPreference(PreferenceScreen screen) {
// Need to update footerPreference's data before super.displayPreference(), then it will use
// data to update related property of footerPreference.
final int titleResource = AccessibilityUtil.isGestureNavigateEnabled(mContext)
? R.string.accessibility_button_gesture_description
: R.string.accessibility_button_description;
final int titleResource;
if (android.provider.Flags.a11yStandaloneGestureEnabled()) {
titleResource = R.string.accessibility_button_description;
} else {
titleResource = AccessibilityUtil.isGestureNavigateEnabled(mContext)
? R.string.accessibility_button_gesture_description
: R.string.accessibility_button_description;
}
final CharSequence footerText = Html.fromHtml(
MessageFormat.format(mContext.getString(titleResource), 1, 2, 3),
Html.FROM_HTML_MODE_COMPACT);

View File

@@ -61,7 +61,12 @@ public class AccessibilityButtonPreferenceController extends BasePreferenceContr
}
private int getPreferenceTitleResource() {
return AccessibilityUtil.isGestureNavigateEnabled(mContext)
? R.string.accessibility_button_gesture_title : R.string.accessibility_button_title;
if (android.provider.Flags.a11yStandaloneGestureEnabled()) {
return R.string.accessibility_button_title;
} else {
return AccessibilityUtil.isGestureNavigateEnabled(mContext)
? R.string.accessibility_button_gesture_title
: R.string.accessibility_button_title;
}
}
}

View File

@@ -17,10 +17,8 @@
package com.android.settings.accessibility;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.DEFAULT;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
import static com.android.settings.accessibility.AccessibilityUtil.getShortcutSummaryList;
import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_GENERAL_CATEGORY;
import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_QS_TOOLTIP_TYPE;
@@ -30,7 +28,6 @@ import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.icu.text.CaseMap;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
@@ -46,18 +43,15 @@ import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.utils.LocaleUtils;
import com.google.android.setupcompat.util.WizardManagerHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Base class for accessibility fragments shortcut functions and dialog management.
@@ -340,37 +334,7 @@ public abstract class AccessibilityShortcutPreferenceFragment extends Restricted
}
final int shortcutTypes = getUserPreferredShortcutTypes();
// LINT.IfChange(shortcut_type_ui_order)
final List<CharSequence> list = new ArrayList<>();
if (android.view.accessibility.Flags.a11yQsShortcut()) {
if (hasShortcutType(shortcutTypes, QUICK_SETTINGS)) {
final CharSequence qsTitle = context.getText(
R.string.accessibility_feature_shortcut_setting_summary_quick_settings);
list.add(qsTitle);
}
}
if (hasShortcutType(shortcutTypes, SOFTWARE)) {
list.add(getSoftwareShortcutTypeSummary(context));
}
if (hasShortcutType(shortcutTypes, HARDWARE)) {
final CharSequence hardwareTitle = context.getText(
R.string.accessibility_shortcut_hardware_keyword);
list.add(hardwareTitle);
}
// LINT.ThenChange(/res/xml/accessibility_edit_shortcuts.xml:shortcut_type_ui_order)
// Show software shortcut if first time to use.
if (list.isEmpty()) {
list.add(getSoftwareShortcutTypeSummary(context));
}
return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */
null, LocaleUtils.getConcatenatedString(list));
}
private boolean hasShortcutType(int value, @UserShortcutType int type) {
return (value & type) == type;
return getShortcutSummaryList(context, shortcutTypes);
}
protected void updateShortcutPreferenceData() {

View File

@@ -16,15 +16,19 @@
package com.android.settings.accessibility;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TRIPLETAP;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TWOFINGER_DOUBLETAP;
import android.annotation.SuppressLint;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
@@ -60,7 +64,9 @@ import androidx.core.widget.TextViewCompat;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.android.server.accessibility.Flags;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.utils.StringUtil;
@@ -396,95 +402,84 @@ public final class AccessibilityShortcutsTutorial {
return textView;
}
private static TutorialPage createSoftwareTutorialPage(@NonNull Context context) {
final int type = SOFTWARE;
final CharSequence title = getSoftwareTitle(context);
final View image = createSoftwareImage(context);
final CharSequence instruction = getSoftwareInstruction(context);
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
return new TutorialPage(type, title, image, indicatorIcon, instruction);
@SuppressLint("SwitchIntDef")
private static CharSequence getShortcutTitle(
@NonNull Context context, @UserShortcutType int shortcutType, int buttonMode) {
return switch (shortcutType) {
case HARDWARE -> context.getText(R.string.accessibility_tutorial_dialog_title_volume);
case SOFTWARE -> getSoftwareTitle(context, buttonMode);
case GESTURE -> context.getText(R.string.accessibility_tutorial_dialog_title_gesture);
case TRIPLETAP -> context.getText(R.string.accessibility_tutorial_dialog_title_triple);
case TWOFINGER_DOUBLETAP -> context.getString(
R.string.accessibility_tutorial_dialog_title_two_finger_double, 2);
case QUICK_SETTINGS -> context.getText(
R.string.accessibility_tutorial_dialog_title_quick_setting);
default -> "";
};
}
private static TutorialPage createHardwareTutorialPage(@NonNull Context context) {
final int type = HARDWARE;
final CharSequence title =
context.getText(R.string.accessibility_tutorial_dialog_title_volume);
final View image =
createIllustrationView(context, R.drawable.accessibility_shortcut_type_volume_keys);
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
final CharSequence instruction =
context.getText(R.string.accessibility_tutorial_dialog_message_volume);
indicatorIcon.setEnabled(false);
return new TutorialPage(type, title, image, indicatorIcon, instruction);
}
private static TutorialPage createTripleTapTutorialPage(@NonNull Context context) {
final int type = TRIPLETAP;
final CharSequence title =
context.getText(R.string.accessibility_tutorial_dialog_title_triple);
final View image =
createIllustrationViewWithImageRawResource(context,
R.raw.accessibility_shortcut_type_tripletap);
final CharSequence instruction = context.getString(
R.string.accessibility_tutorial_dialog_tripletap_instruction, 3);
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
return new TutorialPage(type, title, image, indicatorIcon, instruction);
}
private static TutorialPage createTwoFingerTripleTapTutorialPage(@NonNull Context context) {
final int type = TWOFINGER_DOUBLETAP;
final int numFingers = 2;
final CharSequence title = context.getString(
R.string.accessibility_tutorial_dialog_title_two_finger_double, numFingers);
final View image =
createIllustrationViewWithImageRawResource(context,
R.raw.accessibility_shortcut_type_2finger_doubletap);
final CharSequence instruction = context.getString(
R.string.accessibility_tutorial_dialog_twofinger_doubletap_instruction, numFingers);
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
return new TutorialPage(type, title, image, indicatorIcon, instruction);
}
private static TutorialPage createQuickSettingsTutorialPage(
@NonNull Context context, @NonNull CharSequence featureName, boolean inSetupWizard) {
final int type = QUICK_SETTINGS;
final CharSequence title =
context.getText(R.string.accessibility_tutorial_dialog_title_quick_setting);
final View image =
createIllustrationView(context,
@SuppressLint("SwitchIntDef")
private static View getShortcutImage(
@NonNull Context context, @UserShortcutType int shortcutType, int buttonMode) {
return switch (shortcutType) {
case HARDWARE -> createIllustrationView(
context, R.drawable.accessibility_shortcut_type_volume_keys);
case SOFTWARE -> createSoftwareImage(context, buttonMode);
case GESTURE -> createIllustrationView(context,
AccessibilityUtil.isTouchExploreEnabled(context)
? R.drawable.accessibility_shortcut_type_gesture_touch_explore_on
: R.drawable.accessibility_shortcut_type_gesture);
case TRIPLETAP -> createIllustrationViewWithImageRawResource(context,
R.raw.accessibility_shortcut_type_tripletap);
case TWOFINGER_DOUBLETAP -> createIllustrationViewWithImageRawResource(context,
R.raw.accessibility_shortcut_type_2finger_doubletap);
case QUICK_SETTINGS -> {
View v = createIllustrationView(context,
R.drawable.accessibility_shortcut_type_quick_settings);
// Remove the unneeded background, since the main image already includes a background
image.findViewById(R.id.image_background).setVisibility(GONE);
final int numFingers = AccessibilityUtil.isTouchExploreEnabled(context) ? 2 : 1;
Map<String, Object> arguments = new ArrayMap<>();
arguments.put("count", numFingers);
arguments.put("featureName", featureName);
final CharSequence instruction = StringUtil.getIcuPluralsString(context,
arguments,
R.string.accessibility_tutorial_dialog_message_quick_setting);
final SpannableStringBuilder tutorialText = new SpannableStringBuilder();
if (inSetupWizard) {
tutorialText.append(context.getText(
R.string.accessibility_tutorial_dialog_shortcut_unavailable_in_suw))
.append("\n\n");
}
tutorialText.append(instruction);
View bg = v.findViewById(R.id.image_background);
if (bg != null) {
bg.setVisibility(GONE);
}
yield v;
}
default -> new View(context);
};
}
private static CharSequence getShortcutInstruction(
@NonNull Context context, @UserShortcutType int shortcutType, int buttonMode,
@NonNull CharSequence featureName, boolean inSetupWizard) {
return switch (shortcutType) {
case HARDWARE -> context.getText(R.string.accessibility_tutorial_dialog_message_volume);
case SOFTWARE -> getSoftwareInstruction(context, buttonMode);
case GESTURE -> StringUtil.getIcuPluralsString(
context,
AccessibilityUtil.isTouchExploreEnabled(context) ? 3 : 2,
R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction);
case TRIPLETAP -> context.getString(
R.string.accessibility_tutorial_dialog_tripletap_instruction, 3);
case TWOFINGER_DOUBLETAP -> context.getString(
R.string.accessibility_tutorial_dialog_twofinger_doubletap_instruction, 2);
case QUICK_SETTINGS -> getQuickSettingsInstruction(context, featureName, inSetupWizard);
default -> "";
};
}
@SuppressLint("SwitchIntDef")
private static TutorialPage createShortcutTutorialPage(
@NonNull Context context, @UserShortcutType int shortcutType, int buttonMode,
@NonNull CharSequence featureName, boolean inSetupWizard) {
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
return new TutorialPage(type, title, image, indicatorIcon, tutorialText);
return new TutorialPage(shortcutType,
getShortcutTitle(context, shortcutType, buttonMode),
getShortcutImage(context, shortcutType, buttonMode),
createImageView(context, R.drawable.ic_accessibility_page_indicator),
getShortcutInstruction(
context, shortcutType, buttonMode, featureName, inSetupWizard));
}
/**
@@ -497,79 +492,58 @@ public final class AccessibilityShortcutsTutorial {
boolean inSetupWizard) {
// LINT.IfChange(shortcut_type_ui_order)
final List<TutorialPage> tutorialPages = new ArrayList<>();
if (android.view.accessibility.Flags.a11yQsShortcut()) {
if ((shortcutTypes & QUICK_SETTINGS)
== QUICK_SETTINGS) {
tutorialPages.add(
createQuickSettingsTutorialPage(context, featureName, inSetupWizard));
int buttonMode = ShortcutUtils.getButtonMode(context, context.getUserId());
for (int shortcutType: ShortcutConstants.USER_SHORTCUT_TYPES) {
if ((shortcutTypes & shortcutType) == 0) {
continue;
}
}
if ((shortcutTypes & SOFTWARE) == SOFTWARE) {
tutorialPages.add(createSoftwareTutorialPage(context));
}
if ((shortcutTypes & HARDWARE) == HARDWARE) {
tutorialPages.add(createHardwareTutorialPage(context));
}
if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
if ((shortcutTypes & TWOFINGER_DOUBLETAP)
== TWOFINGER_DOUBLETAP) {
tutorialPages.add(createTwoFingerTripleTapTutorialPage(context));
if ((shortcutTypes & QUICK_SETTINGS) == QUICK_SETTINGS
&& !android.view.accessibility.Flags.a11yQsShortcut()) {
continue;
}
}
if ((shortcutTypes & TRIPLETAP) == TRIPLETAP) {
tutorialPages.add(createTripleTapTutorialPage(context));
tutorialPages.add(
createShortcutTutorialPage(
context, shortcutType, buttonMode, featureName, inSetupWizard));
}
// LINT.ThenChange(/res/xml/accessibility_edit_shortcuts.xml:shortcut_type_ui_order)
return tutorialPages;
}
private static View createSoftwareImage(Context context) {
int resId;
if (AccessibilityUtil.isFloatingMenuEnabled(context)) {
return createIllustrationViewWithImageRawResource(
context, R.raw.accessibility_shortcut_type_fab);
} else if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
resId = AccessibilityUtil.isTouchExploreEnabled(context)
? R.drawable.accessibility_shortcut_type_gesture_touch_explore_on
: R.drawable.accessibility_shortcut_type_gesture;
} else {
resId = R.drawable.accessibility_shortcut_type_navbar;
}
return createIllustrationView(context, resId);
private static View createSoftwareImage(Context context, int buttonMode) {
return switch(buttonMode) {
case ACCESSIBILITY_BUTTON_MODE_GESTURE ->
createIllustrationView(context,
AccessibilityUtil.isTouchExploreEnabled(context)
? R.drawable
.accessibility_shortcut_type_gesture_touch_explore_on
: R.drawable.accessibility_shortcut_type_gesture);
case ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU ->
createIllustrationViewWithImageRawResource(
context, R.raw.accessibility_shortcut_type_fab);
default -> createIllustrationView(
context, R.drawable.accessibility_shortcut_type_navbar);
};
}
private static CharSequence getSoftwareTitle(Context context) {
int resId;
if (AccessibilityUtil.isFloatingMenuEnabled(context)) {
resId = R.string.accessibility_tutorial_dialog_title_button;
} else if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
resId = R.string.accessibility_tutorial_dialog_title_gesture;
} else {
resId = R.string.accessibility_tutorial_dialog_title_button;
}
return context.getText(resId);
private static CharSequence getSoftwareTitle(Context context, int buttonMode) {
return context.getText(buttonMode == ACCESSIBILITY_BUTTON_MODE_GESTURE
? R.string.accessibility_tutorial_dialog_title_gesture
: R.string.accessibility_tutorial_dialog_title_button);
}
private static CharSequence getSoftwareInstruction(Context context) {
final SpannableStringBuilder sb = new SpannableStringBuilder();
if (AccessibilityUtil.isFloatingMenuEnabled(context)) {
final int resId = R.string.accessibility_tutorial_dialog_message_floating_button;
sb.append(context.getText(resId));
} else if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
final int numFingers = AccessibilityUtil.isTouchExploreEnabled(context) ? 3 : 2;
sb.append(StringUtil.getIcuPluralsString(
private static CharSequence getSoftwareInstruction(Context context, int buttonMode) {
return switch(buttonMode) {
case ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU -> context.getText(
R.string.accessibility_tutorial_dialog_message_floating_button);
case ACCESSIBILITY_BUTTON_MODE_GESTURE -> StringUtil.getIcuPluralsString(
context,
numFingers,
R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction));
} else {
final int resId = R.string.accessibility_tutorial_dialog_message_button;
sb.append(getSoftwareInstructionWithIcon(context, context.getText(resId)));
}
return sb;
AccessibilityUtil.isTouchExploreEnabled(context) ? 3 : 2,
R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction);
default -> getSoftwareInstructionWithIcon(context,
context.getText(R.string.accessibility_tutorial_dialog_message_button));
};
}
private static CharSequence getSoftwareInstructionWithIcon(Context context, CharSequence text) {
@@ -590,6 +564,24 @@ public final class AccessibilityShortcutsTutorial {
return spannableInstruction;
}
private static CharSequence getQuickSettingsInstruction(
Context context, CharSequence featureName, boolean inSetupWizard) {
Map<String, Object> arguments = new ArrayMap<>();
arguments.put("count",
AccessibilityUtil.isTouchExploreEnabled(context) ? 2 : 1);
arguments.put("featureName", featureName);
final CharSequence pluralsString = StringUtil.getIcuPluralsString(
context, arguments,
R.string.accessibility_tutorial_dialog_message_quick_setting);
final SpannableStringBuilder tutorialText = new SpannableStringBuilder();
if (inSetupWizard) {
tutorialText.append(context.getText(R.string
.accessibility_tutorial_dialog_shortcut_unavailable_in_suw))
.append("\n\n");
}
return tutorialText.append(pluralsString);
}
private static class TutorialPage {
private final int mType;
private final CharSequence mTitle;

View File

@@ -22,10 +22,12 @@ import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.DEFAULT;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TRIPLETAP;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TWOFINGER_DOUBLETAP;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
@@ -33,6 +35,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
import android.icu.text.CaseMap;
import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;
@@ -47,11 +50,17 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.annotation.VisibleForTesting;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import com.android.settings.utils.LocaleUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringJoiner;
@@ -139,8 +148,8 @@ public final class AccessibilityUtil {
/** Determines if a gesture navigation bar is being used. */
public static boolean isGestureNavigateEnabled(Context context) {
return context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode)
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, -1)
== NAV_BAR_MODE_GESTURAL;
}
@@ -335,22 +344,23 @@ public final class AccessibilityUtil {
*/
static boolean hasValuesInSettings(Context context, int shortcutTypes,
@NonNull ComponentName componentName) {
boolean exist = false;
if ((shortcutTypes & SOFTWARE) == SOFTWARE) {
exist = hasValueInSettings(context, SOFTWARE, componentName);
}
if (((shortcutTypes & HARDWARE) == HARDWARE)) {
exist |= hasValueInSettings(context, HARDWARE, componentName);
}
if (android.view.accessibility.Flags.a11yQsShortcut()) {
if ((shortcutTypes & QUICK_SETTINGS)
== QUICK_SETTINGS) {
exist |= hasValueInSettings(context, QUICK_SETTINGS,
componentName);
for (int shortcutType : ShortcutConstants.USER_SHORTCUT_TYPES) {
if (!android.view.accessibility.Flags.a11yQsShortcut()) {
if ((shortcutType & QUICK_SETTINGS) == QUICK_SETTINGS) {
continue;
}
}
if (!android.provider.Flags.a11yStandaloneGestureEnabled()) {
if ((shortcutType & GESTURE) == GESTURE) {
continue;
}
}
if ((shortcutTypes & shortcutType) == shortcutType
&& hasValueInSettings(context, shortcutType, componentName)) {
return true;
}
}
return exist;
return false;
}
/**
@@ -364,29 +374,14 @@ public final class AccessibilityUtil {
@VisibleForTesting
static boolean hasValueInSettings(Context context, @UserShortcutType int shortcutType,
@NonNull ComponentName componentName) {
if (android.view.accessibility.Flags.a11yQsShortcut()) {
return ShortcutUtils.getShortcutTargetsFromSettings(
context, shortcutType, UserHandle.myUserId()
).contains(componentName.flattenToString());
}
final String targetKey = convertKeyFromSettings(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (TextUtils.isEmpty(targetString)) {
if (!android.view.accessibility.Flags.a11yQsShortcut()
&& (shortcutType & QUICK_SETTINGS) == QUICK_SETTINGS) {
return false;
}
sStringColonSplitter.setString(targetString);
while (sStringColonSplitter.hasNext()) {
final String name = sStringColonSplitter.next();
if ((componentName.flattenToString()).equals(name)) {
return true;
}
}
return false;
return ShortcutUtils.getShortcutTargetsFromSettings(
context, shortcutType, UserHandle.myUserId()
).contains(componentName.flattenToString());
}
/**
@@ -400,15 +395,19 @@ public final class AccessibilityUtil {
static int getUserShortcutTypesFromSettings(Context context,
@NonNull ComponentName componentName) {
int shortcutTypes = DEFAULT;
if (hasValuesInSettings(context, SOFTWARE, componentName)) {
shortcutTypes |= SOFTWARE;
}
if (hasValuesInSettings(context, HARDWARE, componentName)) {
shortcutTypes |= HARDWARE;
}
if (android.view.accessibility.Flags.a11yQsShortcut()) {
if (hasValuesInSettings(context, QUICK_SETTINGS, componentName)) {
shortcutTypes |= QUICK_SETTINGS;
for (int shortcutType : ShortcutConstants.USER_SHORTCUT_TYPES) {
if (!android.view.accessibility.Flags.a11yQsShortcut()) {
if ((shortcutType & QUICK_SETTINGS) == QUICK_SETTINGS) {
continue;
}
}
if (!android.provider.Flags.a11yStandaloneGestureEnabled()) {
if ((shortcutType & GESTURE) == GESTURE) {
continue;
}
}
if (hasValueInSettings(context, shortcutType, componentName)) {
shortcutTypes |= shortcutType;
}
}
@@ -505,4 +504,66 @@ public final class AccessibilityUtil {
Settings.Secure.SKIP_ACCESSIBILITY_SHORTCUT_DIALOG_TIMEOUT_RESTRICTION, /*
true */ 1);
}
/**
* Assembles a localized string describing the provided shortcut types.
*/
public static CharSequence getShortcutSummaryList(Context context, int shortcutTypes) {
final List<CharSequence> list = new ArrayList<>();
// LINT.IfChange(shortcut_type_ui_order)
for (int shortcutType : ShortcutConstants.USER_SHORTCUT_TYPES) {
if (!android.view.accessibility.Flags.a11yQsShortcut()
&& (shortcutType & QUICK_SETTINGS) == QUICK_SETTINGS) {
continue;
}
if (!android.provider.Flags.a11yStandaloneGestureEnabled()
&& (shortcutType & GESTURE) == GESTURE) {
continue;
}
if (!com.android.server.accessibility.Flags
.enableMagnificationMultipleFingerMultipleTapGesture()
&& (shortcutType & TWOFINGER_DOUBLETAP) == TWOFINGER_DOUBLETAP) {
continue;
}
if ((shortcutTypes & shortcutType) == shortcutType) {
list.add(switch (shortcutType) {
case QUICK_SETTINGS -> context.getText(
R.string.accessibility_feature_shortcut_setting_summary_quick_settings);
case SOFTWARE -> getSoftwareShortcutSummary(context);
case GESTURE -> context.getText(
R.string.accessibility_shortcut_edit_summary_software_gesture);
case HARDWARE -> context.getText(
R.string.accessibility_shortcut_hardware_keyword);
case TWOFINGER_DOUBLETAP -> context.getString(
R.string.accessibility_shortcut_two_finger_double_tap_keyword, 2);
case TRIPLETAP -> context.getText(
R.string.accessibility_shortcut_triple_tap_keyword);
default -> "";
});
}
}
list.sort(CharSequence::compare);
return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */
null, LocaleUtils.getConcatenatedString(list));
// LINT.ThenChange(/res/xml/accessibility_edit_shortcuts.xml:shortcut_type_ui_order)
}
@VisibleForTesting
static CharSequence getSoftwareShortcutSummary(Context context) {
if (android.provider.Flags.a11yStandaloneGestureEnabled()) {
return context.getText(R.string.accessibility_shortcut_edit_summary_software);
}
int resId;
if (AccessibilityUtil.isFloatingMenuEnabled(context)) {
resId = R.string.accessibility_shortcut_edit_summary_software;
} else if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
resId = R.string.accessibility_shortcut_edit_summary_software_gesture;
} else {
resId = R.string.accessibility_shortcut_edit_summary_software;
}
return context.getText(resId);
}
}

View File

@@ -17,10 +17,9 @@
package com.android.settings.accessibility;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.DEFAULT;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
import static com.android.settings.accessibility.AccessibilityUtil.getShortcutSummaryList;
import android.app.Activity;
import android.app.Dialog;
@@ -34,7 +33,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
import android.icu.text.CaseMap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -59,14 +57,12 @@ import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.utils.LocaleUtils;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settings.widget.SettingsMainSwitchPreference;
import com.android.settingslib.widget.IllustrationPreference;
@@ -76,7 +72,6 @@ import com.google.android.setupcompat.util.WizardManagerHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Base class for accessibility fragments with toggle, shortcut, some helper functions
@@ -627,10 +622,6 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
mFooterPreferenceController.displayPreference(screen);
}
private boolean hasShortcutType(int value, @UserShortcutType int type) {
return (value & type) == type;
}
protected CharSequence getShortcutTypeSummary(Context context) {
if (!mShortcutPreference.isSettingsEditable()) {
return context.getText(R.string.accessibility_shortcut_edit_dialog_title_hardware);
@@ -640,47 +631,9 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
return context.getText(R.string.accessibility_shortcut_state_off);
}
// LINT.IfChange(shortcut_type_ui_order)
final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(
context, mComponentName.flattenToString(), getDefaultShortcutTypes());
final List<CharSequence> list = new ArrayList<>();
if (android.view.accessibility.Flags.a11yQsShortcut()) {
if (hasShortcutType(shortcutTypes, QUICK_SETTINGS)) {
final CharSequence qsTitle = context.getText(
R.string.accessibility_feature_shortcut_setting_summary_quick_settings);
list.add(qsTitle);
}
}
if (hasShortcutType(shortcutTypes, SOFTWARE)) {
list.add(getSoftwareShortcutTypeSummary(context));
}
if (hasShortcutType(shortcutTypes, HARDWARE)) {
final CharSequence hardwareTitle = context.getText(
R.string.accessibility_shortcut_hardware_keyword);
list.add(hardwareTitle);
}
// LINT.ThenChange(/res/xml/accessibility_edit_shortcuts.xml:shortcut_type_ui_order)
// Show software shortcut if first time to use.
if (list.isEmpty()) {
list.add(getSoftwareShortcutTypeSummary(context));
}
return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */
null, LocaleUtils.getConcatenatedString(list));
}
private static CharSequence getSoftwareShortcutTypeSummary(Context context) {
int resId;
if (AccessibilityUtil.isFloatingMenuEnabled(context)) {
resId = R.string.accessibility_shortcut_edit_summary_software;
} else if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
resId = R.string.accessibility_shortcut_edit_summary_software_gesture;
} else {
resId = R.string.accessibility_shortcut_edit_summary_software;
}
return context.getText(resId);
return getShortcutSummaryList(context, shortcutTypes);
}
/**

View File

@@ -19,6 +19,7 @@ package com.android.settings.accessibility;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.DEFAULT;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
@@ -27,6 +28,7 @@ import static com.android.internal.accessibility.common.ShortcutConstants.UserSh
import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.android.settings.accessibility.AccessibilityUtil.getShortcutSummaryList;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
@@ -34,7 +36,6 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.icu.text.CaseMap;
import android.icu.text.MessageFormat;
import android.net.Uri;
import android.os.Bundle;
@@ -55,6 +56,7 @@ import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreferenceCompat;
import androidx.preference.TwoStatePreference;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.accessibility.Flags;
@@ -62,7 +64,6 @@ import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.utils.LocaleUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.widget.IllustrationPreference;
@@ -70,7 +71,6 @@ import com.google.android.setupcompat.util.WizardManagerHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringJoiner;
@@ -348,22 +348,6 @@ public class ToggleScreenMagnificationPreferenceFragment extends
mDialogDelegate = delegate;
}
private boolean hasShortcutType(int value, @UserShortcutType int type) {
return (value & type) == type;
}
private static CharSequence getSoftwareShortcutTypeSummary(Context context) {
int resId;
if (AccessibilityUtil.isFloatingMenuEnabled(context)) {
resId = R.string.accessibility_shortcut_edit_summary_software;
} else if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
resId = R.string.accessibility_shortcut_edit_summary_software_gesture;
} else {
resId = R.string.accessibility_shortcut_edit_summary_software;
}
return context.getText(resId);
}
@Override
protected void registerKeysToObserverCallback(
AccessibilitySettingsContentObserver contentObserver) {
@@ -423,47 +407,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends
return context.getText(R.string.switch_off_text);
}
final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(context,
MAGNIFICATION_CONTROLLER_NAME);
// LINT.IfChange(shortcut_type_ui_order)
final List<CharSequence> list = new ArrayList<>();
if (android.view.accessibility.Flags.a11yQsShortcut()) {
if (hasShortcutType(shortcutTypes, QUICK_SETTINGS)) {
final CharSequence qsTitle = context.getText(
R.string.accessibility_feature_shortcut_setting_summary_quick_settings);
list.add(qsTitle);
}
}
if (hasShortcutType(shortcutTypes, SOFTWARE)) {
list.add(getSoftwareShortcutTypeSummary(context));
}
if (hasShortcutType(shortcutTypes, HARDWARE)) {
final CharSequence hardwareTitle = context.getText(
R.string.accessibility_shortcut_hardware_keyword);
list.add(hardwareTitle);
}
if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
if (hasShortcutType(shortcutTypes, TWOFINGER_DOUBLETAP)) {
final CharSequence twoFingerDoubleTapTitle = context.getString(
R.string.accessibility_shortcut_two_finger_double_tap_keyword, 2);
list.add(twoFingerDoubleTapTitle);
}
}
if (hasShortcutType(shortcutTypes, TRIPLETAP)) {
final CharSequence tripleTapTitle = context.getText(
R.string.accessibility_shortcut_triple_tap_keyword);
list.add(tripleTapTitle);
}
// LINT.ThenChange(/res/xml/accessibility_edit_shortcuts.xml:shortcut_type_ui_order)
// Show software shortcut if first time to use.
if (list.isEmpty()) {
list.add(getSoftwareShortcutTypeSummary(context));
}
return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */
null, LocaleUtils.getConcatenatedString(list));
return getShortcutSummaryList(context,
PreferredShortcuts.retrieveUserShortcutType(context,
MAGNIFICATION_CONTROLLER_NAME));
}
@Override
@@ -595,6 +541,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends
if (((shortcutTypes & TRIPLETAP) == TRIPLETAP)) {
optInMagnificationValueToSettings(context, TRIPLETAP);
}
if (((shortcutTypes & GESTURE) == GESTURE)) {
optInMagnificationValueToSettings(context, GESTURE);
}
if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
if (((shortcutTypes & TWOFINGER_DOUBLETAP)
== TWOFINGER_DOUBLETAP)) {
@@ -680,6 +629,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends
if (((shortcutTypes & TRIPLETAP) == TRIPLETAP)) {
optOutMagnificationValueFromSettings(context, TRIPLETAP);
}
if (((shortcutTypes & GESTURE) == GESTURE)) {
optOutMagnificationValueFromSettings(context, GESTURE);
}
if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
if (((shortcutTypes & TWOFINGER_DOUBLETAP)
== TWOFINGER_DOUBLETAP)) {
@@ -749,25 +701,21 @@ public class ToggleScreenMagnificationPreferenceFragment extends
@VisibleForTesting
static boolean hasMagnificationValuesInSettings(Context context, int shortcutTypes) {
boolean exist = false;
if ((shortcutTypes & SOFTWARE) == SOFTWARE) {
exist = hasMagnificationValueInSettings(context, SOFTWARE);
}
if (((shortcutTypes & HARDWARE) == HARDWARE)) {
exist |= hasMagnificationValueInSettings(context, HARDWARE);
}
if (((shortcutTypes & TRIPLETAP) == TRIPLETAP)) {
exist |= hasMagnificationValueInSettings(context, TRIPLETAP);
}
if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
if (((shortcutTypes & TWOFINGER_DOUBLETAP)
== TWOFINGER_DOUBLETAP)) {
exist |= hasMagnificationValueInSettings(context,
TWOFINGER_DOUBLETAP);
for (int shortcutType : ShortcutConstants.USER_SHORTCUT_TYPES) {
if ((shortcutTypes & shortcutType) == 0) {
continue;
}
if (((shortcutType & TWOFINGER_DOUBLETAP)
== TWOFINGER_DOUBLETAP)
&& !Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
continue;
}
if (hasMagnificationValueInSettings(context, shortcutType)) {
return true;
}
}
return exist;
return false;
}
private static boolean hasMagnificationValueInSettings(Context context,
@@ -776,7 +724,6 @@ public class ToggleScreenMagnificationPreferenceFragment extends
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF) == ON;
}
if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
if (shortcutType == TWOFINGER_DOUBLETAP) {
return Settings.Secure.getInt(context.getContentResolver(),
@@ -805,20 +752,18 @@ public class ToggleScreenMagnificationPreferenceFragment extends
private static int getUserShortcutTypeFromSettings(Context context) {
int shortcutTypes = DEFAULT;
if (hasMagnificationValuesInSettings(context, SOFTWARE)) {
shortcutTypes |= SOFTWARE;
}
if (hasMagnificationValuesInSettings(context, HARDWARE)) {
shortcutTypes |= HARDWARE;
}
if (hasMagnificationValuesInSettings(context, TRIPLETAP)) {
shortcutTypes |= TRIPLETAP;
}
if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
if (hasMagnificationValuesInSettings(context, TWOFINGER_DOUBLETAP)) {
shortcutTypes |= TWOFINGER_DOUBLETAP;
for (int shortcutType : ShortcutConstants.USER_SHORTCUT_TYPES) {
if ((shortcutType & (TWOFINGER_DOUBLETAP | QUICK_SETTINGS | GESTURE | TRIPLETAP))
== shortcutType
&& !android.view.accessibility.Flags.a11yQsShortcut()) {
// These shortcuts will throw if we try to look up their settings without the flag.
continue;
}
if (hasMagnificationValueInSettings(context, shortcutType)) {
shortcutTypes |= shortcutType;
}
}
return shortcutTypes;
}

View File

@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
import static android.provider.Settings.Secure.NAVIGATION_MODE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -26,11 +28,17 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.icu.text.MessageFormat;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Flags;
import android.provider.Settings;
import android.text.Html;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import org.junit.Before;
@@ -47,6 +55,8 @@ import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonFooterPreferenceControllerTest {
@Rule
public final SetFlagsRule mCheckFlagsRule = new SetFlagsRule();
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
@@ -69,9 +79,12 @@ public class AccessibilityButtonFooterPreferenceControllerTest {
}
@Test
@DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void displayPreference_navigationGestureEnabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
ShortcutUtils.setButtonMode(
mContext, ACCESSIBILITY_BUTTON_MODE_GESTURE, mContext.getUserId());
mController.displayPreference(mScreen);
@@ -82,11 +95,26 @@ public class AccessibilityButtonFooterPreferenceControllerTest {
Html.FROM_HTML_MODE_COMPACT).toString());
}
@Test
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void displayPreference_navigationGestureEnabled_flag_setCorrectTitle() {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
assertThat(AccessibilityUtil.isGestureNavigateEnabled(mContext)).isTrue();
mController.displayPreference(mScreen);
assertThat(mPreference.getTitle().toString()).isEqualTo(
Html.fromHtml(
MessageFormat.format(mContext.getString(
R.string.accessibility_button_description), 1, 2, 3),
Html.FROM_HTML_MODE_COMPACT).toString());
}
@Test
public void displayPreference_navigationGestureDisabled_setCorrectTitle() {
when(mResources.getInteger(
com.android.internal.R.integer.config_navBarInteractionMode)).thenReturn(
NAV_BAR_MODE_2BUTTON);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_2BUTTON, mContext.getUserId());
mController.displayPreference(mScreen);

View File

@@ -32,6 +32,7 @@ import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Flags;
import android.provider.Settings;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.PreferenceManager;
@@ -92,8 +93,9 @@ public class AccessibilityButtonFragmentTest {
@Test
@DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void onCreate_navigationGestureEnabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
Settings.Secure.putIntForUser(
mContext.getContentResolver(), Settings.Secure.NAVIGATION_MODE,
NAV_BAR_MODE_GESTURAL, mContext.getUserId());
mFragment.onAttach(mContext);
mFragment.onCreate(Bundle.EMPTY);
@@ -104,9 +106,10 @@ public class AccessibilityButtonFragmentTest {
@Test
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void onCreate_navigationGestureEnabled_gestureFlag_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
public void onCreate_navigationGestureEnabled_flag_setCorrectTitle() {
Settings.Secure.putIntForUser(
mContext.getContentResolver(), Settings.Secure.NAVIGATION_MODE,
NAV_BAR_MODE_GESTURAL, mContext.getUserId());
mFragment.onAttach(mContext);
mFragment.onCreate(Bundle.EMPTY);
@@ -117,8 +120,9 @@ public class AccessibilityButtonFragmentTest {
@Test
public void onCreate_navigationBarEnabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
Settings.Secure.putIntForUser(
mContext.getContentResolver(), Settings.Secure.NAVIGATION_MODE,
NAV_BAR_MODE_2BUTTON, mContext.getUserId());
mFragment.onAttach(mContext);
mFragment.onCreate(Bundle.EMPTY);

View File

@@ -75,26 +75,25 @@ public class AccessibilityButtonGesturePreferenceControllerTest {
@Test
@DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void getAvailabilityStatus_navigationGestureEnabled_returnAvailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void
getAvailabilityStatus_navigationGestureEnabled_gestureFlag_conditionallyUnavailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
public void getAvailabilityStatus_navigationGestureEnabled_returnConditionallyUnavailable() {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_navigationGestureDisabled_returnConditionallyUnavailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_2BUTTON, mContext.getUserId());
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}

View File

@@ -69,16 +69,16 @@ public class AccessibilityButtonLocationPreferenceControllerTest {
@Test
public void getAvailabilityStatus_navigationGestureEnabled_returnConditionallyUnavailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_navigationGestureDisabled_returnAvailable() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_2BUTTON, mContext.getUserId());
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.accessibility;
import static android.provider.Settings.Secure.NAVIGATION_MODE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -25,6 +26,11 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Flags;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -50,6 +56,8 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonPreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Spy
@@ -72,9 +80,10 @@ public class AccessibilityButtonPreferenceControllerTest {
}
@Test
@DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void displayPreference_navigationGestureEnabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
mController.displayPreference(mScreen);
@@ -83,9 +92,10 @@ public class AccessibilityButtonPreferenceControllerTest {
}
@Test
public void displayPreference_navigationGestureDisabled_setCorrectTitle() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void displayPreference_navigationGestureEnabled_flag_setCorrectTitle() {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
mController.displayPreference(mScreen);
@@ -94,9 +104,21 @@ public class AccessibilityButtonPreferenceControllerTest {
}
@Test
public void displayPreference_navigationGestureDisabled_setCorrectTitle() {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_2BUTTON, mContext.getUserId());
mController.displayPreference(mScreen);
assertThat(mPreference.getTitle()).isEqualTo(
mContext.getText(R.string.accessibility_button_title));
}
@Test
@DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void updateDynamicRawDataToIndex_navigationGestureEnabled_setCorrectIndex() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_GESTURAL);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
List<SearchIndexableRaw> rawDataList = new ArrayList<>();
mController.updateDynamicRawDataToIndex(rawDataList);
@@ -109,10 +131,27 @@ public class AccessibilityButtonPreferenceControllerTest {
mResources.getString(R.string.accessibility_shortcuts_settings_title));
}
@Test
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void updateDynamicRawDataToIndex_navigationGestureEnabled_flag_setCorrectIndex() {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL, mContext.getUserId());
List<SearchIndexableRaw> rawDataList = new ArrayList<>();
mController.updateDynamicRawDataToIndex(rawDataList);
assertThat(rawDataList).hasSize(1);
SearchIndexableRaw raw = rawDataList.get(0);
assertThat(raw.title).isEqualTo(
mResources.getString(R.string.accessibility_button_title));
assertThat(raw.screenTitle).isEqualTo(
mResources.getString(R.string.accessibility_shortcuts_settings_title));
}
@Test
public void updateDynamicRawDataToIndex_navigationGestureDisabled_setCorrectIndex() {
when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode))
.thenReturn(NAV_BAR_MODE_2BUTTON);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
NAVIGATION_MODE, NAV_BAR_MODE_2BUTTON, mContext.getUserId());
List<SearchIndexableRaw> rawDataList = new ArrayList<>();
mController.updateDynamicRawDataToIndex(rawDataList);

View File

@@ -16,6 +16,7 @@
package com.android.settings.accessibility;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
@@ -36,6 +37,7 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.text.SpannableStringBuilder;
@@ -479,9 +481,37 @@ public final class AccessibilityShortcutsTutorialTest {
}
@Test
@DisableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_verifyText() {
mShortcutTypes |= SOFTWARE;
setTouchExplorationEnabled(true);
AccessibilityTestUtils.setSoftwareShortcutMode(
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
final String expectedTitle = mContext.getString(
R.string.accessibility_tutorial_dialog_title_gesture);
final String expectedInstruction = StringUtil.getIcuPluralsString(
mContext,
/* count= */ 3,
R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction);
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(
mContext, mShortcutTypes, FAKE_FEATURE_NAME);
alertDialog.show();
ShadowLooper.idleMainLooper();
verifyTutorialTitleAndInstruction(
alertDialog,
expectedTitle,
expectedInstruction);
}
@Test
@EnableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_flag_verifyText() {
mShortcutTypes |= GESTURE;
setTouchExplorationEnabled(true);
AccessibilityTestUtils.setSoftwareShortcutMode(
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
final String expectedTitle = mContext.getString(
@@ -504,6 +534,7 @@ public final class AccessibilityShortcutsTutorialTest {
}
@Test
@DisableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_verifyText() {
mShortcutTypes |= SOFTWARE;
setTouchExplorationEnabled(false);
@@ -528,6 +559,32 @@ public final class AccessibilityShortcutsTutorialTest {
expectedInstruction);
}
@Test
@EnableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_flag_verifyText() {
mShortcutTypes |= GESTURE;
setTouchExplorationEnabled(false);
AccessibilityTestUtils.setSoftwareShortcutMode(
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
final String expectedTitle = mContext.getString(
R.string.accessibility_tutorial_dialog_title_gesture);
final String expectedInstruction = StringUtil.getIcuPluralsString(
mContext,
/* count= */ 2,
R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction);
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(
mContext, mShortcutTypes, FAKE_FEATURE_NAME);
alertDialog.show();
ShadowLooper.idleMainLooper();
verifyTutorialTitleAndInstruction(
alertDialog,
expectedTitle,
expectedInstruction);
}
@Test
public void performClickOnPositiveButton_turnOnSoftwareShortcut_dismiss() {
mShortcutTypes |= SOFTWARE;

View File

@@ -16,6 +16,11 @@
package com.android.settings.accessibility;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
@@ -398,6 +403,49 @@ public final class AccessibilityUtilTest {
.isEqualTo(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
}
@Test
@EnableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void getSoftwareShortcutSummary_returnsSoftwareSummary() {
assertThat(AccessibilityUtil.getSoftwareShortcutSummary(mContext)).isEqualTo(
mContext.getText(R.string.accessibility_shortcut_edit_summary_software));
}
@Test
@DisableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void getSoftwareShortcutSummary_gestureMode_floatingButton_returnsSoftwareSummary() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
assertThat(AccessibilityUtil.getSoftwareShortcutSummary(mContext)).isEqualTo(
mContext.getText(R.string.accessibility_shortcut_edit_summary_software));
}
@Test
@DisableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void getSoftwareShortcutSummary_gestureMode_gesture_returnsGestureSummary() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_GESTURAL);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
ACCESSIBILITY_BUTTON_MODE_GESTURE);
assertThat(AccessibilityUtil.getSoftwareShortcutSummary(mContext)).isEqualTo(
mContext.getText(R.string.accessibility_shortcut_edit_summary_software_gesture));
}
@Test
@DisableFlags(android.provider.Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void getSoftwareShortcutSummary_navBarMode_returnsSoftwareSummary() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, NAV_BAR_MODE_3BUTTON);
assertThat(AccessibilityUtil.getSoftwareShortcutSummary(mContext)).isEqualTo(
mContext.getText(R.string.accessibility_shortcut_edit_summary_software));
}
private AccessibilityServiceInfo getMockAccessibilityServiceInfo() {
final ApplicationInfo applicationInfo = new ApplicationInfo();
final ServiceInfo serviceInfo = new ServiceInfo();

View File

@@ -17,11 +17,11 @@
package com.android.settings.testutils;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -35,8 +35,6 @@ import android.os.Build;
import android.provider.Settings;
import android.view.accessibility.AccessibilityManager;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
@@ -48,15 +46,18 @@ public class AccessibilityTestUtils {
public static void setSoftwareShortcutMode(
Context context, boolean gestureNavEnabled, boolean floatingButtonEnabled) {
int buttonMode = floatingButtonEnabled ? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : -1;
int buttonMode = ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
if (floatingButtonEnabled) {
buttonMode = ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
} else if (gestureNavEnabled) {
buttonMode = ACCESSIBILITY_BUTTON_MODE_GESTURE;
}
int navMode = gestureNavEnabled ? NAV_BAR_MODE_GESTURAL : NAV_BAR_MODE_3BUTTON;
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, buttonMode);
SettingsShadowResources.overrideResource(
com.android.internal.R.integer.config_navBarInteractionMode, navMode);
assertThat(context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode)).isEqualTo(navMode);
Settings.Secure.putIntForUser(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, buttonMode, context.getUserId());
Settings.Secure.putIntForUser(context.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, navMode, context.getUserId());
}
/**