Avoid users add one-handed mode by edit shortcut dialog in unsupported devices

Root cause: We show preinstalled framework features in edit shortcut dialog
Solution: Only show one-handed mode if the device supports

Bug: 260182478
Test: atest AccessibilityTargetHelperTest
Change-Id: Id0696bff522cb7e19c5a16a47bbb76a794472c52
This commit is contained in:
menghanli
2022-12-20 15:30:53 +08:00
parent b0f1e19c1a
commit 1a9081a982
6 changed files with 185 additions and 67 deletions

View File

@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets; import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets;
import static com.android.internal.os.RoSystemProperties.SUPPORT_ONE_HANDED_MODE;
import static com.android.internal.util.ArrayUtils.convertToLongArray; import static com.android.internal.util.ArrayUtils.convertToLongArray;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
@@ -151,11 +152,13 @@ public class AccessibilityShortcutController {
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
"1" /* Value to enable */, "0" /* Value to disable */, "1" /* Value to enable */, "0" /* Value to disable */,
R.string.color_correction_feature_name)); R.string.color_correction_feature_name));
featuresMap.put(ONE_HANDED_COMPONENT_NAME, if (SUPPORT_ONE_HANDED_MODE) {
new ToggleableFrameworkFeatureInfo( featuresMap.put(ONE_HANDED_COMPONENT_NAME,
Settings.Secure.ONE_HANDED_MODE_ACTIVATED, new ToggleableFrameworkFeatureInfo(
"1" /* Value to enable */, "0" /* Value to disable */, Settings.Secure.ONE_HANDED_MODE_ACTIVATED,
R.string.one_handed_mode_feature_name)); "1" /* Value to enable */, "0" /* Value to disable */,
R.string.one_handed_mode_feature_name));
}
featuresMap.put(REDUCE_BRIGHT_COLORS_COMPONENT_NAME, featuresMap.put(REDUCE_BRIGHT_COLORS_COMPONENT_NAME,
new ToggleableFrameworkFeatureInfo( new ToggleableFrameworkFeatureInfo(
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,

View File

@@ -26,6 +26,7 @@ import static com.android.internal.accessibility.AccessibilityShortcutController
import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME;
import static com.android.internal.accessibility.util.AccessibilityUtils.getAccessibilityServiceFragmentType; import static com.android.internal.accessibility.util.AccessibilityUtils.getAccessibilityServiceFragmentType;
import static com.android.internal.accessibility.util.ShortcutUtils.isShortcutContained; import static com.android.internal.accessibility.util.ShortcutUtils.isShortcutContained;
import static com.android.internal.os.RoSystemProperties.SUPPORT_ONE_HANDED_MODE;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityShortcutInfo; import android.accessibilityservice.AccessibilityShortcutInfo;
@@ -210,6 +211,7 @@ public final class AccessibilityTargetHelper {
context.getString(R.string.accessibility_magnification_chooser_text), context.getString(R.string.accessibility_magnification_chooser_text),
context.getDrawable(R.drawable.ic_accessibility_magnification), context.getDrawable(R.drawable.ic_accessibility_magnification),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
targets.add(magnification);
final ToggleAllowListingFeatureTarget daltonizer = final ToggleAllowListingFeatureTarget daltonizer =
new ToggleAllowListingFeatureTarget(context, new ToggleAllowListingFeatureTarget(context,
@@ -220,6 +222,7 @@ public final class AccessibilityTargetHelper {
context.getString(R.string.color_correction_feature_name), context.getString(R.string.color_correction_feature_name),
context.getDrawable(R.drawable.ic_accessibility_color_correction), context.getDrawable(R.drawable.ic_accessibility_color_correction),
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED); Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
targets.add(daltonizer);
final ToggleAllowListingFeatureTarget colorInversion = final ToggleAllowListingFeatureTarget colorInversion =
new ToggleAllowListingFeatureTarget(context, new ToggleAllowListingFeatureTarget(context,
@@ -230,16 +233,20 @@ public final class AccessibilityTargetHelper {
context.getString(R.string.color_inversion_feature_name), context.getString(R.string.color_inversion_feature_name),
context.getDrawable(R.drawable.ic_accessibility_color_inversion), context.getDrawable(R.drawable.ic_accessibility_color_inversion),
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
targets.add(colorInversion);
final ToggleAllowListingFeatureTarget oneHandedMode = if (SUPPORT_ONE_HANDED_MODE) {
new ToggleAllowListingFeatureTarget(context, final ToggleAllowListingFeatureTarget oneHandedMode =
shortcutType, new ToggleAllowListingFeatureTarget(context,
isShortcutContained(context, shortcutType, shortcutType,
ONE_HANDED_COMPONENT_NAME.flattenToString()), isShortcutContained(context, shortcutType,
ONE_HANDED_COMPONENT_NAME.flattenToString(), ONE_HANDED_COMPONENT_NAME.flattenToString()),
context.getString(R.string.one_handed_mode_feature_name), ONE_HANDED_COMPONENT_NAME.flattenToString(),
context.getDrawable(R.drawable.ic_accessibility_one_handed), context.getString(R.string.one_handed_mode_feature_name),
Settings.Secure.ONE_HANDED_MODE_ACTIVATED); context.getDrawable(R.drawable.ic_accessibility_one_handed),
Settings.Secure.ONE_HANDED_MODE_ACTIVATED);
targets.add(oneHandedMode);
}
final ToggleAllowListingFeatureTarget reduceBrightColors = final ToggleAllowListingFeatureTarget reduceBrightColors =
new ToggleAllowListingFeatureTarget(context, new ToggleAllowListingFeatureTarget(context,
@@ -250,6 +257,7 @@ public final class AccessibilityTargetHelper {
context.getString(R.string.reduce_bright_colors_feature_name), context.getString(R.string.reduce_bright_colors_feature_name),
context.getDrawable(R.drawable.ic_accessibility_reduce_bright_colors), context.getDrawable(R.drawable.ic_accessibility_reduce_bright_colors),
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED); Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED);
targets.add(reduceBrightColors);
final InvisibleToggleAllowListingFeatureTarget hearingAids = final InvisibleToggleAllowListingFeatureTarget hearingAids =
new InvisibleToggleAllowListingFeatureTarget(context, new InvisibleToggleAllowListingFeatureTarget(context,
@@ -260,11 +268,6 @@ public final class AccessibilityTargetHelper {
context.getString(R.string.hearing_aids_feature_name), context.getString(R.string.hearing_aids_feature_name),
context.getDrawable(R.drawable.ic_accessibility_hearing_aid), context.getDrawable(R.drawable.ic_accessibility_hearing_aid),
/* key= */ null); /* key= */ null);
targets.add(magnification);
targets.add(daltonizer);
targets.add(colorInversion);
targets.add(oneHandedMode);
targets.add(reduceBrightColors);
targets.add(hearingAids); targets.add(hearingAids);
return targets; return targets;

View File

@@ -31,6 +31,8 @@ public class RoSystemProperties {
SystemProperties.getInt("ro.factorytest", 0); SystemProperties.getInt("ro.factorytest", 0);
public static final String CONTROL_PRIVAPP_PERMISSIONS = public static final String CONTROL_PRIVAPP_PERMISSIONS =
SystemProperties.get("ro.control_privapp_permissions"); SystemProperties.get("ro.control_privapp_permissions");
public static final boolean SUPPORT_ONE_HANDED_MODE =
SystemProperties.getBoolean("ro.support_one_handed_mode", /* def= */ false);
// ------ ro.hdmi.* -------- // // ------ ro.hdmi.* -------- //
/** /**

View File

@@ -20,16 +20,19 @@ import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.doubleClick; import static androidx.test.espresso.action.ViewActions.doubleClick;
import static androidx.test.espresso.action.ViewActions.scrollTo; import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.action.ViewActions.swipeUp;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.RootMatchers.isDialog; import static androidx.test.espresso.matcher.RootMatchers.isDialog;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText; import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.endsWith;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
@@ -39,7 +42,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager; import android.view.accessibility.IAccessibilityManager;
@@ -52,11 +54,12 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity; import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity;
import org.junit.Before; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.util.Collections; import java.util.Collections;
@@ -65,57 +68,93 @@ import java.util.Collections;
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class AccessibilityShortcutChooserActivityTest { public class AccessibilityShortcutChooserActivityTest {
private static final String ONE_HANDED_MODE = "One-Handed mode";
private static final String TEST_LABEL = "TEST_LABEL"; private static final String TEST_LABEL = "TEST_LABEL";
private static final Context sContext = private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("package", "class");
InstrumentationRegistry.getInstrumentation().getContext();
private ActivityScenario<TestAccessibilityShortcutChooserActivity> mScenario;
private static IAccessibilityManager sAccessibilityManagerService;
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock @Mock
private AccessibilityServiceInfo mAccessibilityServiceInfo; private AccessibilityServiceInfo mAccessibilityServiceInfo;
@Mock @Mock
private ResolveInfo mResolveInfo; private ResolveInfo mResolveInfo;
@Mock @Mock
private ServiceInfo mServiceInfo; private ServiceInfo mServiceInfo;
@Mock @Mock
private ApplicationInfo mApplicationInfo; private ApplicationInfo mApplicationInfo;
@Mock
@Before private IAccessibilityManager mAccessibilityManagerService;
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
sAccessibilityManagerService = mock(IAccessibilityManager.class);
when(mAccessibilityServiceInfo.getResolveInfo()).thenReturn(mResolveInfo);
mResolveInfo.serviceInfo = mServiceInfo;
mServiceInfo.applicationInfo = mApplicationInfo;
when(mResolveInfo.loadLabel(any(PackageManager.class))).thenReturn(TEST_LABEL);
when(mAccessibilityServiceInfo.getComponentName()).thenReturn(
new ComponentName("package", "class"));
when(sAccessibilityManagerService.getInstalledAccessibilityServiceList(
anyInt())).thenReturn(Collections.singletonList(mAccessibilityServiceInfo));
mScenario = ActivityScenario.launch(TestAccessibilityShortcutChooserActivity.class);
}
@Test @Test
public void doubleClickServiceTargetAndClickDenyButton_permissionDialogDoesNotExist() { public void doubleClickTestServiceAndClickDenyButton_permissionDialogDoesNotExist()
mScenario.moveToState(Lifecycle.State.CREATED); throws Exception {
mScenario.moveToState(Lifecycle.State.STARTED); configureTestService();
mScenario.moveToState(Lifecycle.State.RESUMED); final ActivityScenario<TestAccessibilityShortcutChooserActivity> scenario =
ActivityScenario.launch(TestAccessibilityShortcutChooserActivity.class);
scenario.moveToState(Lifecycle.State.CREATED);
scenario.moveToState(Lifecycle.State.STARTED);
scenario.moveToState(Lifecycle.State.RESUMED);
onView(withText(R.string.accessibility_select_shortcut_menu_title)).inRoot( onView(withText(R.string.accessibility_select_shortcut_menu_title)).inRoot(
isDialog()).check(matches(isDisplayed())); isDialog()).check(matches(isDisplayed()));
onView(withText(R.string.edit_accessibility_shortcut_menu_button)).perform(click()); onView(withText(R.string.edit_accessibility_shortcut_menu_button)).perform(click());
onView(withText(TEST_LABEL)).perform(scrollTo(), doubleClick()); onView(withText(TEST_LABEL)).perform(scrollTo(), doubleClick());
onView(withId(R.id.accessibility_permission_enable_deny_button)).perform(scrollTo(), onView(withId(R.id.accessibility_permission_enable_deny_button)).perform(scrollTo(),
click()); click());
onView(withId(R.id.accessibility_permissionDialog_title)).inRoot(isDialog()).check( onView(withId(R.id.accessibility_permissionDialog_title)).inRoot(isDialog()).check(
doesNotExist()); doesNotExist());
mScenario.moveToState(Lifecycle.State.DESTROYED); scenario.moveToState(Lifecycle.State.DESTROYED);
}
@Test
public void popEditShortcutMenuList_oneHandedModeEnabled_shouldBeInListView() {
TestUtils.setOneHandedModeEnabled(this, /* enabled= */ true);
final ActivityScenario<TestAccessibilityShortcutChooserActivity> scenario =
ActivityScenario.launch(TestAccessibilityShortcutChooserActivity.class);
scenario.moveToState(Lifecycle.State.CREATED);
scenario.moveToState(Lifecycle.State.STARTED);
scenario.moveToState(Lifecycle.State.RESUMED);
onView(withText(R.string.accessibility_select_shortcut_menu_title)).inRoot(
isDialog()).check(matches(isDisplayed()));
onView(withText(R.string.edit_accessibility_shortcut_menu_button)).perform(click());
onView(allOf(withClassName(endsWith("ListView")), isDisplayed())).perform(swipeUp());
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
onView(withText(ONE_HANDED_MODE)).inRoot(isDialog()).check(matches(isDisplayed()));
scenario.moveToState(Lifecycle.State.DESTROYED);
}
@Test
public void popEditShortcutMenuList_oneHandedModeDisabled_shouldNotBeInListView() {
TestUtils.setOneHandedModeEnabled(this, /* enabled= */ false);
final ActivityScenario<TestAccessibilityShortcutChooserActivity> scenario =
ActivityScenario.launch(TestAccessibilityShortcutChooserActivity.class);
scenario.moveToState(Lifecycle.State.CREATED);
scenario.moveToState(Lifecycle.State.STARTED);
scenario.moveToState(Lifecycle.State.RESUMED);
onView(withText(R.string.accessibility_select_shortcut_menu_title)).inRoot(
isDialog()).check(matches(isDisplayed()));
onView(withText(R.string.edit_accessibility_shortcut_menu_button)).perform(click());
onView(allOf(withClassName(endsWith("ListView")), isDisplayed())).perform(swipeUp());
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
onView(withText(ONE_HANDED_MODE)).inRoot(isDialog()).check(doesNotExist());
scenario.moveToState(Lifecycle.State.DESTROYED);
}
private void configureTestService() throws Exception {
when(mAccessibilityServiceInfo.getResolveInfo()).thenReturn(mResolveInfo);
mResolveInfo.serviceInfo = mServiceInfo;
mServiceInfo.applicationInfo = mApplicationInfo;
when(mResolveInfo.loadLabel(any(PackageManager.class))).thenReturn(TEST_LABEL);
when(mAccessibilityServiceInfo.getComponentName()).thenReturn(TEST_COMPONENT_NAME);
when(mAccessibilityManagerService.getInstalledAccessibilityServiceList(
anyInt())).thenReturn(Collections.singletonList(mAccessibilityServiceInfo));
TestAccessibilityShortcutChooserActivity.setupForTesting(mAccessibilityManagerService);
} }
/** /**
@@ -123,19 +162,18 @@ public class AccessibilityShortcutChooserActivityTest {
*/ */
public static class TestAccessibilityShortcutChooserActivity extends public static class TestAccessibilityShortcutChooserActivity extends
AccessibilityShortcutChooserActivity { AccessibilityShortcutChooserActivity {
private AccessibilityManager mAccessibilityManager; private static IAccessibilityManager sAccessibilityManagerService;
@Override public static void setupForTesting(IAccessibilityManager accessibilityManagerService) {
protected void onCreate(Bundle savedInstanceState) { sAccessibilityManagerService = accessibilityManagerService;
mAccessibilityManager = new AccessibilityManager(sContext, new Handler(getMainLooper()),
sAccessibilityManagerService, /* userId= */ 0, /* serviceConnect= */ true);
super.onCreate(savedInstanceState);
} }
@Override @Override
public Object getSystemService(String name) { public Object getSystemService(String name) {
if (Context.ACCESSIBILITY_SERVICE.equals(name)) { if (Context.ACCESSIBILITY_SERVICE.equals(name)
return mAccessibilityManager; && sAccessibilityManagerService != null) {
return new AccessibilityManager(this, new Handler(getMainLooper()),
sAccessibilityManagerService, /* userId= */ 0, /* serviceConnect= */ true);
} }
return super.getSystemService(name); return super.getSystemService(name);

View File

@@ -208,6 +208,17 @@ public class AccessibilityShortcutControllerTest {
when(mAlertDialog.getWindow()).thenReturn(window); when(mAlertDialog.getWindow()).thenReturn(window);
when(mTextToSpeech.getVoice()).thenReturn(mVoice); when(mTextToSpeech.getVoice()).thenReturn(mVoice);
// Clears the sFrameworkShortcutFeaturesMap field which was not properly initialized
// during testing.
try {
Field field = AccessibilityShortcutController.class.getDeclaredField(
"sFrameworkShortcutFeaturesMap");
field.setAccessible(true);
field.set(window, null);
} catch (Exception e) {
throw new RuntimeException("Unable to set sFrameworkShortcutFeaturesMap", e);
}
} }
@AfterClass @AfterClass
@@ -433,11 +444,10 @@ public class AccessibilityShortcutControllerTest {
} }
@Test @Test
public void getFrameworkFeatureMap_shouldBeNonNullAndUnmodifiable() { public void getFrameworkFeatureMap_shouldBeUnmodifiable() {
Map<ComponentName, AccessibilityShortcutController.FrameworkFeatureInfo> final Map<ComponentName, AccessibilityShortcutController.FrameworkFeatureInfo>
frameworkFeatureMap = frameworkFeatureMap =
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap(); AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
assertTrue("Framework features not supported", frameworkFeatureMap.size() > 0);
try { try {
frameworkFeatureMap.clear(); frameworkFeatureMap.clear();
@@ -448,18 +458,39 @@ public class AccessibilityShortcutControllerTest {
} }
@Test @Test
public void getFrameworkFeatureMap_containsExpectedKey() { public void getFrameworkFeatureMap_containsExpectedDefaultKeys() {
Map<ComponentName, AccessibilityShortcutController.FrameworkFeatureInfo> final Map<ComponentName, AccessibilityShortcutController.FrameworkFeatureInfo>
frameworkFeatureMap = frameworkFeatureMap =
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap(); AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
assertTrue(frameworkFeatureMap.containsKey(COLOR_INVERSION_COMPONENT_NAME)); assertTrue(frameworkFeatureMap.containsKey(COLOR_INVERSION_COMPONENT_NAME));
assertTrue(frameworkFeatureMap.containsKey(DALTONIZER_COMPONENT_NAME)); assertTrue(frameworkFeatureMap.containsKey(DALTONIZER_COMPONENT_NAME));
assertTrue(frameworkFeatureMap.containsKey(ONE_HANDED_COMPONENT_NAME));
assertTrue(frameworkFeatureMap.containsKey(REDUCE_BRIGHT_COLORS_COMPONENT_NAME)); assertTrue(frameworkFeatureMap.containsKey(REDUCE_BRIGHT_COLORS_COMPONENT_NAME));
assertTrue(frameworkFeatureMap.containsKey(ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME)); assertTrue(frameworkFeatureMap.containsKey(ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME));
} }
@Test
public void getFrameworkFeatureMap_oneHandedModeEnabled_containsExpectedKey() {
TestUtils.setOneHandedModeEnabled(this, /* enabled= */ true);
final Map<ComponentName, AccessibilityShortcutController.FrameworkFeatureInfo>
frameworkFeatureMap =
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
assertTrue(frameworkFeatureMap.containsKey(ONE_HANDED_COMPONENT_NAME));
}
@Test
public void getFrameworkFeatureMap_oneHandedModeDisabled_containsExpectedKey() {
TestUtils.setOneHandedModeEnabled(this, /* enabled= */ false);
final Map<ComponentName, AccessibilityShortcutController.FrameworkFeatureInfo>
frameworkFeatureMap =
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
assertFalse(frameworkFeatureMap.containsKey(ONE_HANDED_COMPONENT_NAME));
}
@Test @Test
public void testOnAccessibilityShortcut_forServiceWithNoSummary_doesNotCrash() public void testOnAccessibilityShortcut_forServiceWithNoSummary_doesNotCrash()
throws Exception { throws Exception {

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.accessibility;
import com.android.internal.os.RoSystemProperties;
import java.lang.reflect.Field;
/**
* Test utility methods.
*/
public class TestUtils {
/**
* Sets the {@code enabled} of the given OneHandedMode flags to simulate device behavior.
*/
public static void setOneHandedModeEnabled(Object obj, boolean enabled) {
try {
final Field field = RoSystemProperties.class.getDeclaredField(
"SUPPORT_ONE_HANDED_MODE");
field.setAccessible(true);
field.setBoolean(obj, enabled);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
}