1 /* 2 * Copyright (C) 2019 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.server.accessibility; 18 19 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO; 20 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE; 21 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN; 22 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN; 23 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD; 24 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK; 25 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; 26 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON; 27 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; 28 import static android.view.accessibility.AccessibilityManager.ShortcutType; 29 30 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; 31 32 import android.accessibilityservice.AccessibilityService.SoftKeyboardShowMode; 33 import android.accessibilityservice.AccessibilityServiceInfo; 34 import android.accessibilityservice.AccessibilityShortcutInfo; 35 import android.annotation.NonNull; 36 import android.annotation.Nullable; 37 import android.content.ComponentName; 38 import android.content.Context; 39 import android.os.Binder; 40 import android.os.RemoteCallbackList; 41 import android.provider.Settings; 42 import android.text.TextUtils; 43 import android.util.ArraySet; 44 import android.util.Slog; 45 import android.view.accessibility.AccessibilityManager; 46 import android.view.accessibility.IAccessibilityManagerClient; 47 48 import com.android.internal.R; 49 import com.android.internal.accessibility.AccessibilityShortcutController; 50 51 import java.io.FileDescriptor; 52 import java.io.PrintWriter; 53 import java.util.ArrayList; 54 import java.util.Arrays; 55 import java.util.Collection; 56 import java.util.HashMap; 57 import java.util.HashSet; 58 import java.util.Iterator; 59 import java.util.List; 60 import java.util.Map; 61 import java.util.Set; 62 63 /** 64 * Class that hold states and settings per user and share between 65 * {@link AccessibilityManagerService} and {@link AccessibilityServiceConnection}. 66 */ 67 class AccessibilityUserState { 68 private static final String LOG_TAG = AccessibilityUserState.class.getSimpleName(); 69 70 final int mUserId; 71 72 // Non-transient state. 73 74 final RemoteCallbackList<IAccessibilityManagerClient> mUserClients = new RemoteCallbackList<>(); 75 76 // Transient state. 77 78 final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>(); 79 80 final Map<ComponentName, AccessibilityServiceConnection> mComponentNameToServiceMap = 81 new HashMap<>(); 82 83 final List<AccessibilityServiceInfo> mInstalledServices = new ArrayList<>(); 84 85 final List<AccessibilityShortcutInfo> mInstalledShortcuts = new ArrayList<>(); 86 87 final Set<ComponentName> mBindingServices = new HashSet<>(); 88 89 final Set<ComponentName> mCrashedServices = new HashSet<>(); 90 91 final Set<ComponentName> mEnabledServices = new HashSet<>(); 92 93 final Set<ComponentName> mTouchExplorationGrantedServices = new HashSet<>(); 94 95 final ArraySet<String> mAccessibilityShortcutKeyTargets = new ArraySet<>(); 96 97 final ArraySet<String> mAccessibilityButtonTargets = new ArraySet<>(); 98 99 private final ServiceInfoChangeListener mServiceInfoChangeListener; 100 101 private ComponentName mServiceChangingSoftKeyboardMode; 102 103 private String mTargetAssignedToAccessibilityButton; 104 105 private boolean mBindInstantServiceAllowed; 106 private boolean mIsAutoclickEnabled; 107 private boolean mIsDisplayMagnificationEnabled; 108 private boolean mIsFilterKeyEventsEnabled; 109 private boolean mIsPerformGesturesEnabled; 110 private boolean mAccessibilityFocusOnlyInActiveWindow; 111 private boolean mIsTextHighContrastEnabled; 112 private boolean mIsTouchExplorationEnabled; 113 private boolean mServiceHandlesDoubleTap; 114 private boolean mRequestMultiFingerGestures; 115 private boolean mRequestTwoFingerPassthrough; 116 private boolean mSendMotionEventsEnabled; 117 private int mUserInteractiveUiTimeout; 118 private int mUserNonInteractiveUiTimeout; 119 private int mNonInteractiveUiTimeout = 0; 120 private int mInteractiveUiTimeout = 0; 121 private int mLastSentClientState = -1; 122 123 /** {@code true} if the device config supports magnification area. */ 124 private final boolean mSupportMagnificationArea; 125 // The magnification mode of default display. 126 private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; 127 // The magnification capabilities used to know magnification mode could be switched. 128 private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; 129 130 /** The stroke width of the focus rectangle in pixels */ 131 private int mFocusStrokeWidth; 132 /** The color of the focus rectangle */ 133 private int mFocusColor; 134 // The default value of the focus stroke width. 135 private final int mFocusStrokeWidthDefaultValue; 136 // The default value of the focus color. 137 private final int mFocusColorDefaultValue; 138 139 private Context mContext; 140 141 @SoftKeyboardShowMode 142 private int mSoftKeyboardShowMode = SHOW_MODE_AUTO; 143 isValidMagnificationModeLocked()144 boolean isValidMagnificationModeLocked() { 145 if (!mSupportMagnificationArea 146 && mMagnificationMode == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { 147 return false; 148 } 149 return (mMagnificationCapabilities & mMagnificationMode) != 0; 150 } 151 152 interface ServiceInfoChangeListener { onServiceInfoChangedLocked(AccessibilityUserState userState)153 void onServiceInfoChangedLocked(AccessibilityUserState userState); 154 } 155 AccessibilityUserState(int userId, @NonNull Context context, @NonNull ServiceInfoChangeListener serviceInfoChangeListener)156 AccessibilityUserState(int userId, @NonNull Context context, 157 @NonNull ServiceInfoChangeListener serviceInfoChangeListener) { 158 mUserId = userId; 159 mContext = context; 160 mServiceInfoChangeListener = serviceInfoChangeListener; 161 mFocusStrokeWidthDefaultValue = mContext.getResources().getDimensionPixelSize( 162 R.dimen.accessibility_focus_highlight_stroke_width); 163 mFocusColorDefaultValue = mContext.getResources().getColor( 164 R.color.accessibility_focus_highlight_color); 165 mFocusStrokeWidth = mFocusStrokeWidthDefaultValue; 166 mFocusColor = mFocusColorDefaultValue; 167 mSupportMagnificationArea = mContext.getResources().getBoolean( 168 R.bool.config_magnification_area); 169 } 170 isHandlingAccessibilityEventsLocked()171 boolean isHandlingAccessibilityEventsLocked() { 172 return !mBoundServices.isEmpty() || !mBindingServices.isEmpty(); 173 } 174 onSwitchToAnotherUserLocked()175 void onSwitchToAnotherUserLocked() { 176 // Unbind all services. 177 unbindAllServicesLocked(); 178 179 // Clear service management state. 180 mBoundServices.clear(); 181 mBindingServices.clear(); 182 mCrashedServices.clear(); 183 184 // Clear event management state. 185 mLastSentClientState = -1; 186 187 // clear UI timeout 188 mNonInteractiveUiTimeout = 0; 189 mInteractiveUiTimeout = 0; 190 191 // Clear state persisted in settings. 192 mEnabledServices.clear(); 193 mTouchExplorationGrantedServices.clear(); 194 mAccessibilityShortcutKeyTargets.clear(); 195 mAccessibilityButtonTargets.clear(); 196 mTargetAssignedToAccessibilityButton = null; 197 mIsTouchExplorationEnabled = false; 198 mServiceHandlesDoubleTap = false; 199 mRequestMultiFingerGestures = false; 200 mRequestTwoFingerPassthrough = false; 201 mSendMotionEventsEnabled = false; 202 mIsDisplayMagnificationEnabled = false; 203 mIsAutoclickEnabled = false; 204 mUserNonInteractiveUiTimeout = 0; 205 mUserInteractiveUiTimeout = 0; 206 mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; 207 mFocusStrokeWidth = mFocusStrokeWidthDefaultValue; 208 mFocusColor = mFocusColorDefaultValue; 209 } 210 addServiceLocked(AccessibilityServiceConnection serviceConnection)211 void addServiceLocked(AccessibilityServiceConnection serviceConnection) { 212 if (!mBoundServices.contains(serviceConnection)) { 213 serviceConnection.onAdded(); 214 mBoundServices.add(serviceConnection); 215 mComponentNameToServiceMap.put(serviceConnection.getComponentName(), serviceConnection); 216 mServiceInfoChangeListener.onServiceInfoChangedLocked(this); 217 } 218 } 219 220 /** 221 * Removes a service. 222 * There are three states to a service here: off, bound, and binding. 223 * This stops tracking the service as bound. 224 * 225 * @param serviceConnection The service. 226 */ removeServiceLocked(AccessibilityServiceConnection serviceConnection)227 void removeServiceLocked(AccessibilityServiceConnection serviceConnection) { 228 mBoundServices.remove(serviceConnection); 229 serviceConnection.onRemoved(); 230 if ((mServiceChangingSoftKeyboardMode != null) 231 && (mServiceChangingSoftKeyboardMode.equals( 232 serviceConnection.getServiceInfo().getComponentName()))) { 233 setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null); 234 } 235 // It may be possible to bind a service twice, which confuses the map. Rebuild the map 236 // to make sure we can still reach a service 237 mComponentNameToServiceMap.clear(); 238 for (int i = 0; i < mBoundServices.size(); i++) { 239 AccessibilityServiceConnection boundClient = mBoundServices.get(i); 240 mComponentNameToServiceMap.put(boundClient.getComponentName(), boundClient); 241 } 242 mServiceInfoChangeListener.onServiceInfoChangedLocked(this); 243 } 244 245 /** 246 * Make sure a services disconnected but still 'on' state is reflected in AccessibilityUserState 247 * There are four states to a service here: off, bound, and binding, and crashed. 248 * This drops a service from a bound state, to the crashed state. 249 * The crashed state describes the situation where a service used to be bound, but no longer is 250 * despite still being enabled. 251 * 252 * @param serviceConnection The service. 253 */ serviceDisconnectedLocked(AccessibilityServiceConnection serviceConnection)254 void serviceDisconnectedLocked(AccessibilityServiceConnection serviceConnection) { 255 removeServiceLocked(serviceConnection); 256 mCrashedServices.add(serviceConnection.getComponentName()); 257 } 258 259 /** 260 * Set the soft keyboard mode. This mode is a bit odd, as it spans multiple settings. 261 * The ACCESSIBILITY_SOFT_KEYBOARD_MODE setting can be checked by the rest of the system 262 * to see if it should suppress showing the IME. The SHOW_IME_WITH_HARD_KEYBOARD setting 263 * setting can be changed by the user, and prevents the system from suppressing the soft 264 * keyboard when the hard keyboard is connected. The hard keyboard setting needs to defer 265 * to the user's preference, if they have supplied one. 266 * 267 * @param newMode The new mode 268 * @param requester The service requesting the change, so we can undo it when the 269 * service stops. Set to null if something other than a service is forcing 270 * the change. 271 * 272 * @return Whether or not the soft keyboard mode equals the new mode after the call 273 */ setSoftKeyboardModeLocked(@oftKeyboardShowMode int newMode, @Nullable ComponentName requester)274 boolean setSoftKeyboardModeLocked(@SoftKeyboardShowMode int newMode, 275 @Nullable ComponentName requester) { 276 if ((newMode != SHOW_MODE_AUTO) 277 && (newMode != SHOW_MODE_HIDDEN) 278 && (newMode != SHOW_MODE_IGNORE_HARD_KEYBOARD)) { 279 Slog.w(LOG_TAG, "Invalid soft keyboard mode"); 280 return false; 281 } 282 if (mSoftKeyboardShowMode == newMode) { 283 return true; 284 } 285 286 if (newMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) { 287 if (hasUserOverriddenHardKeyboardSetting()) { 288 // The user has specified a default for this setting 289 return false; 290 } 291 // Save the original value. But don't do this if the value in settings is already 292 // the new mode. That happens when we start up after a reboot, and we don't want 293 // to overwrite the value we had from when we first started controlling the setting. 294 if (getSoftKeyboardValueFromSettings() != SHOW_MODE_IGNORE_HARD_KEYBOARD) { 295 setOriginalHardKeyboardValue(getSecureIntForUser( 296 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mUserId) != 0); 297 } 298 putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1, mUserId); 299 } else if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) { 300 putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 301 getOriginalHardKeyboardValue() ? 1 : 0, mUserId); 302 } 303 304 saveSoftKeyboardValueToSettings(newMode); 305 mSoftKeyboardShowMode = newMode; 306 mServiceChangingSoftKeyboardMode = requester; 307 for (int i = mBoundServices.size() - 1; i >= 0; i--) { 308 final AccessibilityServiceConnection service = mBoundServices.get(i); 309 service.notifySoftKeyboardShowModeChangedLocked(mSoftKeyboardShowMode); 310 } 311 return true; 312 } 313 314 @SoftKeyboardShowMode getSoftKeyboardShowModeLocked()315 int getSoftKeyboardShowModeLocked() { 316 return mSoftKeyboardShowMode; 317 } 318 319 /** 320 * If the settings are inconsistent with the internal state, make the internal state 321 * match the settings. 322 */ reconcileSoftKeyboardModeWithSettingsLocked()323 void reconcileSoftKeyboardModeWithSettingsLocked() { 324 final boolean showWithHardKeyboardSettings = 325 getSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mUserId) != 0; 326 if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) { 327 if (!showWithHardKeyboardSettings) { 328 // The user has overridden the setting. Respect that and prevent further changes 329 // to this behavior. 330 setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null); 331 setUserOverridesHardKeyboardSetting(); 332 } 333 } 334 335 // If the setting and the internal state are out of sync, set both to default 336 if (getSoftKeyboardValueFromSettings() != mSoftKeyboardShowMode) { 337 Slog.e(LOG_TAG, "Show IME setting inconsistent with internal state. Overwriting"); 338 setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null); 339 putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 340 SHOW_MODE_AUTO, mUserId); 341 } 342 } 343 getBindInstantServiceAllowedLocked()344 boolean getBindInstantServiceAllowedLocked() { 345 return mBindInstantServiceAllowed; 346 } 347 348 /* Need to have a permission check on callee */ setBindInstantServiceAllowedLocked(boolean allowed)349 void setBindInstantServiceAllowedLocked(boolean allowed) { 350 mBindInstantServiceAllowed = allowed; 351 } 352 353 /** 354 * Returns binding service list. 355 */ getBindingServicesLocked()356 Set<ComponentName> getBindingServicesLocked() { 357 return mBindingServices; 358 } 359 360 /** 361 * Returns crashed service list. 362 */ getCrashedServicesLocked()363 Set<ComponentName> getCrashedServicesLocked() { 364 return mCrashedServices; 365 } 366 367 /** 368 * Returns enabled service list. 369 */ getEnabledServicesLocked()370 Set<ComponentName> getEnabledServicesLocked() { 371 return mEnabledServices; 372 } 373 374 /** 375 * Remove service from crashed service list if users disable it. 376 */ updateCrashedServicesIfNeededLocked()377 void updateCrashedServicesIfNeededLocked() { 378 for (int i = 0, count = mInstalledServices.size(); i < count; i++) { 379 final AccessibilityServiceInfo installedService = mInstalledServices.get(i); 380 final ComponentName componentName = ComponentName.unflattenFromString( 381 installedService.getId()); 382 383 if (mCrashedServices.contains(componentName) 384 && !mEnabledServices.contains(componentName)) { 385 // Remove it from mCrashedServices since users toggle the switch bar to retry. 386 mCrashedServices.remove(componentName); 387 } 388 } 389 } 390 getBoundServicesLocked()391 List<AccessibilityServiceConnection> getBoundServicesLocked() { 392 return mBoundServices; 393 } 394 getClientStateLocked(boolean isUiAutomationRunning, int traceClientState)395 int getClientStateLocked(boolean isUiAutomationRunning, int traceClientState) { 396 int clientState = 0; 397 final boolean a11yEnabled = isUiAutomationRunning 398 || isHandlingAccessibilityEventsLocked(); 399 if (a11yEnabled) { 400 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; 401 } 402 // Touch exploration relies on enabled accessibility. 403 if (a11yEnabled && mIsTouchExplorationEnabled) { 404 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; 405 clientState |= AccessibilityManager.STATE_FLAG_DISPATCH_DOUBLE_TAP; 406 clientState |= AccessibilityManager.STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES; 407 } 408 if (mIsTextHighContrastEnabled) { 409 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; 410 } 411 412 clientState |= traceClientState; 413 414 return clientState; 415 } 416 setUserOverridesHardKeyboardSetting()417 private void setUserOverridesHardKeyboardSetting() { 418 final int softKeyboardSetting = getSecureIntForUser( 419 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId); 420 putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 421 softKeyboardSetting | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN, 422 mUserId); 423 } 424 hasUserOverriddenHardKeyboardSetting()425 private boolean hasUserOverriddenHardKeyboardSetting() { 426 final int softKeyboardSetting = getSecureIntForUser( 427 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId); 428 return (softKeyboardSetting & SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN) 429 != 0; 430 } 431 setOriginalHardKeyboardValue(boolean originalHardKeyboardValue)432 private void setOriginalHardKeyboardValue(boolean originalHardKeyboardValue) { 433 final int oldSoftKeyboardSetting = getSecureIntForUser( 434 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId); 435 final int newSoftKeyboardSetting = oldSoftKeyboardSetting 436 & (~SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE) 437 | ((originalHardKeyboardValue) ? SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE : 0); 438 putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 439 newSoftKeyboardSetting, mUserId); 440 } 441 saveSoftKeyboardValueToSettings(int softKeyboardShowMode)442 private void saveSoftKeyboardValueToSettings(int softKeyboardShowMode) { 443 final int oldSoftKeyboardSetting = getSecureIntForUser( 444 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId); 445 final int newSoftKeyboardSetting = oldSoftKeyboardSetting & (~SHOW_MODE_MASK) 446 | softKeyboardShowMode; 447 putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 448 newSoftKeyboardSetting, mUserId); 449 } 450 getSoftKeyboardValueFromSettings()451 private int getSoftKeyboardValueFromSettings() { 452 return getSecureIntForUser( 453 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId) 454 & SHOW_MODE_MASK; 455 } 456 getOriginalHardKeyboardValue()457 private boolean getOriginalHardKeyboardValue() { 458 return (getSecureIntForUser( 459 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId) 460 & SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE) != 0; 461 } 462 unbindAllServicesLocked()463 private void unbindAllServicesLocked() { 464 final List<AccessibilityServiceConnection> services = mBoundServices; 465 for (int count = services.size(); count > 0; count--) { 466 // When the service is unbound, it disappears from the list, so there's no need to 467 // keep track of the index 468 services.get(0).unbindLocked(); 469 } 470 } 471 getSecureIntForUser(String key, int def, int userId)472 private int getSecureIntForUser(String key, int def, int userId) { 473 return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId); 474 } 475 putSecureIntForUser(String key, int value, int userId)476 private void putSecureIntForUser(String key, int value, int userId) { 477 final long identity = Binder.clearCallingIdentity(); 478 try { 479 Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId); 480 } finally { 481 Binder.restoreCallingIdentity(identity); 482 } 483 } 484 dump(FileDescriptor fd, PrintWriter pw, String[] args)485 void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 486 pw.append("User state["); 487 pw.println(); 488 pw.append(" attributes:{id=").append(String.valueOf(mUserId)); 489 pw.append(", touchExplorationEnabled=").append(String.valueOf(mIsTouchExplorationEnabled)); 490 pw.append(", serviceHandlesDoubleTap=") 491 .append(String.valueOf(mServiceHandlesDoubleTap)); 492 pw.append(", requestMultiFingerGestures=") 493 .append(String.valueOf(mRequestMultiFingerGestures)); 494 pw.append(", requestTwoFingerPassthrough=") 495 .append(String.valueOf(mRequestTwoFingerPassthrough)); 496 pw.append(", sendMotionEventsEnabled").append(String.valueOf(mSendMotionEventsEnabled)); 497 pw.append(", displayMagnificationEnabled=").append(String.valueOf( 498 mIsDisplayMagnificationEnabled)); 499 pw.append(", autoclickEnabled=").append(String.valueOf(mIsAutoclickEnabled)); 500 pw.append(", nonInteractiveUiTimeout=").append(String.valueOf(mNonInteractiveUiTimeout)); 501 pw.append(", interactiveUiTimeout=").append(String.valueOf(mInteractiveUiTimeout)); 502 pw.append(", installedServiceCount=").append(String.valueOf(mInstalledServices.size())); 503 pw.append(", magnificationMode=").append(String.valueOf(mMagnificationMode)); 504 pw.append(", magnificationCapabilities=") 505 .append(String.valueOf(mMagnificationCapabilities)); 506 pw.append("}"); 507 pw.println(); 508 pw.append(" shortcut key:{"); 509 int size = mAccessibilityShortcutKeyTargets.size(); 510 for (int i = 0; i < size; i++) { 511 final String componentId = mAccessibilityShortcutKeyTargets.valueAt(i); 512 pw.append(componentId); 513 if (i + 1 < size) { 514 pw.append(", "); 515 } 516 } 517 pw.println("}"); 518 pw.append(" button:{"); 519 size = mAccessibilityButtonTargets.size(); 520 for (int i = 0; i < size; i++) { 521 final String componentId = mAccessibilityButtonTargets.valueAt(i); 522 pw.append(componentId); 523 if (i + 1 < size) { 524 pw.append(", "); 525 } 526 } 527 pw.println("}"); 528 pw.append(" button target:{").append(mTargetAssignedToAccessibilityButton); 529 pw.println("}"); 530 pw.append(" Bound services:{"); 531 final int serviceCount = mBoundServices.size(); 532 for (int j = 0; j < serviceCount; j++) { 533 if (j > 0) { 534 pw.append(", "); 535 pw.println(); 536 pw.append(" "); 537 } 538 AccessibilityServiceConnection service = mBoundServices.get(j); 539 service.dump(fd, pw, args); 540 } 541 pw.println("}"); 542 pw.append(" Enabled services:{"); 543 Iterator<ComponentName> it = mEnabledServices.iterator(); 544 if (it.hasNext()) { 545 ComponentName componentName = it.next(); 546 pw.append(componentName.toShortString()); 547 while (it.hasNext()) { 548 componentName = it.next(); 549 pw.append(", "); 550 pw.append(componentName.toShortString()); 551 } 552 } 553 pw.println("}"); 554 pw.append(" Binding services:{"); 555 it = mBindingServices.iterator(); 556 if (it.hasNext()) { 557 ComponentName componentName = it.next(); 558 pw.append(componentName.toShortString()); 559 while (it.hasNext()) { 560 componentName = it.next(); 561 pw.append(", "); 562 pw.append(componentName.toShortString()); 563 } 564 } 565 pw.println("}"); 566 pw.append(" Crashed services:{"); 567 it = mCrashedServices.iterator(); 568 if (it.hasNext()) { 569 ComponentName componentName = it.next(); 570 pw.append(componentName.toShortString()); 571 while (it.hasNext()) { 572 componentName = it.next(); 573 pw.append(", "); 574 pw.append(componentName.toShortString()); 575 } 576 } 577 pw.println("}"); 578 pw.println(" Client list info:{"); 579 mUserClients.dump(pw, " Client list "); 580 pw.println(" Registered clients:{"); 581 for (int i = 0; i < mUserClients.getRegisteredCallbackCount(); i++) { 582 AccessibilityManagerService.Client client = (AccessibilityManagerService.Client) 583 mUserClients.getRegisteredCallbackCookie(i); 584 pw.append(Arrays.toString(client.mPackageNames)); 585 } 586 pw.println("}]"); 587 } 588 isAutoclickEnabledLocked()589 public boolean isAutoclickEnabledLocked() { 590 return mIsAutoclickEnabled; 591 } 592 setAutoclickEnabledLocked(boolean enabled)593 public void setAutoclickEnabledLocked(boolean enabled) { 594 mIsAutoclickEnabled = enabled; 595 } 596 isDisplayMagnificationEnabledLocked()597 public boolean isDisplayMagnificationEnabledLocked() { 598 return mIsDisplayMagnificationEnabled; 599 } 600 setDisplayMagnificationEnabledLocked(boolean enabled)601 public void setDisplayMagnificationEnabledLocked(boolean enabled) { 602 mIsDisplayMagnificationEnabled = enabled; 603 } 604 isFilterKeyEventsEnabledLocked()605 public boolean isFilterKeyEventsEnabledLocked() { 606 return mIsFilterKeyEventsEnabled; 607 } 608 setFilterKeyEventsEnabledLocked(boolean enabled)609 public void setFilterKeyEventsEnabledLocked(boolean enabled) { 610 mIsFilterKeyEventsEnabled = enabled; 611 } 612 getInteractiveUiTimeoutLocked()613 public int getInteractiveUiTimeoutLocked() { 614 return mInteractiveUiTimeout; 615 } 616 setInteractiveUiTimeoutLocked(int timeout)617 public void setInteractiveUiTimeoutLocked(int timeout) { 618 mInteractiveUiTimeout = timeout; 619 } 620 getLastSentClientStateLocked()621 public int getLastSentClientStateLocked() { 622 return mLastSentClientState; 623 } 624 setLastSentClientStateLocked(int state)625 public void setLastSentClientStateLocked(int state) { 626 mLastSentClientState = state; 627 } 628 629 /** 630 * Returns true if navibar magnification or shortcut key magnification is enabled. 631 */ isShortcutMagnificationEnabledLocked()632 public boolean isShortcutMagnificationEnabledLocked() { 633 return mAccessibilityShortcutKeyTargets.contains(MAGNIFICATION_CONTROLLER_NAME) 634 || mAccessibilityButtonTargets.contains(MAGNIFICATION_CONTROLLER_NAME); 635 } 636 637 /** 638 * Gets the magnification mode of default display. 639 * @return magnification mode 640 * 641 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN 642 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW 643 */ getMagnificationModeLocked()644 public int getMagnificationModeLocked() { 645 return mMagnificationMode; 646 } 647 648 649 /** 650 * Gets the magnification capabilities setting of current user. 651 * 652 * @return magnification capabilities 653 * 654 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN 655 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW 656 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_ALL 657 */ getMagnificationCapabilitiesLocked()658 int getMagnificationCapabilitiesLocked() { 659 return mMagnificationCapabilities; 660 } 661 662 /** 663 * Sets the magnification capabilities from Settings value. 664 * 665 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN 666 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW 667 * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_ALL 668 */ setMagnificationCapabilitiesLocked(int capabilities)669 public void setMagnificationCapabilitiesLocked(int capabilities) { 670 mMagnificationCapabilities = capabilities; 671 } 672 673 /** 674 * Sets the magnification mode of default display. 675 * @param mode The magnification mode. 676 */ setMagnificationModeLocked(int mode)677 public void setMagnificationModeLocked(int mode) { 678 mMagnificationMode = mode; 679 } 680 681 /** 682 * Disable both shortcuts' magnification function. 683 */ disableShortcutMagnificationLocked()684 public void disableShortcutMagnificationLocked() { 685 mAccessibilityShortcutKeyTargets.remove(MAGNIFICATION_CONTROLLER_NAME); 686 mAccessibilityButtonTargets.remove(MAGNIFICATION_CONTROLLER_NAME); 687 } 688 689 /** 690 * Returns a set which contains the flattened component names and the system class names 691 * assigned to the given shortcut. 692 * 693 * @param shortcutType The shortcut type. 694 * @return The array set of the strings 695 */ getShortcutTargetsLocked(@hortcutType int shortcutType)696 public ArraySet<String> getShortcutTargetsLocked(@ShortcutType int shortcutType) { 697 if (shortcutType == ACCESSIBILITY_SHORTCUT_KEY) { 698 return mAccessibilityShortcutKeyTargets; 699 } else if (shortcutType == ACCESSIBILITY_BUTTON) { 700 return mAccessibilityButtonTargets; 701 } 702 return null; 703 } 704 705 /** 706 * Whether or not the given shortcut target is installed in device. 707 * 708 * @param name The shortcut target name 709 * @return true if the shortcut target is installed. 710 */ isShortcutTargetInstalledLocked(String name)711 public boolean isShortcutTargetInstalledLocked(String name) { 712 if (TextUtils.isEmpty(name)) { 713 return false; 714 } 715 if (MAGNIFICATION_CONTROLLER_NAME.equals(name)) { 716 return true; 717 } 718 719 final ComponentName componentName = ComponentName.unflattenFromString(name); 720 if (componentName == null) { 721 return false; 722 } 723 if (AccessibilityShortcutController.getFrameworkShortcutFeaturesMap() 724 .containsKey(componentName)) { 725 return true; 726 } 727 if (getInstalledServiceInfoLocked(componentName) != null) { 728 return true; 729 } 730 for (int i = 0; i < mInstalledShortcuts.size(); i++) { 731 if (mInstalledShortcuts.get(i).getComponentName().equals(componentName)) { 732 return true; 733 } 734 } 735 return false; 736 } 737 738 /** 739 * Removes given shortcut target in the list. 740 * 741 * @param shortcutType The shortcut type. 742 * @param target The component name of the shortcut target. 743 * @return true if the shortcut target is removed. 744 */ removeShortcutTargetLocked(@hortcutType int shortcutType, ComponentName target)745 public boolean removeShortcutTargetLocked(@ShortcutType int shortcutType, 746 ComponentName target) { 747 return getShortcutTargetsLocked(shortcutType).removeIf(name -> { 748 ComponentName componentName; 749 if (name == null 750 || (componentName = ComponentName.unflattenFromString(name)) == null) { 751 return false; 752 } 753 return componentName.equals(target); 754 }); 755 } 756 757 /** 758 * Returns installed accessibility service info by the given service component name. 759 */ getInstalledServiceInfoLocked(ComponentName componentName)760 public AccessibilityServiceInfo getInstalledServiceInfoLocked(ComponentName componentName) { 761 for (int i = 0; i < mInstalledServices.size(); i++) { 762 final AccessibilityServiceInfo serviceInfo = mInstalledServices.get(i); 763 if (serviceInfo.getComponentName().equals(componentName)) { 764 return serviceInfo; 765 } 766 } 767 return null; 768 } 769 770 /** 771 * Returns accessibility service connection by the given service component name. 772 */ getServiceConnectionLocked(ComponentName componentName)773 public AccessibilityServiceConnection getServiceConnectionLocked(ComponentName componentName) { 774 return mComponentNameToServiceMap.get(componentName); 775 } 776 getNonInteractiveUiTimeoutLocked()777 public int getNonInteractiveUiTimeoutLocked() { 778 return mNonInteractiveUiTimeout; 779 } 780 setNonInteractiveUiTimeoutLocked(int timeout)781 public void setNonInteractiveUiTimeoutLocked(int timeout) { 782 mNonInteractiveUiTimeout = timeout; 783 } 784 isPerformGesturesEnabledLocked()785 public boolean isPerformGesturesEnabledLocked() { 786 return mIsPerformGesturesEnabled; 787 } 788 setPerformGesturesEnabledLocked(boolean enabled)789 public void setPerformGesturesEnabledLocked(boolean enabled) { 790 mIsPerformGesturesEnabled = enabled; 791 } 792 isAccessibilityFocusOnlyInActiveWindow()793 public boolean isAccessibilityFocusOnlyInActiveWindow() { 794 return mAccessibilityFocusOnlyInActiveWindow; 795 } 796 setAccessibilityFocusOnlyInActiveWindow(boolean enabled)797 public void setAccessibilityFocusOnlyInActiveWindow(boolean enabled) { 798 mAccessibilityFocusOnlyInActiveWindow = enabled; 799 } getServiceChangingSoftKeyboardModeLocked()800 public ComponentName getServiceChangingSoftKeyboardModeLocked() { 801 return mServiceChangingSoftKeyboardMode; 802 } 803 setServiceChangingSoftKeyboardModeLocked( ComponentName serviceChangingSoftKeyboardMode)804 public void setServiceChangingSoftKeyboardModeLocked( 805 ComponentName serviceChangingSoftKeyboardMode) { 806 mServiceChangingSoftKeyboardMode = serviceChangingSoftKeyboardMode; 807 } 808 isTextHighContrastEnabledLocked()809 public boolean isTextHighContrastEnabledLocked() { 810 return mIsTextHighContrastEnabled; 811 } 812 setTextHighContrastEnabledLocked(boolean enabled)813 public void setTextHighContrastEnabledLocked(boolean enabled) { 814 mIsTextHighContrastEnabled = enabled; 815 } 816 isTouchExplorationEnabledLocked()817 public boolean isTouchExplorationEnabledLocked() { 818 return mIsTouchExplorationEnabled; 819 } 820 setTouchExplorationEnabledLocked(boolean enabled)821 public void setTouchExplorationEnabledLocked(boolean enabled) { 822 mIsTouchExplorationEnabled = enabled; 823 } 824 isServiceHandlesDoubleTapEnabledLocked()825 public boolean isServiceHandlesDoubleTapEnabledLocked() { 826 return mServiceHandlesDoubleTap; 827 } 828 setServiceHandlesDoubleTapLocked(boolean enabled)829 public void setServiceHandlesDoubleTapLocked(boolean enabled) { 830 mServiceHandlesDoubleTap = enabled; 831 } 832 isMultiFingerGesturesEnabledLocked()833 public boolean isMultiFingerGesturesEnabledLocked() { 834 return mRequestMultiFingerGestures; 835 } 836 setMultiFingerGesturesLocked(boolean enabled)837 public void setMultiFingerGesturesLocked(boolean enabled) { 838 mRequestMultiFingerGestures = enabled; 839 } isTwoFingerPassthroughEnabledLocked()840 public boolean isTwoFingerPassthroughEnabledLocked() { 841 return mRequestTwoFingerPassthrough; 842 } 843 setTwoFingerPassthroughLocked(boolean enabled)844 public void setTwoFingerPassthroughLocked(boolean enabled) { 845 mRequestTwoFingerPassthrough = enabled; 846 } 847 isSendMotionEventsEnabled()848 public boolean isSendMotionEventsEnabled() { 849 return mSendMotionEventsEnabled; 850 } 851 setSendMotionEventsEnabled(boolean mode)852 public void setSendMotionEventsEnabled(boolean mode) { 853 mSendMotionEventsEnabled = mode; 854 } 855 getUserInteractiveUiTimeoutLocked()856 public int getUserInteractiveUiTimeoutLocked() { 857 return mUserInteractiveUiTimeout; 858 } 859 setUserInteractiveUiTimeoutLocked(int timeout)860 public void setUserInteractiveUiTimeoutLocked(int timeout) { 861 mUserInteractiveUiTimeout = timeout; 862 } 863 getUserNonInteractiveUiTimeoutLocked()864 public int getUserNonInteractiveUiTimeoutLocked() { 865 return mUserNonInteractiveUiTimeout; 866 } 867 setUserNonInteractiveUiTimeoutLocked(int timeout)868 public void setUserNonInteractiveUiTimeoutLocked(int timeout) { 869 mUserNonInteractiveUiTimeout = timeout; 870 } 871 872 /** 873 * Gets a shortcut target which is assigned to the accessibility button by the chooser 874 * activity. 875 * 876 * @return The flattened component name or the system class name of the shortcut target. 877 */ getTargetAssignedToAccessibilityButton()878 public String getTargetAssignedToAccessibilityButton() { 879 return mTargetAssignedToAccessibilityButton; 880 } 881 882 /** 883 * Sets a shortcut target which is assigned to the accessibility button by the chooser 884 * activity. 885 * 886 * @param target The flattened component name or the system class name of the shortcut target. 887 */ setTargetAssignedToAccessibilityButton(String target)888 public void setTargetAssignedToAccessibilityButton(String target) { 889 mTargetAssignedToAccessibilityButton = target; 890 } 891 892 /** 893 * Whether or not the given target name is contained in the shortcut collection. Since the 894 * component name string format could be short or long, this function un-flatten the component 895 * name from the string in {@code shortcutTargets} and compared with the given target name. 896 * 897 * @param shortcutTargets The shortcut type. 898 * @param targetName The target name. 899 * @return {@code true} if the target is in the shortcut collection. 900 */ doesShortcutTargetsStringContain(Collection<String> shortcutTargets, String targetName)901 public static boolean doesShortcutTargetsStringContain(Collection<String> shortcutTargets, 902 String targetName) { 903 if (shortcutTargets == null || targetName == null) { 904 return false; 905 } 906 // Some system features, such as magnification, don't have component name. Using string 907 // compare first. 908 if (shortcutTargets.contains(targetName)) { 909 return true; 910 } 911 final ComponentName targetComponentName = ComponentName.unflattenFromString(targetName); 912 if (targetComponentName == null) { 913 return false; 914 } 915 for (String stringName : shortcutTargets) { 916 if (!TextUtils.isEmpty(stringName) 917 && targetComponentName.equals(ComponentName.unflattenFromString(stringName))) { 918 return true; 919 } 920 } 921 return false; 922 } 923 924 /** 925 * Gets the stroke width of the focus rectangle. 926 * @return The stroke width. 927 */ getFocusStrokeWidthLocked()928 public int getFocusStrokeWidthLocked() { 929 return mFocusStrokeWidth; 930 } 931 932 /** 933 * Gets the color of the focus rectangle. 934 * @return The color. 935 */ getFocusColorLocked()936 public int getFocusColorLocked() { 937 return mFocusColor; 938 } 939 940 /** 941 * Sets the stroke width and color of the focus rectangle. 942 * 943 * @param strokeWidth The strokeWidth of the focus rectangle. 944 * @param color The color of the focus rectangle. 945 */ setFocusAppearanceLocked(int strokeWidth, int color)946 public void setFocusAppearanceLocked(int strokeWidth, int color) { 947 mFocusStrokeWidth = strokeWidth; 948 mFocusColor = color; 949 } 950 } 951