Accessibility shortcut secondary action - save and restore shortcut key

- Implement onCheckboxClicked() to save shortcut key
- restore shortcut key when onViewCreated()
- Use preferredShortcutType to handle settings key

Bug: 142530063
Test: make -j52 RunSettingsRoboTests ROBOTEST_FILTER=AccessibilityUtilTest
Change-Id: Iabe636641968d346e52becea19b6e201ea5bc1fb
This commit is contained in:
jasonwshsu
2019-12-26 18:39:27 +08:00
parent 8b47bd8665
commit 8ef01d25fb
6 changed files with 542 additions and 154 deletions

View File

@@ -19,16 +19,20 @@ package com.android.settings.accessibility;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import com.android.settings.R; import com.android.settings.R;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.StringJoiner;
/** Provides utility methods to accessibility settings only. */ /** Provides utility methods to accessibility settings only. */
final class AccessibilityUtil { final class AccessibilityUtil {
@@ -56,6 +60,12 @@ final class AccessibilityUtil {
int INTUITIVE = 2; int INTUITIVE = 2;
} }
// TODO(b/147021230): Will move common functions and variables to
// android/internal/accessibility folder
private static final char COMPONENT_NAME_SEPARATOR = ':';
private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
/** /**
* Annotation for different shortcut type UI type. * Annotation for different shortcut type UI type.
* *
@@ -69,14 +79,14 @@ final class AccessibilityUtil {
*/ */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
ShortcutType.DEFAULT, PreferredShortcutType.DEFAULT,
ShortcutType.SOFTWARE, PreferredShortcutType.SOFTWARE,
ShortcutType.HARDWARE, PreferredShortcutType.HARDWARE,
ShortcutType.TRIPLETAP, PreferredShortcutType.TRIPLETAP,
}) })
/** Denotes the shortcut type. */ /** Denotes the shortcut type. */
public @interface ShortcutType { public @interface PreferredShortcutType {
int DEFAULT = 0; int DEFAULT = 0;
int SOFTWARE = 1; // 1 << 0 int SOFTWARE = 1; // 1 << 0
int HARDWARE = 2; // 1 << 1 int HARDWARE = 2; // 1 << 1
@@ -129,7 +139,7 @@ final class AccessibilityUtil {
} }
/** /**
* Gets the corresponding fragment type of a given accessibility service * Gets the corresponding fragment type of a given accessibility service.
* *
* @param accessibilityServiceInfo The accessibilityService's info * @param accessibilityServiceInfo The accessibilityService's info
* @return int from {@link AccessibilityServiceFragmentType} * @return int from {@link AccessibilityServiceFragmentType}
@@ -148,4 +158,112 @@ final class AccessibilityUtil {
? AccessibilityServiceFragmentType.INVISIBLE ? AccessibilityServiceFragmentType.INVISIBLE
: AccessibilityServiceFragmentType.INTUITIVE; : AccessibilityServiceFragmentType.INTUITIVE;
} }
/**
* Opts in component name into colon-separated {@code shortcutType} key's string in Settings.
*
* @param context The current context.
* @param shortcutType The preferred shortcut type user selected.
* @param componentName The component name that need to be opted in Settings.
*/
static void optInValueToSettings(Context context, @PreferredShortcutType int shortcutType,
@NonNull ComponentName componentName) {
final String targetKey = convertKeyFromSettings(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (TextUtils.isEmpty(targetString)) {
return;
}
if (hasValueInSettings(context, shortcutType, componentName)) {
return;
}
final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR));
joiner.add(targetString);
joiner.add(componentName.flattenToString());
Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString());
}
/**
* Opts out component name into colon-separated {@code shortcutType} key's string in Settings.
*
* @param context The current context.
* @param shortcutType The preferred shortcut type user selected.
* @param componentName The component name that need to be opted out from Settings.
*/
static void optOutValueFromSettings(Context context, @PreferredShortcutType int shortcutType,
@NonNull ComponentName componentName) {
final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR));
final String targetKey = convertKeyFromSettings(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (TextUtils.isEmpty(targetString)) {
return;
}
sStringColonSplitter.setString(targetString);
while (sStringColonSplitter.hasNext()) {
final String name = sStringColonSplitter.next();
if (TextUtils.isEmpty(name) || (componentName.flattenToString()).equals(name)) {
continue;
}
joiner.add(name);
}
Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString());
}
/**
* Returns if component name existed in Settings.
*
* @param context The current context.
* @param shortcutType The preferred shortcut type user selected.
* @param componentName The component name that need to be checked existed in Settings.
* @return {@code true} if componentName existed in Settings.
*/
static boolean hasValueInSettings(Context context, @PreferredShortcutType int shortcutType,
@NonNull ComponentName componentName) {
final String targetKey = convertKeyFromSettings(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (TextUtils.isEmpty(targetString)) {
return false;
}
sStringColonSplitter.setString(targetString);
while (sStringColonSplitter.hasNext()) {
final String name = sStringColonSplitter.next();
if ((componentName.flattenToString()).equals(name)) {
return true;
}
}
return false;
}
/**
* Converts {@link PreferredShortcutType} to key in Settings.
*
* @param shortcutType The shortcut type.
* @return Mapping key in Settings.
*/
static String convertKeyFromSettings(@PreferredShortcutType int shortcutType) {
switch (shortcutType) {
case PreferredShortcutType.SOFTWARE:
return Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
case PreferredShortcutType.HARDWARE:
return Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
case PreferredShortcutType.TRIPLETAP:
return Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
default:
throw new IllegalArgumentException(
"Unsupported preferredShortcutType " + shortcutType);
}
}
} }

View File

@@ -47,7 +47,7 @@ import androidx.preference.PreferenceScreen;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.ShortcutType; import com.android.settings.accessibility.AccessibilityUtil.PreferredShortcutType;
import com.android.settings.password.ConfirmDeviceCredentialActivity; import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.ToggleSwitch; import com.android.settings.widget.ToggleSwitch;
@@ -64,11 +64,11 @@ public class ToggleAccessibilityServicePreferenceFragment extends
ToggleFeaturePreferenceFragment implements ShortcutPreference.OnClickListener { ToggleFeaturePreferenceFragment implements ShortcutPreference.OnClickListener {
private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference"; private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference";
private static final String EXTRA_SHORTCUT_TYPE = "shortcutType"; private static final String EXTRA_PREFERRED_SHORTCUT_TYPE = "preferred_shortcutType";
// TODO(b/142530063): Check the new setting key to decide which summary should be shown. // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO; private static final String KEY_PREFERRED_SHORTCUT_TYPE = Settings.System.MASTER_MONO;
private ShortcutPreference mShortcutPreference; private ShortcutPreference mShortcutPreference;
private int mShortcutType = ShortcutType.DEFAULT; private int mPreferredShortcutType = PreferredShortcutType.DEFAULT;
private CheckBox mSoftwareTypeCheckBox; private CheckBox mSoftwareTypeCheckBox;
private CheckBox mHardwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox;
@@ -136,15 +136,16 @@ public class ToggleAccessibilityServicePreferenceFragment extends
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType); outState.putInt(EXTRA_PREFERRED_SHORTCUT_TYPE, mPreferredShortcutType);
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume();
mSettingsContentObserver.register(getContentResolver()); mSettingsContentObserver.register(getContentResolver());
updateSwitchBarToggleSwitch(); updateSwitchBarToggleSwitch();
super.onResume(); updateShortcutPreference();
} }
@Override @Override
@@ -225,8 +226,8 @@ public class ToggleAccessibilityServicePreferenceFragment extends
} }
private void updateAlertDialogCheckState() { private void updateAlertDialogCheckState() {
updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE); updateCheckStatus(mSoftwareTypeCheckBox, PreferredShortcutType.SOFTWARE);
updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE); updateCheckStatus(mHardwareTypeCheckBox, PreferredShortcutType.HARDWARE);
} }
private void updateAlertDialogEnableState() { private void updateAlertDialogEnableState() {
@@ -240,48 +241,48 @@ public class ToggleAccessibilityServicePreferenceFragment extends
} }
} }
private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) { private void updateCheckStatus(CheckBox checkBox, @PreferredShortcutType int type) {
checkBox.setChecked((mShortcutType & type) == type); checkBox.setChecked((mPreferredShortcutType & type) == type);
checkBox.setOnClickListener(v -> { checkBox.setOnClickListener(v -> {
updateShortcutType(false); updatePreferredShortcutType(false);
updateAlertDialogEnableState(); updateAlertDialogEnableState();
}); });
} }
private void updateShortcutType(boolean saveToDB) { private void updatePreferredShortcutType(boolean saveToDB) {
mShortcutType = ShortcutType.DEFAULT; mPreferredShortcutType = PreferredShortcutType.DEFAULT;
if (mSoftwareTypeCheckBox.isChecked()) { if (mSoftwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.SOFTWARE; mPreferredShortcutType |= PreferredShortcutType.SOFTWARE;
} }
if (mHardwareTypeCheckBox.isChecked()) { if (mHardwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.HARDWARE; mPreferredShortcutType |= PreferredShortcutType.HARDWARE;
} }
if (saveToDB) { if (saveToDB) {
setShortcutType(mShortcutType); setPreferredShortcutType(mPreferredShortcutType);
} }
} }
private void setSecureIntValue(String key, @ShortcutType int value) { private void setSecureIntValue(String key, @PreferredShortcutType int value) {
Settings.Secure.putIntForUser(getPrefContext().getContentResolver(), Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
key, value, getPrefContext().getContentResolver().getUserId()); key, value, getPrefContext().getContentResolver().getUserId());
} }
private void setShortcutType(@ShortcutType int type) { private void setPreferredShortcutType(@PreferredShortcutType int type) {
setSecureIntValue(KEY_SHORTCUT_TYPE, type); setSecureIntValue(KEY_PREFERRED_SHORTCUT_TYPE, type);
} }
private String getShortcutTypeSummary(Context context) { private String getShortcutTypeSummary(Context context) {
final int shortcutType = getShortcutType(context); final int shortcutType = getPreferredShortcutType(context);
final CharSequence softwareTitle = final CharSequence softwareTitle =
context.getText(AccessibilityUtil.isGestureNavigateEnabled(context) context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
? R.string.accessibility_shortcut_edit_dialog_title_software_gesture ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
: R.string.accessibility_shortcut_edit_dialog_title_software); : R.string.accessibility_shortcut_edit_dialog_title_software);
List<CharSequence> list = new ArrayList<>(); List<CharSequence> list = new ArrayList<>();
if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) { if ((shortcutType & PreferredShortcutType.SOFTWARE) == PreferredShortcutType.SOFTWARE) {
list.add(softwareTitle); list.add(softwareTitle);
} }
if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) { if ((shortcutType & PreferredShortcutType.HARDWARE) == PreferredShortcutType.HARDWARE) {
final CharSequence hardwareTitle = context.getText( final CharSequence hardwareTitle = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_hardware); R.string.accessibility_shortcut_edit_dialog_title_hardware);
list.add(hardwareTitle); list.add(hardwareTitle);
@@ -295,20 +296,22 @@ public class ToggleAccessibilityServicePreferenceFragment extends
return AccessibilityUtil.capitalize(joinStrings); return AccessibilityUtil.capitalize(joinStrings);
} }
@ShortcutType @PreferredShortcutType
private int getShortcutType(Context context) { private int getPreferredShortcutType(Context context) {
return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE); return getSecureIntValue(context, KEY_PREFERRED_SHORTCUT_TYPE,
PreferredShortcutType.SOFTWARE);
} }
@ShortcutType @PreferredShortcutType
private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) { private int getSecureIntValue(Context context, String key,
@PreferredShortcutType int defaultValue) {
return Settings.Secure.getIntForUser( return Settings.Secure.getIntForUser(
context.getContentResolver(), context.getContentResolver(),
key, defaultValue, context.getContentResolver().getUserId()); key, defaultValue, context.getContentResolver().getUserId());
} }
private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) { private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
updateShortcutType(true); updatePreferredShortcutType(true);
mShortcutPreference.setSummary( mShortcutPreference.setSummary(
getShortcutTypeSummary(getPrefContext())); getShortcutTypeSummary(getPrefContext()));
} }
@@ -339,12 +342,13 @@ public class ToggleAccessibilityServicePreferenceFragment extends
} }
private void initShortcutPreference(Bundle savedInstanceState) { private void initShortcutPreference(Bundle savedInstanceState) {
// Restore the Shortcut type // Restore the PreferredShortcut type
if (savedInstanceState != null) { if (savedInstanceState != null) {
mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT); mPreferredShortcutType = savedInstanceState.getInt(EXTRA_PREFERRED_SHORTCUT_TYPE,
PreferredShortcutType.DEFAULT);
} }
if (mShortcutType == ShortcutType.DEFAULT) { if (mPreferredShortcutType == PreferredShortcutType.DEFAULT) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
} }
// Initial ShortcutPreference widget // Initial ShortcutPreference widget
@@ -353,17 +357,31 @@ public class ToggleAccessibilityServicePreferenceFragment extends
preferenceScreen.getContext(), null); preferenceScreen.getContext(), null);
mShortcutPreference.setPersistent(false); mShortcutPreference.setPersistent(false);
mShortcutPreference.setKey(getShortcutPreferenceKey()); mShortcutPreference.setKey(getShortcutPreferenceKey());
mShortcutPreference.setOrder(-1);
mShortcutPreference.setTitle(R.string.accessibility_shortcut_title); mShortcutPreference.setTitle(R.string.accessibility_shortcut_title);
mShortcutPreference.setOnClickListener(this);
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
mShortcutPreference.setOnClickListener(this);
// Put the shortcutPreference before settingsPreference. // Put the shortcutPreference before settingsPreference.
mShortcutPreference.setOrder(-1); mShortcutPreference.setOrder(-1);
preferenceScreen.addPreference(mShortcutPreference);
// TODO(b/142530063): Check the new key to decide whether checkbox should be checked. // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
preferenceScreen.addPreference(mShortcutPreference);
} }
public String getShortcutPreferenceKey() { private void updateShortcutPreference() {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
ShortcutPreference shortcutPreference = preferenceScreen.findPreference(
getShortcutPreferenceKey());
if (shortcutPreference != null) {
// TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
shortcutPreference.setChecked(
AccessibilityUtil.hasValueInSettings(getContext(),
PreferredShortcutType.SOFTWARE,
mComponentName));
}
}
protected String getShortcutPreferenceKey() {
return KEY_SHORTCUT_PREFERENCE; return KEY_SHORTCUT_PREFERENCE;
} }
@@ -464,15 +482,21 @@ public class ToggleAccessibilityServicePreferenceFragment extends
@Override @Override
public void onCheckboxClicked(ShortcutPreference preference) { public void onCheckboxClicked(ShortcutPreference preference) {
if (preference.getChecked()) { if (preference.getChecked()) {
// TODO(b/142530063): Enable shortcut when checkbox is checked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
AccessibilityUtil.optInValueToSettings(getContext(), PreferredShortcutType.SOFTWARE,
mComponentName);
} else { } else {
// TODO(b/142530063): Disable shortcut when checkbox is unchecked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
AccessibilityUtil.optOutValueFromSettings(getContext(), PreferredShortcutType.SOFTWARE,
mComponentName);
} }
} }
@Override @Override
public void onSettingsClicked(ShortcutPreference preference) { public void onSettingsClicked(ShortcutPreference preference) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
showDialog(DialogType.EDIT_SHORTCUT); showDialog(DialogType.EDIT_SHORTCUT);
} }

View File

@@ -16,8 +16,11 @@
package com.android.settings.accessibility; package com.android.settings.accessibility;
import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME;
import android.app.Dialog; import android.app.Dialog;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.net.Uri; import android.net.Uri;
@@ -36,7 +39,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.ShortcutType; import com.android.settings.accessibility.AccessibilityUtil.PreferredShortcutType;
import com.android.settings.accessibility.AccessibilityUtil.State; import com.android.settings.accessibility.AccessibilityUtil.State;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBar;
@@ -62,7 +65,7 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
private final Handler mHandler = new Handler(); private final Handler mHandler = new Handler();
private ShortcutPreference mShortcutPreference; private ShortcutPreference mShortcutPreference;
private SettingsContentObserver mSettingsContentObserver; private SettingsContentObserver mSettingsContentObserver;
private int mShortcutType = ShortcutType.DEFAULT; private int mPreferredShortcutType = PreferredShortcutType.DEFAULT;
private CheckBox mSoftwareTypeCheckBox; private CheckBox mSoftwareTypeCheckBox;
private CheckBox mHardwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox;
@@ -139,10 +142,16 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType); outState.putInt(EXTRA_SHORTCUT_TYPE, mPreferredShortcutType);
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@Override
public void onResume() {
super.onResume();
updateShortcutPreference();
}
@Override @Override
public Dialog onCreateDialog(int dialogId) { public Dialog onCreateDialog(int dialogId) {
if (dialogId == DIALOG_ID_EDIT_SHORTCUT) { if (dialogId == DIALOG_ID_EDIT_SHORTCUT) {
@@ -167,8 +176,8 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
} }
private void updateAlertDialogCheckState() { private void updateAlertDialogCheckState() {
updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE); updateCheckStatus(mSoftwareTypeCheckBox, PreferredShortcutType.SOFTWARE);
updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE); updateCheckStatus(mHardwareTypeCheckBox, PreferredShortcutType.HARDWARE);
} }
private void updateAlertDialogEnableState() { private void updateAlertDialogEnableState() {
@@ -182,48 +191,48 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
} }
} }
private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) { private void updateCheckStatus(CheckBox checkBox, @PreferredShortcutType int type) {
checkBox.setChecked((mShortcutType & type) == type); checkBox.setChecked((mPreferredShortcutType & type) == type);
checkBox.setOnClickListener(v -> { checkBox.setOnClickListener(v -> {
updateShortcutType(false); updatePreferredShortcutType(false);
updateAlertDialogEnableState(); updateAlertDialogEnableState();
}); });
} }
private void updateShortcutType(boolean saveToDB) { private void updatePreferredShortcutType(boolean saveToDB) {
mShortcutType = ShortcutType.DEFAULT; mPreferredShortcutType = PreferredShortcutType.DEFAULT;
if (mSoftwareTypeCheckBox.isChecked()) { if (mSoftwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.SOFTWARE; mPreferredShortcutType |= PreferredShortcutType.SOFTWARE;
} }
if (mHardwareTypeCheckBox.isChecked()) { if (mHardwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.HARDWARE; mPreferredShortcutType |= PreferredShortcutType.HARDWARE;
} }
if (saveToDB) { if (saveToDB) {
setShortcutType(mShortcutType); setPreferredShortcutType(mPreferredShortcutType);
} }
} }
private void setSecureIntValue(String key, @ShortcutType int value) { private void setSecureIntValue(String key, @PreferredShortcutType int value) {
Settings.Secure.putIntForUser(getPrefContext().getContentResolver(), Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
key, value, getPrefContext().getContentResolver().getUserId()); key, value, getPrefContext().getContentResolver().getUserId());
} }
private void setShortcutType(@ShortcutType int type) { private void setPreferredShortcutType(@PreferredShortcutType int type) {
setSecureIntValue(KEY_SHORTCUT_TYPE, type); setSecureIntValue(KEY_SHORTCUT_TYPE, type);
} }
private String getShortcutTypeSummary(Context context) { private String getShortcutTypeSummary(Context context) {
final int shortcutType = getShortcutType(context); final int shortcutType = getPreferredShortcutType(context);
final CharSequence softwareTitle = final CharSequence softwareTitle =
context.getText(AccessibilityUtil.isGestureNavigateEnabled(context) context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
? R.string.accessibility_shortcut_edit_dialog_title_software_gesture ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
: R.string.accessibility_shortcut_edit_dialog_title_software); : R.string.accessibility_shortcut_edit_dialog_title_software);
List<CharSequence> list = new ArrayList<>(); List<CharSequence> list = new ArrayList<>();
if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) { if ((shortcutType & PreferredShortcutType.SOFTWARE) == PreferredShortcutType.SOFTWARE) {
list.add(softwareTitle); list.add(softwareTitle);
} }
if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) { if ((shortcutType & PreferredShortcutType.HARDWARE) == PreferredShortcutType.HARDWARE) {
final CharSequence hardwareTitle = context.getText( final CharSequence hardwareTitle = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_hardware); R.string.accessibility_shortcut_edit_dialog_title_hardware);
list.add(hardwareTitle); list.add(hardwareTitle);
@@ -237,20 +246,21 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
return AccessibilityUtil.capitalize(joinStrings); return AccessibilityUtil.capitalize(joinStrings);
} }
@ShortcutType @PreferredShortcutType
private int getShortcutType(Context context) { private int getPreferredShortcutType(Context context) {
return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE); return getSecureIntValue(context, KEY_SHORTCUT_TYPE, PreferredShortcutType.SOFTWARE);
} }
@ShortcutType @PreferredShortcutType
private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) { private int getSecureIntValue(Context context, String key,
@PreferredShortcutType int defaultValue) {
return Settings.Secure.getIntForUser( return Settings.Secure.getIntForUser(
context.getContentResolver(), context.getContentResolver(),
key, defaultValue, context.getContentResolver().getUserId()); key, defaultValue, context.getContentResolver().getUserId());
} }
private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) { private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
updateShortcutType(true); updatePreferredShortcutType(true);
mShortcutPreference.setSummary( mShortcutPreference.setSummary(
getShortcutTypeSummary(getPrefContext())); getShortcutTypeSummary(getPrefContext()));
} }
@@ -264,12 +274,13 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
} }
private void initShortcutPreference(Bundle savedInstanceState) { private void initShortcutPreference(Bundle savedInstanceState) {
// Restore the Shortcut type // Restore the PreferredShortcut type
if (savedInstanceState != null) { if (savedInstanceState != null) {
mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT); mPreferredShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE,
PreferredShortcutType.DEFAULT);
} }
if (mShortcutType == ShortcutType.DEFAULT) { if (mPreferredShortcutType == PreferredShortcutType.DEFAULT) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
} }
// Initial ShortcutPreference widget // Initial ShortcutPreference widget
@@ -277,33 +288,58 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
mShortcutPreference = new ShortcutPreference( mShortcutPreference = new ShortcutPreference(
preferenceScreen.getContext(), null); preferenceScreen.getContext(), null);
final Preference previewPreference = findPreference(PREVIEW_PREFERENCE_KEY); final Preference previewPreference = findPreference(PREVIEW_PREFERENCE_KEY);
// Put the shortcutPreference before radioButtonPreference.
mShortcutPreference.setPersistent(false); mShortcutPreference.setPersistent(false);
mShortcutPreference.setKey(getShortcutPreferenceKey()); mShortcutPreference.setKey(getShortcutPreferenceKey());
mShortcutPreference.setTitle(R.string.accessibility_shortcut_title); mShortcutPreference.setTitle(R.string.accessibility_shortcut_title);
mShortcutPreference.setOnClickListener(this);
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
mShortcutPreference.setOnClickListener(this);
// Put the shortcutPreference before previewPreference.
mShortcutPreference.setOrder(previewPreference.getOrder() - 1); mShortcutPreference.setOrder(previewPreference.getOrder() - 1);
preferenceScreen.addPreference(mShortcutPreference);
// TODO(b/142530063): Check the new key to decide whether checkbox should be checked. // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
preferenceScreen.addPreference(mShortcutPreference);
} }
public String getShortcutPreferenceKey() { private void updateShortcutPreference() {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
final ShortcutPreference shortcutPreference = preferenceScreen.findPreference(
getShortcutPreferenceKey());
if (shortcutPreference != null) {
// TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
shortcutPreference.setChecked(
AccessibilityUtil.hasValueInSettings(getContext(),
PreferredShortcutType.SOFTWARE,
getComponentName()));
}
}
private String getShortcutPreferenceKey() {
return KEY_SHORTCUT_PREFERENCE; return KEY_SHORTCUT_PREFERENCE;
} }
private ComponentName getComponentName() {
return COLOR_INVERSION_COMPONENT_NAME;
}
@Override @Override
public void onCheckboxClicked(ShortcutPreference preference) { public void onCheckboxClicked(ShortcutPreference preference) {
if (preference.getChecked()) { if (preference.getChecked()) {
// TODO(b/142530063): Enable shortcut when checkbox is checked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
AccessibilityUtil.optInValueToSettings(getContext(), PreferredShortcutType.SOFTWARE,
getComponentName());
} else { } else {
// TODO(b/142530063): Disable shortcut when checkbox is unchecked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
AccessibilityUtil.optOutValueFromSettings(getContext(), PreferredShortcutType.SOFTWARE,
getComponentName());
} }
} }
@Override @Override
public void onSettingsClicked(ShortcutPreference preference) { public void onSettingsClicked(ShortcutPreference preference) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
showDialog(DIALOG_ID_EDIT_SHORTCUT); showDialog(DIALOG_ID_EDIT_SHORTCUT);
} }

View File

@@ -16,8 +16,11 @@
package com.android.settings.accessibility; package com.android.settings.accessibility;
import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
import android.app.Dialog; import android.app.Dialog;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.res.Resources; import android.content.res.Resources;
@@ -35,7 +38,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.ShortcutType; import com.android.settings.accessibility.AccessibilityUtil.PreferredShortcutType;
import com.android.settings.accessibility.AccessibilityUtil.State; import com.android.settings.accessibility.AccessibilityUtil.State;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBar;
@@ -57,10 +60,11 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
private static final String EXTRA_SHORTCUT_TYPE = "shortcutType"; private static final String EXTRA_SHORTCUT_TYPE = "shortcutType";
// TODO(b/142530063): Check the new setting key to decide which summary should be shown. // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO; private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO;
private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference";
private static final int DIALOG_ID_EDIT_SHORTCUT = 1; private static final int DIALOG_ID_EDIT_SHORTCUT = 1;
private static final List<AbstractPreferenceController> sControllers = new ArrayList<>(); private static final List<AbstractPreferenceController> sControllers = new ArrayList<>();
private ShortcutPreference mShortcutPreference; private ShortcutPreference mShortcutPreference;
private int mShortcutType = ShortcutType.DEFAULT; private int mPreferredShortcutType = PreferredShortcutType.DEFAULT;
private CheckBox mSoftwareTypeCheckBox; private CheckBox mSoftwareTypeCheckBox;
private CheckBox mHardwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox;
@@ -95,7 +99,7 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType); outState.putInt(EXTRA_SHORTCUT_TYPE, mPreferredShortcutType);
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@@ -108,6 +112,7 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
((DaltonizerRadioButtonPreferenceController) controller).displayPreference( ((DaltonizerRadioButtonPreferenceController) controller).displayPreference(
getPreferenceScreen()); getPreferenceScreen());
} }
updateShortcutPreference();
} }
@Override @Override
@@ -143,8 +148,8 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
} }
private void updateAlertDialogCheckState() { private void updateAlertDialogCheckState() {
updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE); updateCheckStatus(mSoftwareTypeCheckBox, PreferredShortcutType.SOFTWARE);
updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE); updateCheckStatus(mHardwareTypeCheckBox, PreferredShortcutType.HARDWARE);
} }
private void updateAlertDialogEnableState() { private void updateAlertDialogEnableState() {
@@ -158,48 +163,48 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
} }
} }
private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) { private void updateCheckStatus(CheckBox checkBox, @PreferredShortcutType int type) {
checkBox.setChecked((mShortcutType & type) == type); checkBox.setChecked((mPreferredShortcutType & type) == type);
checkBox.setOnClickListener(v -> { checkBox.setOnClickListener(v -> {
updateShortcutType(false); updatePreferredShortcutType(false);
updateAlertDialogEnableState(); updateAlertDialogEnableState();
}); });
} }
private void updateShortcutType(boolean saveToDB) { private void updatePreferredShortcutType(boolean saveToDB) {
mShortcutType = ShortcutType.DEFAULT; mPreferredShortcutType = PreferredShortcutType.DEFAULT;
if (mSoftwareTypeCheckBox.isChecked()) { if (mSoftwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.SOFTWARE; mPreferredShortcutType |= PreferredShortcutType.SOFTWARE;
} }
if (mHardwareTypeCheckBox.isChecked()) { if (mHardwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.HARDWARE; mPreferredShortcutType |= PreferredShortcutType.HARDWARE;
} }
if (saveToDB) { if (saveToDB) {
setShortcutType(mShortcutType); setPreferredShortcutType(mPreferredShortcutType);
} }
} }
private void setSecureIntValue(String key, @ShortcutType int value) { private void setSecureIntValue(String key, @PreferredShortcutType int value) {
Settings.Secure.putIntForUser(getPrefContext().getContentResolver(), Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
key, value, getPrefContext().getContentResolver().getUserId()); key, value, getPrefContext().getContentResolver().getUserId());
} }
private void setShortcutType(@ShortcutType int type) { private void setPreferredShortcutType(@PreferredShortcutType int type) {
setSecureIntValue(KEY_SHORTCUT_TYPE, type); setSecureIntValue(KEY_SHORTCUT_TYPE, type);
} }
private String getShortcutTypeSummary(Context context) { private String getShortcutTypeSummary(Context context) {
final int shortcutType = getShortcutType(context); final int shortcutType = getPreferredShortcutType(context);
final CharSequence softwareTitle = final CharSequence softwareTitle =
context.getText(AccessibilityUtil.isGestureNavigateEnabled(context) context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
? R.string.accessibility_shortcut_edit_dialog_title_software_gesture ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
: R.string.accessibility_shortcut_edit_dialog_title_software); : R.string.accessibility_shortcut_edit_dialog_title_software);
List<CharSequence> list = new ArrayList<>(); List<CharSequence> list = new ArrayList<>();
if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) { if ((shortcutType & PreferredShortcutType.SOFTWARE) == PreferredShortcutType.SOFTWARE) {
list.add(softwareTitle); list.add(softwareTitle);
} }
if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) { if ((shortcutType & PreferredShortcutType.HARDWARE) == PreferredShortcutType.HARDWARE) {
final CharSequence hardwareTitle = context.getText( final CharSequence hardwareTitle = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_hardware); R.string.accessibility_shortcut_edit_dialog_title_hardware);
list.add(hardwareTitle); list.add(hardwareTitle);
@@ -213,20 +218,21 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
return AccessibilityUtil.capitalize(joinStrings); return AccessibilityUtil.capitalize(joinStrings);
} }
@ShortcutType @PreferredShortcutType
private int getShortcutType(Context context) { private int getPreferredShortcutType(Context context) {
return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE); return getSecureIntValue(context, KEY_SHORTCUT_TYPE, PreferredShortcutType.SOFTWARE);
} }
@ShortcutType @PreferredShortcutType
private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) { private int getSecureIntValue(Context context, String key,
@PreferredShortcutType int defaultValue) {
return Settings.Secure.getIntForUser( return Settings.Secure.getIntForUser(
context.getContentResolver(), context.getContentResolver(),
key, defaultValue, context.getContentResolver().getUserId()); key, defaultValue, context.getContentResolver().getUserId());
} }
private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) { private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
updateShortcutType(true); updatePreferredShortcutType(true);
mShortcutPreference.setSummary( mShortcutPreference.setSummary(
getShortcutTypeSummary(getPrefContext())); getShortcutTypeSummary(getPrefContext()));
} }
@@ -288,39 +294,72 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
@Override @Override
public void onCheckboxClicked(ShortcutPreference preference) { public void onCheckboxClicked(ShortcutPreference preference) {
if (preference.getChecked()) { if (preference.getChecked()) {
// TODO(b/142530063): Enable shortcut when checkbox is checked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
AccessibilityUtil.optInValueToSettings(getContext(), PreferredShortcutType.SOFTWARE,
getComponentName());
} else { } else {
// TODO(b/142530063): Disable shortcut when checkbox is unchecked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
AccessibilityUtil.optOutValueFromSettings(getContext(), PreferredShortcutType.SOFTWARE,
getComponentName());
} }
} }
@Override @Override
public void onSettingsClicked(ShortcutPreference preference) { public void onSettingsClicked(ShortcutPreference preference) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
showDialog(DIALOG_ID_EDIT_SHORTCUT); showDialog(DIALOG_ID_EDIT_SHORTCUT);
} }
private void initShortcutPreference(Bundle savedInstanceState) { private void initShortcutPreference(Bundle savedInstanceState) {
// Restore the Shortcut type // Restore the PreferredShortcut type
if (savedInstanceState != null) { if (savedInstanceState != null) {
mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT); mPreferredShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE,
PreferredShortcutType.DEFAULT);
} }
if (mShortcutType == ShortcutType.DEFAULT) { if (mPreferredShortcutType == PreferredShortcutType.DEFAULT) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
} }
// Initial ShortcutPreference widget // Initial ShortcutPreference widget
final PreferenceScreen preferenceScreen = getPreferenceScreen(); final PreferenceScreen preferenceScreen = getPreferenceScreen();
mShortcutPreference = new ShortcutPreference( mShortcutPreference = new ShortcutPreference(
preferenceScreen.getContext(), null); preferenceScreen.getContext(), null);
mShortcutPreference.setPersistent(false);
mShortcutPreference.setKey(getShortcutPreferenceKey());
mShortcutPreference.setTitle(R.string.accessibility_shortcut_title); mShortcutPreference.setTitle(R.string.accessibility_shortcut_title);
mShortcutPreference.setOnClickListener(this);
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
// Put the shortcutPreference before radioButtonPreference. mShortcutPreference.setOnClickListener(this);
final RadioButtonPreference radioButtonPreference = findPreference(PREFERENCE_KEY); final RadioButtonPreference radioButtonPreference = findPreference(PREFERENCE_KEY);
// Put the shortcutPreference before radioButtonPreference.
mShortcutPreference.setOrder(radioButtonPreference.getOrder() - 1); mShortcutPreference.setOrder(radioButtonPreference.getOrder() - 1);
preferenceScreen.addPreference(mShortcutPreference);
// TODO(b/142530063): Check the new key to decide whether checkbox should be checked. // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
preferenceScreen.addPreference(mShortcutPreference);
}
private void updateShortcutPreference() {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
final ShortcutPreference shortcutPreference = preferenceScreen.findPreference(
getShortcutPreferenceKey());
if (shortcutPreference != null) {
// TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
shortcutPreference.setChecked(
AccessibilityUtil.hasValueInSettings(getContext(),
PreferredShortcutType.SOFTWARE,
getComponentName()));
}
}
private String getShortcutPreferenceKey() {
return KEY_SHORTCUT_PREFERENCE;
}
private ComponentName getComponentName() {
return DALTONIZER_COMPONENT_NAME;
} }
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =

View File

@@ -16,6 +16,8 @@
package com.android.settings.accessibility; package com.android.settings.accessibility;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import android.app.Dialog; import android.app.Dialog;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -45,13 +47,14 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.ShortcutType; import com.android.settings.accessibility.AccessibilityUtil.PreferredShortcutType;
import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBar;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.StringJoiner;
public class ToggleScreenMagnificationPreferenceFragment extends public class ToggleScreenMagnificationPreferenceFragment extends
ToggleFeaturePreferenceFragment implements SwitchBar.OnSwitchChangeListener, ToggleFeaturePreferenceFragment implements SwitchBar.OnSwitchChangeListener,
@@ -62,10 +65,18 @@ public class ToggleScreenMagnificationPreferenceFragment extends
// TODO(b/142530063): Check the new setting key to decide which summary should be shown. // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO; private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO;
private ShortcutPreference mShortcutPreference; private ShortcutPreference mShortcutPreference;
private int mShortcutType = ShortcutType.DEFAULT; private int mPreferredShortcutType = PreferredShortcutType.DEFAULT;
private CheckBox mSoftwareTypeCheckBox; private CheckBox mSoftwareTypeCheckBox;
private CheckBox mHardwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox;
private CheckBox mTripleTapTypeCheckBox; private CheckBox mTripleTapTypeCheckBox;
private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference";
// TODO(b/147021230): Will move common functions and variables to
// android/internal/accessibility folder. For now, magnification need to be treated
// individually.
private static final char COMPONENT_NAME_SEPARATOR = ':';
private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
protected class VideoPreference extends Preference { protected class VideoPreference extends Preference {
private ImageView mVideoBackgroundView; private ImageView mVideoBackgroundView;
@@ -187,7 +198,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType); outState.putInt(EXTRA_SHORTCUT_TYPE, mPreferredShortcutType);
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@@ -201,6 +212,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends
} }
updateConfigurationWarningIfNeeded(); updateConfigurationWarningIfNeeded();
updateShortcutPreference();
} }
@Override @Override
@@ -243,9 +255,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends
} }
private void updateAlertDialogCheckState() { private void updateAlertDialogCheckState() {
updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE); updateCheckStatus(mSoftwareTypeCheckBox, PreferredShortcutType.SOFTWARE);
updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE); updateCheckStatus(mHardwareTypeCheckBox, PreferredShortcutType.HARDWARE);
updateCheckStatus(mTripleTapTypeCheckBox, ShortcutType.TRIPLETAP); updateCheckStatus(mTripleTapTypeCheckBox, PreferredShortcutType.TRIPLETAP);
} }
private void updateAlertDialogEnableState() { private void updateAlertDialogEnableState() {
@@ -262,57 +274,57 @@ public class ToggleScreenMagnificationPreferenceFragment extends
} }
} }
private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) { private void updateCheckStatus(CheckBox checkBox, @PreferredShortcutType int type) {
checkBox.setChecked((mShortcutType & type) == type); checkBox.setChecked((mPreferredShortcutType & type) == type);
checkBox.setOnClickListener(v -> { checkBox.setOnClickListener(v -> {
updateShortcutType(false); updatePreferredShortcutType(false);
updateAlertDialogEnableState(); updateAlertDialogEnableState();
}); });
} }
private void updateShortcutType(boolean saveToDB) { private void updatePreferredShortcutType(boolean saveToDB) {
mShortcutType = ShortcutType.DEFAULT; mPreferredShortcutType = PreferredShortcutType.DEFAULT;
if (mSoftwareTypeCheckBox.isChecked()) { if (mSoftwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.SOFTWARE; mPreferredShortcutType |= PreferredShortcutType.SOFTWARE;
} }
if (mHardwareTypeCheckBox.isChecked()) { if (mHardwareTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.HARDWARE; mPreferredShortcutType |= PreferredShortcutType.HARDWARE;
} }
if (mTripleTapTypeCheckBox.isChecked()) { if (mTripleTapTypeCheckBox.isChecked()) {
mShortcutType |= ShortcutType.TRIPLETAP; mPreferredShortcutType |= PreferredShortcutType.TRIPLETAP;
} }
if (saveToDB) { if (saveToDB) {
setShortcutType(mShortcutType); setPreferredShortcutType(mPreferredShortcutType);
} }
} }
private void setSecureIntValue(String key, @ShortcutType int value) { private void setSecureIntValue(String key, @PreferredShortcutType int value) {
Settings.Secure.putIntForUser(getPrefContext().getContentResolver(), Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
key, value, getPrefContext().getContentResolver().getUserId()); key, value, getPrefContext().getContentResolver().getUserId());
} }
private void setShortcutType(@ShortcutType int type) { private void setPreferredShortcutType(@PreferredShortcutType int type) {
setSecureIntValue(KEY_SHORTCUT_TYPE, type); setSecureIntValue(KEY_SHORTCUT_TYPE, type);
} }
private String getShortcutTypeSummary(Context context) { private String getShortcutTypeSummary(Context context) {
final int shortcutType = getShortcutType(context); final int shortcutType = getPreferredShortcutType(context);
final CharSequence softwareTitle = final CharSequence softwareTitle =
context.getText(AccessibilityUtil.isGestureNavigateEnabled(context) context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
? R.string.accessibility_shortcut_edit_dialog_title_software_gesture ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
: R.string.accessibility_shortcut_edit_dialog_title_software); : R.string.accessibility_shortcut_edit_dialog_title_software);
List<CharSequence> list = new ArrayList<>(); List<CharSequence> list = new ArrayList<>();
if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) { if ((shortcutType & PreferredShortcutType.SOFTWARE) == PreferredShortcutType.SOFTWARE) {
list.add(softwareTitle); list.add(softwareTitle);
} }
if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) { if ((shortcutType & PreferredShortcutType.HARDWARE) == PreferredShortcutType.HARDWARE) {
final CharSequence hardwareTitle = context.getText( final CharSequence hardwareTitle = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_hardware); R.string.accessibility_shortcut_edit_dialog_title_hardware);
list.add(hardwareTitle); list.add(hardwareTitle);
} }
if ((shortcutType & ShortcutType.TRIPLETAP) == ShortcutType.TRIPLETAP) { if ((shortcutType & PreferredShortcutType.TRIPLETAP) == PreferredShortcutType.TRIPLETAP) {
final CharSequence tripleTapTitle = context.getText( final CharSequence tripleTapTitle = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_triple_tap); R.string.accessibility_shortcut_edit_dialog_title_triple_tap);
list.add(tripleTapTitle); list.add(tripleTapTitle);
@@ -326,20 +338,21 @@ public class ToggleScreenMagnificationPreferenceFragment extends
return AccessibilityUtil.capitalize(joinStrings); return AccessibilityUtil.capitalize(joinStrings);
} }
@ShortcutType @PreferredShortcutType
private int getShortcutType(Context context) { private int getPreferredShortcutType(Context context) {
return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE); return getSecureIntValue(context, KEY_SHORTCUT_TYPE, PreferredShortcutType.SOFTWARE);
} }
@ShortcutType @PreferredShortcutType
private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) { private int getSecureIntValue(Context context, String key,
@PreferredShortcutType int defaultValue) {
return Settings.Secure.getIntForUser( return Settings.Secure.getIntForUser(
context.getContentResolver(), context.getContentResolver(),
key, defaultValue, context.getContentResolver().getUserId()); key, defaultValue, context.getContentResolver().getUserId());
} }
private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) { private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
updateShortcutType(true); updatePreferredShortcutType(true);
mShortcutPreference.setSummary( mShortcutPreference.setSummary(
getShortcutTypeSummary(getPrefContext())); getShortcutTypeSummary(getPrefContext()));
} }
@@ -428,38 +441,67 @@ public class ToggleScreenMagnificationPreferenceFragment extends
@Override @Override
public void onCheckboxClicked(ShortcutPreference preference) { public void onCheckboxClicked(ShortcutPreference preference) {
if (preference.getChecked()) { if (preference.getChecked()) {
// TODO(b/142530063): Enable shortcut when checkbox is checked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
// TODO(b/142531156): ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED need to be treated
// as special case in this file.
optInMagnificationValueToSettings(getContext(), PreferredShortcutType.SOFTWARE);
} else { } else {
// TODO(b/142530063): Disable shortcut when checkbox is unchecked. // TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
// TODO(b/142531156): ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED need to be treated
// as special case in this file.
optOutMagnificationValueFromSettings(getContext(), PreferredShortcutType.SOFTWARE);
} }
} }
@Override @Override
public void onSettingsClicked(ShortcutPreference preference) { public void onSettingsClicked(ShortcutPreference preference) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
showDialog(DialogType.EDIT_SHORTCUT); showDialog(DialogType.EDIT_SHORTCUT);
} }
private void initShortcutPreference(Bundle savedInstanceState) { private void initShortcutPreference(Bundle savedInstanceState) {
// Restore the Shortcut type // Restore the PreferredShortcut type
if (savedInstanceState != null) { if (savedInstanceState != null) {
mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT); mPreferredShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE,
PreferredShortcutType.DEFAULT);
} }
if (mShortcutType == ShortcutType.DEFAULT) { if (mPreferredShortcutType == PreferredShortcutType.DEFAULT) {
mShortcutType = getShortcutType(getPrefContext()); mPreferredShortcutType = getPreferredShortcutType(getPrefContext());
} }
// Initial ShortcutPreference widget // Initial ShortcutPreference widget
final PreferenceScreen preferenceScreen = getPreferenceScreen(); final PreferenceScreen preferenceScreen = getPreferenceScreen();
mShortcutPreference = new ShortcutPreference( mShortcutPreference = new ShortcutPreference(
preferenceScreen.getContext(), null); preferenceScreen.getContext(), null);
mShortcutPreference.setPersistent(false);
mShortcutPreference.setKey(getShortcutPreferenceKey());
mShortcutPreference.setTitle(R.string.accessibility_magnification_shortcut_title); mShortcutPreference.setTitle(R.string.accessibility_magnification_shortcut_title);
mShortcutPreference.setOnClickListener(this);
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
mShortcutPreference.setOnClickListener(this);
// Put the shortcutPreference before videoPreference. // Put the shortcutPreference before videoPreference.
mShortcutPreference.setOrder(mVideoPreference.getOrder() - 1); mShortcutPreference.setOrder(mVideoPreference.getOrder() - 1);
// TODO(b/142530063): Check the new setting key to decide which summary should be shown.
preferenceScreen.addPreference(mShortcutPreference); preferenceScreen.addPreference(mShortcutPreference);
// TODO(b/142530063): Check the new key to decide whether checkbox should be checked. }
private void updateShortcutPreference() {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
final ShortcutPreference shortcutPreference = preferenceScreen.findPreference(
getShortcutPreferenceKey());
if (shortcutPreference != null) {
// TODO(b/142531156): Replace PreferredShortcutType.SOFTWARE value with dialog shortcut
// preferred key.
shortcutPreference.setChecked(
hasMagnificationValueInSettings(getContext(),
PreferredShortcutType.SOFTWARE));
}
}
private String getShortcutPreferenceKey() {
return KEY_SHORTCUT_PREFERENCE;
} }
private void updateConfigurationWarningIfNeeded() { private void updateConfigurationWarningIfNeeded() {
@@ -479,4 +521,68 @@ public class ToggleScreenMagnificationPreferenceFragment extends
int EDIT_SHORTCUT = 3; int EDIT_SHORTCUT = 3;
} }
private static void optInMagnificationValueToSettings(Context context,
@PreferredShortcutType int shortcutType) {
final String targetKey = AccessibilityUtil.convertKeyFromSettings(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (TextUtils.isEmpty(targetString)) {
return;
}
if (hasMagnificationValueInSettings(context, shortcutType)) {
return;
}
final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR));
joiner.add(Settings.Secure.getString(context.getContentResolver(), targetKey));
joiner.add(MAGNIFICATION_CONTROLLER_NAME);
Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString());
}
private static void optOutMagnificationValueFromSettings(Context context,
@PreferredShortcutType int shortcutType) {
final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR));
final String targetKey = AccessibilityUtil.convertKeyFromSettings(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (TextUtils.isEmpty(targetString)) {
return;
}
sStringColonSplitter.setString(targetString);
while (sStringColonSplitter.hasNext()) {
final String name = sStringColonSplitter.next();
if (TextUtils.isEmpty(name) || MAGNIFICATION_CONTROLLER_NAME.equals(name)) {
continue;
}
joiner.add(name);
}
Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString());
}
private static boolean hasMagnificationValueInSettings(Context context,
@PreferredShortcutType int shortcutType) {
final String targetKey = AccessibilityUtil.convertKeyFromSettings(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (TextUtils.isEmpty(targetString)) {
return false;
}
sStringColonSplitter.setString(targetString);
while (sStringColonSplitter.hasNext()) {
final String name = sStringColonSplitter.next();
if (MAGNIFICATION_CONTROLLER_NAME.equals(name)) {
return true;
}
}
return false;
}
} }

View File

@@ -28,6 +28,7 @@ import android.os.Build;
import android.provider.Settings; import android.provider.Settings;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.PreferredShortcutType;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -45,7 +46,14 @@ public final class AccessibilityUtilTest {
private static final String SECURE_TEST_KEY = "secure_test_key"; private static final String SECURE_TEST_KEY = "secure_test_key";
private static final String DUMMY_PACKAGE_NAME = "com.dummy.example"; private static final String DUMMY_PACKAGE_NAME = "com.dummy.example";
private static final String DUMMY_CLASS_NAME = DUMMY_PACKAGE_NAME + ".dummy_a11y_service"; private static final String DUMMY_CLASS_NAME = DUMMY_PACKAGE_NAME + ".dummy_a11y_service";
private static final String DUMMY_COMPONENT_NAME = DUMMY_PACKAGE_NAME + "/" + DUMMY_CLASS_NAME; private static final String DUMMY_CLASS_NAME2 = DUMMY_PACKAGE_NAME + ".dummy_a11y_service2";
private static final ComponentName DUMMY_COMPONENT_NAME = new ComponentName(DUMMY_PACKAGE_NAME,
DUMMY_CLASS_NAME);
private static final ComponentName DUMMY_COMPONENT_NAME2 = new ComponentName(DUMMY_PACKAGE_NAME,
DUMMY_CLASS_NAME2);
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
private Context mContext; private Context mContext;
@Before @Before
@@ -124,6 +132,57 @@ public final class AccessibilityUtilTest {
AccessibilityUtil.AccessibilityServiceFragmentType.INTUITIVE); AccessibilityUtil.AccessibilityServiceFragmentType.INTUITIVE);
} }
@Test
public void hasValueInSettings_dummyComponentName_hasValue() {
putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, DUMMY_COMPONENT_NAME.flattenToString());
assertThat(AccessibilityUtil.hasValueInSettings(mContext, PreferredShortcutType.SOFTWARE,
DUMMY_COMPONENT_NAME)).isTrue();
}
@Test
public void optInValueToSettings_optInDummyComponentName2_haveDummyComponentName2String() {
putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, DUMMY_COMPONENT_NAME.flattenToString());
AccessibilityUtil.optInValueToSettings(mContext, PreferredShortcutType.SOFTWARE,
DUMMY_COMPONENT_NAME2);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEqualTo(
DUMMY_COMPONENT_NAME.flattenToString() + ":"
+ DUMMY_COMPONENT_NAME2.flattenToString());
}
@Test
public void optInValueToSettings_optInTwoDummyComponentName_haveOneDummyComponentName2String() {
putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, DUMMY_COMPONENT_NAME.flattenToString());
AccessibilityUtil.optInValueToSettings(mContext, PreferredShortcutType.SOFTWARE,
DUMMY_COMPONENT_NAME2);
AccessibilityUtil.optInValueToSettings(mContext, PreferredShortcutType.SOFTWARE,
DUMMY_COMPONENT_NAME2);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEqualTo(
DUMMY_COMPONENT_NAME.flattenToString() + ":"
+ DUMMY_COMPONENT_NAME2.flattenToString());
}
@Test
public void optOutValueFromSettings_optOutDummyComponentName_emptyValue() {
putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, DUMMY_COMPONENT_NAME.flattenToString());
AccessibilityUtil.optOutValueFromSettings(mContext, PreferredShortcutType.SOFTWARE,
DUMMY_COMPONENT_NAME);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEmpty();
}
@Test
public void optOutValueFromSettings_optOutDummyComponentName2_haveDummyComponentName() {
putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, DUMMY_COMPONENT_NAME.flattenToString() + ":"
+ DUMMY_COMPONENT_NAME2.flattenToString());
AccessibilityUtil.optOutValueFromSettings(mContext, PreferredShortcutType.SOFTWARE,
DUMMY_COMPONENT_NAME2);
assertThat(getStringFromSettings(SOFTWARE_SHORTCUT_KEY)).isEqualTo(
DUMMY_COMPONENT_NAME.flattenToString());
}
private AccessibilityServiceInfo getMockAccessibilityServiceInfo() { private AccessibilityServiceInfo getMockAccessibilityServiceInfo() {
final ApplicationInfo applicationInfo = new ApplicationInfo(); final ApplicationInfo applicationInfo = new ApplicationInfo();
@@ -139,9 +198,7 @@ public final class AccessibilityUtilTest {
try { try {
final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo, final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
mContext); mContext);
final ComponentName componentName = ComponentName.unflattenFromString( info.setComponentName(DUMMY_COMPONENT_NAME);
DUMMY_COMPONENT_NAME);
info.setComponentName(componentName);
return info; return info;
} catch (XmlPullParserException | IOException e) { } catch (XmlPullParserException | IOException e) {
// Do nothing // Do nothing
@@ -149,4 +206,12 @@ public final class AccessibilityUtilTest {
return null; return null;
} }
private void putStringIntoSettings(String key, String componentName) {
Settings.Secure.putString(mContext.getContentResolver(), key, componentName);
}
private String getStringFromSettings(String key) {
return Settings.Secure.getString(mContext.getContentResolver(), key);
}
} }