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
merged-in: Id0696bff522cb7e19c5a16a47bbb76a794472c52
(cherry picked from commit 1a9081a982)
This commit is contained in:
@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
|
||||
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
|
||||
|
||||
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 android.accessibilityservice.AccessibilityServiceInfo;
|
||||
@@ -147,11 +148,13 @@ public class AccessibilityShortcutController {
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
|
||||
"1" /* Value to enable */, "0" /* Value to disable */,
|
||||
R.string.color_correction_feature_name));
|
||||
featuresMap.put(ONE_HANDED_COMPONENT_NAME,
|
||||
new ToggleableFrameworkFeatureInfo(
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED,
|
||||
"1" /* Value to enable */, "0" /* Value to disable */,
|
||||
R.string.one_handed_mode_feature_name));
|
||||
if (SUPPORT_ONE_HANDED_MODE) {
|
||||
featuresMap.put(ONE_HANDED_COMPONENT_NAME,
|
||||
new ToggleableFrameworkFeatureInfo(
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED,
|
||||
"1" /* Value to enable */, "0" /* Value to disable */,
|
||||
R.string.one_handed_mode_feature_name));
|
||||
}
|
||||
featuresMap.put(REDUCE_BRIGHT_COLORS_COMPONENT_NAME,
|
||||
new ToggleableFrameworkFeatureInfo(
|
||||
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
|
||||
|
||||
@@ -25,6 +25,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.util.AccessibilityUtils.getAccessibilityServiceFragmentType;
|
||||
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.AccessibilityShortcutInfo;
|
||||
@@ -209,6 +210,7 @@ public final class AccessibilityTargetHelper {
|
||||
context.getString(R.string.accessibility_magnification_chooser_text),
|
||||
context.getDrawable(R.drawable.ic_accessibility_magnification),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
|
||||
targets.add(magnification);
|
||||
|
||||
final ToggleAllowListingFeatureTarget daltonizer =
|
||||
new ToggleAllowListingFeatureTarget(context,
|
||||
@@ -219,6 +221,7 @@ public final class AccessibilityTargetHelper {
|
||||
context.getString(R.string.color_correction_feature_name),
|
||||
context.getDrawable(R.drawable.ic_accessibility_color_correction),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
|
||||
targets.add(daltonizer);
|
||||
|
||||
final ToggleAllowListingFeatureTarget colorInversion =
|
||||
new ToggleAllowListingFeatureTarget(context,
|
||||
@@ -229,16 +232,20 @@ public final class AccessibilityTargetHelper {
|
||||
context.getString(R.string.color_inversion_feature_name),
|
||||
context.getDrawable(R.drawable.ic_accessibility_color_inversion),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
|
||||
targets.add(colorInversion);
|
||||
|
||||
final ToggleAllowListingFeatureTarget oneHandedMode =
|
||||
new ToggleAllowListingFeatureTarget(context,
|
||||
shortcutType,
|
||||
isShortcutContained(context, shortcutType,
|
||||
ONE_HANDED_COMPONENT_NAME.flattenToString()),
|
||||
ONE_HANDED_COMPONENT_NAME.flattenToString(),
|
||||
context.getString(R.string.one_handed_mode_feature_name),
|
||||
context.getDrawable(R.drawable.ic_accessibility_one_handed),
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED);
|
||||
if (SUPPORT_ONE_HANDED_MODE) {
|
||||
final ToggleAllowListingFeatureTarget oneHandedMode =
|
||||
new ToggleAllowListingFeatureTarget(context,
|
||||
shortcutType,
|
||||
isShortcutContained(context, shortcutType,
|
||||
ONE_HANDED_COMPONENT_NAME.flattenToString()),
|
||||
ONE_HANDED_COMPONENT_NAME.flattenToString(),
|
||||
context.getString(R.string.one_handed_mode_feature_name),
|
||||
context.getDrawable(R.drawable.ic_accessibility_one_handed),
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED);
|
||||
targets.add(oneHandedMode);
|
||||
}
|
||||
|
||||
final ToggleAllowListingFeatureTarget reduceBrightColors =
|
||||
new ToggleAllowListingFeatureTarget(context,
|
||||
@@ -249,11 +256,6 @@ public final class AccessibilityTargetHelper {
|
||||
context.getString(R.string.reduce_bright_colors_feature_name),
|
||||
context.getDrawable(R.drawable.ic_accessibility_reduce_bright_colors),
|
||||
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED);
|
||||
|
||||
targets.add(magnification);
|
||||
targets.add(daltonizer);
|
||||
targets.add(colorInversion);
|
||||
targets.add(oneHandedMode);
|
||||
targets.add(reduceBrightColors);
|
||||
|
||||
return targets;
|
||||
|
||||
@@ -31,6 +31,8 @@ public class RoSystemProperties {
|
||||
SystemProperties.getInt("ro.factorytest", 0);
|
||||
public static final String 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.* -------- //
|
||||
/**
|
||||
|
||||
@@ -1414,6 +1414,7 @@
|
||||
<activity android:name="com.android.internal.app.ChooserWrapperActivity"/>
|
||||
<activity android:name="com.android.internal.app.ResolverWrapperActivity"/>
|
||||
<activity android:name="com.android.internal.app.IntentForwarderActivityTest$IntentForwarderWrapperActivity"/>
|
||||
<activity android:name="com.android.internal.accessibility.AccessibilityShortcutChooserActivityTest$TestAccessibilityShortcutChooserActivity"/>
|
||||
|
||||
<receiver android:name="android.app.activity.AbortReceiver"
|
||||
android:exported="true">
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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 static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.action.ViewActions.doubleClick;
|
||||
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.matches;
|
||||
import static androidx.test.espresso.matcher.RootMatchers.isDialog;
|
||||
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.withText;
|
||||
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Handler;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.test.core.app.ActivityScenario;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Tests for {@link AccessibilityShortcutChooserActivity}.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class AccessibilityShortcutChooserActivityTest {
|
||||
private static final String ONE_HANDED_MODE = "One-Handed mode";
|
||||
private static final String TEST_LABEL = "TEST_LABEL";
|
||||
private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("package", "class");
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Mock
|
||||
private AccessibilityServiceInfo mAccessibilityServiceInfo;
|
||||
@Mock
|
||||
private ResolveInfo mResolveInfo;
|
||||
@Mock
|
||||
private ServiceInfo mServiceInfo;
|
||||
@Mock
|
||||
private ApplicationInfo mApplicationInfo;
|
||||
@Mock
|
||||
private IAccessibilityManager mAccessibilityManagerService;
|
||||
|
||||
@Test
|
||||
public void doubleClickTestServiceAndClickDenyButton_permissionDialogDoesNotExist()
|
||||
throws Exception {
|
||||
configureTestService();
|
||||
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(withText(TEST_LABEL)).perform(scrollTo(), doubleClick());
|
||||
onView(withId(R.id.accessibility_permission_enable_deny_button)).perform(scrollTo(),
|
||||
click());
|
||||
|
||||
onView(withId(R.id.accessibility_permissionDialog_title)).inRoot(isDialog()).check(
|
||||
doesNotExist());
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for testing.
|
||||
*/
|
||||
public static class TestAccessibilityShortcutChooserActivity extends
|
||||
AccessibilityShortcutChooserActivity {
|
||||
private static IAccessibilityManager sAccessibilityManagerService;
|
||||
|
||||
public static void setupForTesting(IAccessibilityManager accessibilityManagerService) {
|
||||
sAccessibilityManagerService = accessibilityManagerService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
if (Context.ACCESSIBILITY_SERVICE.equals(name)
|
||||
&& sAccessibilityManagerService != null) {
|
||||
return new AccessibilityManager(this, new Handler(getMainLooper()),
|
||||
sAccessibilityManagerService, /* userId= */ 0, /* serviceConnect= */ true);
|
||||
}
|
||||
|
||||
return super.getSystemService(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,11 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SC
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
|
||||
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.ONE_HANDED_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
@@ -203,6 +208,17 @@ public class AccessibilityShortcutControllerTest {
|
||||
when(mAlertDialog.getWindow()).thenReturn(window);
|
||||
|
||||
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
|
||||
@@ -428,11 +444,10 @@ public class AccessibilityShortcutControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFrameworkFeatureMap_shouldBeNonNullAndUnmodifiable() {
|
||||
Map<ComponentName, AccessibilityShortcutController.ToggleableFrameworkFeatureInfo>
|
||||
public void getFrameworkFeatureMap_shouldBeUnmodifiable() {
|
||||
final Map<ComponentName, AccessibilityShortcutController.ToggleableFrameworkFeatureInfo>
|
||||
frameworkFeatureMap =
|
||||
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
|
||||
assertTrue("Framework features not supported", frameworkFeatureMap.size() > 0);
|
||||
|
||||
try {
|
||||
frameworkFeatureMap.clear();
|
||||
@@ -442,7 +457,38 @@ public class AccessibilityShortcutControllerTest {
|
||||
}
|
||||
}
|
||||
|
||||
public void getFrameworkFeatureMap_containsExpectedDefaultKeys() {
|
||||
final Map<ComponentName, AccessibilityShortcutController.ToggleableFrameworkFeatureInfo>
|
||||
frameworkFeatureMap =
|
||||
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
|
||||
|
||||
assertTrue(frameworkFeatureMap.containsKey(COLOR_INVERSION_COMPONENT_NAME));
|
||||
assertTrue(frameworkFeatureMap.containsKey(DALTONIZER_COMPONENT_NAME));
|
||||
assertTrue(frameworkFeatureMap.containsKey(REDUCE_BRIGHT_COLORS_COMPONENT_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFrameworkFeatureMap_oneHandedModeEnabled_containsExpectedKey() {
|
||||
TestUtils.setOneHandedModeEnabled(this, /* enabled= */ true);
|
||||
|
||||
final Map<ComponentName, AccessibilityShortcutController.ToggleableFrameworkFeatureInfo>
|
||||
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.ToggleableFrameworkFeatureInfo>
|
||||
frameworkFeatureMap =
|
||||
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
|
||||
|
||||
assertFalse(frameworkFeatureMap.containsKey(ONE_HANDED_COMPONENT_NAME));
|
||||
}
|
||||
|
||||
public void testOnAccessibilityShortcut_forServiceWithNoSummary_doesNotCrash()
|
||||
throws Exception {
|
||||
configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user