Cleanup of AccessibilityUtil#hasValueInSettings

Settings should now be able to directly use the equivalent ShortcutUtils functions,
so the unnecessary code is being removed from AccessibilityUtil.
This does cause much behavior to depend on A11yManager instead of Settings.Secure,
so several tests need their conditions updated.

Test: atest com.android.settings.accessibility
Flag: EXEMPT internal refactoring
Bug: 367414968

Change-Id: I95f81f7d78b074def0fe2d1e01f60ceb7e142dac
This commit is contained in:
Riley Jones
2024-12-12 20:19:11 +00:00
parent 74b1086f23
commit 178bdd4c60
10 changed files with 56 additions and 163 deletions

View File

@@ -41,6 +41,7 @@ import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.dashboard.RestrictedDashboardFragment;
@@ -308,8 +309,8 @@ public abstract class AccessibilityShortcutPreferenceFragment extends Restricted
final int shortcutTypes = getUserPreferredShortcutTypes();
mShortcutPreference.setChecked(
AccessibilityUtil.hasValuesInSettings(getPrefContext(), shortcutTypes,
getComponentName()));
ShortcutUtils.isShortcutContained(
getPrefContext(), shortcutTypes, getComponentName().flattenToString()));
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
}

View File

@@ -21,7 +21,6 @@ import static android.view.WindowInsets.Type.displayCutout;
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;
@@ -37,7 +36,6 @@ 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;
import android.text.TextUtils;
import android.util.TypedValue;
@@ -194,52 +192,6 @@ public final class AccessibilityUtil {
: AccessibilityServiceFragmentType.TOGGLE;
}
/**
* Returns if component name existed in one of {@code shortcutTypes} string in Settings.
*
* @param context The current context.
* @param shortcutTypes A combination of {@link UserShortcutType}.
* @param componentName The component name that need to be checked existed in Settings.
* @return {@code true} if componentName existed in Settings.
*/
static boolean hasValuesInSettings(Context context, int shortcutTypes,
@NonNull ComponentName componentName) {
for (int shortcutType : AccessibilityUtil.SHORTCUTS_ORDER_IN_UI) {
if (!android.provider.Flags.a11yStandaloneGestureEnabled()) {
if ((shortcutType & GESTURE) == GESTURE) {
continue;
}
}
if ((shortcutTypes & shortcutType) == shortcutType
&& hasValueInSettings(context, shortcutType, componentName)) {
return true;
}
}
return false;
}
/**
* Returns if component name existed in {@code shortcutType} string 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.
*
* @deprecated use
* {@link ShortcutUtils#isShortcutContained(Context, int, String)} instead.
*
* (TODO 367414968: finish removal.)
*/
@Deprecated
@VisibleForTesting
static boolean hasValueInSettings(Context context, @UserShortcutType int shortcutType,
@NonNull ComponentName componentName) {
return ShortcutUtils.getShortcutTargetsFromSettings(
context, shortcutType, UserHandle.myUserId()
).contains(componentName.flattenToString());
}
/**
* Gets the corresponding user shortcut type of a given accessibility service.
*
@@ -250,14 +202,15 @@ public final class AccessibilityUtil {
*/
static int getUserShortcutTypesFromSettings(Context context,
@NonNull ComponentName componentName) {
int shortcutTypes = DEFAULT;
int shortcutTypes = UserShortcutType.DEFAULT;
for (int shortcutType : AccessibilityUtil.SHORTCUTS_ORDER_IN_UI) {
if (!android.provider.Flags.a11yStandaloneGestureEnabled()) {
if ((shortcutType & GESTURE) == GESTURE) {
continue;
}
}
if (hasValueInSettings(context, shortcutType, componentName)) {
if (ShortcutUtils.isShortcutContained(
context, shortcutType, componentName.flattenToString())) {
shortcutTypes |= shortcutType;
}
}

View File

@@ -56,6 +56,7 @@ import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
@@ -630,8 +631,8 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
final int shortcutTypes = getUserPreferredShortcutTypes();
mShortcutPreference.setChecked(
AccessibilityUtil.hasValuesInSettings(getPrefContext(), shortcutTypes,
mComponentName));
ShortcutUtils.isShortcutContained(
getPrefContext(), shortcutTypes, mComponentName.flattenToString()));
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
}

View File

@@ -1,6 +1,7 @@
sdk=NEWEST_SDK
shadows=\
com.android.settings.testutils.shadow.ShadowThreadUtils \
com.android.settings.testutils.shadow.ShadowAccessibilityManager \
com.android.settings.network.ShadowServiceManagerExtend
instrumentedPackages=androidx.preference
sqliteMode=native

View File

@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -564,9 +566,8 @@ public class AccessibilitySettingsTest {
}
private void setShortcutEnabled(ComponentName componentName, boolean enabled) {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
enabled ? componentName.flattenToString() : "");
mShadowAccessibilityManager.setAccessibilityShortcutTargets(
SOFTWARE, (enabled) ? List.of(componentName.flattenToString()) : List.of());
}
private BooleanSubject assertUriObserversContainsClazz(

View File

@@ -40,6 +40,7 @@ import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.PopupWindow;
import androidx.annotation.Nullable;
@@ -52,6 +53,7 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.testutils.shadow.ShadowAccessibilityManager;
import com.android.settings.testutils.shadow.ShadowFragment;
import org.junit.Before;
@@ -66,36 +68,31 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
import java.util.List;
import java.util.Locale;
/** Tests for {@link AccessibilityShortcutPreferenceFragment} */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class,
})
@Config(shadows = com.android.settings.testutils.shadow.ShadowFragment.class)
public class AccessibilityShortcutPreferenceFragmentTest {
private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example";
private static final String PLACEHOLDER_CLASS_NAME = PLACEHOLDER_PACKAGE_NAME + ".placeholder";
private static final String PLACEHOLDER_TILE_CLASS_NAME =
PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME);
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
private TestAccessibilityShortcutPreferenceFragment mFragment;
private PreferenceScreen mScreen;
private Context mContext = ApplicationProvider.getApplicationContext();
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
private ShadowAccessibilityManager mShadowAccessibilityManager;
@Before
public void setUpTestFragment() {
MockitoAnnotations.initMocks(this);
mShadowAccessibilityManager = Shadow.extract(
mContext.getSystemService(AccessibilityManager.class));
mFragment = spy(new TestAccessibilityShortcutPreferenceFragment(null));
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
@@ -118,8 +115,10 @@ public class AccessibilityShortcutPreferenceFragmentTest {
@Test
public void updateShortcutPreferenceData_hasValueInSettings_assignToVariable() {
putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
putStringIntoSettings(HARDWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
mShadowAccessibilityManager.setAccessibilityShortcutTargets(
SOFTWARE, List.of(PLACEHOLDER_COMPONENT_NAME.flattenToString()));
mShadowAccessibilityManager.setAccessibilityShortcutTargets(
HARDWARE, List.of(PLACEHOLDER_COMPONENT_NAME.flattenToString()));
mFragment.updateShortcutPreferenceData();

View File

@@ -45,8 +45,6 @@ import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import org.junit.Before;
@@ -57,7 +55,6 @@ import org.robolectric.RobolectricTestRunner;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.StringJoiner;
@RunWith(RobolectricTestRunner.class)
public final class AccessibilityUtilTest {
@@ -67,16 +64,6 @@ public final class AccessibilityUtilTest {
private static final String MOCK_CLASS_NAME2 = MOCK_PACKAGE_NAME + ".mock_a11y_service2";
private static final ComponentName MOCK_COMPONENT_NAME = new ComponentName(MOCK_PACKAGE_NAME,
MOCK_CLASS_NAME);
private static final ComponentName MOCK_COMPONENT_NAME2 = new ComponentName(MOCK_PACKAGE_NAME,
MOCK_CLASS_NAME2);
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
private static final String QUICK_SETTINGS_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_QS_TARGETS;
private static final String PLACEHOLDER_SETTING_FEATURE = "placeholderSettingFeature";
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -161,56 +148,6 @@ public final class AccessibilityUtilTest {
AccessibilityUtil.AccessibilityServiceFragmentType.TOGGLE);
}
@Test
public void hasValueInSettings_putValue_hasValue() {
setShortcut(SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
assertThat(AccessibilityUtil.hasValueInSettings(mContext, SOFTWARE,
MOCK_COMPONENT_NAME)).isTrue();
}
@Test
public void getUserShortcutTypeFromSettings_putOneValue_hasValue() {
setShortcut(SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
final int shortcutTypes = AccessibilityUtil.getUserShortcutTypesFromSettings(mContext,
MOCK_COMPONENT_NAME);
assertThat(shortcutTypes).isEqualTo(
SOFTWARE
);
}
@Test
public void getUserShortcutTypeFromSettings_putTwoValues_hasValue() {
setShortcut(SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
setShortcut(HARDWARE, MOCK_COMPONENT_NAME.flattenToString());
final int shortcutTypes = AccessibilityUtil.getUserShortcutTypesFromSettings(mContext,
MOCK_COMPONENT_NAME);
assertThat(shortcutTypes).isEqualTo(
SOFTWARE
| HARDWARE
);
}
@Test
public void getUserShortcutTypeFromSettings_threeShortcutTypesChosen() {
setShortcut(SOFTWARE, MOCK_COMPONENT_NAME.flattenToString());
setShortcut(HARDWARE, MOCK_COMPONENT_NAME.flattenToString());
setShortcut(QUICK_SETTINGS, MOCK_COMPONENT_NAME.flattenToString());
final int shortcutTypes = AccessibilityUtil.getUserShortcutTypesFromSettings(mContext,
MOCK_COMPONENT_NAME);
assertThat(shortcutTypes).isEqualTo(
SOFTWARE
| HARDWARE
| QUICK_SETTINGS
);
}
@Test
public void convertKeyFromSettings_shortcutTypeSoftware() {
assertThat(AccessibilityUtil.convertKeyFromSettings(SOFTWARE))
@@ -308,28 +245,9 @@ public final class AccessibilityUtilTest {
return null;
}
private String getStringFromSettings(String key) {
return Settings.Secure.getString(mContext.getContentResolver(), key);
}
private void setSettingsFeatureEnabled(String settingsKey, boolean enabled) {
Settings.Secure.putInt(mContext.getContentResolver(),
settingsKey,
enabled ? AccessibilityUtil.State.ON : AccessibilityUtil.State.OFF);
}
private void setShortcut(@UserShortcutType int shortcutType, String... componentNames) {
StringJoiner shortcutComponents = new StringJoiner(":");
for (String componentName : componentNames) {
shortcutComponents.add(componentName);
}
Settings.Secure.putString(mContext.getContentResolver(),
ShortcutUtils.convertToKey(shortcutType), shortcutComponents.toString());
}
private void clearShortcuts() {
Settings.Secure.putString(mContext.getContentResolver(), SOFTWARE_SHORTCUT_KEY, "");
Settings.Secure.putString(mContext.getContentResolver(), HARDWARE_SHORTCUT_KEY, "");
Settings.Secure.putString(mContext.getContentResolver(), QUICK_SETTINGS_SHORTCUT_KEY, "");
}
}

View File

@@ -193,7 +193,6 @@ public class ToggleDaltonizerPreferenceFragmentTest {
}
private ToggleDaltonizerPreferenceFragment getFragmentInResumedState() {
mActivityController.create().start().resume();
Fragment fragment = mActivityController.get().getSupportFragmentManager().findFragmentById(
R.id.main_content);

View File

@@ -43,6 +43,7 @@ import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.PopupWindow;
import androidx.fragment.app.FragmentActivity;
@@ -54,6 +55,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowAccessibilityManager;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settingslib.widget.TopIntroPreference;
@@ -72,12 +74,14 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
import java.util.List;
import java.util.Locale;
/** Tests for {@link ToggleFeaturePreferenceFragment} */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowFragment.class,
ShadowAccessibilityManager.class
})
public class ToggleFeaturePreferenceFragmentTest {
@Rule
@@ -109,6 +113,7 @@ public class ToggleFeaturePreferenceFragmentTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
private ShadowAccessibilityManager mShadowAccessibilityManager;
@Mock
private FragmentActivity mActivity;
@@ -120,6 +125,8 @@ public class ToggleFeaturePreferenceFragmentTest {
@Before
public void setUpTestFragment() {
MockitoAnnotations.initMocks(this);
mShadowAccessibilityManager = Shadow.extract(
mContext.getSystemService(AccessibilityManager.class));
mFragment = spy(new TestToggleFeaturePreferenceFragment());
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
@@ -178,10 +185,10 @@ public class ToggleFeaturePreferenceFragmentTest {
@Test
public void updateShortcutPreferenceData_hasValueInSettings_assignToVariable() {
mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
putSecureStringIntoSettings(SOFTWARE_SHORTCUT_KEY,
PLACEHOLDER_COMPONENT_NAME.flattenToString());
putSecureStringIntoSettings(HARDWARE_SHORTCUT_KEY,
PLACEHOLDER_COMPONENT_NAME.flattenToString());
mShadowAccessibilityManager.setAccessibilityShortcutTargets(
SOFTWARE, List.of(PLACEHOLDER_COMPONENT_NAME.flattenToString()));
mShadowAccessibilityManager.setAccessibilityShortcutTargets(
HARDWARE, List.of(PLACEHOLDER_COMPONENT_NAME.flattenToString()));
mFragment.updateShortcutPreferenceData();
@@ -339,10 +346,6 @@ public class ToggleFeaturePreferenceFragmentTest {
assertThat(summary).isEqualTo(expected);
}
private void putSecureStringIntoSettings(String key, String componentName) {
Settings.Secure.putString(mContext.getContentResolver(), key, componentName);
}
private String getSecureStringFromSettings(String key) {
return Settings.Secure.getString(mContext.getContentResolver(), key);
}

View File

@@ -16,6 +16,8 @@
package com.android.settings.testutils.shadow;
import static com.google.common.truth.Truth.assertThat;
import android.accessibilityservice.AccessibilityShortcutInfo;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
@@ -24,11 +26,12 @@ import android.content.Context;
import android.util.ArrayMap;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -39,6 +42,7 @@ import java.util.Map;
public class ShadowAccessibilityManager extends org.robolectric.shadows.ShadowAccessibilityManager {
private Map<ComponentName, ComponentName> mA11yFeatureToTileMap = new ArrayMap<>();
private List<AccessibilityShortcutInfo> mInstalledAccessibilityShortcutList = List.of();
private Map<Integer, List<String>> mShortcutTargets = new ArrayMap<>();
/**
* Implements a hidden method {@link AccessibilityManager#getA11yFeatureToTileMap}
@@ -80,7 +84,20 @@ public class ShadowAccessibilityManager extends org.robolectric.shadows.ShadowAc
*/
@Implementation
public List<String> getAccessibilityShortcutTargets(
@ShortcutConstants.UserShortcutType int shortcutType) {
return List.of();
@UserShortcutType int shortcutType) {
if (!mShortcutTargets.containsKey(shortcutType)) {
mShortcutTargets.put(shortcutType, new ArrayList<>());
}
List<String> targets = mShortcutTargets.get(shortcutType);
assertThat(targets).isNotNull();
return targets;
}
/**
* Used by tests to easily write directly to a shortcut targets value
*/
public void setAccessibilityShortcutTargets(
@UserShortcutType int shortcutType, List<String> targets) {
mShortcutTargets.put(shortcutType, targets);
}
}