Merge "feat(#MagnificationJoystick): add preference for enabling Joystick to Settings"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cc8baf0..5d32022 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4104,6 +4104,10 @@
<string name="accessibility_screen_magnification_always_on_title">Always On</string>
<!-- Summary for accessibility magnifier preference where the magnifier never turns off on its own. [CHAR LIMIT=none] -->
<string name="accessibility_screen_magnification_always_on_summary">Instead of deactivating magnification when changing apps, it simply zooms out to normal size. Pinch to zoom back in whenever you want.</string>
+ <!-- Title for accessibility on-screen joystick controller preference that controls magnification position. [CHAR LIMIT=35] -->
+ <string name="accessibility_screen_magnification_joystick_title">Joystick</string>
+ <!-- Summary for accessibility on-screen joystick controller preference that controls magnification position. [CHAR LIMIT=none] -->
+ <string name="accessibility_screen_magnification_joystick_summary">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.</string>
<!-- Title for screen magnification footer. [CHAR LIMIT=60] -->
<string name="accessibility_screen_magnification_about_title">About magnification</string>
<!-- Screen magnification footer link content description [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java b/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java
new file mode 100644
index 0000000..bc9e093
--- /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 0558f25..9c2424c 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -217,6 +217,7 @@
addPreferenceController(mFollowTypingPreferenceController);
addAlwaysOnSetting(generalCategory);
+ addJoystickSetting(generalCategory);
}
private void addAlwaysOnSetting(PreferenceCategory generalCategory) {
@@ -244,6 +245,34 @@
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);
@@ -349,7 +378,8 @@
var 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 0000000..236f18c
--- /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();
+ }
+}