From 43d5042ff900ab91251eb4c96bdc63f4a8ed4481 Mon Sep 17 00:00:00 2001 From: Tyler Freeman Date: Fri, 13 Jan 2023 01:29:26 +0000 Subject: [PATCH] feat(#MagnificationJoystick): add preference for enabling Joystick to Settings Hide behind feature flag so no one sees the preference unless its enabled. Bug: b/265688847 Test: atest MagnificationJoystickPreferenceControllerTest Change-Id: Id5cc9385f25395f53809a79ba70c84205f9758c2 --- res/values/strings.xml | 4 + ...ificationJoystickPreferenceController.java | 92 +++++++++++++++ ...ScreenMagnificationPreferenceFragment.java | 32 +++++- ...ationJoystickPreferenceControllerTest.java | 108 ++++++++++++++++++ 4 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/MagnificationJoystickPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 83698eb8e79..bc386ebc3f2 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4104,6 +4104,10 @@ Always On Instead of deactivating magnification when changing apps, it simply zooms out to normal size. Pinch to zoom back in whenever you want. + + Joystick + + Activate and move the magnifier with an on-screen joystick. Tap and hold, then drag on the joystick to control the magnifier. Tap and drag to move the joystick itself. About magnification diff --git a/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java b/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java new file mode 100644 index 00000000000..bc9e093ffc9 --- /dev/null +++ b/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java @@ -0,0 +1,92 @@ +/* + * 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.settings.accessibility; + +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + +import android.content.Context; +import android.provider.Settings; + +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; + +/** + * Controller that accesses and switches the preference status of the magnification joystick feature + */ +public class MagnificationJoystickPreferenceController extends TogglePreferenceController + implements LifecycleObserver { + + private static final String TAG = + MagnificationJoystickPreferenceController.class.getSimpleName(); + static final String PREF_KEY = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED; + + private SwitchPreference mSwitchPreference; + + public MagnificationJoystickPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public boolean isChecked() { + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED, OFF) == ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED, + (isChecked ? ON : OFF)); + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_accessibility; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mSwitchPreference = screen.findPreference(getPreferenceKey()); + } + + // TODO(b/186731461): Remove it when this controller is used in DashBoardFragment only. + @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) + void onResume() { + updateState(); + } + + /** + * Updates the state of preference components which has been displayed by + * {@link MagnificationJoystickPreferenceController#displayPreference}. + */ + void updateState() { + updateState(mSwitchPreference); + } +} diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index e59b4c24e9a..4a12c414026 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -217,6 +217,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends addPreferenceController(mFollowTypingPreferenceController); addAlwaysOnSetting(generalCategory); + addJoystickSetting(generalCategory); } private void addAlwaysOnSetting(PreferenceCategory generalCategory) { @@ -245,6 +246,34 @@ public class ToggleScreenMagnificationPreferenceFragment extends addPreferenceController(alwaysOnPreferenceController); } + private void addJoystickSetting(PreferenceCategory generalCategory) { + if (!DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_WINDOW_MANAGER, + "MagnificationJoystick__enable_magnification_joystick", + false + )) { + return; + } + + SwitchPreference joystickPreference = new SwitchPreference(getPrefContext()); + joystickPreference.setTitle( + R.string.accessibility_screen_magnification_joystick_title); + joystickPreference.setSummary( + R.string.accessibility_screen_magnification_joystick_summary); + joystickPreference.setKey( + MagnificationJoystickPreferenceController.PREF_KEY); + generalCategory.addPreference(joystickPreference); + + MagnificationJoystickPreferenceController joystickPreferenceController = + new MagnificationJoystickPreferenceController( + getContext(), + MagnificationJoystickPreferenceController.PREF_KEY + ); + getSettingsLifecycle().addObserver(joystickPreferenceController); + joystickPreferenceController.displayPreference(getPreferenceScreen()); + addPreferenceController(joystickPreferenceController); + } + @Override public void showDialog(int dialogId) { super.showDialog(dialogId); @@ -350,7 +379,8 @@ public class ToggleScreenMagnificationPreferenceFragment extends List keysToObserve = List.of( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED, - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED, + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED ); contentObserver.registerKeysToObserverCallback(keysToObserve, key -> updatePreferencesState()); diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationJoystickPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationJoystickPreferenceControllerTest.java new file mode 100644 index 00000000000..236f18ce70b --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationJoystickPreferenceControllerTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2023 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.settings.accessibility; + +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.provider.Settings; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class MagnificationJoystickPreferenceControllerTest { + + private static final String KEY_JOYSTICK = + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED; + + private final Context mContext = ApplicationProvider.getApplicationContext(); + private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext)); + private final MagnificationJoystickPreferenceController mController = + new MagnificationJoystickPreferenceController(mContext, + MagnificationJoystickPreferenceController.PREF_KEY); + + @Before + public void setUp() { + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); + mSwitchPreference.setKey(MagnificationJoystickPreferenceController.PREF_KEY); + screen.addPreference(mSwitchPreference); + mController.displayPreference(screen); + } + + @Test + public void isChecked_defaultStateForJoystick_onResumeShouldReturnFalse() { + mController.onResume(); + + assertThat(mController.isChecked()).isFalse(); + assertThat(mSwitchPreference.isChecked()).isFalse(); + } + + @Test + public void isChecked_enableJoystick_onResumeShouldReturnTrue() { + Settings.Secure.putInt(mContext.getContentResolver(), KEY_JOYSTICK, ON); + mController.onResume(); + + assertThat(mController.isChecked()).isTrue(); + assertThat(mSwitchPreference.isChecked()).isTrue(); + } + + @Test + public void isChecked_disableJoystick_onResumeShouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), KEY_JOYSTICK, OFF); + mController.onResume(); + + assertThat(mController.isChecked()).isFalse(); + assertThat(mSwitchPreference.isChecked()).isFalse(); + } + + @Test + public void performClick_switchDefaultStateForJoystick_shouldReturnTrue() { + mController.onResume(); + + mSwitchPreference.performClick(); + + verify(mSwitchPreference).setChecked(true); + assertThat(mController.isChecked()).isTrue(); + assertThat(mSwitchPreference.isChecked()).isTrue(); + } + + @Test + public void updateState_disableJoystick_shouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), KEY_JOYSTICK, OFF); + + mController.updateState(); + + verify(mSwitchPreference).setChecked(false); + assertThat(mController.isChecked()).isFalse(); + assertThat(mSwitchPreference.isChecked()).isFalse(); + } +}