diff --git a/res/values/strings.xml b/res/values/strings.xml index 4edc3b505ea..bec50d4f7d8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3972,6 +3972,10 @@ Magnify typing Magnifier follows text as you type + + Always On + + Instead of deactivating magnification when changing apps, it simply zooms out to normal size. Pinch to zoom back in whenever you want. About magnification diff --git a/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceController.java b/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceController.java new file mode 100644 index 00000000000..b0a6abc8349 --- /dev/null +++ b/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceController.java @@ -0,0 +1,94 @@ +/* + * 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 always on + * feature, where the magnifier will not deactivate on Activity transitions; it will only zoom out + * to 100%. + */ +public class MagnificationAlwaysOnPreferenceController extends TogglePreferenceController + implements LifecycleObserver { + + private static final String TAG = + MagnificationAlwaysOnPreferenceController.class.getSimpleName(); + static final String PREF_KEY = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED; + + private SwitchPreference mSwitchPreference; + + public MagnificationAlwaysOnPreferenceController(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_ALWAYS_ON_ENABLED, ON) == ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_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 MagnificationAlwaysOnPreferenceController#displayPreference}. + */ + void updateState() { + updateState(mSwitchPreference); + } +} diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index 935c3cb452f..979c941489f 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -31,6 +31,7 @@ import android.content.pm.PackageManager; import android.icu.text.CaseMap; import android.net.Uri; import android.os.Bundle; +import android.provider.DeviceConfig; import android.provider.Settings; import android.text.TextUtils; import android.view.LayoutInflater; @@ -212,6 +213,32 @@ public class ToggleScreenMagnificationPreferenceFragment extends getContext(), MagnificationFollowTypingPreferenceController.PREF_KEY); getSettingsLifecycle().addObserver(mFollowTypingPreferenceController); mFollowTypingPreferenceController.displayPreference(getPreferenceScreen()); + + addAlwaysOnSetting(generalCategory); + } + + private void addAlwaysOnSetting(PreferenceCategory generalCategory) { + if (!DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_WINDOW_MANAGER, + "AlwaysOnMagnifier__enable_always_on_magnifier", + false + )) { + return; + } + + var alwaysOnPreference = new SwitchPreference(getPrefContext()); + alwaysOnPreference.setTitle( + R.string.accessibility_screen_magnification_always_on_title); + alwaysOnPreference.setSummary( + R.string.accessibility_screen_magnification_always_on_summary); + alwaysOnPreference.setKey( + MagnificationAlwaysOnPreferenceController.PREF_KEY); + generalCategory.addPreference(alwaysOnPreference); + + var alwaysOnPreferenceController = new MagnificationAlwaysOnPreferenceController( + getContext(), MagnificationAlwaysOnPreferenceController.PREF_KEY); + getSettingsLifecycle().addObserver(alwaysOnPreferenceController); + alwaysOnPreferenceController.displayPreference(getPreferenceScreen()); } @Override diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceControllerTest.java new file mode 100644 index 00000000000..e8015c5afcf --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceControllerTest.java @@ -0,0 +1,108 @@ +/* + * 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 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 MagnificationAlwaysOnPreferenceControllerTest { + + private static final String KEY_ALWAYS_ON = + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED; + + private final Context mContext = ApplicationProvider.getApplicationContext(); + private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext)); + private final MagnificationAlwaysOnPreferenceController mController = + new MagnificationAlwaysOnPreferenceController(mContext, + MagnificationAlwaysOnPreferenceController.PREF_KEY); + + @Before + public void setUp() { + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); + mSwitchPreference.setKey(MagnificationAlwaysOnPreferenceController.PREF_KEY); + screen.addPreference(mSwitchPreference); + mController.displayPreference(screen); + } + + @Test + public void isChecked_defaultStateForAlwaysOn_onResumeShouldReturnTrue() { + mController.onResume(); + + assertThat(mController.isChecked()).isTrue(); + assertThat(mSwitchPreference.isChecked()).isTrue(); + } + + @Test + public void isChecked_enableAlwaysOn_onResumeShouldReturnTrue() { + Settings.Secure.putInt(mContext.getContentResolver(), KEY_ALWAYS_ON, ON); + mController.onResume(); + + assertThat(mController.isChecked()).isTrue(); + assertThat(mSwitchPreference.isChecked()).isTrue(); + } + + @Test + public void isChecked_disableAlwaysOn_onResumeShouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), KEY_ALWAYS_ON, OFF); + mController.onResume(); + + assertThat(mController.isChecked()).isFalse(); + assertThat(mSwitchPreference.isChecked()).isFalse(); + } + + @Test + public void performClick_switchDefaultStateForAlwaysOn_shouldReturnFalse() { + mController.onResume(); + + mSwitchPreference.performClick(); + + verify(mSwitchPreference).setChecked(false); + assertThat(mController.isChecked()).isFalse(); + assertThat(mSwitchPreference.isChecked()).isFalse(); + } + + @Test + public void updateState_disableAlwaysOn_shouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), KEY_ALWAYS_ON, OFF); + + mController.updateState(); + + verify(mSwitchPreference).setChecked(false); + assertThat(mController.isChecked()).isFalse(); + assertThat(mSwitchPreference.isChecked()).isFalse(); + } +}