2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.accessibility;
19 import android.accessibilityservice.AccessibilityServiceInfo;
20 import android.app.Dialog;
21 import android.app.admin.DevicePolicyManager;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.pm.PackageManager;
26 import android.content.pm.ServiceInfo;
27 import android.content.res.Resources;
28 import android.graphics.drawable.Drawable;
29 import android.net.Uri;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.UserHandle;
33 import android.provider.SearchIndexableResource;
34 import android.provider.Settings;
35 import android.support.v14.preference.SwitchPreference;
36 import android.support.v7.preference.ListPreference;
37 import android.support.v7.preference.Preference;
38 import android.support.v7.preference.PreferenceCategory;
39 import android.support.v7.preference.PreferenceScreen;
40 import android.text.TextUtils;
41 import android.util.ArrayMap;
42 import android.view.KeyCharacterMap;
43 import android.view.KeyEvent;
44 import android.view.accessibility.AccessibilityManager;
46 import com.android.internal.content.PackageMonitor;
47 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
48 import com.android.internal.view.RotationPolicy;
49 import com.android.internal.view.RotationPolicy.RotationPolicyListener;
50 import com.android.settings.R;
51 import com.android.settings.SettingsPreferenceFragment;
52 import com.android.settings.Utils;
53 import com.android.settings.search.BaseSearchIndexProvider;
54 import com.android.settings.search.Indexable;
55 import com.android.settings.search.SearchIndexableRaw;
56 import com.android.settingslib.RestrictedLockUtils;
57 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
58 import com.android.settingslib.RestrictedPreference;
59 import com.android.settingslib.accessibility.AccessibilityUtils;
61 import java.util.ArrayList;
62 import java.util.HashMap;
63 import java.util.List;
68 * Activity with the accessibility settings.
70 public class AccessibilitySettings extends SettingsPreferenceFragment implements
71 Preference.OnPreferenceChangeListener, Indexable {
73 // Index of the first preference in a preference category.
74 private static final int FIRST_PREFERENCE_IN_CATEGORY_INDEX = -1;
76 // Preference categories
77 private static final String CATEGORY_SCREEN_READER = "screen_reader_category";
78 private static final String CATEGORY_AUDIO_AND_CAPTIONS = "audio_and_captions_category";
79 private static final String CATEGORY_DISPLAY = "display_category";
80 private static final String CATEGORY_INTERACTION_CONTROL = "interaction_control_category";
81 private static final String CATEGORY_DOWNLOADED_SERVICES = "user_installed_services_category";
83 private static final String[] CATEGORIES = new String[] {
84 CATEGORY_SCREEN_READER, CATEGORY_AUDIO_AND_CAPTIONS, CATEGORY_DISPLAY,
85 CATEGORY_INTERACTION_CONTROL, CATEGORY_DOWNLOADED_SERVICES
89 private static final String TOGGLE_HIGH_TEXT_CONTRAST_PREFERENCE =
90 "toggle_high_text_contrast_preference";
91 private static final String TOGGLE_INVERSION_PREFERENCE =
92 "toggle_inversion_preference";
93 private static final String TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE =
94 "toggle_power_button_ends_call_preference";
95 private static final String TOGGLE_LOCK_SCREEN_ROTATION_PREFERENCE =
96 "toggle_lock_screen_rotation_preference";
97 private static final String TOGGLE_LARGE_POINTER_ICON =
98 "toggle_large_pointer_icon";
99 private static final String TOGGLE_MASTER_MONO =
100 "toggle_master_mono";
101 private static final String SELECT_LONG_PRESS_TIMEOUT_PREFERENCE =
102 "select_long_press_timeout_preference";
103 private static final String ACCESSIBILITY_SHORTCUT_PREFERENCE =
104 "accessibility_shortcut_preference";
105 private static final String CAPTIONING_PREFERENCE_SCREEN =
106 "captioning_preference_screen";
107 private static final String DISPLAY_MAGNIFICATION_PREFERENCE_SCREEN =
108 "screen_magnification_preference_screen";
109 private static final String FONT_SIZE_PREFERENCE_SCREEN =
110 "font_size_preference_screen";
111 private static final String AUTOCLICK_PREFERENCE_SCREEN =
112 "autoclick_preference_screen";
113 private static final String DISPLAY_DALTONIZER_PREFERENCE_SCREEN =
114 "daltonizer_preference_screen";
116 // Extras passed to sub-fragments.
117 static final String EXTRA_PREFERENCE_KEY = "preference_key";
118 static final String EXTRA_CHECKED = "checked";
119 static final String EXTRA_TITLE = "title";
120 static final String EXTRA_SUMMARY = "summary";
121 static final String EXTRA_SETTINGS_TITLE = "settings_title";
122 static final String EXTRA_COMPONENT_NAME = "component_name";
123 static final String EXTRA_SETTINGS_COMPONENT_NAME = "settings_component_name";
124 static final String EXTRA_VIDEO_RAW_RESOURCE_ID = "video_resource";
125 static final String EXTRA_LAUNCHED_FROM_SUW = "from_suw";
127 // Timeout before we update the services if packages are added/removed
128 // since the AccessibilityManagerService has to do that processing first
129 // to generate the AccessibilityServiceInfo we need for proper
131 private static final long DELAY_UPDATE_SERVICES_MILLIS = 1000;
133 // ID for dialog that confirms shortcut capabilities
134 private static final int DIALOG_ID_ADD_SHORTCUT_WARNING = 1;
136 private final Map<String, String> mLongPressTimeoutValueToTitleMap = new HashMap<>();
138 private final Handler mHandler = new Handler();
140 private final Runnable mUpdateRunnable = new Runnable() {
143 if (getActivity() != null) {
144 updateServicePreferences();
149 private final PackageMonitor mSettingsPackageMonitor = new PackageMonitor() {
151 public void onPackageAdded(String packageName, int uid) {
156 public void onPackageAppeared(String packageName, int reason) {
161 public void onPackageDisappeared(String packageName, int reason) {
166 public void onPackageRemoved(String packageName, int uid) {
170 private void sendUpdate() {
171 mHandler.postDelayed(mUpdateRunnable, DELAY_UPDATE_SERVICES_MILLIS);
175 private final SettingsContentObserver mSettingsContentObserver =
176 new SettingsContentObserver(mHandler) {
178 public void onChange(boolean selfChange, Uri uri) {
179 updateServicePreferences();
183 private final RotationPolicyListener mRotationPolicyListener = new RotationPolicyListener() {
185 public void onChange() {
186 updateLockScreenRotationCheckbox();
190 private final Map<String, PreferenceCategory> mCategoryToPrefCategoryMap =
192 private final Map<Preference, PreferenceCategory> mServicePreferenceToPreferenceCategoryMap =
194 private final Map<ComponentName, PreferenceCategory> mPreBundledServiceComponentToCategoryMap =
197 private SwitchPreference mToggleHighTextContrastPreference;
198 private SwitchPreference mTogglePowerButtonEndsCallPreference;
199 private SwitchPreference mToggleLockScreenRotationPreference;
200 private SwitchPreference mToggleLargePointerIconPreference;
201 private SwitchPreference mToggleMasterMonoPreference;
202 private ListPreference mSelectLongPressTimeoutPreference;
203 private Preference mNoServicesMessagePreference;
204 private Preference mCaptioningPreferenceScreen;
205 private Preference mDisplayMagnificationPreferenceScreen;
206 private Preference mFontSizePreferenceScreen;
207 private Preference mAutoclickPreferenceScreen;
208 private ListPreference mAccessibilityShortcutPreference;
209 private Preference mDisplayDaltonizerPreferenceScreen;
210 private SwitchPreference mToggleInversionPreference;
212 private int mLongPressTimeoutDefault;
214 private DevicePolicyManager mDpm;
217 public int getMetricsCategory() {
218 return MetricsEvent.ACCESSIBILITY;
222 protected int getHelpResource() {
223 return R.string.help_uri_accessibility;
227 public void onCreate(Bundle icicle) {
228 super.onCreate(icicle);
229 addPreferencesFromResource(R.xml.accessibility_settings);
230 initializeAllPreferences();
231 mDpm = (DevicePolicyManager) (getActivity()
232 .getSystemService(Context.DEVICE_POLICY_SERVICE));
236 public void onResume() {
238 updateAllPreferences();
240 mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
241 mSettingsContentObserver.register(getContentResolver());
242 if (RotationPolicy.isRotationSupported(getActivity())) {
243 RotationPolicy.registerRotationPolicyListener(getActivity(),
244 mRotationPolicyListener);
249 public void onPause() {
250 mSettingsPackageMonitor.unregister();
251 mSettingsContentObserver.unregister(getContentResolver());
252 if (RotationPolicy.isRotationSupported(getActivity())) {
253 RotationPolicy.unregisterRotationPolicyListener(getActivity(),
254 mRotationPolicyListener);
260 public boolean onPreferenceChange(Preference preference, Object newValue) {
261 if (mSelectLongPressTimeoutPreference == preference) {
262 handleLongPressTimeoutPreferenceChange((String) newValue);
264 } else if (mToggleInversionPreference == preference) {
265 handleToggleInversionPreferenceChange((Boolean) newValue);
267 } else if (mAccessibilityShortcutPreference == preference) {
268 handleAccessibilityShortcutPreferenceChange((String) newValue);
274 private void handleLongPressTimeoutPreferenceChange(String stringValue) {
275 Settings.Secure.putInt(getContentResolver(),
276 Settings.Secure.LONG_PRESS_TIMEOUT, Integer.parseInt(stringValue));
277 mSelectLongPressTimeoutPreference.setSummary(
278 mLongPressTimeoutValueToTitleMap.get(stringValue));
281 private void handleToggleInversionPreferenceChange(boolean checked) {
282 Settings.Secure.putInt(getContentResolver(),
283 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, (checked ? 1 : 0));
286 private void handleAccessibilityShortcutPreferenceChange(String serviceComponentName) {
287 // When assigning a service to the shortcut the user must explicitly agree to the same
288 // capabilities that are present if the service were being enabled.
289 // No need if clearing the setting or the service is already enabled.
290 if (TextUtils.isEmpty(serviceComponentName)
291 || AccessibilityUtils.getEnabledServicesFromSettings(getActivity())
292 .contains(ComponentName.unflattenFromString(serviceComponentName))) {
293 Settings.Secure.putString(getContentResolver(),
294 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, serviceComponentName);
295 updateAccessibilityShortcut();
298 if (!serviceComponentName.equals(mAccessibilityShortcutPreference.getValue())) {
299 showDialog(DIALOG_ID_ADD_SHORTCUT_WARNING);
304 public Dialog onCreateDialog(int dialogId) {
306 case DIALOG_ID_ADD_SHORTCUT_WARNING: {
307 DialogInterface.OnClickListener listener =
308 (DialogInterface dialogInterface, int buttonId) -> {
309 if (buttonId == DialogInterface.BUTTON_POSITIVE) {
310 Settings.Secure.putString(getContentResolver(),
311 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
312 mAccessibilityShortcutPreference.getValue());
314 updateAccessibilityShortcut();
316 AccessibilityServiceInfo info = AccessibilityManager.getInstance(getActivity())
317 .getInstalledServiceInfoWithComponentName(
318 ComponentName.unflattenFromString(
319 mAccessibilityShortcutPreference.getValue()));
323 return AccessibilityServiceWarning
324 .createCapabilitiesDialog(getActivity(), info, listener);
327 throw new IllegalArgumentException();
333 public int getDialogMetricsCategory(int dialogId) {
334 // The only dialog is the one that confirms the properties for the accessibility shortcut
335 return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
339 public boolean onPreferenceTreeClick(Preference preference) {
340 if (mToggleHighTextContrastPreference == preference) {
341 handleToggleTextContrastPreferenceClick();
343 } else if (mTogglePowerButtonEndsCallPreference == preference) {
344 handleTogglePowerButtonEndsCallPreferenceClick();
346 } else if (mToggleLockScreenRotationPreference == preference) {
347 handleLockScreenRotationPreferenceClick();
349 } else if (mToggleLargePointerIconPreference == preference) {
350 handleToggleLargePointerIconPreferenceClick();
352 } else if (mToggleMasterMonoPreference == preference) {
353 handleToggleMasterMonoPreferenceClick();
356 return super.onPreferenceTreeClick(preference);
359 private void handleToggleTextContrastPreferenceClick() {
360 Settings.Secure.putInt(getContentResolver(),
361 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
362 (mToggleHighTextContrastPreference.isChecked() ? 1 : 0));
365 private void handleTogglePowerButtonEndsCallPreferenceClick() {
366 Settings.Secure.putInt(getContentResolver(),
367 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
368 (mTogglePowerButtonEndsCallPreference.isChecked()
369 ? Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP
370 : Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF));
373 private void handleLockScreenRotationPreferenceClick() {
374 RotationPolicy.setRotationLockForAccessibility(getActivity(),
375 !mToggleLockScreenRotationPreference.isChecked());
378 private void handleToggleLargePointerIconPreferenceClick() {
379 Settings.Secure.putInt(getContentResolver(),
380 Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
381 mToggleLargePointerIconPreference.isChecked() ? 1 : 0);
384 private void handleToggleMasterMonoPreferenceClick() {
385 Settings.System.putIntForUser(getContentResolver(), Settings.System.MASTER_MONO,
386 mToggleMasterMonoPreference.isChecked() ? 1 : 0, UserHandle.USER_CURRENT);
389 private void initializeAllPreferences() {
390 for (int i = 0; i < CATEGORIES.length; i++) {
391 PreferenceCategory prefCategory = (PreferenceCategory) findPreference(CATEGORIES[i]);
392 mCategoryToPrefCategoryMap.put(CATEGORIES[i], prefCategory);
396 mToggleHighTextContrastPreference =
397 (SwitchPreference) findPreference(TOGGLE_HIGH_TEXT_CONTRAST_PREFERENCE);
399 // Display inversion.
400 mToggleInversionPreference = (SwitchPreference) findPreference(TOGGLE_INVERSION_PREFERENCE);
401 mToggleInversionPreference.setOnPreferenceChangeListener(this);
403 // Power button ends calls.
404 mTogglePowerButtonEndsCallPreference =
405 (SwitchPreference) findPreference(TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE);
406 if (!KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
407 || !Utils.isVoiceCapable(getActivity())) {
408 mCategoryToPrefCategoryMap.get(CATEGORY_INTERACTION_CONTROL)
409 .removePreference(mTogglePowerButtonEndsCallPreference);
412 // Lock screen rotation.
413 mToggleLockScreenRotationPreference =
414 (SwitchPreference) findPreference(TOGGLE_LOCK_SCREEN_ROTATION_PREFERENCE);
415 if (!RotationPolicy.isRotationSupported(getActivity())) {
416 mCategoryToPrefCategoryMap.get(CATEGORY_INTERACTION_CONTROL)
417 .removePreference(mToggleLockScreenRotationPreference);
420 // Large pointer icon.
421 mToggleLargePointerIconPreference =
422 (SwitchPreference) findPreference(TOGGLE_LARGE_POINTER_ICON);
425 mToggleMasterMonoPreference =
426 (SwitchPreference) findPreference(TOGGLE_MASTER_MONO);
428 // Long press timeout.
429 mSelectLongPressTimeoutPreference =
430 (ListPreference) findPreference(SELECT_LONG_PRESS_TIMEOUT_PREFERENCE);
431 mSelectLongPressTimeoutPreference.setOnPreferenceChangeListener(this);
432 if (mLongPressTimeoutValueToTitleMap.size() == 0) {
433 String[] timeoutValues = getResources().getStringArray(
434 R.array.long_press_timeout_selector_values);
435 mLongPressTimeoutDefault = Integer.parseInt(timeoutValues[0]);
436 String[] timeoutTitles = getResources().getStringArray(
437 R.array.long_press_timeout_selector_titles);
438 final int timeoutValueCount = timeoutValues.length;
439 for (int i = 0; i < timeoutValueCount; i++) {
440 mLongPressTimeoutValueToTitleMap.put(timeoutValues[i], timeoutTitles[i]);
445 mCaptioningPreferenceScreen = findPreference(CAPTIONING_PREFERENCE_SCREEN);
447 // Display magnification.
448 mDisplayMagnificationPreferenceScreen = findPreference(
449 DISPLAY_MAGNIFICATION_PREFERENCE_SCREEN);
452 mFontSizePreferenceScreen = findPreference(FONT_SIZE_PREFERENCE_SCREEN);
454 // Autoclick after pointer stops.
455 mAutoclickPreferenceScreen = findPreference(AUTOCLICK_PREFERENCE_SCREEN);
457 // Display color adjustments.
458 mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN);
460 // Accessibility shortcut
461 mAccessibilityShortcutPreference =
462 (ListPreference) findPreference(ACCESSIBILITY_SHORTCUT_PREFERENCE);
463 mAccessibilityShortcutPreference.setOnPreferenceChangeListener(this);
466 private void updateAllPreferences() {
467 updateSystemPreferences();
468 updateServicePreferences();
471 private void updateServicePreferences() {
472 // Since services category is auto generated we have to do a pass
473 // to generate it since services can come and go and then based on
474 // the global accessibility state to decided whether it is enabled.
477 ArrayList<Preference> servicePreferences =
478 new ArrayList<>(mServicePreferenceToPreferenceCategoryMap.keySet());
479 for (int i = 0; i < servicePreferences.size(); i++) {
480 Preference service = servicePreferences.get(i);
481 PreferenceCategory category = mServicePreferenceToPreferenceCategoryMap.get(service);
482 category.removePreference(service);
485 initializePreBundledServicesMapFromArray(CATEGORY_SCREEN_READER,
486 R.array.config_preinstalled_screen_reader_services);
487 initializePreBundledServicesMapFromArray(CATEGORY_AUDIO_AND_CAPTIONS,
488 R.array.config_preinstalled_audio_and_caption_services);
489 initializePreBundledServicesMapFromArray(CATEGORY_DISPLAY,
490 R.array.config_preinstalled_display_services);
491 initializePreBundledServicesMapFromArray(CATEGORY_INTERACTION_CONTROL,
492 R.array.config_preinstalled_interaction_control_services);
494 AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getActivity());
496 List<AccessibilityServiceInfo> installedServices =
497 accessibilityManager.getInstalledAccessibilityServiceList();
498 Set<ComponentName> enabledServices = AccessibilityUtils.getEnabledServicesFromSettings(
500 List<String> permittedServices = mDpm.getPermittedAccessibilityServices(
501 UserHandle.myUserId());
502 final boolean accessibilityEnabled = Settings.Secure.getInt(getContentResolver(),
503 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
505 PreferenceCategory downloadedServicesCategory =
506 mCategoryToPrefCategoryMap.get(CATEGORY_DOWNLOADED_SERVICES);
507 // Temporarily add the downloaded services category back if it was previously removed.
508 if (findPreference(CATEGORY_DOWNLOADED_SERVICES) == null) {
509 getPreferenceScreen().addPreference(downloadedServicesCategory);
512 for (int i = 0, count = installedServices.size(); i < count; ++i) {
513 AccessibilityServiceInfo info = installedServices.get(i);
515 RestrictedPreference preference =
516 new RestrictedPreference(downloadedServicesCategory.getContext());
517 String title = info.getResolveInfo().loadLabel(getPackageManager()).toString();
519 Drawable icon = info.getResolveInfo().loadIcon(getPackageManager());
521 // todo (saigem): add a default
524 ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
525 String packageName = serviceInfo.packageName;
526 ComponentName componentName = new ComponentName(packageName, serviceInfo.name);
527 String componentNameKey = componentName.flattenToString();
529 preference.setKey(componentName.flattenToString());
531 preference.setTitle(title);
532 preference.setIcon(icon);
533 final boolean serviceEnabled = accessibilityEnabled
534 && enabledServices.contains(componentName);
535 String serviceState = serviceEnabled ?
536 getString(R.string.accessibility_feature_state_on) :
537 getString(R.string.accessibility_feature_state_off);
538 String serviceSummary = info.loadSummary(getPackageManager());
539 serviceSummary = (TextUtils.isEmpty(serviceSummary)) ? serviceState :
542 // Disable all accessibility services that are not permitted.
543 boolean serviceAllowed =
544 permittedServices == null || permittedServices.contains(packageName);
545 if (!serviceAllowed && !serviceEnabled) {
546 EnforcedAdmin admin = RestrictedLockUtils.checkIfAccessibilityServiceDisallowed(
547 getActivity(), packageName, UserHandle.myUserId());
549 preference.setDisabledByAdmin(admin);
551 preference.setEnabled(false);
554 preference.setEnabled(true);
557 preference.setSummary(serviceSummary);
558 preference.setFragment(ToggleAccessibilityServicePreferenceFragment.class.getName());
559 preference.setPersistent(true);
561 Bundle extras = preference.getExtras();
562 extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey());
563 extras.putBoolean(EXTRA_CHECKED, serviceEnabled);
564 extras.putString(EXTRA_TITLE, title);
566 String description = info.loadDescription(getPackageManager());
567 if (TextUtils.isEmpty(description)) {
568 description = getString(R.string.accessibility_service_default_description);
570 extras.putString(EXTRA_SUMMARY, description);
572 String settingsClassName = info.getSettingsActivityName();
573 if (!TextUtils.isEmpty(settingsClassName)) {
574 extras.putString(EXTRA_SETTINGS_TITLE,
575 getString(R.string.accessibility_menu_item_settings));
576 extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
577 new ComponentName(packageName, settingsClassName).flattenToString());
579 extras.putParcelable(EXTRA_COMPONENT_NAME, componentName);
581 PreferenceCategory prefCategory = downloadedServicesCategory;
582 // Set the appropriate category if the service comes pre-installed.
583 if (mPreBundledServiceComponentToCategoryMap.containsKey(componentName)) {
584 prefCategory = mPreBundledServiceComponentToCategoryMap.get(componentName);
586 preference.setOrder(FIRST_PREFERENCE_IN_CATEGORY_INDEX);
587 prefCategory.addPreference(preference);
588 mServicePreferenceToPreferenceCategoryMap.put(preference, prefCategory);
591 // If the user has not installed any additional services, hide the category.
592 if (downloadedServicesCategory.getPreferenceCount() == 0) {
593 PreferenceScreen screen = getPreferenceScreen();
594 screen.removePreference(downloadedServicesCategory);
598 private void initializePreBundledServicesMapFromArray(String categoryKey, int key) {
599 String[] services = getResources().getStringArray(key);
600 PreferenceCategory category = mCategoryToPrefCategoryMap.get(categoryKey);
601 for (int i = 0; i < services.length; i++) {
602 ComponentName component = ComponentName.unflattenFromString(services[i]);
603 mPreBundledServiceComponentToCategoryMap.put(component, category);
607 private void updateSystemPreferences() {
609 mToggleHighTextContrastPreference.setChecked(
610 Settings.Secure.getInt(getContentResolver(),
611 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0) == 1);
613 // If the quick setting is enabled, the preference MUST be enabled.
614 mToggleInversionPreference.setChecked(Settings.Secure.getInt(getContentResolver(),
615 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0) == 1);
617 // Power button ends calls.
618 if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
619 && Utils.isVoiceCapable(getActivity())) {
620 final int incallPowerBehavior = Settings.Secure.getInt(getContentResolver(),
621 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
622 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
623 final boolean powerButtonEndsCall =
624 (incallPowerBehavior == Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP);
625 mTogglePowerButtonEndsCallPreference.setChecked(powerButtonEndsCall);
628 // Auto-rotate screen
629 updateLockScreenRotationCheckbox();
631 // Large pointer icon.
632 mToggleLargePointerIconPreference.setChecked(Settings.Secure.getInt(getContentResolver(),
633 Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, 0) != 0);
638 // Long press timeout.
639 final int longPressTimeout = Settings.Secure.getInt(getContentResolver(),
640 Settings.Secure.LONG_PRESS_TIMEOUT, mLongPressTimeoutDefault);
641 String value = String.valueOf(longPressTimeout);
642 mSelectLongPressTimeoutPreference.setValue(value);
643 mSelectLongPressTimeoutPreference.setSummary(mLongPressTimeoutValueToTitleMap.get(value));
645 updateFeatureSummary(Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED,
646 mCaptioningPreferenceScreen);
647 updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
648 mDisplayDaltonizerPreferenceScreen);
650 updateFontSizeSummary(mFontSizePreferenceScreen);
652 updateAutoclickSummary(mAutoclickPreferenceScreen);
654 updateAccessibilityShortcut();
657 private void updateFeatureSummary(String prefKey, Preference pref) {
658 final boolean enabled = Settings.Secure.getInt(getContentResolver(), prefKey, 0) == 1;
659 pref.setSummary(enabled ? R.string.accessibility_feature_state_on
660 : R.string.accessibility_feature_state_off);
663 private void updateAutoclickSummary(Preference pref) {
664 final boolean enabled = Settings.Secure.getInt(
665 getContentResolver(), Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 0) == 1;
667 pref.setSummary(R.string.accessibility_feature_state_off);
670 int delay = Settings.Secure.getInt(
671 getContentResolver(), Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
672 AccessibilityManager.AUTOCLICK_DELAY_DEFAULT);
673 pref.setSummary(ToggleAutoclickPreferenceFragment.getAutoclickPreferenceSummary(
674 getResources(), delay));
677 private void updateFontSizeSummary(Preference pref) {
678 final float currentScale = Settings.System.getFloat(getContext().getContentResolver(),
679 Settings.System.FONT_SCALE, 1.0f);
680 final Resources res = getContext().getResources();
681 final String[] entries = res.getStringArray(R.array.entries_font_size);
682 final String[] strEntryValues = res.getStringArray(R.array.entryvalues_font_size);
683 final int index = ToggleFontSizePreferenceFragment.fontSizeValueToIndex(currentScale,
685 pref.setSummary(entries[index]);
688 private void updateLockScreenRotationCheckbox() {
689 Context context = getActivity();
690 if (context != null) {
691 mToggleLockScreenRotationPreference.setChecked(
692 !RotationPolicy.isRotationLocked(context));
696 private void updateMasterMono() {
697 final boolean masterMono = Settings.System.getIntForUser(
698 getContentResolver(), Settings.System.MASTER_MONO,
699 0 /* default */, UserHandle.USER_CURRENT) == 1;
700 mToggleMasterMonoPreference.setChecked(masterMono);
703 private void updateAccessibilityShortcut() {
704 String currentShortcutNameString =
705 AccessibilityUtils.getShortcutTargetServiceComponentNameString(getActivity(),
706 UserHandle.myUserId());
707 final PackageManager pm = getPackageManager();
708 final AccessibilityManager accessibilityManager = getActivity()
709 .getSystemService(AccessibilityManager.class);
710 final List<AccessibilityServiceInfo> installedServices =
711 accessibilityManager.getInstalledAccessibilityServiceList();
712 final int numInstalledServices = installedServices.size();
714 CharSequence[] entries = new CharSequence[numInstalledServices + 1];
715 CharSequence[] entryValues = new CharSequence[numInstalledServices + 1];
716 int currentSettingIndex = numInstalledServices;
717 for (int i = 0; i < numInstalledServices; i++) {
718 AccessibilityServiceInfo installedService = installedServices.get(i);
719 entries[i] = installedService.getResolveInfo().loadLabel(pm);
720 entryValues[i] = installedService.getComponentName().flattenToShortString();
721 if (installedService.getId().equals(currentShortcutNameString)) {
722 currentSettingIndex = i;
725 entries[numInstalledServices] =
726 getString(com.android.internal.R.string.disable_accessibility_shortcut);
727 entryValues[numInstalledServices] = "";
728 mAccessibilityShortcutPreference.setEntryValues(entryValues);
729 mAccessibilityShortcutPreference.setEntries(entries);
730 mAccessibilityShortcutPreference.setSummary(entries[currentSettingIndex]);
731 mAccessibilityShortcutPreference.setValueIndex(currentSettingIndex);
734 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
735 new BaseSearchIndexProvider() {
737 public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
738 List<SearchIndexableRaw> indexables = new ArrayList<SearchIndexableRaw>();
740 PackageManager packageManager = context.getPackageManager();
741 AccessibilityManager accessibilityManager =
742 context.getSystemService(AccessibilityManager.class);
744 String screenTitle = context.getResources().getString(
745 R.string.accessibility_settings);
747 // Indexing all services, regardless if enabled.
748 List<AccessibilityServiceInfo> services = accessibilityManager
749 .getInstalledAccessibilityServiceList();
750 final int serviceCount = services.size();
751 for (int i = 0; i < serviceCount; i++) {
752 AccessibilityServiceInfo service = services.get(i);
753 if (service == null || service.getResolveInfo() == null) {
757 ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
758 ComponentName componentName = new ComponentName(serviceInfo.packageName,
761 SearchIndexableRaw indexable = new SearchIndexableRaw(context);
762 indexable.key = componentName.flattenToString();
763 indexable.title = service.getResolveInfo().loadLabel(packageManager).toString();
764 indexable.screenTitle = screenTitle;
765 indexables.add(indexable);
772 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
774 List<SearchIndexableResource> indexables = new ArrayList<>();
775 SearchIndexableResource indexable = new SearchIndexableResource(context);
776 indexable.xmlResId = R.xml.accessibility_settings;
777 indexables.add(indexable);