From 756104417a61bde4fad82b415d156592204f4482 Mon Sep 17 00:00:00 2001 From: menghanli Date: Wed, 18 Dec 2019 20:42:47 +0800 Subject: [PATCH] Create settings for window magnification (2/n) Provide a setting for new Magnify area feature and joystick controller Bug: 146019459 Bug: 146473544 Test: make RunSettingsRoboTests ROBOTEST_FILTER=MagnificationModePreferenceControllerTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=MagnificationWindowControlPreferenceControllerTest Test: make RunSettingsRoboTests2 Change-Id: Ia32fa073c59ad304e9ef9eb530ba37dd24c2f2f6 --- ...ccessibility_magnification_full_screen.png | Bin 0 -> 2469 bytes ...essibility_magnification_window_screen.png | Bin 0 -> 2024 bytes .../accessibility_edit_magnification_mode.xml | 44 ++++ .../accessibility_edit_shortcut_component.xml | 6 +- res/values/arrays.xml | 19 +- res/values/strings.xml | 20 ++ ...ibility_magnification_service_settings.xml | 36 +++ .../AccessibilityEditDialogUtils.java | 57 ++++- .../DaltonizerPreferenceController.java | 6 +- ...MagnificationModePreferenceController.java | 41 +++ .../MagnificationSettingsFragment.java | 234 ++++++++++++++++++ ...tionWindowControlPreferenceController.java | 60 +++++ ...ScreenMagnificationPreferenceFragment.java | 10 + ...ificationModePreferenceControllerTest.java | 68 +++++ ...WindowControlPreferenceControllerTest.java | 96 +++++++ 15 files changed, 688 insertions(+), 9 deletions(-) create mode 100644 res/drawable/accessibility_magnification_full_screen.png create mode 100644 res/drawable/accessibility_magnification_window_screen.png create mode 100644 res/layout/accessibility_edit_magnification_mode.xml create mode 100644 res/xml/accessibility_magnification_service_settings.xml create mode 100644 src/com/android/settings/accessibility/MagnificationModePreferenceController.java create mode 100644 src/com/android/settings/accessibility/MagnificationSettingsFragment.java create mode 100644 src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java diff --git a/res/drawable/accessibility_magnification_full_screen.png b/res/drawable/accessibility_magnification_full_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..7fcd17d5cb5f422a4ca0b11b4e365539f279f1ef GIT binary patch literal 2469 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 literal 0 HcmV?d00001 diff --git a/res/drawable/accessibility_magnification_window_screen.png b/res/drawable/accessibility_magnification_window_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..db1f33274b104246fb0857411b956fce56679e42 GIT binary patch literal 2024 zcmZuyX;4#H7JeW|KxhzfK)bbNQM4Q}0R@RRiiT}i1jMD0MNm}44MahKR**ql0NX~} z1_VryB`y(0K!g?{Y(jv9uqW)v%L~~PlDw=;y5`5!R87@A=ljmB^W7i!oKxpPNU*P& z$p#Yu0L=XTFkw23)7f*xDxJ4Xd*`YHgY#ZNUI0*6xJDgosEaqB@e2zAfZJOE;BF28 zD0NqNApp361c0T}0Dyi005;c3KZouIfK@<9V7T|n%8FL2)o3(owR(AZnaO0*Xtc4h zvC+}d$;rw2`FTE{uT&~kD%H}`((LT)!otGz^z_u!lvFC^a5ytFGh8kghGB(5A(zXA zLLq~}kVqtSI$bOl%VaVZi#0JZ0fOM%+#H+D9v&VRi9`Z{fI^|@URA2pun3Ye2BeGq z(nZoTW022YkW4kR@!?Qa5L6uuRR@9i6BAu{$}p8gB8kTctn#10l09IF8|&3!;Z)1A zR3;w#z^d>BOWnXycNWfDzR*dfQswiVU>O?1c|(={P^BOE(qnm?05f{w#U7aPZF!^? zstVwIh*1eV-c!}GP$ZbsIHe6)ago0)JmE1`M zYX}Ah!14ntT8&n%RPv{Vy-%R3K&?it63mJEic~_Kf5xs3X1zMJM2KeBgs`xO`G2NM zs5QKno9x<978V0D`W0*{|4W8O#+OiVFtcBylqq>M2?eXGBL7RKsP_rK^_EgFC+sPJ zYQuy*Pqb=1W-fS~K4czI_G18O3VO@T{W(mES^_CpWCf%< z6eXX&M2J!>jVV}z?AkDXYZ|ZR1`CJb(mH29-sZReQ%KAe_7pBI%#BfpRIp@ZWMpx1 zv9GU>OeXVqJP3lu$HzNJAOD&gy|@5h43KBI(N7l`rT7PV8!eie8En;?2eihB<9PQH25sjoi z*~rbwnRLOQ9ES0Q*s|2Nm?60`b7i4DJp-ODED;p=sLoT?yPZBmzGGz@c%J3j8Be27b;q#vB!bCn{P8!@xT3n^o0e}d@1~L;hl$ZQIH-K%fC#50 z_mFMdUklB9wLY}mI}X;4u9o?E7WpN+FZ*Dtg2FMzfn%-S0hSFHr&l}p_0k$0n#M2f zatKU;{0bmz#EX#B@A^WKrr3b-E7Jo~XuUxeG`i0*{8>~@ec@_-%6r0CefKw&m!0x{ z1j5t=b$YI%{c!GgYwr17$St%*)ho!M7RC+EX({lFI;4$tzMFGg#<7e(Vn@Z=b}M_Q zg^tQ^E;}6$*{t<2TsgwVRRteyw?q44f_vO&T(Rc{i_IS7l{pX%HJ6BV+Y6no?1+r* z>vz|oB!`P^ADj7wkg^|W*O+aH;9|S#w*)-z4z)|^Ul=`}&)jj`nHcldB<3GHJ#(r8l$jSi)7{uBie}i-F%{O-hmzBlV!D@ zZB&4-&pFc*OEL`3Dc$>E%|qgLy_|C;rmudwflf3%j~LkFaj16moNzo(99UVYhZrPt6Toh7z`&Tdg@4s1NhFYGzC=It29ZkPz zv(02x(mI^aX@b}xy6u*#fF46Jn+ZXZ2q=wda?e^`zB9qB0LqI{DE9(_TZ0<+FiszawdHu+H;fr zHUAgRhiaYNdkVMg2$6s^8?K69E3+!I<}lPG|oc*G6|j literal 0 HcmV?d00001 diff --git a/res/layout/accessibility_edit_magnification_mode.xml b/res/layout/accessibility_edit_magnification_mode.xml new file mode 100644 index 00000000000..e34f32e51b9 --- /dev/null +++ b/res/layout/accessibility_edit_magnification_mode.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + diff --git a/res/layout/accessibility_edit_shortcut_component.xml b/res/layout/accessibility_edit_shortcut_component.xml index 2e1ad2de3d3..52b89359b59 100644 --- a/res/layout/accessibility_edit_shortcut_component.xml +++ b/res/layout/accessibility_edit_shortcut_component.xml @@ -19,12 +19,14 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical"> + android:orientation="vertical" + android:paddingBottom="16dp"> + android:layout_height="wrap_content" + android:saveEnabled="false"/> \? + + + @string/accessibility_magnification_area_settings_full_screen_summary + @string/accessibility_magnification_area_settings_window_screen_summary + @string/accessibility_magnification_area_settings_all_summary + + + + + + 1 + + 2 + + 3 + + - + @string/daltonizer_mode_deuteranomaly @string/daltonizer_mode_protanomaly @string/daltonizer_mode_tritanomaly diff --git a/res/values/strings.xml b/res/values/strings.xml index 621d364b275..d0704ededcf 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4755,6 +4755,26 @@ Caption preferences Magnification + + Magnification area + + Choose the magnification area(s) you want to use when magnifying the screen + + Full screen + + Part of screen + + Full screen & part of screen + + Magnify entire screen + + Magnify part of screen + + Show move controller + + Show a joystick-like controller to move the magnification area + + Magnify settings Magnify with triple-tap diff --git a/res/xml/accessibility_magnification_service_settings.xml b/res/xml/accessibility_magnification_service_settings.xml new file mode 100644 index 00000000000..d67fc66c75c --- /dev/null +++ b/res/xml/accessibility_magnification_service_settings.xml @@ -0,0 +1,36 @@ + + + + + + + + + diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java index fb96bfdb801..1d874771517 100644 --- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java +++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java @@ -24,6 +24,7 @@ import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.text.Spannable; import android.text.SpannableString; +import android.text.TextUtils; import android.text.style.ImageSpan; import android.view.LayoutInflater; import android.view.View; @@ -53,13 +54,15 @@ public class AccessibilityEditDialogUtils { */ @Retention(RetentionPolicy.SOURCE) @IntDef({ - DialogType.EDIT_SHORTCUT_GENERIC, - DialogType.EDIT_SHORTCUT_MAGNIFICATION, + DialogType.EDIT_SHORTCUT_GENERIC, + DialogType.EDIT_SHORTCUT_MAGNIFICATION, + DialogType.EDIT_MAGNIFICATION_MODE, }) private @interface DialogType { int EDIT_SHORTCUT_GENERIC = 0; int EDIT_SHORTCUT_MAGNIFICATION = 1; + int EDIT_MAGNIFICATION_MODE = 2; } /** @@ -96,6 +99,23 @@ public class AccessibilityEditDialogUtils { return alertDialog; } + /** + * Method to show the magnification mode dialog in Magnification. + * + * @param context A valid context + * @param dialogTitle The title of magnify mode dialog + * @param listener The listener to determine the action of magnify mode dialog + * @return A magnification mode dialog in Magnification + */ + public static AlertDialog showMagnificationModeDialog(Context context, + CharSequence dialogTitle, DialogInterface.OnClickListener listener) { + final AlertDialog alertDialog = createDialog(context, + DialogType.EDIT_MAGNIFICATION_MODE, dialogTitle, listener); + alertDialog.show(); + + return alertDialog; + } + private static AlertDialog createDialog(Context context, int dialogType, CharSequence dialogTitle, DialogInterface.OnClickListener listener) { @@ -138,6 +158,12 @@ public class AccessibilityEditDialogUtils { initMagnifyShortcut(context, contentView); initAdvancedWidget(contentView); break; + case DialogType.EDIT_MAGNIFICATION_MODE: + contentView = inflater.inflate( + R.layout.accessibility_edit_magnification_mode, null); + initMagnifyFullScreen(context, contentView); + initMagnifyWindowScreen(context, contentView); + break; default: throw new IllegalArgumentException(); } @@ -145,12 +171,37 @@ public class AccessibilityEditDialogUtils { return contentView; } + private static void initMagnifyFullScreen(Context context, View view) { + final View dialogView = view.findViewById(R.id.magnify_full_screen); + final String title = context.getString( + R.string.accessibility_magnification_area_settings_full_screen); + // TODO(b/146019459): Use vector drawable instead of temporal png file to avoid distorted. + setupShortcutWidget(dialogView, title, R.drawable.accessibility_magnification_full_screen); + } + + private static void initMagnifyWindowScreen(Context context, View view) { + final View dialogView = view.findViewById(R.id.magnify_window_screen); + final String title = context.getString( + R.string.accessibility_magnification_area_settings_window_screen); + // TODO(b/146019459): Use vector drawable instead of temporal png file to avoid distorted. + setupShortcutWidget(dialogView, title, + R.drawable.accessibility_magnification_window_screen); + } + + private static void setupShortcutWidget(View view, CharSequence titleText, int imageResId) { + setupShortcutWidget(view, titleText, null, imageResId); + } + private static void setupShortcutWidget(View view, CharSequence titleText, CharSequence summaryText, int imageResId) { final CheckBox checkBox = view.findViewById(R.id.checkbox); checkBox.setText(titleText); final TextView summary = view.findViewById(R.id.summary); - summary.setText(summaryText); + if (TextUtils.isEmpty(summaryText)) { + summary.setVisibility(View.GONE); + } else { + summary.setText(summaryText); + } final ImageView image = view.findViewById(R.id.image); image.setImageResource(imageResId); } diff --git a/src/com/android/settings/accessibility/DaltonizerPreferenceController.java b/src/com/android/settings/accessibility/DaltonizerPreferenceController.java index e026313ea3a..2922b76fefc 100644 --- a/src/com/android/settings/accessibility/DaltonizerPreferenceController.java +++ b/src/com/android/settings/accessibility/DaltonizerPreferenceController.java @@ -42,15 +42,15 @@ public class DaltonizerPreferenceController extends BasePreferenceController { @Override public CharSequence getSummary() { - final String[] daltonizerSummarys = mContext.getResources().getStringArray( - R.array.daltonizer_mode_summary); + final String[] daltonizerSummaries = mContext.getResources().getStringArray( + R.array.daltonizer_mode_summaries); final int[] daltonizerValues = mContext.getResources().getIntArray( R.array.daltonizer_type_values); final int timeoutValue = DaltonizerRadioButtonPreferenceController.getSecureAccessibilityDaltonizerValue( mContext.getContentResolver(), DALTONIZER_TYPE); final int idx = Ints.indexOf(daltonizerValues, timeoutValue); - final String serviceSummary = daltonizerSummarys[idx == -1 ? 0 : idx]; + final String serviceSummary = daltonizerSummaries[idx == -1 ? 0 : idx]; final CharSequence serviceState = AccessibilityUtil.getSummary(mContext, DALTONIZER_ENABLED); diff --git a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java new file mode 100644 index 00000000000..b45ad88a520 --- /dev/null +++ b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 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 android.content.Context; + +import com.android.settings.core.BasePreferenceController; + +/** Controller that shows the magnification area mode summary. */ +public class MagnificationModePreferenceController extends BasePreferenceController { + + public MagnificationModePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + + @Override + public CharSequence getSummary() { + return MagnificationSettingsFragment.getMagnificationCapabilitiesSummary( + mContext); + } +} diff --git a/src/com/android/settings/accessibility/MagnificationSettingsFragment.java b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java new file mode 100644 index 00000000000..0e766b4cf5d --- /dev/null +++ b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2019 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 android.app.Dialog; +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.provider.Settings; +import android.view.View; +import android.widget.CheckBox; + +import androidx.annotation.IntDef; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.search.SearchIndexable; + +import com.google.common.primitives.Ints; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** Settings page for magnification. */ +@SearchIndexable +public class MagnificationSettingsFragment extends DashboardFragment { + + private static final String TAG = "MagnificationSettingsFragment"; + private static final String PREF_KEY_MODE = "magnification_mode"; + // TODO(b/146019459): Use magnification_capability. + private static final String KEY_CAPABILITY = Settings.System.MASTER_MONO; + private static final int DIALOG_MAGNIFICATION_CAPABILITY = 1; + private static final String EXTRA_CAPABILITY = "capability"; + private Preference mModePreference; + private int mCapabilities = MagnifyMode.NONE; + private CheckBox mMagnifyFullScreenCheckBox; + private CheckBox mMagnifyWindowCheckBox; + + static String getMagnificationCapabilitiesSummary(Context context) { + final String[] magnificationModeSummaries = context.getResources().getStringArray( + R.array.magnification_mode_summaries); + final int[] magnificationModeValues = context.getResources().getIntArray( + R.array.magnification_mode_values); + final int capabilities = MagnificationSettingsFragment.getMagnificationCapabilities( + context); + + final int idx = Ints.indexOf(magnificationModeValues, capabilities); + return magnificationModeSummaries[idx == -1 ? 0 : idx]; + } + + private static int getMagnificationCapabilities(Context context) { + return getSecureIntValue(context, KEY_CAPABILITY, MagnifyMode.FULLSCREEN); + } + + private static int getSecureIntValue(Context context, String key, int defaultValue) { + return Settings.Secure.getIntForUser( + context.getContentResolver(), + key, defaultValue, context.getContentResolver().getUserId()); + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.ACCESSIBILITY_MAGNIFICATION_SETTINGS; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putInt(EXTRA_CAPABILITY, mCapabilities); + super.onSaveInstanceState(outState); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if (savedInstanceState != null) { + mCapabilities = savedInstanceState.getInt(EXTRA_CAPABILITY, MagnifyMode.NONE); + } + if (mCapabilities == MagnifyMode.NONE) { + mCapabilities = getMagnificationCapabilities(getPrefContext()); + } + } + + @Override + public int getDialogMetricsCategory(int dialogId) { + switch (dialogId) { + case DIALOG_MAGNIFICATION_CAPABILITY: + return SettingsEnums.DIALOG_MAGNIFICATION_CAPABILITY; + default: + return 0; + } + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mModePreference = findPreference(PREF_KEY_MODE); + mModePreference.setOnPreferenceClickListener(preference -> { + mCapabilities = getMagnificationCapabilities(getPrefContext()); + showDialog(DIALOG_MAGNIFICATION_CAPABILITY); + return true; + }); + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.accessibility_magnification_service_settings; + } + + @Override + public Dialog onCreateDialog(int dialogId) { + if (dialogId == DIALOG_MAGNIFICATION_CAPABILITY) { + final String title = getPrefContext().getString( + R.string.accessibility_magnification_mode_title); + AlertDialog alertDialog = AccessibilityEditDialogUtils + .showMagnificationModeDialog(getPrefContext(), title, + this::callOnAlertDialogCheckboxClicked); + initializeDialogCheckBox(alertDialog); + return alertDialog; + } + throw new IllegalArgumentException("Unsupported dialogId " + dialogId); + } + + private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) { + updateCapabilities(true); + mModePreference.setSummary( + getMagnificationCapabilitiesSummary(getPrefContext())); + } + + private void initializeDialogCheckBox(AlertDialog dialog) { + final View dialogFullScreenView = dialog.findViewById(R.id.magnify_full_screen); + mMagnifyFullScreenCheckBox = dialogFullScreenView.findViewById(R.id.checkbox); + + final View dialogWidowView = dialog.findViewById(R.id.magnify_window_screen); + mMagnifyWindowCheckBox = dialogWidowView.findViewById(R.id.checkbox); + + updateAlertDialogCheckState(); + updateAlertDialogEnableState(); + } + + private void updateAlertDialogCheckState() { + updateCheckStatus(mMagnifyWindowCheckBox, MagnifyMode.WINDOW); + updateCheckStatus(mMagnifyFullScreenCheckBox, MagnifyMode.FULLSCREEN); + + } + + private void updateCheckStatus(CheckBox checkBox, int mode) { + checkBox.setChecked((mode & mCapabilities) != 0); + checkBox.setOnClickListener(v -> { + updateCapabilities(false); + updateAlertDialogEnableState(); + }); + } + + private void updateAlertDialogEnableState() { + if (mCapabilities != MagnifyMode.ALL) { + disableEnabledMagnificationModePreference(); + } else { + enableAllPreference(); + } + } + + private void enableAllPreference() { + mMagnifyFullScreenCheckBox.setEnabled(true); + mMagnifyWindowCheckBox.setEnabled(true); + } + + private void disableEnabledMagnificationModePreference() { + if (!mMagnifyFullScreenCheckBox.isChecked()) { + mMagnifyWindowCheckBox.setEnabled(false); + } else if (!mMagnifyWindowCheckBox.isChecked()) { + mMagnifyFullScreenCheckBox.setEnabled(false); + } + } + + private void updateCapabilities(boolean saveToDB) { + int capabilities = 0; + capabilities |= + mMagnifyFullScreenCheckBox.isChecked() ? MagnifyMode.FULLSCREEN : 0; + capabilities |= mMagnifyWindowCheckBox.isChecked() ? MagnifyMode.WINDOW : 0; + mCapabilities = capabilities; + if (saveToDB) { + setMagnificationCapabilities(capabilities); + } + } + + private void setSecureIntValue(String key, int value) { + Settings.Secure.putIntForUser(getPrefContext().getContentResolver(), + key, value, getPrefContext().getContentResolver().getUserId()); + } + + private void setMagnificationCapabilities(int capabilities) { + setSecureIntValue(KEY_CAPABILITY, capabilities); + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + MagnifyMode.NONE, + MagnifyMode.FULLSCREEN, + MagnifyMode.WINDOW, + MagnifyMode.ALL, + }) + private @interface MagnifyMode { + int NONE = 0; + int FULLSCREEN = 1; + int WINDOW = 2; + int ALL = 3; + } + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.accessibility_magnification_service_settings); +} diff --git a/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java b/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java new file mode 100644 index 00000000000..4badc3f4ecf --- /dev/null +++ b/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 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 android.content.Context; +import android.os.UserHandle; +import android.provider.Settings; + +import com.android.settings.core.TogglePreferenceController; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** Controller that shows and updates the magnification window control switch. */ +public class MagnificationWindowControlPreferenceController extends TogglePreferenceController { + + // TODO(b/146019459): Use magnification_window_control_enabled. + private static final String KEY_CONTROL = Settings.System.MASTER_MONO; + + public MagnificationWindowControlPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public boolean isChecked() { + return Settings.System.getIntForUser(mContext.getContentResolver(), + KEY_CONTROL, State.OFF, UserHandle.USER_CURRENT) == State.ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.System.putIntForUser(mContext.getContentResolver(), + KEY_CONTROL, isChecked ? State.ON : State.OFF, UserHandle.USER_CURRENT); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Retention(RetentionPolicy.SOURCE) + private @interface State { + int OFF = 0; + int ON = 1; + } +} diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index 43619337165..f9016e8002d 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -54,6 +54,7 @@ import com.android.settings.widget.SwitchBar; public class ToggleScreenMagnificationPreferenceFragment extends ToggleFeaturePreferenceFragment implements SwitchBar.OnSwitchChangeListener { + private static final String SETTINGS_KEY = "screen_magnification_settings"; private static final int DIALOG_ID_GESTURE_NAVIGATION_TUTORIAL = 1; private static final int DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL = 2; private static final int DIALOG_ID_EDIT_SHORTCUT = 3; @@ -170,6 +171,13 @@ public class ToggleScreenMagnificationPreferenceFragment extends mVideoPreference.setPersistent(false); mVideoPreference.setLayoutResource(R.layout.magnification_video_preference); + final Preference settingsPreference = new Preference(getPrefContext()); + final String SettingsText = getString(R.string.settings_button); + settingsPreference.setTitle(SettingsText); + settingsPreference.setKey(SETTINGS_KEY); + settingsPreference.setFragment(MagnificationSettingsFragment.class.getName()); + settingsPreference.setPersistent(false); + mConfigWarningPreference = new Preference(getPrefContext()); mConfigWarningPreference.setSelectable(false); mConfigWarningPreference.setPersistent(false); @@ -179,8 +187,10 @@ public class ToggleScreenMagnificationPreferenceFragment extends final PreferenceScreen preferenceScreen = getPreferenceManager().getPreferenceScreen(); preferenceScreen.setOrderingAsAdded(false); mVideoPreference.setOrder(0); + settingsPreference.setOrder(1); mConfigWarningPreference.setOrder(2); preferenceScreen.addPreference(mVideoPreference); + preferenceScreen.addPreference(settingsPreference); preferenceScreen.addPreference(mConfigWarningPreference); } diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java new file mode 100644 index 00000000000..5162bc24ff6 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 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.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.provider.Settings; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class MagnificationModePreferenceControllerTest { + private static final String PREF_KEY = "screen_magnification_mode"; + // TODO(b/146019459): Use magnification_capability. + private static final String KEY_CAPABILITY = Settings.System.MASTER_MONO; + private static final int WINDOW_SCREEN_VALUE = 2; + private static final int ALL_VALUE = 3; + + private Context mContext; + private MagnificationModePreferenceController mController; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mController = new MagnificationModePreferenceController(mContext, PREF_KEY); + } + + @Test + public void getSummary_saveWindowScreen_shouldReturnWindowScreenSummary() { + Settings.Secure.putInt(mContext.getContentResolver(), + KEY_CAPABILITY, WINDOW_SCREEN_VALUE); + + assertThat(mController.getSummary()) + .isEqualTo(mContext.getString( + R.string.accessibility_magnification_area_settings_window_screen_summary)); + } + + @Test + public void getSummary_saveAll_shouldReturnAllSummary() { + Settings.Secure.putInt(mContext.getContentResolver(), + KEY_CAPABILITY, ALL_VALUE); + + assertThat(mController.getSummary()) + .isEqualTo(mContext.getString( + R.string.accessibility_magnification_area_settings_all_summary)); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java new file mode 100644 index 00000000000..05dbb57ead0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 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.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.os.UserHandle; +import android.provider.Settings; + +import androidx.preference.SwitchPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@RunWith(RobolectricTestRunner.class) +public class MagnificationWindowControlPreferenceControllerTest { + private static final String PREF_KEY = "screen_magnification_window_control_switch"; + // TODO(b/146019459): Use magnification_window_control_enabled. + private static final String KEY_CONTROL = Settings.System.MASTER_MONO; + private Context mContext; + private SwitchPreference mPreference; + private MagnificationWindowControlPreferenceController mController; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mPreference = new SwitchPreference(mContext); + mController = new MagnificationWindowControlPreferenceController(mContext, PREF_KEY); + } + + @Test + public void isChecked_enabledWindowControl_shouldReturnTrue() { + Settings.System.putIntForUser(mContext.getContentResolver(), + KEY_CONTROL, State.ON, UserHandle.USER_CURRENT); + + mController.updateState(mPreference); + + assertThat(mController.isChecked()).isTrue(); + assertThat(mPreference.isChecked()).isTrue(); + } + + @Test + public void isChecked_disabledWindowControl_shouldReturnFalse() { + Settings.System.putIntForUser(mContext.getContentResolver(), + KEY_CONTROL, State.OFF, UserHandle.USER_CURRENT); + + mController.updateState(mPreference); + + assertThat(mController.isChecked()).isFalse(); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void setChecked_setTrue_shouldEnableWindowControl() { + mController.setChecked(true); + + assertThat(Settings.System.getIntForUser(mContext.getContentResolver(), + KEY_CONTROL, State.UNKNOWN, UserHandle.USER_CURRENT)).isEqualTo(State.ON); + } + + @Test + public void setChecked_setFalse_shouldDisableWindowControl() { + mController.setChecked(false); + + assertThat(Settings.System.getIntForUser(mContext.getContentResolver(), + KEY_CONTROL, State.UNKNOWN, UserHandle.USER_CURRENT)).isEqualTo(State.OFF); + } + + @Retention(RetentionPolicy.SOURCE) + private @interface State { + int UNKNOWN = -1; + int OFF = 0; + int ON = 1; + } +}