1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.accessibility; 18 19 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; 20 import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums; 21 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; 22 import static com.android.settings.accessibility.AccessibilityUtil.State.ON; 23 24 import android.app.Dialog; 25 import android.app.settings.SettingsEnums; 26 import android.content.ComponentName; 27 import android.content.ContentResolver; 28 import android.content.Context; 29 import android.content.DialogInterface; 30 import android.content.pm.PackageManager; 31 import android.icu.text.CaseMap; 32 import android.net.Uri; 33 import android.os.Bundle; 34 import android.provider.Settings; 35 import android.text.TextUtils; 36 import android.view.LayoutInflater; 37 import android.view.View; 38 import android.view.ViewGroup; 39 import android.view.accessibility.AccessibilityManager; 40 import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener; 41 import android.widget.CheckBox; 42 43 import androidx.preference.Preference; 44 import androidx.preference.PreferenceCategory; 45 import androidx.preference.SwitchPreference; 46 47 import com.android.internal.annotations.VisibleForTesting; 48 import com.android.settings.DialogCreatable; 49 import com.android.settings.R; 50 import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType; 51 import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; 52 import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; 53 import com.android.settings.utils.LocaleUtils; 54 55 import com.google.android.setupcompat.util.WizardManagerHelper; 56 57 import java.util.ArrayList; 58 import java.util.List; 59 import java.util.Locale; 60 import java.util.StringJoiner; 61 62 /** 63 * Fragment that shows the actual UI for providing basic magnification accessibility service setup 64 * and does not have toggle bar to turn on service to use. 65 */ 66 public class ToggleScreenMagnificationPreferenceFragment extends 67 ToggleFeaturePreferenceFragment implements 68 MagnificationModePreferenceController.DialogHelper { 69 // TODO(b/147021230): Move duplicated functions with android/internal/accessibility into util. 70 private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; 71 72 private CheckBox mSoftwareTypeCheckBox; 73 private CheckBox mHardwareTypeCheckBox; 74 private CheckBox mTripleTapTypeCheckBox; 75 76 private static final char COMPONENT_NAME_SEPARATOR = ':'; 77 private static final TextUtils.SimpleStringSplitter sStringColonSplitter = 78 new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); 79 80 private DialogCreatable mDialogDelegate; 81 private MagnificationFollowTypingPreferenceController mFollowTypingPreferenceController; 82 83 protected SwitchPreference mFollowingTypingSwitchPreference; 84 85 @Override onCreate(Bundle savedInstanceState)86 public void onCreate(Bundle savedInstanceState) { 87 super.onCreate(savedInstanceState); 88 getActivity().setTitle(R.string.accessibility_screen_magnification_title); 89 } 90 91 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)92 public View onCreateView(LayoutInflater inflater, ViewGroup container, 93 Bundle savedInstanceState) { 94 mPackageName = getString(R.string.accessibility_screen_magnification_title); 95 mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) 96 .authority(getPrefContext().getPackageName()) 97 .appendPath(String.valueOf(R.raw.a11y_magnification_banner)) 98 .build(); 99 mTouchExplorationStateChangeListener = isTouchExplorationEnabled -> { 100 removeDialog(DialogEnums.EDIT_SHORTCUT); 101 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 102 }; 103 104 final View view = super.onCreateView(inflater, container, savedInstanceState); 105 updateFooterPreference(); 106 return view; 107 } 108 updateFooterPreference()109 private void updateFooterPreference() { 110 final String title = getPrefContext().getString( 111 R.string.accessibility_screen_magnification_about_title); 112 final String learnMoreText = getPrefContext().getString( 113 R.string.accessibility_screen_magnification_footer_learn_more_content_description); 114 mFooterPreferenceController.setIntroductionTitle(title); 115 mFooterPreferenceController.setupHelpLink(getHelpResource(), learnMoreText); 116 mFooterPreferenceController.displayPreference(getPreferenceScreen()); 117 } 118 119 @Override onResume()120 public void onResume() { 121 super.onResume(); 122 123 final AccessibilityManager am = getPrefContext().getSystemService( 124 AccessibilityManager.class); 125 am.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); 126 } 127 128 @Override onPause()129 public void onPause() { 130 final AccessibilityManager am = getPrefContext().getSystemService( 131 AccessibilityManager.class); 132 am.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); 133 134 super.onPause(); 135 } 136 137 @Override onCreateDialog(int dialogId)138 public Dialog onCreateDialog(int dialogId) { 139 if (mDialogDelegate != null) { 140 mDialog = mDialogDelegate.onCreateDialog(dialogId); 141 if (mDialog != null) { 142 return mDialog; 143 } 144 } 145 switch (dialogId) { 146 case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: 147 return AccessibilityGestureNavigationTutorial 148 .showAccessibilityGestureTutorialDialog(getPrefContext()); 149 case DialogEnums.MAGNIFICATION_EDIT_SHORTCUT: 150 final CharSequence dialogTitle = getShortcutTitle(); 151 final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent()) 152 ? DialogType.EDIT_SHORTCUT_MAGNIFICATION_SUW 153 : DialogType.EDIT_SHORTCUT_MAGNIFICATION; 154 mDialog = AccessibilityDialogUtils.showEditShortcutDialog(getPrefContext(), 155 dialogType, dialogTitle, this::callOnAlertDialogCheckboxClicked); 156 setupMagnificationEditShortcutDialog(mDialog); 157 return mDialog; 158 default: 159 return super.onCreateDialog(dialogId); 160 } 161 } 162 163 @Override initSettingsPreference()164 protected void initSettingsPreference() { 165 // If the device doesn't support window magnification feature, it should hide the 166 // settings preference. 167 final boolean supportWindowMagnification = 168 getContext().getResources().getBoolean( 169 com.android.internal.R.bool.config_magnification_area) 170 && getContext().getPackageManager().hasSystemFeature( 171 PackageManager.FEATURE_WINDOW_MAGNIFICATION); 172 if (!supportWindowMagnification) { 173 return; 174 } 175 mSettingsPreference = new Preference(getPrefContext()); 176 mSettingsPreference.setTitle(R.string.accessibility_magnification_mode_title); 177 mSettingsPreference.setKey(MagnificationModePreferenceController.PREF_KEY); 178 mSettingsPreference.setPersistent(false); 179 180 final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY); 181 generalCategory.addPreference(mSettingsPreference); 182 183 final MagnificationModePreferenceController magnificationModePreferenceController = 184 new MagnificationModePreferenceController(getContext(), 185 MagnificationModePreferenceController.PREF_KEY); 186 magnificationModePreferenceController.setDialogHelper(this); 187 getSettingsLifecycle().addObserver(magnificationModePreferenceController); 188 magnificationModePreferenceController.displayPreference(getPreferenceScreen()); 189 190 mFollowingTypingSwitchPreference = 191 new SwitchPreference(getPrefContext()); 192 mFollowingTypingSwitchPreference.setTitle( 193 R.string.accessibility_screen_magnification_follow_typing_title); 194 mFollowingTypingSwitchPreference.setSummary( 195 R.string.accessibility_screen_magnification_follow_typing_summary); 196 mFollowingTypingSwitchPreference.setKey( 197 MagnificationFollowTypingPreferenceController.PREF_KEY); 198 generalCategory.addPreference(mFollowingTypingSwitchPreference); 199 200 mFollowTypingPreferenceController = new MagnificationFollowTypingPreferenceController( 201 getContext(), MagnificationFollowTypingPreferenceController.PREF_KEY); 202 getSettingsLifecycle().addObserver(mFollowTypingPreferenceController); 203 mFollowTypingPreferenceController.displayPreference(getPreferenceScreen()); 204 } 205 206 @Override showDialog(int dialogId)207 public void showDialog(int dialogId) { 208 super.showDialog(dialogId); 209 } 210 211 @Override setDialogDelegate(DialogCreatable delegate)212 public void setDialogDelegate(DialogCreatable delegate) { 213 mDialogDelegate = delegate; 214 } 215 216 @Override getShortcutTypeCheckBoxValue()217 protected int getShortcutTypeCheckBoxValue() { 218 if (mSoftwareTypeCheckBox == null || mHardwareTypeCheckBox == null) { 219 return NOT_SET; 220 } 221 222 int value = UserShortcutType.EMPTY; 223 if (mSoftwareTypeCheckBox.isChecked()) { 224 value |= UserShortcutType.SOFTWARE; 225 } 226 if (mHardwareTypeCheckBox.isChecked()) { 227 value |= UserShortcutType.HARDWARE; 228 } 229 if (mTripleTapTypeCheckBox.isChecked()) { 230 value |= UserShortcutType.TRIPLETAP; 231 } 232 return value; 233 } 234 235 @VisibleForTesting setupMagnificationEditShortcutDialog(Dialog dialog)236 void setupMagnificationEditShortcutDialog(Dialog dialog) { 237 final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut); 238 mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox); 239 setDialogTextAreaClickListener(dialogSoftwareView, mSoftwareTypeCheckBox); 240 241 final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut); 242 mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox); 243 setDialogTextAreaClickListener(dialogHardwareView, mHardwareTypeCheckBox); 244 245 final View dialogTripleTapView = dialog.findViewById(R.id.triple_tap_shortcut); 246 mTripleTapTypeCheckBox = dialogTripleTapView.findViewById(R.id.checkbox); 247 setDialogTextAreaClickListener(dialogTripleTapView, mTripleTapTypeCheckBox); 248 249 final View advancedView = dialog.findViewById(R.id.advanced_shortcut); 250 if (mTripleTapTypeCheckBox.isChecked()) { 251 advancedView.setVisibility(View.GONE); 252 dialogTripleTapView.setVisibility(View.VISIBLE); 253 } 254 255 updateMagnificationEditShortcutDialogCheckBox(); 256 } 257 setDialogTextAreaClickListener(View dialogView, CheckBox checkBox)258 private void setDialogTextAreaClickListener(View dialogView, CheckBox checkBox) { 259 final View dialogTextArea = dialogView.findViewById(R.id.container); 260 dialogTextArea.setOnClickListener(v -> checkBox.toggle()); 261 } 262 updateMagnificationEditShortcutDialogCheckBox()263 private void updateMagnificationEditShortcutDialogCheckBox() { 264 // If it is during onConfigChanged process then restore the value, or get the saved value 265 // when shortcutPreference is checked. 266 int value = restoreOnConfigChangedValue(); 267 if (value == NOT_SET) { 268 final int lastNonEmptyUserShortcutType = PreferredShortcuts.retrieveUserShortcutType( 269 getPrefContext(), MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE); 270 value = mShortcutPreference.isChecked() ? lastNonEmptyUserShortcutType 271 : UserShortcutType.EMPTY; 272 } 273 274 mSoftwareTypeCheckBox.setChecked( 275 hasShortcutType(value, UserShortcutType.SOFTWARE)); 276 mHardwareTypeCheckBox.setChecked( 277 hasShortcutType(value, UserShortcutType.HARDWARE)); 278 mTripleTapTypeCheckBox.setChecked( 279 hasShortcutType(value, UserShortcutType.TRIPLETAP)); 280 } 281 restoreOnConfigChangedValue()282 private int restoreOnConfigChangedValue() { 283 final int savedValue = mSavedCheckBoxValue; 284 mSavedCheckBoxValue = NOT_SET; 285 return savedValue; 286 } 287 hasShortcutType(int value, @UserShortcutType int type)288 private boolean hasShortcutType(int value, @UserShortcutType int type) { 289 return (value & type) == type; 290 } 291 getSoftwareShortcutTypeSummary(Context context)292 private static CharSequence getSoftwareShortcutTypeSummary(Context context) { 293 int resId; 294 if (AccessibilityUtil.isFloatingMenuEnabled(context)) { 295 resId = R.string.accessibility_shortcut_edit_summary_software; 296 } else if (AccessibilityUtil.isGestureNavigateEnabled(context)) { 297 resId = R.string.accessibility_shortcut_edit_summary_software_gesture; 298 } else { 299 resId = R.string.accessibility_shortcut_edit_summary_software; 300 } 301 return context.getText(resId); 302 } 303 304 @Override registerKeysToObserverCallback( AccessibilitySettingsContentObserver contentObserver)305 protected void registerKeysToObserverCallback( 306 AccessibilitySettingsContentObserver contentObserver) { 307 super.registerKeysToObserverCallback(contentObserver); 308 309 final List<String> followingTypingKeys = new ArrayList<>(); 310 followingTypingKeys.add(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED); 311 contentObserver.registerKeysToObserverCallback(followingTypingKeys, 312 key -> updateFollowTypingState()); 313 } 314 updateFollowTypingState()315 private void updateFollowTypingState() { 316 mFollowTypingPreferenceController.updateState(); 317 } 318 319 @Override getShortcutFeatureSettingsKeys()320 protected List<String> getShortcutFeatureSettingsKeys() { 321 final List<String> shortcutKeys = super.getShortcutFeatureSettingsKeys(); 322 shortcutKeys.add(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); 323 return shortcutKeys; 324 } 325 326 @Override getShortcutTypeSummary(Context context)327 protected CharSequence getShortcutTypeSummary(Context context) { 328 if (!mShortcutPreference.isChecked()) { 329 return context.getText(R.string.switch_off_text); 330 } 331 332 final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(context, 333 MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE); 334 335 final List<CharSequence> list = new ArrayList<>(); 336 if (hasShortcutType(shortcutTypes, UserShortcutType.SOFTWARE)) { 337 list.add(getSoftwareShortcutTypeSummary(context)); 338 } 339 if (hasShortcutType(shortcutTypes, UserShortcutType.HARDWARE)) { 340 final CharSequence hardwareTitle = context.getText( 341 R.string.accessibility_shortcut_hardware_keyword); 342 list.add(hardwareTitle); 343 } 344 if (hasShortcutType(shortcutTypes, UserShortcutType.TRIPLETAP)) { 345 final CharSequence tripleTapTitle = context.getText( 346 R.string.accessibility_shortcut_triple_tap_keyword); 347 list.add(tripleTapTitle); 348 } 349 350 // Show software shortcut if first time to use. 351 if (list.isEmpty()) { 352 list.add(getSoftwareShortcutTypeSummary(context)); 353 } 354 355 return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */ 356 null, LocaleUtils.getConcatenatedString(list)); 357 } 358 359 @Override callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which)360 protected void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) { 361 final int value = getShortcutTypeCheckBoxValue(); 362 363 saveNonEmptyUserShortcutType(value); 364 optInAllMagnificationValuesToSettings(getPrefContext(), value); 365 optOutAllMagnificationValuesFromSettings(getPrefContext(), ~value); 366 mShortcutPreference.setChecked(value != UserShortcutType.EMPTY); 367 mShortcutPreference.setSummary( 368 getShortcutTypeSummary(getPrefContext())); 369 370 if (mHardwareTypeCheckBox.isChecked()) { 371 AccessibilityUtil.skipVolumeShortcutDialogTimeoutRestriction(getPrefContext()); 372 } 373 } 374 375 @Override getHelpResource()376 public int getHelpResource() { 377 return R.string.help_url_magnification; 378 } 379 380 @Override getMetricsCategory()381 public int getMetricsCategory() { 382 // TODO: Distinguish between magnification modes 383 return SettingsEnums.ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION; 384 } 385 386 @Override getDialogMetricsCategory(int dialogId)387 public int getDialogMetricsCategory(int dialogId) { 388 if (mDialogDelegate != null) { 389 final int category = mDialogDelegate.getDialogMetricsCategory(dialogId); 390 if (category != 0) { 391 return category; 392 } 393 } 394 395 switch (dialogId) { 396 case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: 397 return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION; 398 case DialogEnums.ACCESSIBILITY_BUTTON_TUTORIAL: 399 return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_ACCESSIBILITY_BUTTON; 400 case DialogEnums.MAGNIFICATION_EDIT_SHORTCUT: 401 return SettingsEnums.DIALOG_MAGNIFICATION_EDIT_SHORTCUT; 402 default: 403 return super.getDialogMetricsCategory(dialogId); 404 } 405 } 406 407 @Override getUserShortcutTypes()408 int getUserShortcutTypes() { 409 return getUserShortcutTypeFromSettings(getPrefContext()); 410 } 411 412 @Override getTileComponentName()413 ComponentName getTileComponentName() { 414 return null; 415 } 416 417 @Override getTileTooltipContent(@uickSettingsTooltipType int type)418 CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { 419 return null; 420 } 421 422 @Override onPreferenceToggled(String preferenceKey, boolean enabled)423 protected void onPreferenceToggled(String preferenceKey, boolean enabled) { 424 if (enabled && TextUtils.equals( 425 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 426 preferenceKey)) { 427 showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL); 428 } 429 MagnificationPreferenceFragment.setChecked(getContentResolver(), preferenceKey, enabled); 430 } 431 432 @Override onInstallSwitchPreferenceToggleSwitch()433 protected void onInstallSwitchPreferenceToggleSwitch() { 434 mToggleServiceSwitchPreference.setVisible(false); 435 } 436 437 @Override onToggleClicked(ShortcutPreference preference)438 public void onToggleClicked(ShortcutPreference preference) { 439 final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(getPrefContext(), 440 MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE); 441 if (preference.isChecked()) { 442 optInAllMagnificationValuesToSettings(getPrefContext(), shortcutTypes); 443 showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL); 444 } else { 445 optOutAllMagnificationValuesFromSettings(getPrefContext(), shortcutTypes); 446 } 447 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 448 } 449 450 @Override onSettingsClicked(ShortcutPreference preference)451 public void onSettingsClicked(ShortcutPreference preference) { 452 showDialog(DialogEnums.MAGNIFICATION_EDIT_SHORTCUT); 453 } 454 455 @Override updateShortcutPreferenceData()456 protected void updateShortcutPreferenceData() { 457 final int shortcutTypes = getUserShortcutTypeFromSettings(getPrefContext()); 458 if (shortcutTypes != UserShortcutType.EMPTY) { 459 final PreferredShortcut shortcut = new PreferredShortcut( 460 MAGNIFICATION_CONTROLLER_NAME, shortcutTypes); 461 PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut); 462 } 463 } 464 465 @Override initShortcutPreference()466 protected void initShortcutPreference() { 467 mShortcutPreference = new ShortcutPreference(getPrefContext(), null); 468 mShortcutPreference.setPersistent(false); 469 mShortcutPreference.setKey(getShortcutPreferenceKey()); 470 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 471 mShortcutPreference.setOnClickCallback(this); 472 mShortcutPreference.setTitle(getShortcutTitle()); 473 474 final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY); 475 generalCategory.addPreference(mShortcutPreference); 476 } 477 478 @Override getShortcutTitle()479 protected CharSequence getShortcutTitle() { 480 return getText(R.string.accessibility_screen_magnification_shortcut_title); 481 } 482 483 @Override updateShortcutPreference()484 protected void updateShortcutPreference() { 485 final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(getPrefContext(), 486 MAGNIFICATION_CONTROLLER_NAME, UserShortcutType.SOFTWARE); 487 mShortcutPreference.setChecked( 488 hasMagnificationValuesInSettings(getPrefContext(), shortcutTypes)); 489 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 490 } 491 492 @VisibleForTesting saveNonEmptyUserShortcutType(int type)493 void saveNonEmptyUserShortcutType(int type) { 494 if (type == UserShortcutType.EMPTY) { 495 return; 496 } 497 498 final PreferredShortcut shortcut = new PreferredShortcut( 499 MAGNIFICATION_CONTROLLER_NAME, type); 500 PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut); 501 } 502 503 @VisibleForTesting optInAllMagnificationValuesToSettings(Context context, int shortcutTypes)504 static void optInAllMagnificationValuesToSettings(Context context, int shortcutTypes) { 505 if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) { 506 optInMagnificationValueToSettings(context, UserShortcutType.SOFTWARE); 507 } 508 if (((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE)) { 509 optInMagnificationValueToSettings(context, UserShortcutType.HARDWARE); 510 } 511 if (((shortcutTypes & UserShortcutType.TRIPLETAP) == UserShortcutType.TRIPLETAP)) { 512 optInMagnificationValueToSettings(context, UserShortcutType.TRIPLETAP); 513 } 514 } 515 optInMagnificationValueToSettings(Context context, @UserShortcutType int shortcutType)516 private static void optInMagnificationValueToSettings(Context context, 517 @UserShortcutType int shortcutType) { 518 if (shortcutType == UserShortcutType.TRIPLETAP) { 519 Settings.Secure.putInt(context.getContentResolver(), 520 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ON); 521 return; 522 } 523 524 if (hasMagnificationValueInSettings(context, shortcutType)) { 525 return; 526 } 527 528 final String targetKey = AccessibilityUtil.convertKeyFromSettings(shortcutType); 529 final String targetString = Settings.Secure.getString(context.getContentResolver(), 530 targetKey); 531 final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR)); 532 533 if (!TextUtils.isEmpty(targetString)) { 534 joiner.add(targetString); 535 } 536 joiner.add(MAGNIFICATION_CONTROLLER_NAME); 537 538 Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString()); 539 } 540 541 @VisibleForTesting optOutAllMagnificationValuesFromSettings(Context context, int shortcutTypes)542 static void optOutAllMagnificationValuesFromSettings(Context context, 543 int shortcutTypes) { 544 if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) { 545 optOutMagnificationValueFromSettings(context, UserShortcutType.SOFTWARE); 546 } 547 if (((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE)) { 548 optOutMagnificationValueFromSettings(context, UserShortcutType.HARDWARE); 549 } 550 if (((shortcutTypes & UserShortcutType.TRIPLETAP) == UserShortcutType.TRIPLETAP)) { 551 optOutMagnificationValueFromSettings(context, UserShortcutType.TRIPLETAP); 552 } 553 } 554 optOutMagnificationValueFromSettings(Context context, @UserShortcutType int shortcutType)555 private static void optOutMagnificationValueFromSettings(Context context, 556 @UserShortcutType int shortcutType) { 557 if (shortcutType == UserShortcutType.TRIPLETAP) { 558 Settings.Secure.putInt(context.getContentResolver(), 559 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF); 560 return; 561 } 562 563 final String targetKey = AccessibilityUtil.convertKeyFromSettings(shortcutType); 564 final String targetString = Settings.Secure.getString(context.getContentResolver(), 565 targetKey); 566 567 if (TextUtils.isEmpty(targetString)) { 568 return; 569 } 570 571 final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR)); 572 573 sStringColonSplitter.setString(targetString); 574 while (sStringColonSplitter.hasNext()) { 575 final String name = sStringColonSplitter.next(); 576 if (TextUtils.isEmpty(name) || MAGNIFICATION_CONTROLLER_NAME.equals(name)) { 577 continue; 578 } 579 joiner.add(name); 580 } 581 582 Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString()); 583 } 584 585 @VisibleForTesting hasMagnificationValuesInSettings(Context context, int shortcutTypes)586 static boolean hasMagnificationValuesInSettings(Context context, int shortcutTypes) { 587 boolean exist = false; 588 589 if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) { 590 exist = hasMagnificationValueInSettings(context, UserShortcutType.SOFTWARE); 591 } 592 if (((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE)) { 593 exist |= hasMagnificationValueInSettings(context, UserShortcutType.HARDWARE); 594 } 595 if (((shortcutTypes & UserShortcutType.TRIPLETAP) == UserShortcutType.TRIPLETAP)) { 596 exist |= hasMagnificationValueInSettings(context, UserShortcutType.TRIPLETAP); 597 } 598 return exist; 599 } 600 hasMagnificationValueInSettings(Context context, @UserShortcutType int shortcutType)601 private static boolean hasMagnificationValueInSettings(Context context, 602 @UserShortcutType int shortcutType) { 603 if (shortcutType == UserShortcutType.TRIPLETAP) { 604 return Settings.Secure.getInt(context.getContentResolver(), 605 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF) == ON; 606 } 607 608 final String targetKey = AccessibilityUtil.convertKeyFromSettings(shortcutType); 609 final String targetString = Settings.Secure.getString(context.getContentResolver(), 610 targetKey); 611 612 if (TextUtils.isEmpty(targetString)) { 613 return false; 614 } 615 616 sStringColonSplitter.setString(targetString); 617 while (sStringColonSplitter.hasNext()) { 618 final String name = sStringColonSplitter.next(); 619 if (MAGNIFICATION_CONTROLLER_NAME.equals(name)) { 620 return true; 621 } 622 } 623 return false; 624 } 625 isWindowMagnification(Context context)626 private boolean isWindowMagnification(Context context) { 627 final int mode = Settings.Secure.getIntForUser( 628 context.getContentResolver(), 629 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 630 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, 631 context.getContentResolver().getUserId()); 632 return mode == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; 633 } 634 getUserShortcutTypeFromSettings(Context context)635 private static int getUserShortcutTypeFromSettings(Context context) { 636 int shortcutTypes = UserShortcutType.EMPTY; 637 if (hasMagnificationValuesInSettings(context, UserShortcutType.SOFTWARE)) { 638 shortcutTypes |= UserShortcutType.SOFTWARE; 639 } 640 if (hasMagnificationValuesInSettings(context, UserShortcutType.HARDWARE)) { 641 shortcutTypes |= UserShortcutType.HARDWARE; 642 } 643 if (hasMagnificationValuesInSettings(context, UserShortcutType.TRIPLETAP)) { 644 shortcutTypes |= UserShortcutType.TRIPLETAP; 645 } 646 return shortcutTypes; 647 } 648 649 /** 650 * Gets the service summary of magnification. 651 * 652 * @param context The current context. 653 */ getServiceSummary(Context context)654 public static CharSequence getServiceSummary(Context context) { 655 // Get the user shortcut type from settings provider. 656 final int uerShortcutType = getUserShortcutTypeFromSettings(context); 657 return (uerShortcutType != AccessibilityUtil.UserShortcutType.EMPTY) 658 ? context.getText(R.string.accessibility_summary_shortcut_enabled) 659 : context.getText(R.string.accessibility_summary_shortcut_disabled); 660 } 661 } 662