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