1 /* 2 * Copyright (C) 2009 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 android.accessibilityservice.AccessibilityServiceInfo; 20 import android.app.ActivityManagerNative; 21 import android.app.admin.DevicePolicyManager; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.pm.PackageManager; 25 import android.content.pm.ResolveInfo; 26 import android.content.pm.ServiceInfo; 27 import android.content.res.Configuration; 28 import android.net.Uri; 29 import android.os.Bundle; 30 import android.os.Handler; 31 import android.os.RemoteException; 32 import android.os.UserHandle; 33 import android.preference.ListPreference; 34 import android.preference.Preference; 35 import android.preference.PreferenceCategory; 36 import android.preference.PreferenceScreen; 37 import android.preference.SwitchPreference; 38 import android.provider.SearchIndexableResource; 39 import android.provider.Settings; 40 import android.text.TextUtils; 41 import android.text.TextUtils.SimpleStringSplitter; 42 import android.view.KeyCharacterMap; 43 import android.view.KeyEvent; 44 import android.view.accessibility.AccessibilityManager; 45 import com.android.internal.content.PackageMonitor; 46 import com.android.internal.logging.MetricsLogger; 47 import com.android.internal.view.RotationPolicy; 48 import com.android.internal.view.RotationPolicy.RotationPolicyListener; 49 import com.android.settings.DialogCreatable; 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 57 import java.util.ArrayList; 58 import java.util.HashMap; 59 import java.util.HashSet; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.Set; 63 64 /** 65 * Activity with the accessibility settings. 66 */ 67 public class AccessibilitySettings extends SettingsPreferenceFragment implements DialogCreatable, 68 Preference.OnPreferenceChangeListener, Indexable { 69 70 private static final float LARGE_FONT_SCALE = 1.3f; 71 72 static final char ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':'; 73 74 // Preference categories 75 private static final String SERVICES_CATEGORY = "services_category"; 76 private static final String SYSTEM_CATEGORY = "system_category"; 77 78 // Preferences 79 private static final String TOGGLE_LARGE_TEXT_PREFERENCE = 80 "toggle_large_text_preference"; 81 private static final String TOGGLE_HIGH_TEXT_CONTRAST_PREFERENCE = 82 "toggle_high_text_contrast_preference"; 83 private static final String TOGGLE_INVERSION_PREFERENCE = 84 "toggle_inversion_preference"; 85 private static final String TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE = 86 "toggle_power_button_ends_call_preference"; 87 private static final String TOGGLE_LOCK_SCREEN_ROTATION_PREFERENCE = 88 "toggle_lock_screen_rotation_preference"; 89 private static final String TOGGLE_SPEAK_PASSWORD_PREFERENCE = 90 "toggle_speak_password_preference"; 91 private static final String SELECT_LONG_PRESS_TIMEOUT_PREFERENCE = 92 "select_long_press_timeout_preference"; 93 private static final String ENABLE_ACCESSIBILITY_GESTURE_PREFERENCE_SCREEN = 94 "enable_global_gesture_preference_screen"; 95 private static final String CAPTIONING_PREFERENCE_SCREEN = 96 "captioning_preference_screen"; 97 private static final String DISPLAY_MAGNIFICATION_PREFERENCE_SCREEN = 98 "screen_magnification_preference_screen"; 99 private static final String DISPLAY_DALTONIZER_PREFERENCE_SCREEN = 100 "daltonizer_preference_screen"; 101 102 // Extras passed to sub-fragments. 103 static final String EXTRA_PREFERENCE_KEY = "preference_key"; 104 static final String EXTRA_CHECKED = "checked"; 105 static final String EXTRA_TITLE = "title"; 106 static final String EXTRA_SUMMARY = "summary"; 107 static final String EXTRA_SETTINGS_TITLE = "settings_title"; 108 static final String EXTRA_COMPONENT_NAME = "component_name"; 109 static final String EXTRA_SETTINGS_COMPONENT_NAME = "settings_component_name"; 110 111 // Timeout before we update the services if packages are added/removed 112 // since the AccessibilityManagerService has to do that processing first 113 // to generate the AccessibilityServiceInfo we need for proper 114 // presentation. 115 private static final long DELAY_UPDATE_SERVICES_MILLIS = 1000; 116 117 // Auxiliary members. 118 final static SimpleStringSplitter sStringColonSplitter = 119 new SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR); 120 121 static final Set<ComponentName> sInstalledServices = new HashSet<ComponentName>(); 122 123 private final Map<String, String> mLongPressTimeoutValuetoTitleMap = 124 new HashMap<String, String>(); 125 126 private final Configuration mCurConfig = new Configuration(); 127 128 private final Handler mHandler = new Handler(); 129 130 private final Runnable mUpdateRunnable = new Runnable() { 131 @Override 132 public void run() { 133 loadInstalledServices(); 134 updateServicesPreferences(); 135 } 136 }; 137 138 private final PackageMonitor mSettingsPackageMonitor = new PackageMonitor() { 139 @Override 140 public void onPackageAdded(String packageName, int uid) { 141 sendUpdate(); 142 } 143 144 @Override 145 public void onPackageAppeared(String packageName, int reason) { 146 sendUpdate(); 147 } 148 149 @Override 150 public void onPackageDisappeared(String packageName, int reason) { 151 sendUpdate(); 152 } 153 154 @Override 155 public void onPackageRemoved(String packageName, int uid) { 156 sendUpdate(); 157 } 158 159 private void sendUpdate() { 160 mHandler.postDelayed(mUpdateRunnable, DELAY_UPDATE_SERVICES_MILLIS); 161 } 162 }; 163 164 private final SettingsContentObserver mSettingsContentObserver = 165 new SettingsContentObserver(mHandler) { 166 @Override 167 public void onChange(boolean selfChange, Uri uri) { 168 loadInstalledServices(); 169 updateServicesPreferences(); 170 } 171 }; 172 173 private final RotationPolicyListener mRotationPolicyListener = new RotationPolicyListener() { 174 @Override 175 public void onChange() { 176 updateLockScreenRotationCheckbox(); 177 } 178 }; 179 180 // Preference controls. 181 private PreferenceCategory mServicesCategory; 182 private PreferenceCategory mSystemsCategory; 183 184 private SwitchPreference mToggleLargeTextPreference; 185 private SwitchPreference mToggleHighTextContrastPreference; 186 private SwitchPreference mTogglePowerButtonEndsCallPreference; 187 private SwitchPreference mToggleLockScreenRotationPreference; 188 private SwitchPreference mToggleSpeakPasswordPreference; 189 private ListPreference mSelectLongPressTimeoutPreference; 190 private Preference mNoServicesMessagePreference; 191 private PreferenceScreen mCaptioningPreferenceScreen; 192 private PreferenceScreen mDisplayMagnificationPreferenceScreen; 193 private PreferenceScreen mGlobalGesturePreferenceScreen; 194 private PreferenceScreen mDisplayDaltonizerPreferenceScreen; 195 private SwitchPreference mToggleInversionPreference; 196 197 private int mLongPressTimeoutDefault; 198 199 private DevicePolicyManager mDpm; 200 201 @Override getMetricsCategory()202 protected int getMetricsCategory() { 203 return MetricsLogger.ACCESSIBILITY; 204 } 205 206 @Override getHelpResource()207 protected int getHelpResource() { 208 return R.string.help_uri_accessibility; 209 } 210 211 @Override onCreate(Bundle icicle)212 public void onCreate(Bundle icicle) { 213 super.onCreate(icicle); 214 addPreferencesFromResource(R.xml.accessibility_settings); 215 initializeAllPreferences(); 216 mDpm = (DevicePolicyManager) (getActivity() 217 .getSystemService(Context.DEVICE_POLICY_SERVICE)); 218 } 219 220 @Override onResume()221 public void onResume() { 222 super.onResume(); 223 loadInstalledServices(); 224 updateAllPreferences(); 225 226 mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false); 227 mSettingsContentObserver.register(getContentResolver()); 228 if (RotationPolicy.isRotationSupported(getActivity())) { 229 RotationPolicy.registerRotationPolicyListener(getActivity(), 230 mRotationPolicyListener); 231 } 232 } 233 234 @Override onPause()235 public void onPause() { 236 mSettingsPackageMonitor.unregister(); 237 mSettingsContentObserver.unregister(getContentResolver()); 238 if (RotationPolicy.isRotationSupported(getActivity())) { 239 RotationPolicy.unregisterRotationPolicyListener(getActivity(), 240 mRotationPolicyListener); 241 } 242 super.onPause(); 243 } 244 245 @Override onPreferenceChange(Preference preference, Object newValue)246 public boolean onPreferenceChange(Preference preference, Object newValue) { 247 if (mSelectLongPressTimeoutPreference == preference) { 248 handleLongPressTimeoutPreferenceChange((String) newValue); 249 return true; 250 } else if (mToggleInversionPreference == preference) { 251 handleToggleInversionPreferenceChange((Boolean) newValue); 252 return true; 253 } 254 return false; 255 } 256 handleLongPressTimeoutPreferenceChange(String stringValue)257 private void handleLongPressTimeoutPreferenceChange(String stringValue) { 258 Settings.Secure.putInt(getContentResolver(), 259 Settings.Secure.LONG_PRESS_TIMEOUT, Integer.parseInt(stringValue)); 260 mSelectLongPressTimeoutPreference.setSummary( 261 mLongPressTimeoutValuetoTitleMap.get(stringValue)); 262 } 263 handleToggleInversionPreferenceChange(boolean checked)264 private void handleToggleInversionPreferenceChange(boolean checked) { 265 Settings.Secure.putInt(getContentResolver(), 266 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, (checked ? 1 : 0)); 267 } 268 269 @Override onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)270 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 271 if (mToggleLargeTextPreference == preference) { 272 handleToggleLargeTextPreferenceClick(); 273 return true; 274 } else if (mToggleHighTextContrastPreference == preference) { 275 handleToggleTextContrastPreferenceClick(); 276 return true; 277 } else if (mTogglePowerButtonEndsCallPreference == preference) { 278 handleTogglePowerButtonEndsCallPreferenceClick(); 279 return true; 280 } else if (mToggleLockScreenRotationPreference == preference) { 281 handleLockScreenRotationPreferenceClick(); 282 return true; 283 } else if (mToggleSpeakPasswordPreference == preference) { 284 handleToggleSpeakPasswordPreferenceClick(); 285 return true; 286 } else if (mGlobalGesturePreferenceScreen == preference) { 287 handleToggleEnableAccessibilityGesturePreferenceClick(); 288 return true; 289 } else if (mDisplayMagnificationPreferenceScreen == preference) { 290 handleDisplayMagnificationPreferenceScreenClick(); 291 return true; 292 } 293 return super.onPreferenceTreeClick(preferenceScreen, preference); 294 } 295 handleToggleLargeTextPreferenceClick()296 private void handleToggleLargeTextPreferenceClick() { 297 try { 298 mCurConfig.fontScale = mToggleLargeTextPreference.isChecked() ? LARGE_FONT_SCALE : 1; 299 ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig); 300 } catch (RemoteException re) { 301 /* ignore */ 302 } 303 } 304 handleToggleTextContrastPreferenceClick()305 private void handleToggleTextContrastPreferenceClick() { 306 Settings.Secure.putInt(getContentResolver(), 307 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 308 (mToggleHighTextContrastPreference.isChecked() ? 1 : 0)); 309 } 310 handleTogglePowerButtonEndsCallPreferenceClick()311 private void handleTogglePowerButtonEndsCallPreferenceClick() { 312 Settings.Secure.putInt(getContentResolver(), 313 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 314 (mTogglePowerButtonEndsCallPreference.isChecked() 315 ? Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP 316 : Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF)); 317 } 318 handleLockScreenRotationPreferenceClick()319 private void handleLockScreenRotationPreferenceClick() { 320 RotationPolicy.setRotationLockForAccessibility(getActivity(), 321 !mToggleLockScreenRotationPreference.isChecked()); 322 } 323 handleToggleSpeakPasswordPreferenceClick()324 private void handleToggleSpeakPasswordPreferenceClick() { 325 Settings.Secure.putInt(getContentResolver(), 326 Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 327 mToggleSpeakPasswordPreference.isChecked() ? 1 : 0); 328 } 329 handleToggleEnableAccessibilityGesturePreferenceClick()330 private void handleToggleEnableAccessibilityGesturePreferenceClick() { 331 Bundle extras = mGlobalGesturePreferenceScreen.getExtras(); 332 extras.putString(EXTRA_TITLE, getString( 333 R.string.accessibility_global_gesture_preference_title)); 334 extras.putString(EXTRA_SUMMARY, getString( 335 R.string.accessibility_global_gesture_preference_description)); 336 extras.putBoolean(EXTRA_CHECKED, Settings.Global.getInt(getContentResolver(), 337 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1); 338 super.onPreferenceTreeClick(mGlobalGesturePreferenceScreen, 339 mGlobalGesturePreferenceScreen); 340 } 341 handleDisplayMagnificationPreferenceScreenClick()342 private void handleDisplayMagnificationPreferenceScreenClick() { 343 Bundle extras = mDisplayMagnificationPreferenceScreen.getExtras(); 344 extras.putString(EXTRA_TITLE, getString( 345 R.string.accessibility_screen_magnification_title)); 346 extras.putCharSequence(EXTRA_SUMMARY, getActivity().getResources().getText( 347 R.string.accessibility_screen_magnification_summary)); 348 extras.putBoolean(EXTRA_CHECKED, Settings.Secure.getInt(getContentResolver(), 349 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1); 350 super.onPreferenceTreeClick(mDisplayMagnificationPreferenceScreen, 351 mDisplayMagnificationPreferenceScreen); 352 } 353 initializeAllPreferences()354 private void initializeAllPreferences() { 355 mServicesCategory = (PreferenceCategory) findPreference(SERVICES_CATEGORY); 356 mSystemsCategory = (PreferenceCategory) findPreference(SYSTEM_CATEGORY); 357 358 // Large text. 359 mToggleLargeTextPreference = 360 (SwitchPreference) findPreference(TOGGLE_LARGE_TEXT_PREFERENCE); 361 362 // Text contrast. 363 mToggleHighTextContrastPreference = 364 (SwitchPreference) findPreference(TOGGLE_HIGH_TEXT_CONTRAST_PREFERENCE); 365 366 // Display inversion. 367 mToggleInversionPreference = (SwitchPreference) findPreference(TOGGLE_INVERSION_PREFERENCE); 368 mToggleInversionPreference.setOnPreferenceChangeListener(this); 369 370 // Power button ends calls. 371 mTogglePowerButtonEndsCallPreference = 372 (SwitchPreference) findPreference(TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE); 373 if (!KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER) 374 || !Utils.isVoiceCapable(getActivity())) { 375 mSystemsCategory.removePreference(mTogglePowerButtonEndsCallPreference); 376 } 377 378 // Lock screen rotation. 379 mToggleLockScreenRotationPreference = 380 (SwitchPreference) findPreference(TOGGLE_LOCK_SCREEN_ROTATION_PREFERENCE); 381 if (!RotationPolicy.isRotationSupported(getActivity())) { 382 mSystemsCategory.removePreference(mToggleLockScreenRotationPreference); 383 } 384 385 // Speak passwords. 386 mToggleSpeakPasswordPreference = 387 (SwitchPreference) findPreference(TOGGLE_SPEAK_PASSWORD_PREFERENCE); 388 389 // Long press timeout. 390 mSelectLongPressTimeoutPreference = 391 (ListPreference) findPreference(SELECT_LONG_PRESS_TIMEOUT_PREFERENCE); 392 mSelectLongPressTimeoutPreference.setOnPreferenceChangeListener(this); 393 if (mLongPressTimeoutValuetoTitleMap.size() == 0) { 394 String[] timeoutValues = getResources().getStringArray( 395 R.array.long_press_timeout_selector_values); 396 mLongPressTimeoutDefault = Integer.parseInt(timeoutValues[0]); 397 String[] timeoutTitles = getResources().getStringArray( 398 R.array.long_press_timeout_selector_titles); 399 final int timeoutValueCount = timeoutValues.length; 400 for (int i = 0; i < timeoutValueCount; i++) { 401 mLongPressTimeoutValuetoTitleMap.put(timeoutValues[i], timeoutTitles[i]); 402 } 403 } 404 405 // Captioning. 406 mCaptioningPreferenceScreen = (PreferenceScreen) findPreference( 407 CAPTIONING_PREFERENCE_SCREEN); 408 409 // Display magnification. 410 mDisplayMagnificationPreferenceScreen = (PreferenceScreen) findPreference( 411 DISPLAY_MAGNIFICATION_PREFERENCE_SCREEN); 412 413 // Display color adjustments. 414 mDisplayDaltonizerPreferenceScreen = (PreferenceScreen) findPreference( 415 DISPLAY_DALTONIZER_PREFERENCE_SCREEN); 416 417 // Global gesture. 418 mGlobalGesturePreferenceScreen = 419 (PreferenceScreen) findPreference(ENABLE_ACCESSIBILITY_GESTURE_PREFERENCE_SCREEN); 420 final int longPressOnPowerBehavior = getActivity().getResources().getInteger( 421 com.android.internal.R.integer.config_longPressOnPowerBehavior); 422 final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; 423 if (!KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER) 424 || longPressOnPowerBehavior != LONG_PRESS_POWER_GLOBAL_ACTIONS) { 425 // Remove accessibility shortcut if power key is not present 426 // nor long press power does not show global actions menu. 427 mSystemsCategory.removePreference(mGlobalGesturePreferenceScreen); 428 } 429 } 430 updateAllPreferences()431 private void updateAllPreferences() { 432 updateServicesPreferences(); 433 updateSystemPreferences(); 434 } 435 updateServicesPreferences()436 private void updateServicesPreferences() { 437 // Since services category is auto generated we have to do a pass 438 // to generate it since services can come and go and then based on 439 // the global accessibility state to decided whether it is enabled. 440 441 // Generate. 442 mServicesCategory.removeAll(); 443 444 AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getActivity()); 445 446 List<AccessibilityServiceInfo> installedServices = 447 accessibilityManager.getInstalledAccessibilityServiceList(); 448 Set<ComponentName> enabledServices = AccessibilityUtils.getEnabledServicesFromSettings( 449 getActivity()); 450 List<String> permittedServices = mDpm.getPermittedAccessibilityServices( 451 UserHandle.myUserId()); 452 final boolean accessibilityEnabled = Settings.Secure.getInt(getContentResolver(), 453 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1; 454 455 for (int i = 0, count = installedServices.size(); i < count; ++i) { 456 AccessibilityServiceInfo info = installedServices.get(i); 457 458 PreferenceScreen preference = getPreferenceManager().createPreferenceScreen( 459 getActivity()); 460 String title = info.getResolveInfo().loadLabel(getPackageManager()).toString(); 461 462 ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo; 463 ComponentName componentName = new ComponentName(serviceInfo.packageName, 464 serviceInfo.name); 465 466 preference.setKey(componentName.flattenToString()); 467 468 preference.setTitle(title); 469 final boolean serviceEnabled = accessibilityEnabled 470 && enabledServices.contains(componentName); 471 String serviceEnabledString; 472 if (serviceEnabled) { 473 serviceEnabledString = getString(R.string.accessibility_feature_state_on); 474 } else { 475 serviceEnabledString = getString(R.string.accessibility_feature_state_off); 476 } 477 478 // Disable all accessibility services that are not permitted. 479 String packageName = serviceInfo.packageName; 480 boolean serviceAllowed = 481 permittedServices == null || permittedServices.contains(packageName); 482 preference.setEnabled(serviceAllowed || serviceEnabled); 483 484 String summaryString; 485 if (serviceAllowed) { 486 summaryString = serviceEnabledString; 487 } else { 488 summaryString = getString(R.string.accessibility_feature_or_input_method_not_allowed); 489 } 490 preference.setSummary(summaryString); 491 492 preference.setOrder(i); 493 preference.setFragment(ToggleAccessibilityServicePreferenceFragment.class.getName()); 494 preference.setPersistent(true); 495 496 Bundle extras = preference.getExtras(); 497 extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey()); 498 extras.putBoolean(EXTRA_CHECKED, serviceEnabled); 499 extras.putString(EXTRA_TITLE, title); 500 501 String description = info.loadDescription(getPackageManager()); 502 if (TextUtils.isEmpty(description)) { 503 description = getString(R.string.accessibility_service_default_description); 504 } 505 extras.putString(EXTRA_SUMMARY, description); 506 507 String settingsClassName = info.getSettingsActivityName(); 508 if (!TextUtils.isEmpty(settingsClassName)) { 509 extras.putString(EXTRA_SETTINGS_TITLE, 510 getString(R.string.accessibility_menu_item_settings)); 511 extras.putString(EXTRA_SETTINGS_COMPONENT_NAME, 512 new ComponentName(info.getResolveInfo().serviceInfo.packageName, 513 settingsClassName).flattenToString()); 514 } 515 516 extras.putParcelable(EXTRA_COMPONENT_NAME, componentName); 517 518 mServicesCategory.addPreference(preference); 519 } 520 521 if (mServicesCategory.getPreferenceCount() == 0) { 522 if (mNoServicesMessagePreference == null) { 523 mNoServicesMessagePreference = new Preference(getActivity()); 524 mNoServicesMessagePreference.setPersistent(false); 525 mNoServicesMessagePreference.setLayoutResource( 526 R.layout.text_description_preference); 527 mNoServicesMessagePreference.setSelectable(false); 528 mNoServicesMessagePreference.setSummary( 529 getString(R.string.accessibility_no_services_installed)); 530 } 531 mServicesCategory.addPreference(mNoServicesMessagePreference); 532 } 533 } 534 updateSystemPreferences()535 private void updateSystemPreferences() { 536 // Large text. 537 try { 538 mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration()); 539 } catch (RemoteException re) { 540 /* ignore */ 541 } 542 mToggleLargeTextPreference.setChecked(mCurConfig.fontScale == LARGE_FONT_SCALE); 543 544 mToggleHighTextContrastPreference.setChecked( 545 Settings.Secure.getInt(getContentResolver(), 546 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0) == 1); 547 548 // If the quick setting is enabled, the preference MUST be enabled. 549 mToggleInversionPreference.setChecked(Settings.Secure.getInt(getContentResolver(), 550 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0) == 1); 551 552 // Power button ends calls. 553 if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER) 554 && Utils.isVoiceCapable(getActivity())) { 555 final int incallPowerBehavior = Settings.Secure.getInt(getContentResolver(), 556 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 557 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT); 558 final boolean powerButtonEndsCall = 559 (incallPowerBehavior == Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP); 560 mTogglePowerButtonEndsCallPreference.setChecked(powerButtonEndsCall); 561 } 562 563 // Auto-rotate screen 564 updateLockScreenRotationCheckbox(); 565 566 // Speak passwords. 567 final boolean speakPasswordEnabled = Settings.Secure.getInt(getContentResolver(), 568 Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0; 569 mToggleSpeakPasswordPreference.setChecked(speakPasswordEnabled); 570 571 // Long press timeout. 572 final int longPressTimeout = Settings.Secure.getInt(getContentResolver(), 573 Settings.Secure.LONG_PRESS_TIMEOUT, mLongPressTimeoutDefault); 574 String value = String.valueOf(longPressTimeout); 575 mSelectLongPressTimeoutPreference.setValue(value); 576 mSelectLongPressTimeoutPreference.setSummary(mLongPressTimeoutValuetoTitleMap.get(value)); 577 578 updateFeatureSummary(Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, 579 mCaptioningPreferenceScreen); 580 updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 581 mDisplayMagnificationPreferenceScreen); 582 updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 583 mDisplayDaltonizerPreferenceScreen); 584 585 // Global gesture 586 final boolean globalGestureEnabled = Settings.Global.getInt(getContentResolver(), 587 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 588 if (globalGestureEnabled) { 589 mGlobalGesturePreferenceScreen.setSummary( 590 R.string.accessibility_global_gesture_preference_summary_on); 591 } else { 592 mGlobalGesturePreferenceScreen.setSummary( 593 R.string.accessibility_global_gesture_preference_summary_off); 594 } 595 } 596 updateFeatureSummary(String prefKey, Preference pref)597 private void updateFeatureSummary(String prefKey, Preference pref) { 598 final boolean enabled = Settings.Secure.getInt(getContentResolver(), prefKey, 0) == 1; 599 pref.setSummary(enabled ? R.string.accessibility_feature_state_on 600 : R.string.accessibility_feature_state_off); 601 } 602 updateLockScreenRotationCheckbox()603 private void updateLockScreenRotationCheckbox() { 604 Context context = getActivity(); 605 if (context != null) { 606 mToggleLockScreenRotationPreference.setChecked( 607 !RotationPolicy.isRotationLocked(context)); 608 } 609 } 610 loadInstalledServices()611 private void loadInstalledServices() { 612 Set<ComponentName> installedServices = sInstalledServices; 613 installedServices.clear(); 614 615 List<AccessibilityServiceInfo> installedServiceInfos = 616 AccessibilityManager.getInstance(getActivity()) 617 .getInstalledAccessibilityServiceList(); 618 if (installedServiceInfos == null) { 619 return; 620 } 621 622 final int installedServiceInfoCount = installedServiceInfos.size(); 623 for (int i = 0; i < installedServiceInfoCount; i++) { 624 ResolveInfo resolveInfo = installedServiceInfos.get(i).getResolveInfo(); 625 ComponentName installedService = new ComponentName( 626 resolveInfo.serviceInfo.packageName, 627 resolveInfo.serviceInfo.name); 628 installedServices.add(installedService); 629 } 630 } 631 632 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 633 new BaseSearchIndexProvider() { 634 @Override 635 public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { 636 List<SearchIndexableRaw> indexables = new ArrayList<SearchIndexableRaw>(); 637 638 PackageManager packageManager = context.getPackageManager(); 639 AccessibilityManager accessibilityManager = (AccessibilityManager) 640 context.getSystemService(Context.ACCESSIBILITY_SERVICE); 641 642 String screenTitle = context.getResources().getString( 643 R.string.accessibility_services_title); 644 645 // Indexing all services, regardless if enabled. 646 List<AccessibilityServiceInfo> services = accessibilityManager 647 .getInstalledAccessibilityServiceList(); 648 final int serviceCount = services.size(); 649 for (int i = 0; i < serviceCount; i++) { 650 AccessibilityServiceInfo service = services.get(i); 651 if (service == null || service.getResolveInfo() == null) { 652 continue; 653 } 654 655 ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo; 656 ComponentName componentName = new ComponentName(serviceInfo.packageName, 657 serviceInfo.name); 658 659 SearchIndexableRaw indexable = new SearchIndexableRaw(context); 660 indexable.key = componentName.flattenToString(); 661 indexable.title = service.getResolveInfo().loadLabel(packageManager).toString(); 662 indexable.summaryOn = context.getString(R.string.accessibility_feature_state_on); 663 indexable.summaryOff = context.getString(R.string.accessibility_feature_state_off); 664 indexable.screenTitle = screenTitle; 665 indexables.add(indexable); 666 } 667 668 return indexables; 669 } 670 671 @Override 672 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, 673 boolean enabled) { 674 List<SearchIndexableResource> indexables = new ArrayList<SearchIndexableResource>(); 675 SearchIndexableResource indexable = new SearchIndexableResource(context); 676 indexable.xmlResId = R.xml.accessibility_settings; 677 indexables.add(indexable); 678 return indexables; 679 } 680 }; 681 } 682