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