1 /* 2 * Copyright (C) 2021 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.settings.accessibility.AccessibilityDialogUtils.DialogEnums; 20 import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_GENERAL_CATEGORY; 21 import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_QS_TOOLTIP_TYPE; 22 23 import android.app.Activity; 24 import android.app.Dialog; 25 import android.app.settings.SettingsEnums; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.DialogInterface; 29 import android.icu.text.CaseMap; 30 import android.os.Bundle; 31 import android.os.Handler; 32 import android.provider.Settings; 33 import android.text.TextUtils; 34 import android.view.LayoutInflater; 35 import android.view.View; 36 import android.view.ViewGroup; 37 import android.view.accessibility.AccessibilityManager; 38 import android.widget.CheckBox; 39 40 import androidx.annotation.Nullable; 41 import androidx.annotation.VisibleForTesting; 42 import androidx.preference.PreferenceCategory; 43 import androidx.preference.PreferenceScreen; 44 45 import com.android.internal.accessibility.common.ShortcutConstants; 46 import com.android.settings.R; 47 import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; 48 import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment; 49 import com.android.settings.dashboard.RestrictedDashboardFragment; 50 import com.android.settings.utils.LocaleUtils; 51 52 import com.google.android.setupcompat.util.WizardManagerHelper; 53 54 import java.util.ArrayList; 55 import java.util.List; 56 import java.util.Locale; 57 58 /** 59 * Base class for accessibility fragments shortcut functions and dialog management. 60 */ 61 public abstract class AccessibilityShortcutPreferenceFragment extends RestrictedDashboardFragment 62 implements ShortcutPreference.OnClickCallback { 63 private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference"; 64 protected static final String KEY_SAVED_USER_SHORTCUT_TYPE = "shortcut_type"; 65 protected static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow"; 66 protected static final int NOT_SET = -1; 67 // Save user's shortcutType value when savedInstance has value (e.g. device rotated). 68 protected int mSavedCheckBoxValue = NOT_SET; 69 70 protected ShortcutPreference mShortcutPreference; 71 protected Dialog mDialog; 72 private AccessibilityManager.TouchExplorationStateChangeListener 73 mTouchExplorationStateChangeListener; 74 private AccessibilitySettingsContentObserver mSettingsContentObserver; 75 private CheckBox mSoftwareTypeCheckBox; 76 private CheckBox mHardwareTypeCheckBox; 77 private AccessibilityQuickSettingsTooltipWindow mTooltipWindow; 78 private boolean mNeedsQSTooltipReshow = false; 79 private int mNeedsQSTooltipType = QuickSettingsTooltipType.GUIDE_TO_EDIT; 80 AccessibilityShortcutPreferenceFragment(String restrictionKey)81 public AccessibilityShortcutPreferenceFragment(String restrictionKey) { 82 super(restrictionKey); 83 } 84 85 /** Returns the accessibility component name. */ getComponentName()86 protected abstract ComponentName getComponentName(); 87 88 /** Returns the accessibility feature name. */ getLabelName()89 protected abstract CharSequence getLabelName(); 90 91 /** Returns the accessibility tile component name. */ getTileComponentName()92 protected abstract ComponentName getTileComponentName(); 93 94 /** Returns the accessibility tile tooltip content. */ getTileTooltipContent(@uickSettingsTooltipType int type)95 protected abstract CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type); 96 97 @Override onCreate(Bundle savedInstanceState)98 public void onCreate(Bundle savedInstanceState) { 99 super.onCreate(savedInstanceState); 100 101 // Restore the user shortcut type and tooltip. 102 if (savedInstanceState != null) { 103 if (savedInstanceState.containsKey(KEY_SAVED_USER_SHORTCUT_TYPE)) { 104 mSavedCheckBoxValue = savedInstanceState.getInt(KEY_SAVED_USER_SHORTCUT_TYPE, 105 NOT_SET); 106 } 107 if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) { 108 mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW); 109 } 110 if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_TYPE)) { 111 mNeedsQSTooltipType = savedInstanceState.getInt(KEY_SAVED_QS_TOOLTIP_TYPE); 112 } 113 } 114 115 final int resId = getPreferenceScreenResId(); 116 if (resId <= 0) { 117 final PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen( 118 getPrefContext()); 119 setPreferenceScreen(preferenceScreen); 120 } 121 122 if (showGeneralCategory()) { 123 initGeneralCategory(); 124 } 125 126 final List<String> shortcutFeatureKeys = new ArrayList<>(); 127 shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); 128 shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); 129 if (android.view.accessibility.Flags.a11yQsShortcut()) { 130 shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS); 131 } 132 mSettingsContentObserver = new AccessibilitySettingsContentObserver(new Handler()); 133 mSettingsContentObserver.registerKeysToObserverCallback(shortcutFeatureKeys, key -> { 134 updateShortcutPreferenceData(); 135 updateShortcutPreference(); 136 }); 137 } 138 139 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)140 public View onCreateView(LayoutInflater inflater, ViewGroup container, 141 Bundle savedInstanceState) { 142 mShortcutPreference = new ShortcutPreference(getPrefContext(), /* attrs= */ null); 143 mShortcutPreference.setPersistent(false); 144 mShortcutPreference.setKey(getShortcutPreferenceKey()); 145 mShortcutPreference.setOnClickCallback(this); 146 mShortcutPreference.setTitle(getShortcutTitle()); 147 148 getPreferenceScreen().addPreference(mShortcutPreference); 149 150 mTouchExplorationStateChangeListener = isTouchExplorationEnabled -> { 151 removeDialog(DialogEnums.EDIT_SHORTCUT); 152 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 153 }; 154 155 return super.onCreateView(inflater, container, savedInstanceState); 156 } 157 158 @Override onViewCreated(View view, Bundle savedInstanceState)159 public void onViewCreated(View view, Bundle savedInstanceState) { 160 super.onViewCreated(view, savedInstanceState); 161 162 // Reshow tooltip when activity recreate, such as rotate device. 163 if (mNeedsQSTooltipReshow) { 164 view.post(() -> { 165 final Activity activity = getActivity(); 166 if (activity != null && !activity.isFinishing()) { 167 showQuickSettingsTooltipIfNeeded(); 168 } 169 }); 170 } 171 } 172 173 @Override onResume()174 public void onResume() { 175 super.onResume(); 176 177 final AccessibilityManager am = getPrefContext().getSystemService( 178 AccessibilityManager.class); 179 am.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); 180 mSettingsContentObserver.register(getContentResolver()); 181 updateShortcutPreferenceData(); 182 updateShortcutPreference(); 183 184 updateEditShortcutDialogIfNeeded(); 185 } 186 187 @Override onPause()188 public void onPause() { 189 final AccessibilityManager am = getPrefContext().getSystemService( 190 AccessibilityManager.class); 191 am.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); 192 mSettingsContentObserver.unregister(getContentResolver()); 193 super.onPause(); 194 } 195 196 @Override onSaveInstanceState(Bundle outState)197 public void onSaveInstanceState(Bundle outState) { 198 final int value = getShortcutTypeCheckBoxValue(); 199 if (value != NOT_SET) { 200 outState.putInt(KEY_SAVED_USER_SHORTCUT_TYPE, value); 201 } 202 final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing(); 203 if (mNeedsQSTooltipReshow || isTooltipWindowShowing) { 204 outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true); 205 outState.putInt(KEY_SAVED_QS_TOOLTIP_TYPE, mNeedsQSTooltipType); 206 } 207 super.onSaveInstanceState(outState); 208 } 209 210 @Override onCreateDialog(int dialogId)211 public Dialog onCreateDialog(int dialogId) { 212 switch (dialogId) { 213 case DialogEnums.EDIT_SHORTCUT: 214 final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent()) 215 ? AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC_SUW : 216 AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC; 217 mDialog = AccessibilityDialogUtils.showEditShortcutDialog( 218 getPrefContext(), dialogType, getShortcutTitle(), 219 this::callOnAlertDialogCheckboxClicked); 220 setupEditShortcutDialog(mDialog); 221 return mDialog; 222 case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL: 223 if (WizardManagerHelper.isAnySetupWizard(getIntent())) { 224 mDialog = AccessibilityShortcutsTutorial 225 .createAccessibilityTutorialDialogForSetupWizard( 226 getPrefContext(), getUserPreferredShortcutTypes(), 227 this::callOnTutorialDialogButtonClicked, getLabelName()); 228 } else { 229 mDialog = AccessibilityShortcutsTutorial 230 .createAccessibilityTutorialDialog( 231 getPrefContext(), getUserPreferredShortcutTypes(), 232 this::callOnTutorialDialogButtonClicked, getLabelName()); 233 } 234 mDialog.setCanceledOnTouchOutside(false); 235 return mDialog; 236 default: 237 throw new IllegalArgumentException("Unsupported dialogId " + dialogId); 238 } 239 } 240 getShortcutTitle()241 protected CharSequence getShortcutTitle() { 242 return getString(R.string.accessibility_shortcut_title, getLabelName()); 243 } 244 245 @Override getDialogMetricsCategory(int dialogId)246 public int getDialogMetricsCategory(int dialogId) { 247 switch (dialogId) { 248 case DialogEnums.EDIT_SHORTCUT: 249 return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT; 250 case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL: 251 return SettingsEnums.DIALOG_ACCESSIBILITY_TUTORIAL; 252 default: 253 return SettingsEnums.ACTION_UNKNOWN; 254 } 255 } 256 257 @Override onSettingsClicked(ShortcutPreference preference)258 public void onSettingsClicked(ShortcutPreference preference) { 259 if (Flags.editShortcutsInFullScreen()) { 260 EditShortcutsPreferenceFragment.showEditShortcutScreen( 261 getContext(), 262 getMetricsCategory(), 263 getShortcutTitle(), 264 getComponentName(), 265 getIntent() 266 ); 267 } else { 268 showDialog(DialogEnums.EDIT_SHORTCUT); 269 } 270 } 271 272 @Override onToggleClicked(ShortcutPreference preference)273 public void onToggleClicked(ShortcutPreference preference) { 274 if (getComponentName() == null) { 275 return; 276 } 277 278 final int shortcutTypes = getUserPreferredShortcutTypes(); 279 if (preference.isChecked()) { 280 AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes, 281 getComponentName()); 282 showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL); 283 } else { 284 AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes, 285 getComponentName()); 286 } 287 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 288 } 289 290 /** 291 * Overrides to return specific shortcut preference key 292 * 293 * @return String The specific shortcut preference key 294 */ getShortcutPreferenceKey()295 protected String getShortcutPreferenceKey() { 296 return KEY_SHORTCUT_PREFERENCE; 297 } 298 299 @VisibleForTesting setupEditShortcutDialog(Dialog dialog)300 void setupEditShortcutDialog(Dialog dialog) { 301 final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut); 302 mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox); 303 setDialogTextAreaClickListener(dialogSoftwareView, mSoftwareTypeCheckBox); 304 305 final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut); 306 mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox); 307 setDialogTextAreaClickListener(dialogHardwareView, mHardwareTypeCheckBox); 308 309 updateEditShortcutDialogCheckBox(); 310 } 311 312 /** 313 * Returns accumulated {@link AccessibilityUtil.UserShortcutType} checkbox value or 314 * {@code NOT_SET} if checkboxes did not exist. 315 */ getShortcutTypeCheckBoxValue()316 protected int getShortcutTypeCheckBoxValue() { 317 if (mSoftwareTypeCheckBox == null || mHardwareTypeCheckBox == null) { 318 return NOT_SET; 319 } 320 321 int value = AccessibilityUtil.UserShortcutType.EMPTY; 322 if (mSoftwareTypeCheckBox.isChecked()) { 323 value |= AccessibilityUtil.UserShortcutType.SOFTWARE; 324 } 325 if (mHardwareTypeCheckBox.isChecked()) { 326 value |= AccessibilityUtil.UserShortcutType.HARDWARE; 327 } 328 return value; 329 } 330 331 /** 332 * Returns the shortcut type list which has been checked by user. 333 */ getUserShortcutTypes()334 protected int getUserShortcutTypes() { 335 return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(), 336 getComponentName()); 337 }; 338 getSoftwareShortcutTypeSummary(Context context)339 private static CharSequence getSoftwareShortcutTypeSummary(Context context) { 340 int resId; 341 if (AccessibilityUtil.isFloatingMenuEnabled(context)) { 342 resId = R.string.accessibility_shortcut_edit_summary_software; 343 } else if (AccessibilityUtil.isGestureNavigateEnabled(context)) { 344 resId = R.string.accessibility_shortcut_edit_summary_software_gesture; 345 } else { 346 resId = R.string.accessibility_shortcut_edit_summary_software; 347 } 348 return context.getText(resId); 349 } 350 351 /** 352 * This method will be invoked when a button in the tutorial dialog is clicked. 353 * 354 * @param dialog The dialog that received the click 355 * @param which The button that was clicked 356 */ callOnTutorialDialogButtonClicked(DialogInterface dialog, int which)357 private void callOnTutorialDialogButtonClicked(DialogInterface dialog, int which) { 358 dialog.dismiss(); 359 showQuickSettingsTooltipIfNeeded(); 360 } 361 362 /** 363 * This method will be invoked when a button in the edit shortcut dialog is clicked. 364 * 365 * @param dialog The dialog that received the click 366 * @param which The button that was clicked 367 */ callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which)368 protected void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) { 369 if (getComponentName() == null) { 370 return; 371 } 372 373 final int value = getShortcutTypeCheckBoxValue(); 374 saveNonEmptyUserShortcutType(value); 375 AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), value, getComponentName()); 376 AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), ~value, getComponentName()); 377 final boolean shortcutAssigned = value != AccessibilityUtil.UserShortcutType.EMPTY; 378 mShortcutPreference.setChecked(shortcutAssigned); 379 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 380 381 if (mHardwareTypeCheckBox.isChecked()) { 382 AccessibilityUtil.skipVolumeShortcutDialogTimeoutRestriction(getPrefContext()); 383 } 384 385 // Show the quick setting tooltip if the shortcut assigned in the first time 386 if (shortcutAssigned) { 387 showQuickSettingsTooltipIfNeeded(); 388 } 389 } 390 391 @VisibleForTesting initGeneralCategory()392 void initGeneralCategory() { 393 final PreferenceCategory generalCategory = new PreferenceCategory(getPrefContext()); 394 generalCategory.setKey(KEY_GENERAL_CATEGORY); 395 generalCategory.setTitle(getGeneralCategoryDescription(null)); 396 397 getPreferenceScreen().addPreference(generalCategory); 398 } 399 updateEditShortcutDialogIfNeeded()400 private void updateEditShortcutDialogIfNeeded() { 401 if (mDialog == null || !mDialog.isShowing()) { 402 return; 403 } 404 AccessibilityDialogUtils.updateShortcutInDialog(getContext(), mDialog); 405 } 406 407 @VisibleForTesting saveNonEmptyUserShortcutType(int type)408 void saveNonEmptyUserShortcutType(int type) { 409 if (type == AccessibilityUtil.UserShortcutType.EMPTY) { 410 return; 411 } 412 413 final PreferredShortcut shortcut = new PreferredShortcut( 414 getComponentName().flattenToString(), type); 415 PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut); 416 } 417 418 /** 419 * Overrides to return customized description for general category above shortcut 420 * 421 * @return CharSequence The customized description for general category 422 */ getGeneralCategoryDescription(@ullable CharSequence title)423 protected CharSequence getGeneralCategoryDescription(@Nullable CharSequence title) { 424 if (title == null || title.toString().isEmpty()) { 425 // Return default 'Options' string for category 426 return getContext().getString(R.string.accessibility_screen_option); 427 } 428 return title; 429 } 430 431 /** 432 * Overrides to determinate if showing additional category description above shortcut 433 * 434 * @return boolean true to show category, false otherwise. 435 */ showGeneralCategory()436 protected boolean showGeneralCategory() { 437 return false; 438 } 439 setDialogTextAreaClickListener(View dialogView, CheckBox checkBox)440 private void setDialogTextAreaClickListener(View dialogView, CheckBox checkBox) { 441 final View dialogTextArea = dialogView.findViewById(R.id.container); 442 dialogTextArea.setOnClickListener(v -> checkBox.toggle()); 443 } 444 getShortcutTypeSummary(Context context)445 protected CharSequence getShortcutTypeSummary(Context context) { 446 if (!mShortcutPreference.isSettingsEditable()) { 447 return context.getText(R.string.accessibility_shortcut_edit_dialog_title_hardware); 448 } 449 450 if (!mShortcutPreference.isChecked()) { 451 return context.getText(R.string.accessibility_shortcut_state_off); 452 } 453 454 final int shortcutTypes = getUserPreferredShortcutTypes(); 455 456 // LINT.IfChange(shortcut_type_ui_order) 457 final List<CharSequence> list = new ArrayList<>(); 458 if (android.view.accessibility.Flags.a11yQsShortcut()) { 459 if (hasShortcutType(shortcutTypes, AccessibilityUtil.UserShortcutType.QUICK_SETTINGS)) { 460 final CharSequence qsTitle = context.getText( 461 R.string.accessibility_feature_shortcut_setting_summary_quick_settings); 462 list.add(qsTitle); 463 } 464 } 465 if (hasShortcutType(shortcutTypes, AccessibilityUtil.UserShortcutType.SOFTWARE)) { 466 list.add(getSoftwareShortcutTypeSummary(context)); 467 } 468 if (hasShortcutType(shortcutTypes, AccessibilityUtil.UserShortcutType.HARDWARE)) { 469 final CharSequence hardwareTitle = context.getText( 470 R.string.accessibility_shortcut_hardware_keyword); 471 list.add(hardwareTitle); 472 } 473 // LINT.ThenChange(/res/xml/accessibility_edit_shortcuts.xml:shortcut_type_ui_order) 474 475 // Show software shortcut if first time to use. 476 if (list.isEmpty()) { 477 list.add(getSoftwareShortcutTypeSummary(context)); 478 } 479 480 return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */ 481 null, LocaleUtils.getConcatenatedString(list)); 482 } 483 updateEditShortcutDialogCheckBox()484 private void updateEditShortcutDialogCheckBox() { 485 // If it is during onConfigChanged process then restore the value, or get the saved value 486 // when shortcutPreference is checked. 487 int value = restoreOnConfigChangedValue(); 488 if (value == NOT_SET) { 489 final int lastNonEmptyUserShortcutType = getUserPreferredShortcutTypes(); 490 value = mShortcutPreference.isChecked() ? lastNonEmptyUserShortcutType 491 : AccessibilityUtil.UserShortcutType.EMPTY; 492 } 493 494 mSoftwareTypeCheckBox.setChecked( 495 hasShortcutType(value, AccessibilityUtil.UserShortcutType.SOFTWARE)); 496 mHardwareTypeCheckBox.setChecked( 497 hasShortcutType(value, AccessibilityUtil.UserShortcutType.HARDWARE)); 498 } 499 restoreOnConfigChangedValue()500 private int restoreOnConfigChangedValue() { 501 final int savedValue = mSavedCheckBoxValue; 502 mSavedCheckBoxValue = NOT_SET; 503 return savedValue; 504 } 505 hasShortcutType(int value, @AccessibilityUtil.UserShortcutType int type)506 private boolean hasShortcutType(int value, @AccessibilityUtil.UserShortcutType int type) { 507 return (value & type) == type; 508 } 509 updateShortcutPreferenceData()510 protected void updateShortcutPreferenceData() { 511 if (getComponentName() == null) { 512 return; 513 } 514 515 final int shortcutTypes = AccessibilityUtil.getUserShortcutTypesFromSettings( 516 getPrefContext(), getComponentName()); 517 if (shortcutTypes != AccessibilityUtil.UserShortcutType.EMPTY) { 518 final PreferredShortcut shortcut = new PreferredShortcut( 519 getComponentName().flattenToString(), shortcutTypes); 520 PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut); 521 } 522 } 523 updateShortcutPreference()524 protected void updateShortcutPreference() { 525 if (getComponentName() == null) { 526 return; 527 } 528 529 final int shortcutTypes = getUserPreferredShortcutTypes(); 530 mShortcutPreference.setChecked( 531 AccessibilityUtil.hasValuesInSettings(getPrefContext(), shortcutTypes, 532 getComponentName())); 533 mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); 534 } 535 536 /** 537 * Shows the quick settings tooltip if the quick settings feature is assigned. The tooltip only 538 * shows once. 539 * 540 * @param type The quick settings tooltip type 541 */ showQuickSettingsTooltipIfNeeded(@uickSettingsTooltipType int type)542 protected void showQuickSettingsTooltipIfNeeded(@QuickSettingsTooltipType int type) { 543 mNeedsQSTooltipType = type; 544 showQuickSettingsTooltipIfNeeded(); 545 } 546 showQuickSettingsTooltipIfNeeded()547 private void showQuickSettingsTooltipIfNeeded() { 548 if (android.view.accessibility.Flags.a11yQsShortcut()) { 549 // Don't show Quick Settings tooltip 550 return; 551 } 552 final ComponentName tileComponentName = getTileComponentName(); 553 if (tileComponentName == null) { 554 // Returns if no tile service assigned. 555 return; 556 } 557 558 if (!mNeedsQSTooltipReshow && AccessibilityQuickSettingUtils.hasValueInSharedPreferences( 559 getContext(), tileComponentName)) { 560 // Returns if quick settings tooltip only show once. 561 return; 562 } 563 564 final CharSequence content = getTileTooltipContent(mNeedsQSTooltipType); 565 if (TextUtils.isEmpty(content)) { 566 // Returns if no content of tile tooltip assigned. 567 return; 568 } 569 570 final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT 571 ? R.drawable.accessibility_qs_tooltip_illustration 572 : R.drawable.accessibility_auto_added_qs_tooltip_illustration; 573 mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext()); 574 mTooltipWindow.setup(content, imageResId); 575 mTooltipWindow.showAtTopCenter(getView()); 576 AccessibilityQuickSettingUtils.optInValueToSharedPreferences(getContext(), 577 tileComponentName); 578 mNeedsQSTooltipReshow = false; 579 } 580 581 /** 582 * Returns the user preferred shortcut types or the default shortcut types if not set 583 */ 584 @ShortcutConstants.UserShortcutType getUserPreferredShortcutTypes()585 protected int getUserPreferredShortcutTypes() { 586 return PreferredShortcuts.retrieveUserShortcutType( 587 getPrefContext(), 588 getComponentName().flattenToString()); 589 } 590 } 591