1 /* 2 ** Copyright 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.server.accessibility; 18 19 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; 20 import static android.view.Display.DEFAULT_DISPLAY; 21 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 22 23 import android.Manifest; 24 import android.accessibilityservice.AccessibilityService; 25 import android.accessibilityservice.AccessibilityServiceInfo; 26 import android.accessibilityservice.GestureDescription; 27 import android.accessibilityservice.IAccessibilityServiceClient; 28 import android.accessibilityservice.IAccessibilityServiceConnection; 29 import android.annotation.NonNull; 30 import android.app.AlertDialog; 31 import android.app.PendingIntent; 32 import android.app.StatusBarManager; 33 import android.app.UiAutomation; 34 import android.content.BroadcastReceiver; 35 import android.content.ComponentName; 36 import android.content.ContentResolver; 37 import android.content.Context; 38 import android.content.DialogInterface; 39 import android.content.DialogInterface.OnClickListener; 40 import android.content.Intent; 41 import android.content.IntentFilter; 42 import android.content.ServiceConnection; 43 import android.content.pm.PackageManager; 44 import android.content.pm.ParceledListSlice; 45 import android.content.pm.ResolveInfo; 46 import android.content.pm.ServiceInfo; 47 import android.content.pm.UserInfo; 48 import android.database.ContentObserver; 49 import android.graphics.Point; 50 import android.graphics.Rect; 51 import android.graphics.Region; 52 import android.hardware.display.DisplayManager; 53 import android.hardware.fingerprint.IFingerprintService; 54 import android.hardware.input.InputManager; 55 import android.media.AudioManagerInternal; 56 import android.net.Uri; 57 import android.os.Binder; 58 import android.os.Build; 59 import android.os.Bundle; 60 import android.os.Handler; 61 import android.os.IBinder; 62 import android.os.Looper; 63 import android.os.Message; 64 import android.os.PowerManager; 65 import android.os.Process; 66 import android.os.RemoteCallbackList; 67 import android.os.RemoteException; 68 import android.os.ServiceManager; 69 import android.os.SystemClock; 70 import android.os.UserHandle; 71 import android.os.UserManager; 72 import android.os.UserManagerInternal; 73 import android.provider.Settings; 74 import android.provider.SettingsStringUtil; 75 import android.provider.SettingsStringUtil.ComponentNameSet; 76 import android.provider.SettingsStringUtil.SettingStringHelper; 77 import android.text.TextUtils; 78 import android.text.TextUtils.SimpleStringSplitter; 79 import android.util.IntArray; 80 import android.util.Slog; 81 import android.util.SparseArray; 82 import android.view.Display; 83 import android.view.IWindow; 84 import android.view.InputDevice; 85 import android.view.KeyCharacterMap; 86 import android.view.KeyEvent; 87 import android.view.MagnificationSpec; 88 import android.view.View; 89 import android.view.WindowInfo; 90 import android.view.WindowManager; 91 import android.view.WindowManagerInternal; 92 import android.view.accessibility.AccessibilityCache; 93 import android.view.accessibility.AccessibilityEvent; 94 import android.view.accessibility.AccessibilityInteractionClient; 95 import android.view.accessibility.AccessibilityManager; 96 import android.view.accessibility.AccessibilityNodeInfo; 97 import android.view.accessibility.AccessibilityWindowInfo; 98 import android.view.accessibility.IAccessibilityInteractionConnection; 99 import android.view.accessibility.IAccessibilityInteractionConnectionCallback; 100 import android.view.accessibility.IAccessibilityManager; 101 import android.view.accessibility.IAccessibilityManagerClient; 102 103 import com.android.internal.R; 104 import com.android.internal.annotations.GuardedBy; 105 import com.android.internal.content.PackageMonitor; 106 import com.android.internal.os.SomeArgs; 107 import com.android.internal.util.DumpUtils; 108 import com.android.internal.util.IntPair; 109 import com.android.server.LocalServices; 110 import com.android.server.policy.AccessibilityShortcutController; 111 import com.android.server.statusbar.StatusBarManagerInternal; 112 113 import org.xmlpull.v1.XmlPullParserException; 114 115 import java.io.FileDescriptor; 116 import java.io.IOException; 117 import java.io.PrintWriter; 118 import java.util.ArrayList; 119 import java.util.Arrays; 120 import java.util.Collections; 121 import java.util.HashMap; 122 import java.util.HashSet; 123 import java.util.Iterator; 124 import java.util.List; 125 import java.util.Map; 126 import java.util.Set; 127 import java.util.concurrent.CopyOnWriteArrayList; 128 import java.util.function.Consumer; 129 130 /** 131 * This class is instantiated by the system as a system level service and can be 132 * accessed only by the system. The task of this service is to be a centralized 133 * event dispatch for {@link AccessibilityEvent}s generated across all processes 134 * on the device. Events are dispatched to {@link AccessibilityService}s. 135 */ 136 public class AccessibilityManagerService extends IAccessibilityManager.Stub { 137 138 private static final boolean DEBUG = false; 139 140 private static final String LOG_TAG = "AccessibilityManagerService"; 141 142 // TODO: This is arbitrary. When there is time implement this by watching 143 // when that accessibility services are bound. 144 private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000; 145 146 private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000; 147 148 // TODO: Restructure service initialization so services aren't connected before all of 149 // their capabilities are ready. 150 private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000; 151 152 private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = 153 "registerUiTestAutomationService"; 154 155 private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED = 156 "temporaryEnableAccessibilityStateUntilKeyguardRemoved"; 157 158 private static final String GET_WINDOW_TOKEN = "getWindowToken"; 159 160 private static final String SET_PIP_ACTION_REPLACEMENT = 161 "setPictureInPictureActionReplacingConnection"; 162 163 private static final ComponentName sFakeAccessibilityServiceComponentName = 164 new ComponentName("foo.bar", "FakeService"); 165 166 private static final String FUNCTION_DUMP = "dump"; 167 168 private static final char COMPONENT_NAME_SEPARATOR = ':'; 169 170 private static final int OWN_PROCESS_ID = android.os.Process.myPid(); 171 172 // Each service has an ID. Also provide one for magnification gesture handling 173 public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0; 174 175 private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1; 176 177 private static int sNextWindowId; 178 179 private final Context mContext; 180 181 private final Object mLock = new Object(); 182 183 private final SimpleStringSplitter mStringColonSplitter = 184 new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); 185 186 private final Rect mTempRect = new Rect(); 187 188 private final Rect mTempRect1 = new Rect(); 189 190 private final Point mTempPoint = new Point(); 191 192 private final PackageManager mPackageManager; 193 194 private final PowerManager mPowerManager; 195 196 private final WindowManagerInternal mWindowManagerService; 197 198 private final SecurityPolicy mSecurityPolicy; 199 200 private final MainHandler mMainHandler; 201 202 private MagnificationController mMagnificationController; 203 204 private InteractionBridge mInteractionBridge; 205 206 private AlertDialog mEnableTouchExplorationDialog; 207 208 private AccessibilityInputFilter mInputFilter; 209 210 private boolean mHasInputFilter; 211 212 private KeyEventDispatcher mKeyEventDispatcher; 213 214 private MotionEventInjector mMotionEventInjector; 215 216 private FingerprintGestureDispatcher mFingerprintGestureDispatcher; 217 218 private final Set<ComponentName> mTempComponentNameSet = new HashSet<>(); 219 220 private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList = 221 new ArrayList<>(); 222 223 private final IntArray mTempIntArray = new IntArray(0); 224 225 private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients = 226 new RemoteCallbackList<>(); 227 228 private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections = 229 new SparseArray<>(); 230 231 private AccessibilityConnectionWrapper mPictureInPictureActionReplacingConnection; 232 233 private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>(); 234 235 private final SparseArray<UserState> mUserStates = new SparseArray<>(); 236 237 private final UserManager mUserManager; 238 239 private int mCurrentUserId = UserHandle.USER_SYSTEM; 240 241 //TODO: Remove this hack 242 private boolean mInitialized; 243 244 private WindowsForAccessibilityCallback mWindowsForAccessibilityCallback; 245 246 private boolean mIsAccessibilityButtonShown; 247 getCurrentUserStateLocked()248 private UserState getCurrentUserStateLocked() { 249 return getUserStateLocked(mCurrentUserId); 250 } 251 252 /** 253 * Creates a new instance. 254 * 255 * @param context A {@link Context} instance. 256 */ AccessibilityManagerService(Context context)257 public AccessibilityManagerService(Context context) { 258 mContext = context; 259 mPackageManager = mContext.getPackageManager(); 260 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 261 mWindowManagerService = LocalServices.getService(WindowManagerInternal.class); 262 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 263 mSecurityPolicy = new SecurityPolicy(); 264 mMainHandler = new MainHandler(mContext.getMainLooper()); 265 registerBroadcastReceivers(); 266 new AccessibilityContentObserver(mMainHandler).register( 267 context.getContentResolver()); 268 } 269 getUserStateLocked(int userId)270 private UserState getUserStateLocked(int userId) { 271 UserState state = mUserStates.get(userId); 272 if (state == null) { 273 state = new UserState(userId); 274 mUserStates.put(userId, state); 275 } 276 return state; 277 } 278 registerBroadcastReceivers()279 private void registerBroadcastReceivers() { 280 PackageMonitor monitor = new PackageMonitor() { 281 @Override 282 public void onSomePackagesChanged() { 283 synchronized (mLock) { 284 // Only the profile parent can install accessibility services. 285 // Therefore we ignore packages from linked profiles. 286 if (getChangingUserId() != mCurrentUserId) { 287 return; 288 } 289 // We will update when the automation service dies. 290 UserState userState = getCurrentUserStateLocked(); 291 // We have to reload the installed services since some services may 292 // have different attributes, resolve info (does not support equals), 293 // etc. Remove them then to force reload. 294 userState.mInstalledServices.clear(); 295 if (!userState.isUiAutomationSuppressingOtherServices()) { 296 if (readConfigurationForUserStateLocked(userState)) { 297 onUserStateChangedLocked(userState); 298 } 299 } 300 } 301 } 302 303 @Override 304 public void onPackageUpdateFinished(String packageName, int uid) { 305 // Unbind all services from this package, and then update the user state to 306 // re-bind new versions of them. 307 synchronized (mLock) { 308 final int userId = getChangingUserId(); 309 if (userId != mCurrentUserId) { 310 return; 311 } 312 UserState userState = getUserStateLocked(userId); 313 boolean unboundAService = false; 314 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 315 Service boundService = userState.mBoundServices.get(i); 316 String servicePkg = boundService.mComponentName.getPackageName(); 317 if (servicePkg.equals(packageName)) { 318 boundService.unbindLocked(); 319 unboundAService = true; 320 } 321 } 322 if (unboundAService) { 323 onUserStateChangedLocked(userState); 324 } 325 } 326 } 327 328 @Override 329 public void onPackageRemoved(String packageName, int uid) { 330 synchronized (mLock) { 331 final int userId = getChangingUserId(); 332 // Only the profile parent can install accessibility services. 333 // Therefore we ignore packages from linked profiles. 334 if (userId != mCurrentUserId) { 335 return; 336 } 337 UserState userState = getUserStateLocked(userId); 338 Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 339 while (it.hasNext()) { 340 ComponentName comp = it.next(); 341 String compPkg = comp.getPackageName(); 342 if (compPkg.equals(packageName)) { 343 it.remove(); 344 // Update the enabled services setting. 345 persistComponentNamesToSettingLocked( 346 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 347 userState.mEnabledServices, userId); 348 // Update the touch exploration granted services setting. 349 userState.mTouchExplorationGrantedServices.remove(comp); 350 persistComponentNamesToSettingLocked( 351 Settings.Secure. 352 TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 353 userState.mTouchExplorationGrantedServices, userId); 354 // We will update when the automation service dies. 355 if (!userState.isUiAutomationSuppressingOtherServices()) { 356 onUserStateChangedLocked(userState); 357 } 358 return; 359 } 360 } 361 } 362 } 363 364 @Override 365 public boolean onHandleForceStop(Intent intent, String[] packages, 366 int uid, boolean doit) { 367 synchronized (mLock) { 368 final int userId = getChangingUserId(); 369 // Only the profile parent can install accessibility services. 370 // Therefore we ignore packages from linked profiles. 371 if (userId != mCurrentUserId) { 372 return false; 373 } 374 UserState userState = getUserStateLocked(userId); 375 Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 376 while (it.hasNext()) { 377 ComponentName comp = it.next(); 378 String compPkg = comp.getPackageName(); 379 for (String pkg : packages) { 380 if (compPkg.equals(pkg)) { 381 if (!doit) { 382 return true; 383 } 384 it.remove(); 385 persistComponentNamesToSettingLocked( 386 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 387 userState.mEnabledServices, userId); 388 // We will update when the automation service dies. 389 if (!userState.isUiAutomationSuppressingOtherServices()) { 390 onUserStateChangedLocked(userState); 391 } 392 } 393 } 394 } 395 return false; 396 } 397 } 398 }; 399 400 // package changes 401 monitor.register(mContext, null, UserHandle.ALL, true); 402 403 // user change and unlock 404 IntentFilter intentFilter = new IntentFilter(); 405 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 406 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); 407 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 408 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 409 intentFilter.addAction(Intent.ACTION_SETTING_RESTORED); 410 411 mContext.registerReceiverAsUser(new BroadcastReceiver() { 412 @Override 413 public void onReceive(Context context, Intent intent) { 414 String action = intent.getAction(); 415 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 416 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 417 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { 418 unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 419 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 420 removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 421 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { 422 // We will update when the automation service dies. 423 synchronized (mLock) { 424 UserState userState = getCurrentUserStateLocked(); 425 if (!userState.isUiAutomationSuppressingOtherServices()) { 426 if (readConfigurationForUserStateLocked(userState)) { 427 onUserStateChangedLocked(userState); 428 } 429 } 430 } 431 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { 432 final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); 433 if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) { 434 synchronized (mLock) { 435 restoreEnabledAccessibilityServicesLocked( 436 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE), 437 intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)); 438 } 439 } 440 } 441 } 442 }, UserHandle.ALL, intentFilter, null, null); 443 } 444 445 @Override addClient(IAccessibilityManagerClient client, int userId)446 public long addClient(IAccessibilityManagerClient client, int userId) { 447 synchronized (mLock) { 448 // We treat calls from a profile as if made by its parent as profiles 449 // share the accessibility state of the parent. The call below 450 // performs the current profile parent resolution. 451 final int resolvedUserId = mSecurityPolicy 452 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 453 // If the client is from a process that runs across users such as 454 // the system UI or the system we add it to the global state that 455 // is shared across users. 456 UserState userState = getUserStateLocked(resolvedUserId); 457 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 458 mGlobalClients.register(client); 459 if (DEBUG) { 460 Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid()); 461 } 462 return IntPair.of( 463 userState.getClientState(), userState.mLastSentRelevantEventTypes); 464 } else { 465 userState.mUserClients.register(client); 466 // If this client is not for the current user we do not 467 // return a state since it is not for the foreground user. 468 // We will send the state to the client on a user switch. 469 if (DEBUG) { 470 Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid() 471 + " and userId:" + mCurrentUserId); 472 } 473 return IntPair.of( 474 (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0, 475 userState.mLastSentRelevantEventTypes); 476 } 477 } 478 } 479 480 @Override sendAccessibilityEvent(AccessibilityEvent event, int userId)481 public void sendAccessibilityEvent(AccessibilityEvent event, int userId) { 482 boolean dispatchEvent = false; 483 484 synchronized (mLock) { 485 if (event.getWindowId() == 486 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) { 487 // The replacer window isn't shown to services. Move its events into the pip. 488 AccessibilityWindowInfo pip = mSecurityPolicy.getPictureInPictureWindow(); 489 if (pip != null) { 490 int pipId = pip.getId(); 491 event.setWindowId(pipId); 492 event.setSealed(true); 493 AccessibilityNodeInfo info = event.getSource(); 494 info.setSealed(false); 495 event.setSealed(false); 496 if (info != null) { 497 info.setSourceNodeId(info.getSourceNodeId(), pipId); 498 event.setSource(info); 499 info.recycle(); 500 } 501 } 502 } 503 504 // We treat calls from a profile as if made by its parent as profiles 505 // share the accessibility state of the parent. The call below 506 // performs the current profile parent resolution.. 507 final int resolvedUserId = mSecurityPolicy 508 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 509 // This method does nothing for a background user. 510 if (resolvedUserId == mCurrentUserId) { 511 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) { 512 mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked( 513 event.getWindowId(), event.getSourceNodeId(), 514 event.getEventType(), event.getAction()); 515 mSecurityPolicy.updateEventSourceLocked(event); 516 dispatchEvent = true; 517 } 518 if (mHasInputFilter && mInputFilter != null) { 519 mMainHandler.obtainMessage( 520 MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER, 521 AccessibilityEvent.obtain(event)).sendToTarget(); 522 } 523 } 524 } 525 526 if (dispatchEvent) { 527 // Make sure clients receiving this event will be able to get the 528 // current state of the windows as the window manager may be delaying 529 // the computation for performance reasons. 530 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 531 && mWindowsForAccessibilityCallback != null) { 532 WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class); 533 wm.computeWindowsForAccessibility(); 534 } 535 synchronized (mLock) { 536 notifyAccessibilityServicesDelayedLocked(event, false); 537 notifyAccessibilityServicesDelayedLocked(event, true); 538 } 539 } 540 541 if (OWN_PROCESS_ID != Binder.getCallingPid()) { 542 event.recycle(); 543 } 544 } 545 546 @Override getInstalledAccessibilityServiceList(int userId)547 public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) { 548 synchronized (mLock) { 549 // We treat calls from a profile as if made by its parent as profiles 550 // share the accessibility state of the parent. The call below 551 // performs the current profile parent resolution. 552 final int resolvedUserId = mSecurityPolicy 553 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 554 // The automation service is a fake one and should not be reported 555 // to clients as being installed - it really is not. 556 UserState userState = getUserStateLocked(resolvedUserId); 557 if (userState.mUiAutomationService != null) { 558 List<AccessibilityServiceInfo> installedServices = new ArrayList<>(); 559 installedServices.addAll(userState.mInstalledServices); 560 installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo); 561 return installedServices; 562 } 563 return userState.mInstalledServices; 564 } 565 } 566 567 @Override getEnabledAccessibilityServiceList(int feedbackType, int userId)568 public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, 569 int userId) { 570 synchronized (mLock) { 571 // We treat calls from a profile as if made by its parent as profiles 572 // share the accessibility state of the parent. The call below 573 // performs the current profile parent resolution. 574 final int resolvedUserId = mSecurityPolicy 575 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 576 577 // The automation service can suppress other services. 578 final UserState userState = getUserStateLocked(resolvedUserId); 579 if (userState.isUiAutomationSuppressingOtherServices()) { 580 return Collections.emptyList(); 581 } 582 583 final List<Service> services = userState.mBoundServices; 584 final int serviceCount = services.size(); 585 final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount); 586 for (int i = 0; i < serviceCount; ++i) { 587 final Service service = services.get(i); 588 // Don't report the UIAutomation (fake service) 589 if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName) 590 && (service.mFeedbackType & feedbackType) != 0) { 591 result.add(service.mAccessibilityServiceInfo); 592 } 593 } 594 return result; 595 } 596 } 597 598 @Override interrupt(int userId)599 public void interrupt(int userId) { 600 List<IAccessibilityServiceClient> interfacesToInterrupt; 601 synchronized (mLock) { 602 // We treat calls from a profile as if made by its parent as profiles 603 // share the accessibility state of the parent. The call below 604 // performs the current profile parent resolution. 605 final int resolvedUserId = mSecurityPolicy 606 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 607 // This method does nothing for a background user. 608 if (resolvedUserId != mCurrentUserId) { 609 return; 610 } 611 List<Service> services = getUserStateLocked(resolvedUserId).mBoundServices; 612 int numServices = services.size(); 613 interfacesToInterrupt = new ArrayList<>(numServices); 614 for (int i = 0; i < numServices; i++) { 615 Service service = services.get(i); 616 IBinder a11yServiceBinder = service.mService; 617 IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface; 618 if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) { 619 interfacesToInterrupt.add(a11yServiceInterface); 620 } 621 } 622 } 623 for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) { 624 try { 625 interfacesToInterrupt.get(i).onInterrupt(); 626 } catch (RemoteException re) { 627 Slog.e(LOG_TAG, "Error sending interrupt request to " 628 + interfacesToInterrupt.get(i), re); 629 } 630 } 631 } 632 633 @Override addAccessibilityInteractionConnection(IWindow windowToken, IAccessibilityInteractionConnection connection, int userId)634 public int addAccessibilityInteractionConnection(IWindow windowToken, 635 IAccessibilityInteractionConnection connection, int userId) throws RemoteException { 636 synchronized (mLock) { 637 // We treat calls from a profile as if made by its parent as profiles 638 // share the accessibility state of the parent. The call below 639 // performs the current profile parent resolution. 640 final int resolvedUserId = mSecurityPolicy 641 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 642 final int windowId = sNextWindowId++; 643 // If the window is from a process that runs across users such as 644 // the system UI or the system we add it to the global state that 645 // is shared across users. 646 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 647 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 648 windowId, connection, UserHandle.USER_ALL); 649 wrapper.linkToDeath(); 650 mGlobalInteractionConnections.put(windowId, wrapper); 651 mGlobalWindowTokens.put(windowId, windowToken.asBinder()); 652 if (DEBUG) { 653 Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid() 654 + " with windowId: " + windowId + " and token: " + windowToken.asBinder()); 655 } 656 } else { 657 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 658 windowId, connection, resolvedUserId); 659 wrapper.linkToDeath(); 660 UserState userState = getUserStateLocked(resolvedUserId); 661 userState.mInteractionConnections.put(windowId, wrapper); 662 userState.mWindowTokens.put(windowId, windowToken.asBinder()); 663 if (DEBUG) { 664 Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid() 665 + " with windowId: " + windowId + " and userId:" + mCurrentUserId 666 + " and token: " + windowToken.asBinder()); 667 } 668 } 669 return windowId; 670 } 671 } 672 673 @Override removeAccessibilityInteractionConnection(IWindow window)674 public void removeAccessibilityInteractionConnection(IWindow window) { 675 synchronized (mLock) { 676 // We treat calls from a profile as if made by its parent as profiles 677 // share the accessibility state of the parent. The call below 678 // performs the current profile parent resolution. 679 mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( 680 UserHandle.getCallingUserId()); 681 IBinder token = window.asBinder(); 682 final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked( 683 token, mGlobalWindowTokens, mGlobalInteractionConnections); 684 if (removedWindowId >= 0) { 685 if (DEBUG) { 686 Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid() 687 + " with windowId: " + removedWindowId + " and token: " + window.asBinder()); 688 } 689 return; 690 } 691 final int userCount = mUserStates.size(); 692 for (int i = 0; i < userCount; i++) { 693 UserState userState = mUserStates.valueAt(i); 694 final int removedWindowIdForUser = 695 removeAccessibilityInteractionConnectionInternalLocked( 696 token, userState.mWindowTokens, userState.mInteractionConnections); 697 if (removedWindowIdForUser >= 0) { 698 if (DEBUG) { 699 Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid() 700 + " with windowId: " + removedWindowIdForUser + " and userId:" 701 + mUserStates.keyAt(i) + " and token: " + window.asBinder()); 702 } 703 return; 704 } 705 } 706 } 707 } 708 removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, SparseArray<IBinder> windowTokens, SparseArray<AccessibilityConnectionWrapper> interactionConnections)709 private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, 710 SparseArray<IBinder> windowTokens, 711 SparseArray<AccessibilityConnectionWrapper> interactionConnections) { 712 final int count = windowTokens.size(); 713 for (int i = 0; i < count; i++) { 714 if (windowTokens.valueAt(i) == windowToken) { 715 final int windowId = windowTokens.keyAt(i); 716 windowTokens.removeAt(i); 717 AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId); 718 wrapper.unlinkToDeath(); 719 interactionConnections.remove(windowId); 720 return windowId; 721 } 722 } 723 return -1; 724 } 725 726 @Override setPictureInPictureActionReplacingConnection( IAccessibilityInteractionConnection connection)727 public void setPictureInPictureActionReplacingConnection( 728 IAccessibilityInteractionConnection connection) throws RemoteException { 729 mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA, 730 SET_PIP_ACTION_REPLACEMENT); 731 synchronized (mLock) { 732 if (mPictureInPictureActionReplacingConnection != null) { 733 mPictureInPictureActionReplacingConnection.unlinkToDeath(); 734 mPictureInPictureActionReplacingConnection = null; 735 } 736 if (connection != null) { 737 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 738 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID, 739 connection, UserHandle.USER_ALL); 740 mPictureInPictureActionReplacingConnection = wrapper; 741 wrapper.linkToDeath(); 742 } 743 mSecurityPolicy.notifyWindowsChanged(); 744 } 745 } 746 747 @Override registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient serviceClient, AccessibilityServiceInfo accessibilityServiceInfo, int flags)748 public void registerUiTestAutomationService(IBinder owner, 749 IAccessibilityServiceClient serviceClient, 750 AccessibilityServiceInfo accessibilityServiceInfo, 751 int flags) { 752 mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, 753 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE); 754 755 accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName); 756 757 synchronized (mLock) { 758 UserState userState = getCurrentUserStateLocked(); 759 760 if (userState.mUiAutomationService != null) { 761 throw new IllegalStateException("UiAutomationService " + serviceClient 762 + "already registered!"); 763 } 764 765 try { 766 owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0); 767 } catch (RemoteException re) { 768 Slog.e(LOG_TAG, "Couldn't register for the death of a" 769 + " UiTestAutomationService!", re); 770 return; 771 } 772 773 userState.mUiAutomationServiceOwner = owner; 774 userState.mUiAutomationServiceClient = serviceClient; 775 userState.mUiAutomationFlags = flags; 776 userState.mInstalledServices.add(accessibilityServiceInfo); 777 if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) { 778 // Set the temporary state, and use it instead of settings 779 userState.mIsTouchExplorationEnabled = false; 780 userState.mIsDisplayMagnificationEnabled = false; 781 userState.mIsNavBarMagnificationEnabled = false; 782 userState.mIsAutoclickEnabled = false; 783 userState.mEnabledServices.clear(); 784 } 785 userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); 786 userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName); 787 788 // Use the new state instead of settings. 789 onUserStateChangedLocked(userState); 790 } 791 } 792 793 @Override unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient)794 public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) { 795 synchronized (mLock) { 796 UserState userState = getCurrentUserStateLocked(); 797 // Automation service is not bound, so pretend it died to perform clean up. 798 if (userState.mUiAutomationService != null 799 && serviceClient != null 800 && userState.mUiAutomationService.mServiceInterface != null 801 && userState.mUiAutomationService.mServiceInterface.asBinder() 802 == serviceClient.asBinder()) { 803 userState.mUiAutomationService.binderDied(); 804 } else { 805 throw new IllegalStateException("UiAutomationService " + serviceClient 806 + " not registered!"); 807 } 808 } 809 } 810 811 @Override temporaryEnableAccessibilityStateUntilKeyguardRemoved( ComponentName service, boolean touchExplorationEnabled)812 public void temporaryEnableAccessibilityStateUntilKeyguardRemoved( 813 ComponentName service, boolean touchExplorationEnabled) { 814 mSecurityPolicy.enforceCallingPermission( 815 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY, 816 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED); 817 if (!mWindowManagerService.isKeyguardLocked()) { 818 return; 819 } 820 synchronized (mLock) { 821 // Set the temporary state. 822 UserState userState = getCurrentUserStateLocked(); 823 824 // This is a nop if UI automation is enabled. 825 if (userState.isUiAutomationSuppressingOtherServices()) { 826 return; 827 } 828 829 userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 830 userState.mIsDisplayMagnificationEnabled = false; 831 userState.mIsNavBarMagnificationEnabled = false; 832 userState.mIsAutoclickEnabled = false; 833 userState.mEnabledServices.clear(); 834 userState.mEnabledServices.add(service); 835 userState.mBindingServices.clear(); 836 userState.mTouchExplorationGrantedServices.clear(); 837 userState.mTouchExplorationGrantedServices.add(service); 838 839 // User the current state instead settings. 840 onUserStateChangedLocked(userState); 841 } 842 } 843 844 @Override getWindowToken(int windowId, int userId)845 public IBinder getWindowToken(int windowId, int userId) { 846 mSecurityPolicy.enforceCallingPermission( 847 Manifest.permission.RETRIEVE_WINDOW_TOKEN, 848 GET_WINDOW_TOKEN); 849 synchronized (mLock) { 850 // We treat calls from a profile as if made by its parent as profiles 851 // share the accessibility state of the parent. The call below 852 // performs the current profile parent resolution. 853 final int resolvedUserId = mSecurityPolicy 854 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 855 if (resolvedUserId != mCurrentUserId) { 856 return null; 857 } 858 if (mSecurityPolicy.findWindowById(windowId) == null) { 859 return null; 860 } 861 IBinder token = mGlobalWindowTokens.get(windowId); 862 if (token != null) { 863 return token; 864 } 865 return getCurrentUserStateLocked().mWindowTokens.get(windowId); 866 } 867 } 868 869 /** 870 * Invoked remotely over AIDL by SysUi when the accessibility button within the system's 871 * navigation area has been clicked. 872 */ 873 @Override notifyAccessibilityButtonClicked()874 public void notifyAccessibilityButtonClicked() { 875 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 876 != PackageManager.PERMISSION_GRANTED) { 877 throw new SecurityException("Caller does not hold permission " 878 + android.Manifest.permission.STATUS_BAR_SERVICE); 879 } 880 synchronized (mLock) { 881 notifyAccessibilityButtonClickedLocked(); 882 } 883 } 884 885 /** 886 * Invoked remotely over AIDL by SysUi when the visibility of the accessibility 887 * button within the system's navigation area has changed. 888 * 889 * @param shown {@code true} if the accessibility button is shown to the 890 * user, {@code false} otherwise 891 */ 892 @Override notifyAccessibilityButtonVisibilityChanged(boolean shown)893 public void notifyAccessibilityButtonVisibilityChanged(boolean shown) { 894 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 895 != PackageManager.PERMISSION_GRANTED) { 896 throw new SecurityException("Caller does not hold permission " 897 + android.Manifest.permission.STATUS_BAR_SERVICE); 898 } 899 synchronized (mLock) { 900 notifyAccessibilityButtonVisibilityChangedLocked(shown); 901 } 902 } 903 904 onGesture(int gestureId)905 boolean onGesture(int gestureId) { 906 synchronized (mLock) { 907 boolean handled = notifyGestureLocked(gestureId, false); 908 if (!handled) { 909 handled = notifyGestureLocked(gestureId, true); 910 } 911 return handled; 912 } 913 } 914 notifyKeyEvent(KeyEvent event, int policyFlags)915 boolean notifyKeyEvent(KeyEvent event, int policyFlags) { 916 synchronized (mLock) { 917 List<Service> boundServices = getCurrentUserStateLocked().mBoundServices; 918 if (boundServices.isEmpty()) { 919 return false; 920 } 921 return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices); 922 } 923 } 924 925 /** 926 * Called by the MagnificationController when the state of display 927 * magnification changes. 928 * 929 * @param region the new magnified region, may be empty if 930 * magnification is not enabled (e.g. scale is 1) 931 * @param scale the new scale 932 * @param centerX the new screen-relative center X coordinate 933 * @param centerY the new screen-relative center Y coordinate 934 */ notifyMagnificationChanged(@onNull Region region, float scale, float centerX, float centerY)935 public void notifyMagnificationChanged(@NonNull Region region, 936 float scale, float centerX, float centerY) { 937 synchronized (mLock) { 938 notifyClearAccessibilityCacheLocked(); 939 notifyMagnificationChangedLocked(region, scale, centerX, centerY); 940 } 941 } 942 943 /** 944 * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector. 945 * Not using a getter because the AccessibilityInputFilter isn't thread-safe 946 * 947 * @param motionEventInjector The new value of the motionEventInjector. May be null. 948 */ setMotionEventInjector(MotionEventInjector motionEventInjector)949 void setMotionEventInjector(MotionEventInjector motionEventInjector) { 950 synchronized (mLock) { 951 mMotionEventInjector = motionEventInjector; 952 // We may be waiting on this object being set 953 mLock.notifyAll(); 954 } 955 } 956 957 /** 958 * Gets a point within the accessibility focused node where we can send down 959 * and up events to perform a click. 960 * 961 * @param outPoint The click point to populate. 962 * @return Whether accessibility a click point was found and set. 963 */ 964 // TODO: (multi-display) Make sure this works for multiple displays. getAccessibilityFocusClickPointInScreen(Point outPoint)965 boolean getAccessibilityFocusClickPointInScreen(Point outPoint) { 966 return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint); 967 } 968 969 /** 970 * Perform an accessibility action on the view that currently has accessibility focus. 971 * Has no effect if no item has accessibility focus, if the item with accessibility 972 * focus does not expose the specified action, or if the action fails. 973 * 974 * @param actionId The id of the action to perform. 975 * 976 * @return {@code true} if the action was performed. {@code false} if it was not. 977 */ performActionOnAccessibilityFocusedItem( AccessibilityNodeInfo.AccessibilityAction action)978 public boolean performActionOnAccessibilityFocusedItem( 979 AccessibilityNodeInfo.AccessibilityAction action) { 980 return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action); 981 } 982 983 /** 984 * Gets the bounds of a window. 985 * 986 * @param outBounds The output to which to write the bounds. 987 */ getWindowBounds(int windowId, Rect outBounds)988 boolean getWindowBounds(int windowId, Rect outBounds) { 989 IBinder token; 990 synchronized (mLock) { 991 token = mGlobalWindowTokens.get(windowId); 992 if (token == null) { 993 token = getCurrentUserStateLocked().mWindowTokens.get(windowId); 994 } 995 } 996 mWindowManagerService.getWindowFrame(token, outBounds); 997 if (!outBounds.isEmpty()) { 998 return true; 999 } 1000 return false; 1001 } 1002 accessibilityFocusOnlyInActiveWindow()1003 boolean accessibilityFocusOnlyInActiveWindow() { 1004 synchronized (mLock) { 1005 return mWindowsForAccessibilityCallback == null; 1006 } 1007 } 1008 getActiveWindowId()1009 int getActiveWindowId() { 1010 return mSecurityPolicy.getActiveWindowId(); 1011 } 1012 onTouchInteractionStart()1013 void onTouchInteractionStart() { 1014 mSecurityPolicy.onTouchInteractionStart(); 1015 } 1016 onTouchInteractionEnd()1017 void onTouchInteractionEnd() { 1018 mSecurityPolicy.onTouchInteractionEnd(); 1019 } 1020 switchUser(int userId)1021 private void switchUser(int userId) { 1022 synchronized (mLock) { 1023 if (mCurrentUserId == userId && mInitialized) { 1024 return; 1025 } 1026 1027 // Disconnect from services for the old user. 1028 UserState oldUserState = getCurrentUserStateLocked(); 1029 oldUserState.onSwitchToAnotherUser(); 1030 1031 // Disable the local managers for the old user. 1032 if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) { 1033 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER, 1034 oldUserState.mUserId, 0).sendToTarget(); 1035 } 1036 1037 // Announce user changes only if more that one exist. 1038 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1039 final boolean announceNewUser = userManager.getUsers().size() > 1; 1040 1041 // The user changed. 1042 mCurrentUserId = userId; 1043 1044 UserState userState = getCurrentUserStateLocked(); 1045 if (userState.mUiAutomationService != null) { 1046 // Switching users disables the UI automation service. 1047 userState.mUiAutomationService.binderDied(); 1048 } 1049 1050 readConfigurationForUserStateLocked(userState); 1051 // Even if reading did not yield change, we have to update 1052 // the state since the context in which the current user 1053 // state was used has changed since it was inactive. 1054 onUserStateChangedLocked(userState); 1055 1056 if (announceNewUser) { 1057 // Schedule announcement of the current user if needed. 1058 mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED, 1059 WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS); 1060 } 1061 } 1062 } 1063 unlockUser(int userId)1064 private void unlockUser(int userId) { 1065 synchronized (mLock) { 1066 int parentUserId = mSecurityPolicy.resolveProfileParentLocked(userId); 1067 if (parentUserId == mCurrentUserId) { 1068 UserState userState = getUserStateLocked(mCurrentUserId); 1069 onUserStateChangedLocked(userState); 1070 } 1071 } 1072 } 1073 removeUser(int userId)1074 private void removeUser(int userId) { 1075 synchronized (mLock) { 1076 mUserStates.remove(userId); 1077 } 1078 } 1079 1080 // Called only during settings restore; currently supports only the owner user 1081 // TODO: http://b/22388012 restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting)1082 void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) { 1083 readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false); 1084 readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true); 1085 1086 UserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); 1087 userState.mEnabledServices.clear(); 1088 userState.mEnabledServices.addAll(mTempComponentNameSet); 1089 persistComponentNamesToSettingLocked( 1090 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 1091 userState.mEnabledServices, 1092 UserHandle.USER_SYSTEM); 1093 onUserStateChangedLocked(userState); 1094 } 1095 getInteractionBridge()1096 private InteractionBridge getInteractionBridge() { 1097 synchronized (mLock) { 1098 if (mInteractionBridge == null) { 1099 mInteractionBridge = new InteractionBridge(); 1100 } 1101 return mInteractionBridge; 1102 } 1103 } 1104 notifyGestureLocked(int gestureId, boolean isDefault)1105 private boolean notifyGestureLocked(int gestureId, boolean isDefault) { 1106 // TODO: Now we are giving the gestures to the last enabled 1107 // service that can handle them which is the last one 1108 // in our list since we write the last enabled as the 1109 // last record in the enabled services setting. Ideally, 1110 // the user should make the call which service handles 1111 // gestures. However, only one service should handle 1112 // gestures to avoid user frustration when different 1113 // behavior is observed from different combinations of 1114 // enabled accessibility services. 1115 UserState state = getCurrentUserStateLocked(); 1116 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1117 Service service = state.mBoundServices.get(i); 1118 if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { 1119 service.notifyGesture(gestureId); 1120 return true; 1121 } 1122 } 1123 return false; 1124 } 1125 notifyClearAccessibilityCacheLocked()1126 private void notifyClearAccessibilityCacheLocked() { 1127 UserState state = getCurrentUserStateLocked(); 1128 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1129 Service service = state.mBoundServices.get(i); 1130 service.notifyClearAccessibilityNodeInfoCache(); 1131 } 1132 } 1133 notifyMagnificationChangedLocked(@onNull Region region, float scale, float centerX, float centerY)1134 private void notifyMagnificationChangedLocked(@NonNull Region region, 1135 float scale, float centerX, float centerY) { 1136 final UserState state = getCurrentUserStateLocked(); 1137 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1138 final Service service = state.mBoundServices.get(i); 1139 service.notifyMagnificationChangedLocked(region, scale, centerX, centerY); 1140 } 1141 } 1142 notifySoftKeyboardShowModeChangedLocked(int showMode)1143 private void notifySoftKeyboardShowModeChangedLocked(int showMode) { 1144 final UserState state = getCurrentUserStateLocked(); 1145 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1146 final Service service = state.mBoundServices.get(i); 1147 service.notifySoftKeyboardShowModeChangedLocked(showMode); 1148 } 1149 } 1150 notifyAccessibilityButtonClickedLocked()1151 private void notifyAccessibilityButtonClickedLocked() { 1152 final UserState state = getCurrentUserStateLocked(); 1153 1154 int potentialTargets = state.mIsNavBarMagnificationEnabled ? 1 : 0; 1155 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1156 final Service service = state.mBoundServices.get(i); 1157 if (service.mRequestAccessibilityButton) { 1158 potentialTargets++; 1159 } 1160 } 1161 1162 if (potentialTargets == 0) { 1163 return; 1164 } 1165 if (potentialTargets == 1) { 1166 if (state.mIsNavBarMagnificationEnabled) { 1167 mMainHandler.obtainMessage( 1168 MainHandler.MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER).sendToTarget(); 1169 return; 1170 } else { 1171 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1172 final Service service = state.mBoundServices.get(i); 1173 if (service.mRequestAccessibilityButton) { 1174 service.notifyAccessibilityButtonClickedLocked(); 1175 return; 1176 } 1177 } 1178 } 1179 } else { 1180 if (state.mServiceAssignedToAccessibilityButton == null 1181 && !state.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1182 mMainHandler.obtainMessage( 1183 MainHandler.MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER).sendToTarget(); 1184 } else if (state.mIsNavBarMagnificationEnabled 1185 && state.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1186 mMainHandler.obtainMessage( 1187 MainHandler.MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER).sendToTarget(); 1188 return; 1189 } else { 1190 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1191 final Service service = state.mBoundServices.get(i); 1192 if (service.mRequestAccessibilityButton && (service.mComponentName.equals( 1193 state.mServiceAssignedToAccessibilityButton))) { 1194 service.notifyAccessibilityButtonClickedLocked(); 1195 return; 1196 } 1197 } 1198 } 1199 // The user may have turned off the assigned service or feature 1200 mMainHandler.obtainMessage( 1201 MainHandler.MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER).sendToTarget(); 1202 } 1203 } 1204 notifyAccessibilityButtonVisibilityChangedLocked(boolean available)1205 private void notifyAccessibilityButtonVisibilityChangedLocked(boolean available) { 1206 final UserState state = getCurrentUserStateLocked(); 1207 mIsAccessibilityButtonShown = available; 1208 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1209 final Service service = state.mBoundServices.get(i); 1210 if (service.mRequestAccessibilityButton) { 1211 service.notifyAccessibilityButtonAvailabilityChangedLocked( 1212 service.isAccessibilityButtonAvailableLocked(state)); 1213 } 1214 } 1215 } 1216 1217 /** 1218 * Removes an AccessibilityInteractionConnection. 1219 * 1220 * @param windowId The id of the window to which the connection is targeted. 1221 * @param userId The id of the user owning the connection. UserHandle.USER_ALL 1222 * if global. 1223 */ removeAccessibilityInteractionConnectionLocked(int windowId, int userId)1224 private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) { 1225 if (userId == UserHandle.USER_ALL) { 1226 mGlobalWindowTokens.remove(windowId); 1227 mGlobalInteractionConnections.remove(windowId); 1228 } else { 1229 UserState userState = getCurrentUserStateLocked(); 1230 userState.mWindowTokens.remove(windowId); 1231 userState.mInteractionConnections.remove(windowId); 1232 } 1233 if (DEBUG) { 1234 Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId); 1235 } 1236 } 1237 readInstalledAccessibilityServiceLocked(UserState userState)1238 private boolean readInstalledAccessibilityServiceLocked(UserState userState) { 1239 mTempAccessibilityServiceInfoList.clear(); 1240 1241 List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser( 1242 new Intent(AccessibilityService.SERVICE_INTERFACE), 1243 PackageManager.GET_SERVICES 1244 | PackageManager.GET_META_DATA 1245 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 1246 | PackageManager.MATCH_DIRECT_BOOT_AWARE 1247 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 1248 mCurrentUserId); 1249 1250 for (int i = 0, count = installedServices.size(); i < count; i++) { 1251 ResolveInfo resolveInfo = installedServices.get(i); 1252 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 1253 if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals( 1254 serviceInfo.permission)) { 1255 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName( 1256 serviceInfo.packageName, serviceInfo.name).flattenToShortString() 1257 + ": it does not require the permission " 1258 + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE); 1259 continue; 1260 } 1261 AccessibilityServiceInfo accessibilityServiceInfo; 1262 try { 1263 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); 1264 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo); 1265 } catch (XmlPullParserException | IOException xppe) { 1266 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe); 1267 } 1268 } 1269 1270 if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) { 1271 userState.mInstalledServices.clear(); 1272 userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList); 1273 mTempAccessibilityServiceInfoList.clear(); 1274 return true; 1275 } 1276 1277 mTempAccessibilityServiceInfoList.clear(); 1278 return false; 1279 } 1280 readEnabledAccessibilityServicesLocked(UserState userState)1281 private boolean readEnabledAccessibilityServicesLocked(UserState userState) { 1282 mTempComponentNameSet.clear(); 1283 readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 1284 userState.mUserId, mTempComponentNameSet); 1285 if (!mTempComponentNameSet.equals(userState.mEnabledServices)) { 1286 userState.mEnabledServices.clear(); 1287 userState.mEnabledServices.addAll(mTempComponentNameSet); 1288 if (userState.mUiAutomationService != null) { 1289 userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); 1290 } 1291 mTempComponentNameSet.clear(); 1292 return true; 1293 } 1294 mTempComponentNameSet.clear(); 1295 return false; 1296 } 1297 readTouchExplorationGrantedAccessibilityServicesLocked( UserState userState)1298 private boolean readTouchExplorationGrantedAccessibilityServicesLocked( 1299 UserState userState) { 1300 mTempComponentNameSet.clear(); 1301 readComponentNamesFromSettingLocked( 1302 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1303 userState.mUserId, mTempComponentNameSet); 1304 if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) { 1305 userState.mTouchExplorationGrantedServices.clear(); 1306 userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet); 1307 mTempComponentNameSet.clear(); 1308 return true; 1309 } 1310 mTempComponentNameSet.clear(); 1311 return false; 1312 } 1313 1314 /** 1315 * Performs {@link AccessibilityService}s delayed notification. The delay is configurable 1316 * and denotes the period after the last event before notifying the service. 1317 * 1318 * @param event The event. 1319 * @param isDefault True to notify default listeners, not default services. 1320 */ notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, boolean isDefault)1321 private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, 1322 boolean isDefault) { 1323 try { 1324 UserState state = getCurrentUserStateLocked(); 1325 for (int i = 0, count = state.mBoundServices.size(); i < count; i++) { 1326 Service service = state.mBoundServices.get(i); 1327 1328 if (service.mIsDefault == isDefault) { 1329 if (doesServiceWantEventLocked(service, event)) { 1330 service.notifyAccessibilityEvent(event, true); 1331 } else if (service.mUsesAccessibilityCache 1332 && (AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK 1333 & event.getEventType()) != 0) { 1334 service.notifyAccessibilityEvent(event, false); 1335 } 1336 } 1337 } 1338 } catch (IndexOutOfBoundsException oobe) { 1339 // An out of bounds exception can happen if services are going away 1340 // as the for loop is running. If that happens, just bail because 1341 // there are no more services to notify. 1342 } 1343 } 1344 addServiceLocked(Service service, UserState userState)1345 private void addServiceLocked(Service service, UserState userState) { 1346 try { 1347 if (!userState.mBoundServices.contains(service)) { 1348 service.onAdded(); 1349 userState.mBoundServices.add(service); 1350 userState.mComponentNameToServiceMap.put(service.mComponentName, service); 1351 scheduleNotifyClientsOfServicesStateChange(userState); 1352 } 1353 } catch (RemoteException re) { 1354 /* do nothing */ 1355 } 1356 } 1357 1358 /** 1359 * Removes a service. 1360 * 1361 * @param service The service. 1362 */ removeServiceLocked(Service service, UserState userState)1363 private void removeServiceLocked(Service service, UserState userState) { 1364 userState.mBoundServices.remove(service); 1365 service.onRemoved(); 1366 // It may be possible to bind a service twice, which confuses the map. Rebuild the map 1367 // to make sure we can still reach a service 1368 userState.mComponentNameToServiceMap.clear(); 1369 for (int i = 0; i < userState.mBoundServices.size(); i++) { 1370 Service boundService = userState.mBoundServices.get(i); 1371 userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService); 1372 } 1373 scheduleNotifyClientsOfServicesStateChange(userState); 1374 } 1375 updateRelevantEventsLocked(UserState userState)1376 private void updateRelevantEventsLocked(UserState userState) { 1377 int relevantEventTypes = AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK; 1378 for (Service service : userState.mBoundServices) { 1379 relevantEventTypes |= service.mEventTypes; 1380 } 1381 int finalRelevantEventTypes = relevantEventTypes; 1382 1383 if (userState.mLastSentRelevantEventTypes != finalRelevantEventTypes) { 1384 userState.mLastSentRelevantEventTypes = finalRelevantEventTypes; 1385 mMainHandler.obtainMessage(MainHandler.MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS, 1386 userState.mUserId, finalRelevantEventTypes); 1387 mMainHandler.post(() -> { 1388 broadcastToClients(userState, (client) -> { 1389 try { 1390 client.setRelevantEventTypes(finalRelevantEventTypes); 1391 } catch (RemoteException re) { 1392 /* ignore */ 1393 } 1394 }); 1395 }); 1396 } 1397 } 1398 broadcastToClients( UserState userState, Consumer<IAccessibilityManagerClient> clientAction)1399 private void broadcastToClients( 1400 UserState userState, Consumer<IAccessibilityManagerClient> clientAction) { 1401 mGlobalClients.broadcast(clientAction); 1402 userState.mUserClients.broadcast(clientAction); 1403 } 1404 1405 /** 1406 * Determines if given event can be dispatched to a service based on the package of the 1407 * event source. Specifically, a service is notified if it is interested in events from the 1408 * package. 1409 * 1410 * @param service The potential receiver. 1411 * @param event The event. 1412 * @return True if the listener should be notified, false otherwise. 1413 */ doesServiceWantEventLocked(Service service, AccessibilityEvent event)1414 private boolean doesServiceWantEventLocked(Service service, AccessibilityEvent event) { 1415 1416 if (!service.canReceiveEventsLocked()) { 1417 return false; 1418 } 1419 1420 if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) 1421 && !event.isImportantForAccessibility() 1422 && (service.mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) 1423 == 0) { 1424 return false; 1425 } 1426 1427 int eventType = event.getEventType(); 1428 if ((service.mEventTypes & eventType) != eventType) { 1429 return false; 1430 } 1431 1432 Set<String> packageNames = service.mPackageNames; 1433 String packageName = (event.getPackageName() != null) 1434 ? event.getPackageName().toString() : null; 1435 1436 return (packageNames.isEmpty() || packageNames.contains(packageName)); 1437 } 1438 unbindAllServicesLocked(UserState userState)1439 private void unbindAllServicesLocked(UserState userState) { 1440 List<Service> services = userState.mBoundServices; 1441 for (int i = 0, count = services.size(); i < count; i++) { 1442 Service service = services.get(i); 1443 if (service.unbindLocked()) { 1444 i--; 1445 count--; 1446 } 1447 } 1448 } 1449 1450 /** 1451 * Populates a set with the {@link ComponentName}s stored in a colon 1452 * separated value setting for a given user. 1453 * 1454 * @param settingName The setting to parse. 1455 * @param userId The user id. 1456 * @param outComponentNames The output component names. 1457 */ readComponentNamesFromSettingLocked(String settingName, int userId, Set<ComponentName> outComponentNames)1458 private void readComponentNamesFromSettingLocked(String settingName, int userId, 1459 Set<ComponentName> outComponentNames) { 1460 String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(), 1461 settingName, userId); 1462 readComponentNamesFromStringLocked(settingValue, outComponentNames, false); 1463 } 1464 1465 /** 1466 * Populates a set with the {@link ComponentName}s contained in a colon-delimited string. 1467 * 1468 * @param names The colon-delimited string to parse. 1469 * @param outComponentNames The set of component names to be populated based on 1470 * the contents of the <code>names</code> string. 1471 * @param doMerge If true, the parsed component names will be merged into the output 1472 * set, rather than replacing the set's existing contents entirely. 1473 */ readComponentNamesFromStringLocked(String names, Set<ComponentName> outComponentNames, boolean doMerge)1474 private void readComponentNamesFromStringLocked(String names, 1475 Set<ComponentName> outComponentNames, 1476 boolean doMerge) { 1477 if (!doMerge) { 1478 outComponentNames.clear(); 1479 } 1480 if (names != null) { 1481 TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 1482 splitter.setString(names); 1483 while (splitter.hasNext()) { 1484 String str = splitter.next(); 1485 if (str == null || str.length() <= 0) { 1486 continue; 1487 } 1488 ComponentName enabledService = ComponentName.unflattenFromString(str); 1489 if (enabledService != null) { 1490 outComponentNames.add(enabledService); 1491 } 1492 } 1493 } 1494 } 1495 1496 /** 1497 * Persists the component names in the specified setting in a 1498 * colon separated fashion. 1499 * 1500 * @param settingName The setting name. 1501 * @param componentNames The component names. 1502 */ persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)1503 private void persistComponentNamesToSettingLocked(String settingName, 1504 Set<ComponentName> componentNames, int userId) { 1505 StringBuilder builder = new StringBuilder(); 1506 for (ComponentName componentName : componentNames) { 1507 if (builder.length() > 0) { 1508 builder.append(COMPONENT_NAME_SEPARATOR); 1509 } 1510 builder.append(componentName.flattenToShortString()); 1511 } 1512 final long identity = Binder.clearCallingIdentity(); 1513 try { 1514 Settings.Secure.putStringForUser(mContext.getContentResolver(), 1515 settingName, builder.toString(), userId); 1516 } finally { 1517 Binder.restoreCallingIdentity(identity); 1518 } 1519 } 1520 updateServicesLocked(UserState userState)1521 private void updateServicesLocked(UserState userState) { 1522 Map<ComponentName, Service> componentNameToServiceMap = 1523 userState.mComponentNameToServiceMap; 1524 boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class) 1525 .isUserUnlockingOrUnlocked(userState.mUserId); 1526 1527 for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) { 1528 AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i); 1529 ComponentName componentName = ComponentName.unflattenFromString( 1530 installedService.getId()); 1531 1532 Service service = componentNameToServiceMap.get(componentName); 1533 1534 // Ignore non-encryption-aware services until user is unlocked 1535 if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) { 1536 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName); 1537 continue; 1538 } 1539 1540 // Wait for the binding if it is in process. 1541 if (userState.mBindingServices.contains(componentName)) { 1542 continue; 1543 } 1544 if (userState.mEnabledServices.contains(componentName)) { 1545 if (service == null) { 1546 service = new Service(userState.mUserId, componentName, installedService); 1547 } else if (userState.mBoundServices.contains(service)) { 1548 continue; 1549 } 1550 service.bindLocked(); 1551 } else { 1552 if (service != null) { 1553 service.unbindLocked(); 1554 } 1555 } 1556 } 1557 1558 final int count = userState.mBoundServices.size(); 1559 mTempIntArray.clear(); 1560 for (int i = 0; i < count; i++) { 1561 final ResolveInfo resolveInfo = 1562 userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo(); 1563 if (resolveInfo != null) { 1564 mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid); 1565 } 1566 } 1567 // Calling out with lock held, but to a lower-level service 1568 final AudioManagerInternal audioManager = 1569 LocalServices.getService(AudioManagerInternal.class); 1570 if (audioManager != null) { 1571 audioManager.setAccessibilityServiceUids(mTempIntArray); 1572 } 1573 updateAccessibilityEnabledSetting(userState); 1574 } 1575 scheduleUpdateClientsIfNeededLocked(UserState userState)1576 private void scheduleUpdateClientsIfNeededLocked(UserState userState) { 1577 final int clientState = userState.getClientState(); 1578 if (userState.mLastSentClientState != clientState 1579 && (mGlobalClients.getRegisteredCallbackCount() > 0 1580 || userState.mUserClients.getRegisteredCallbackCount() > 0)) { 1581 userState.mLastSentClientState = clientState; 1582 mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS, 1583 clientState, userState.mUserId).sendToTarget(); 1584 } 1585 } 1586 showAccessibilityButtonTargetSelection()1587 private void showAccessibilityButtonTargetSelection() { 1588 Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON); 1589 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1590 mContext.startActivityAsUser(intent, UserHandle.of(mCurrentUserId)); 1591 } 1592 scheduleNotifyClientsOfServicesStateChange(UserState userState)1593 private void scheduleNotifyClientsOfServicesStateChange(UserState userState) { 1594 mMainHandler.obtainMessage(MainHandler.MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS, 1595 userState.mUserId).sendToTarget(); 1596 } 1597 scheduleUpdateInputFilter(UserState userState)1598 private void scheduleUpdateInputFilter(UserState userState) { 1599 mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget(); 1600 } 1601 scheduleUpdateFingerprintGestureHandling(UserState userState)1602 private void scheduleUpdateFingerprintGestureHandling(UserState userState) { 1603 mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_FINGERPRINT, userState).sendToTarget(); 1604 } 1605 updateInputFilter(UserState userState)1606 private void updateInputFilter(UserState userState) { 1607 boolean setInputFilter = false; 1608 AccessibilityInputFilter inputFilter = null; 1609 synchronized (mLock) { 1610 int flags = 0; 1611 if (userState.mIsDisplayMagnificationEnabled) { 1612 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER; 1613 } 1614 if (userState.mIsNavBarMagnificationEnabled) { 1615 flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER; 1616 } 1617 if (userHasMagnificationServicesLocked(userState)) { 1618 flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER; 1619 } 1620 // Touch exploration without accessibility makes no sense. 1621 if (userState.isHandlingAccessibilityEvents() 1622 && userState.mIsTouchExplorationEnabled) { 1623 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION; 1624 } 1625 if (userState.mIsFilterKeyEventsEnabled) { 1626 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS; 1627 } 1628 if (userState.mIsAutoclickEnabled) { 1629 flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK; 1630 } 1631 if (userState.mIsPerformGesturesEnabled) { 1632 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS; 1633 } 1634 if (flags != 0) { 1635 if (!mHasInputFilter) { 1636 mHasInputFilter = true; 1637 if (mInputFilter == null) { 1638 mInputFilter = new AccessibilityInputFilter(mContext, 1639 AccessibilityManagerService.this); 1640 } 1641 inputFilter = mInputFilter; 1642 setInputFilter = true; 1643 } 1644 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags); 1645 } else { 1646 if (mHasInputFilter) { 1647 mHasInputFilter = false; 1648 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0); 1649 inputFilter = null; 1650 setInputFilter = true; 1651 } 1652 } 1653 } 1654 if (setInputFilter) { 1655 mWindowManagerService.setInputFilter(inputFilter); 1656 } 1657 } 1658 showEnableTouchExplorationDialog(final Service service)1659 private void showEnableTouchExplorationDialog(final Service service) { 1660 synchronized (mLock) { 1661 String label = service.mResolveInfo.loadLabel( 1662 mContext.getPackageManager()).toString(); 1663 1664 final UserState state = getCurrentUserStateLocked(); 1665 if (state.mIsTouchExplorationEnabled) { 1666 return; 1667 } 1668 if (mEnableTouchExplorationDialog != null 1669 && mEnableTouchExplorationDialog.isShowing()) { 1670 return; 1671 } 1672 mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) 1673 .setIconAttribute(android.R.attr.alertDialogIcon) 1674 .setPositiveButton(android.R.string.ok, new OnClickListener() { 1675 @Override 1676 public void onClick(DialogInterface dialog, int which) { 1677 // The user allowed the service to toggle touch exploration. 1678 state.mTouchExplorationGrantedServices.add(service.mComponentName); 1679 persistComponentNamesToSettingLocked( 1680 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1681 state.mTouchExplorationGrantedServices, state.mUserId); 1682 // Enable touch exploration. 1683 UserState userState = getUserStateLocked(service.mUserId); 1684 userState.mIsTouchExplorationEnabled = true; 1685 final long identity = Binder.clearCallingIdentity(); 1686 try { 1687 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1688 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, 1689 service.mUserId); 1690 } finally { 1691 Binder.restoreCallingIdentity(identity); 1692 } 1693 onUserStateChangedLocked(userState); 1694 } 1695 }) 1696 .setNegativeButton(android.R.string.cancel, new OnClickListener() { 1697 @Override 1698 public void onClick(DialogInterface dialog, int which) { 1699 dialog.dismiss(); 1700 } 1701 }) 1702 .setTitle(R.string.enable_explore_by_touch_warning_title) 1703 .setMessage(mContext.getString( 1704 R.string.enable_explore_by_touch_warning_message, label)) 1705 .create(); 1706 mEnableTouchExplorationDialog.getWindow().setType( 1707 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 1708 mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags 1709 |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 1710 mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); 1711 mEnableTouchExplorationDialog.show(); 1712 } 1713 } 1714 1715 /** 1716 * Called when any property of the user state has changed. 1717 * 1718 * @param userState the new user state 1719 */ onUserStateChangedLocked(UserState userState)1720 private void onUserStateChangedLocked(UserState userState) { 1721 // TODO: Remove this hack 1722 mInitialized = true; 1723 updateLegacyCapabilitiesLocked(userState); 1724 updateServicesLocked(userState); 1725 updateAccessibilityShortcutLocked(userState); 1726 updateWindowsForAccessibilityCallbackLocked(userState); 1727 updateAccessibilityFocusBehaviorLocked(userState); 1728 updateFilterKeyEventsLocked(userState); 1729 updateTouchExplorationLocked(userState); 1730 updatePerformGesturesLocked(userState); 1731 updateDisplayDaltonizerLocked(userState); 1732 updateDisplayInversionLocked(userState); 1733 updateMagnificationLocked(userState); 1734 updateSoftKeyboardShowModeLocked(userState); 1735 scheduleUpdateFingerprintGestureHandling(userState); 1736 scheduleUpdateInputFilter(userState); 1737 scheduleUpdateClientsIfNeededLocked(userState); 1738 updateRelevantEventsLocked(userState); 1739 updateAccessibilityButtonTargetsLocked(userState); 1740 } 1741 updateAccessibilityFocusBehaviorLocked(UserState userState)1742 private void updateAccessibilityFocusBehaviorLocked(UserState userState) { 1743 // If there is no service that can operate with interactive windows 1744 // then we keep the old behavior where a window loses accessibility 1745 // focus if it is no longer active. This still changes the behavior 1746 // for services that do not operate with interactive windows and run 1747 // at the same time as the one(s) which does. In practice however, 1748 // there is only one service that uses accessibility focus and it 1749 // is typically the one that operates with interactive windows, So, 1750 // this is fine. Note that to allow a service to work across windows 1751 // we have to allow accessibility focus stay in any of them. Sigh... 1752 List<Service> boundServices = userState.mBoundServices; 1753 final int boundServiceCount = boundServices.size(); 1754 for (int i = 0; i < boundServiceCount; i++) { 1755 Service boundService = boundServices.get(i); 1756 if (boundService.canRetrieveInteractiveWindowsLocked()) { 1757 userState.mAccessibilityFocusOnlyInActiveWindow = false; 1758 return; 1759 } 1760 } 1761 userState.mAccessibilityFocusOnlyInActiveWindow = true; 1762 } 1763 updateWindowsForAccessibilityCallbackLocked(UserState userState)1764 private void updateWindowsForAccessibilityCallbackLocked(UserState userState) { 1765 // We observe windows for accessibility only if there is at least 1766 // one bound service that can retrieve window content that specified 1767 // it is interested in accessing such windows. For services that are 1768 // binding we do an update pass after each bind event, so we run this 1769 // code and register the callback if needed. 1770 1771 List<Service> boundServices = userState.mBoundServices; 1772 final int boundServiceCount = boundServices.size(); 1773 for (int i = 0; i < boundServiceCount; i++) { 1774 Service boundService = boundServices.get(i); 1775 if (boundService.canRetrieveInteractiveWindowsLocked()) { 1776 if (mWindowsForAccessibilityCallback == null) { 1777 mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback(); 1778 mWindowManagerService.setWindowsForAccessibilityCallback( 1779 mWindowsForAccessibilityCallback); 1780 } 1781 return; 1782 } 1783 } 1784 1785 if (mWindowsForAccessibilityCallback != null) { 1786 mWindowsForAccessibilityCallback = null; 1787 mWindowManagerService.setWindowsForAccessibilityCallback(null); 1788 // Drop all windows we know about. 1789 mSecurityPolicy.clearWindowsLocked(); 1790 } 1791 } 1792 updateLegacyCapabilitiesLocked(UserState userState)1793 private void updateLegacyCapabilitiesLocked(UserState userState) { 1794 // Up to JB-MR1 we had a white list with services that can enable touch 1795 // exploration. When a service is first started we show a dialog to the 1796 // use to get a permission to white list the service. 1797 final int installedServiceCount = userState.mInstalledServices.size(); 1798 for (int i = 0; i < installedServiceCount; i++) { 1799 AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i); 1800 ResolveInfo resolveInfo = serviceInfo.getResolveInfo(); 1801 if ((serviceInfo.getCapabilities() 1802 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0 1803 && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion 1804 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 1805 ComponentName componentName = new ComponentName( 1806 resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 1807 if (userState.mTouchExplorationGrantedServices.contains(componentName)) { 1808 serviceInfo.setCapabilities(serviceInfo.getCapabilities() 1809 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION); 1810 } 1811 } 1812 } 1813 } 1814 updatePerformGesturesLocked(UserState userState)1815 private void updatePerformGesturesLocked(UserState userState) { 1816 final int serviceCount = userState.mBoundServices.size(); 1817 for (int i = 0; i < serviceCount; i++) { 1818 Service service = userState.mBoundServices.get(i); 1819 if ((service.mAccessibilityServiceInfo.getCapabilities() 1820 & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) { 1821 userState.mIsPerformGesturesEnabled = true; 1822 return; 1823 } 1824 } 1825 userState.mIsPerformGesturesEnabled = false; 1826 } 1827 updateFilterKeyEventsLocked(UserState userState)1828 private void updateFilterKeyEventsLocked(UserState userState) { 1829 final int serviceCount = userState.mBoundServices.size(); 1830 for (int i = 0; i < serviceCount; i++) { 1831 Service service = userState.mBoundServices.get(i); 1832 if (service.mRequestFilterKeyEvents 1833 && (service.mAccessibilityServiceInfo.getCapabilities() 1834 & AccessibilityServiceInfo 1835 .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) { 1836 userState.mIsFilterKeyEventsEnabled = true; 1837 return; 1838 } 1839 } 1840 userState.mIsFilterKeyEventsEnabled = false; 1841 } 1842 readConfigurationForUserStateLocked(UserState userState)1843 private boolean readConfigurationForUserStateLocked(UserState userState) { 1844 boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState); 1845 somethingChanged |= readEnabledAccessibilityServicesLocked(userState); 1846 somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState); 1847 somethingChanged |= readTouchExplorationEnabledSettingLocked(userState); 1848 somethingChanged |= readHighTextContrastEnabledSettingLocked(userState); 1849 somethingChanged |= readMagnificationEnabledSettingsLocked(userState); 1850 somethingChanged |= readAutoclickEnabledSettingLocked(userState); 1851 somethingChanged |= readAccessibilityShortcutSettingLocked(userState); 1852 somethingChanged |= readAccessibilityButtonSettingsLocked(userState); 1853 return somethingChanged; 1854 } 1855 updateAccessibilityEnabledSetting(UserState userState)1856 private void updateAccessibilityEnabledSetting(UserState userState) { 1857 final long identity = Binder.clearCallingIdentity(); 1858 try { 1859 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1860 Settings.Secure.ACCESSIBILITY_ENABLED, 1861 userState.isHandlingAccessibilityEvents() ? 1 : 0, 1862 userState.mUserId); 1863 } finally { 1864 Binder.restoreCallingIdentity(identity); 1865 } 1866 } 1867 readTouchExplorationEnabledSettingLocked(UserState userState)1868 private boolean readTouchExplorationEnabledSettingLocked(UserState userState) { 1869 final boolean touchExplorationEnabled = Settings.Secure.getIntForUser( 1870 mContext.getContentResolver(), 1871 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1; 1872 if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) { 1873 userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 1874 return true; 1875 } 1876 return false; 1877 } 1878 readMagnificationEnabledSettingsLocked(UserState userState)1879 private boolean readMagnificationEnabledSettingsLocked(UserState userState) { 1880 final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser( 1881 mContext.getContentResolver(), 1882 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 1883 0, userState.mUserId) == 1; 1884 final boolean navBarMagnificationEnabled = Settings.Secure.getIntForUser( 1885 mContext.getContentResolver(), 1886 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 1887 0, userState.mUserId) == 1; 1888 if ((displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled) 1889 || (navBarMagnificationEnabled != userState.mIsNavBarMagnificationEnabled)) { 1890 userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled; 1891 userState.mIsNavBarMagnificationEnabled = navBarMagnificationEnabled; 1892 return true; 1893 } 1894 return false; 1895 } 1896 readAutoclickEnabledSettingLocked(UserState userState)1897 private boolean readAutoclickEnabledSettingLocked(UserState userState) { 1898 final boolean autoclickEnabled = Settings.Secure.getIntForUser( 1899 mContext.getContentResolver(), 1900 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 1901 0, userState.mUserId) == 1; 1902 if (autoclickEnabled != userState.mIsAutoclickEnabled) { 1903 userState.mIsAutoclickEnabled = autoclickEnabled; 1904 return true; 1905 } 1906 return false; 1907 } 1908 readHighTextContrastEnabledSettingLocked(UserState userState)1909 private boolean readHighTextContrastEnabledSettingLocked(UserState userState) { 1910 final boolean highTextContrastEnabled = Settings.Secure.getIntForUser( 1911 mContext.getContentResolver(), 1912 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0, 1913 userState.mUserId) == 1; 1914 if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) { 1915 userState.mIsTextHighContrastEnabled = highTextContrastEnabled; 1916 return true; 1917 } 1918 return false; 1919 } 1920 readSoftKeyboardShowModeChangedLocked(UserState userState)1921 private boolean readSoftKeyboardShowModeChangedLocked(UserState userState) { 1922 final int softKeyboardShowMode = Settings.Secure.getIntForUser( 1923 mContext.getContentResolver(), 1924 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, 1925 userState.mUserId); 1926 if (softKeyboardShowMode != userState.mSoftKeyboardShowMode) { 1927 userState.mSoftKeyboardShowMode = softKeyboardShowMode; 1928 return true; 1929 } 1930 return false; 1931 } 1932 updateTouchExplorationLocked(UserState userState)1933 private void updateTouchExplorationLocked(UserState userState) { 1934 boolean enabled = false; 1935 final int serviceCount = userState.mBoundServices.size(); 1936 for (int i = 0; i < serviceCount; i++) { 1937 Service service = userState.mBoundServices.get(i); 1938 if (canRequestAndRequestsTouchExplorationLocked(service)) { 1939 enabled = true; 1940 break; 1941 } 1942 } 1943 if (enabled != userState.mIsTouchExplorationEnabled) { 1944 userState.mIsTouchExplorationEnabled = enabled; 1945 final long identity = Binder.clearCallingIdentity(); 1946 try { 1947 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1948 Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0, 1949 userState.mUserId); 1950 } finally { 1951 Binder.restoreCallingIdentity(identity); 1952 } 1953 } 1954 } 1955 readAccessibilityShortcutSettingLocked(UserState userState)1956 private boolean readAccessibilityShortcutSettingLocked(UserState userState) { 1957 String componentNameToEnableString = AccessibilityShortcutController 1958 .getTargetServiceComponentNameString(mContext, userState.mUserId); 1959 if ((componentNameToEnableString == null) || componentNameToEnableString.isEmpty()) { 1960 if (userState.mServiceToEnableWithShortcut == null) { 1961 return false; 1962 } 1963 userState.mServiceToEnableWithShortcut = null; 1964 return true; 1965 } 1966 ComponentName componentNameToEnable = 1967 ComponentName.unflattenFromString(componentNameToEnableString); 1968 if ((componentNameToEnable != null) 1969 && componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) { 1970 return false; 1971 } 1972 userState.mServiceToEnableWithShortcut = componentNameToEnable; 1973 return true; 1974 } 1975 readAccessibilityButtonSettingsLocked(UserState userState)1976 private boolean readAccessibilityButtonSettingsLocked(UserState userState) { 1977 String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(), 1978 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId); 1979 if (TextUtils.isEmpty(componentId)) { 1980 if ((userState.mServiceAssignedToAccessibilityButton == null) 1981 && !userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1982 return false; 1983 } 1984 userState.mServiceAssignedToAccessibilityButton = null; 1985 userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false; 1986 return true; 1987 } 1988 1989 if (componentId.equals(MagnificationController.class.getName())) { 1990 if (userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1991 return false; 1992 } 1993 userState.mServiceAssignedToAccessibilityButton = null; 1994 userState.mIsNavBarMagnificationAssignedToAccessibilityButton = true; 1995 return true; 1996 } 1997 1998 ComponentName componentName = ComponentName.unflattenFromString(componentId); 1999 if (componentName.equals(userState.mServiceAssignedToAccessibilityButton)) { 2000 return false; 2001 } 2002 userState.mServiceAssignedToAccessibilityButton = componentName; 2003 userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false; 2004 return true; 2005 } 2006 2007 /** 2008 * Check if the service that will be enabled by the shortcut is installed. If it isn't, 2009 * clear the value and the associated setting so a sideloaded service can't spoof the 2010 * package name of the default service. 2011 * 2012 * @param userState 2013 */ updateAccessibilityShortcutLocked(UserState userState)2014 private void updateAccessibilityShortcutLocked(UserState userState) { 2015 if (userState.mServiceToEnableWithShortcut == null) { 2016 return; 2017 } 2018 boolean shortcutServiceIsInstalled = false; 2019 for (int i = 0; i < userState.mInstalledServices.size(); i++) { 2020 if (userState.mInstalledServices.get(i).getComponentName() 2021 .equals(userState.mServiceToEnableWithShortcut)) { 2022 shortcutServiceIsInstalled = true; 2023 } 2024 } 2025 if (!shortcutServiceIsInstalled) { 2026 userState.mServiceToEnableWithShortcut = null; 2027 final long identity = Binder.clearCallingIdentity(); 2028 try { 2029 Settings.Secure.putStringForUser(mContext.getContentResolver(), 2030 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null, userState.mUserId); 2031 2032 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2033 Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0, userState.mUserId); 2034 } finally { 2035 Binder.restoreCallingIdentity(identity); 2036 } 2037 } 2038 } 2039 canRequestAndRequestsTouchExplorationLocked(Service service)2040 private boolean canRequestAndRequestsTouchExplorationLocked(Service service) { 2041 // Service not ready or cannot request the feature - well nothing to do. 2042 if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) { 2043 return false; 2044 } 2045 // UI test automation service can always enable it. 2046 if (service.mIsAutomation) { 2047 return true; 2048 } 2049 if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion 2050 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 2051 // Up to JB-MR1 we had a white list with services that can enable touch 2052 // exploration. When a service is first started we show a dialog to the 2053 // use to get a permission to white list the service. 2054 UserState userState = getUserStateLocked(service.mUserId); 2055 if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { 2056 return true; 2057 } else if (mEnableTouchExplorationDialog == null 2058 || !mEnableTouchExplorationDialog.isShowing()) { 2059 mMainHandler.obtainMessage( 2060 MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG, 2061 service).sendToTarget(); 2062 } 2063 } else { 2064 // Starting in JB-MR2 we request an accessibility service to declare 2065 // certain capabilities in its meta-data to allow it to enable the 2066 // corresponding features. 2067 if ((service.mAccessibilityServiceInfo.getCapabilities() 2068 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) { 2069 return true; 2070 } 2071 } 2072 return false; 2073 } 2074 updateDisplayDaltonizerLocked(UserState userState)2075 private void updateDisplayDaltonizerLocked(UserState userState) { 2076 DisplayAdjustmentUtils.applyDaltonizerSetting(mContext, userState.mUserId); 2077 } 2078 updateDisplayInversionLocked(UserState userState)2079 private void updateDisplayInversionLocked(UserState userState) { 2080 DisplayAdjustmentUtils.applyInversionSetting(mContext, userState.mUserId); 2081 } 2082 updateMagnificationLocked(UserState userState)2083 private void updateMagnificationLocked(UserState userState) { 2084 if (userState.mUserId != mCurrentUserId) { 2085 return; 2086 } 2087 2088 if (userState.mIsDisplayMagnificationEnabled || userState.mIsNavBarMagnificationEnabled 2089 || userHasListeningMagnificationServicesLocked(userState)) { 2090 // Initialize the magnification controller if necessary 2091 getMagnificationController(); 2092 mMagnificationController.register(); 2093 } else if (mMagnificationController != null) { 2094 mMagnificationController.unregister(); 2095 } 2096 } 2097 2098 /** 2099 * Returns whether the specified user has any services that are capable of 2100 * controlling magnification. 2101 */ userHasMagnificationServicesLocked(UserState userState)2102 private boolean userHasMagnificationServicesLocked(UserState userState) { 2103 final List<Service> services = userState.mBoundServices; 2104 for (int i = 0, count = services.size(); i < count; i++) { 2105 final Service service = services.get(i); 2106 if (mSecurityPolicy.canControlMagnification(service)) { 2107 return true; 2108 } 2109 } 2110 return false; 2111 } 2112 2113 /** 2114 * Returns whether the specified user has any services that are capable of 2115 * controlling magnification and are actively listening for magnification updates. 2116 */ userHasListeningMagnificationServicesLocked(UserState userState)2117 private boolean userHasListeningMagnificationServicesLocked(UserState userState) { 2118 final List<Service> services = userState.mBoundServices; 2119 for (int i = 0, count = services.size(); i < count; i++) { 2120 final Service service = services.get(i); 2121 if (mSecurityPolicy.canControlMagnification(service) 2122 && service.mInvocationHandler.mIsMagnificationCallbackEnabled) { 2123 return true; 2124 } 2125 } 2126 return false; 2127 } 2128 updateSoftKeyboardShowModeLocked(UserState userState)2129 private void updateSoftKeyboardShowModeLocked(UserState userState) { 2130 final int userId = userState.mUserId; 2131 // Only check whether we need to reset the soft keyboard mode if it is not set to the 2132 // default. 2133 if ((userId == mCurrentUserId) && (userState.mSoftKeyboardShowMode != 0)) { 2134 // Check whether the last Accessibility Service that changed the soft keyboard mode to 2135 // something other than the default is still enabled and, if not, remove flag and 2136 // reset to the default soft keyboard behavior. 2137 boolean serviceChangingSoftKeyboardModeIsEnabled = 2138 userState.mEnabledServices.contains(userState.mServiceChangingSoftKeyboardMode); 2139 2140 if (!serviceChangingSoftKeyboardModeIsEnabled) { 2141 final long identity = Binder.clearCallingIdentity(); 2142 try { 2143 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2144 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 2145 0, 2146 userState.mUserId); 2147 } finally { 2148 Binder.restoreCallingIdentity(identity); 2149 } 2150 userState.mSoftKeyboardShowMode = 0; 2151 userState.mServiceChangingSoftKeyboardMode = null; 2152 notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode); 2153 } 2154 } 2155 } 2156 updateFingerprintGestureHandling(UserState userState)2157 private void updateFingerprintGestureHandling(UserState userState) { 2158 final List<Service> services; 2159 synchronized (mLock) { 2160 services = userState.mBoundServices; 2161 if ((mFingerprintGestureDispatcher == null) 2162 && mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 2163 // Only create the controller when a service wants to use the feature 2164 int numServices = services.size(); 2165 for (int i = 0; i < numServices; i++) { 2166 if (services.get(i).isCapturingFingerprintGestures()) { 2167 final long identity = Binder.clearCallingIdentity(); 2168 IFingerprintService service = null; 2169 try { 2170 service = IFingerprintService.Stub.asInterface( 2171 ServiceManager.getService(Context.FINGERPRINT_SERVICE)); 2172 } finally { 2173 Binder.restoreCallingIdentity(identity); 2174 } 2175 if (service != null) { 2176 mFingerprintGestureDispatcher = new FingerprintGestureDispatcher( 2177 service, mLock); 2178 break; 2179 } 2180 } 2181 } 2182 } 2183 } 2184 if (mFingerprintGestureDispatcher != null) { 2185 mFingerprintGestureDispatcher.updateClientList(services); 2186 } 2187 } 2188 updateAccessibilityButtonTargetsLocked(UserState userState)2189 private void updateAccessibilityButtonTargetsLocked(UserState userState) { 2190 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 2191 final Service service = userState.mBoundServices.get(i); 2192 if (service.mRequestAccessibilityButton) { 2193 service.notifyAccessibilityButtonAvailabilityChangedLocked( 2194 service.isAccessibilityButtonAvailableLocked(userState)); 2195 } 2196 } 2197 } 2198 2199 @GuardedBy("mLock") getCompatibleMagnificationSpecLocked(int windowId)2200 private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { 2201 IBinder windowToken = mGlobalWindowTokens.get(windowId); 2202 if (windowToken == null) { 2203 windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId); 2204 } 2205 if (windowToken != null) { 2206 return mWindowManagerService.getCompatibleMagnificationSpecForWindow( 2207 windowToken); 2208 } 2209 return null; 2210 } 2211 getKeyEventDispatcher()2212 private KeyEventDispatcher getKeyEventDispatcher() { 2213 if (mKeyEventDispatcher == null) { 2214 mKeyEventDispatcher = new KeyEventDispatcher( 2215 mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock, 2216 mPowerManager); 2217 } 2218 return mKeyEventDispatcher; 2219 } 2220 2221 /** 2222 * AIDL-exposed method to be called when the accessibility shortcut is enabled. Requires 2223 * permission to write secure settings, since someone with that permission can enable 2224 * accessibility services themselves. 2225 */ performAccessibilityShortcut()2226 public void performAccessibilityShortcut() { 2227 if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) 2228 && (mContext.checkCallingPermission(Manifest.permission.WRITE_SECURE_SETTINGS) 2229 != PackageManager.PERMISSION_GRANTED)) { 2230 throw new SecurityException( 2231 "performAccessibilityShortcut requires the WRITE_SECURE_SETTINGS permission"); 2232 } 2233 synchronized(mLock) { 2234 UserState userState = getUserStateLocked(mCurrentUserId); 2235 ComponentName serviceName = userState.mServiceToEnableWithShortcut; 2236 if (serviceName == null) { 2237 return; 2238 } 2239 final long identity = Binder.clearCallingIdentity(); 2240 try { 2241 if (userState.mComponentNameToServiceMap.get(serviceName) == null) { 2242 enableAccessibilityServiceLocked(serviceName, mCurrentUserId); 2243 } else { 2244 disableAccessibilityServiceLocked(serviceName, mCurrentUserId); 2245 } 2246 } finally { 2247 Binder.restoreCallingIdentity(identity); 2248 } 2249 } 2250 }; 2251 2252 /** 2253 * Enables accessibility service specified by {@param componentName} for the {@param userId}. 2254 */ enableAccessibilityServiceLocked(ComponentName componentName, int userId)2255 private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) { 2256 final SettingStringHelper setting = 2257 new SettingStringHelper( 2258 mContext.getContentResolver(), 2259 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 2260 userId); 2261 setting.write(ComponentNameSet.add(setting.read(), componentName)); 2262 2263 UserState userState = getUserStateLocked(userId); 2264 if (userState.mEnabledServices.add(componentName)) { 2265 onUserStateChangedLocked(userState); 2266 } 2267 } 2268 2269 /** 2270 * Disables accessibility service specified by {@param componentName} for the {@param userId}. 2271 */ disableAccessibilityServiceLocked(ComponentName componentName, int userId)2272 private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) { 2273 final SettingsStringUtil.SettingStringHelper setting = 2274 new SettingStringHelper( 2275 mContext.getContentResolver(), 2276 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 2277 userId); 2278 setting.write(ComponentNameSet.remove(setting.read(), componentName)); 2279 2280 UserState userState = getUserStateLocked(userId); 2281 if (userState.mEnabledServices.remove(componentName)) { 2282 onUserStateChangedLocked(userState); 2283 } 2284 } 2285 2286 /** 2287 * AIDL-exposed method. System only. 2288 * Inform accessibility that a fingerprint gesture was performed 2289 * 2290 * @param gestureKeyCode The key code corresponding to the fingerprint gesture. 2291 * @return {@code true} if accessibility consumes the fingerprint gesture, {@code false} if it 2292 * doesn't. 2293 */ 2294 @Override sendFingerprintGesture(int gestureKeyCode)2295 public boolean sendFingerprintGesture(int gestureKeyCode) { 2296 synchronized(mLock) { 2297 if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) { 2298 throw new SecurityException("Only SYSTEM can call sendFingerprintGesture"); 2299 } 2300 } 2301 if (mFingerprintGestureDispatcher == null) { 2302 return false; 2303 } 2304 return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode); 2305 } 2306 2307 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)2308 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 2309 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 2310 synchronized (mLock) { 2311 pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)"); 2312 pw.println(); 2313 final int userCount = mUserStates.size(); 2314 for (int i = 0; i < userCount; i++) { 2315 UserState userState = mUserStates.valueAt(i); 2316 pw.append("User state[attributes:{id=" + userState.mUserId); 2317 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId)); 2318 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled); 2319 pw.append(", displayMagnificationEnabled=" 2320 + userState.mIsDisplayMagnificationEnabled); 2321 pw.append(", navBarMagnificationEnabled=" 2322 + userState.mIsNavBarMagnificationEnabled); 2323 pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled); 2324 if (userState.mUiAutomationService != null) { 2325 pw.append(", "); 2326 userState.mUiAutomationService.dump(fd, pw, args); 2327 pw.println(); 2328 } 2329 pw.append("}"); 2330 pw.println(); 2331 pw.append(" services:{"); 2332 final int serviceCount = userState.mBoundServices.size(); 2333 for (int j = 0; j < serviceCount; j++) { 2334 if (j > 0) { 2335 pw.append(", "); 2336 pw.println(); 2337 pw.append(" "); 2338 } 2339 Service service = userState.mBoundServices.get(j); 2340 service.dump(fd, pw, args); 2341 } 2342 pw.println("}]"); 2343 pw.println(); 2344 } 2345 if (mSecurityPolicy.mWindows != null) { 2346 final int windowCount = mSecurityPolicy.mWindows.size(); 2347 for (int j = 0; j < windowCount; j++) { 2348 if (j > 0) { 2349 pw.append(','); 2350 pw.println(); 2351 } 2352 pw.append("Window["); 2353 AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j); 2354 pw.append(window.toString()); 2355 pw.append(']'); 2356 } 2357 } 2358 } 2359 } 2360 2361 private class AccessibilityConnectionWrapper implements DeathRecipient { 2362 private final int mWindowId; 2363 private final int mUserId; 2364 private final IAccessibilityInteractionConnection mConnection; 2365 AccessibilityConnectionWrapper(int windowId, IAccessibilityInteractionConnection connection, int userId)2366 public AccessibilityConnectionWrapper(int windowId, 2367 IAccessibilityInteractionConnection connection, int userId) { 2368 mWindowId = windowId; 2369 mUserId = userId; 2370 mConnection = connection; 2371 } 2372 linkToDeath()2373 public void linkToDeath() throws RemoteException { 2374 mConnection.asBinder().linkToDeath(this, 0); 2375 } 2376 unlinkToDeath()2377 public void unlinkToDeath() { 2378 mConnection.asBinder().unlinkToDeath(this, 0); 2379 } 2380 2381 @Override binderDied()2382 public void binderDied() { 2383 unlinkToDeath(); 2384 synchronized (mLock) { 2385 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId); 2386 } 2387 } 2388 } 2389 2390 private final class MainHandler extends Handler { 2391 public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1; 2392 public static final int MSG_SEND_STATE_TO_CLIENTS = 2; 2393 public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3; 2394 public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5; 2395 public static final int MSG_UPDATE_INPUT_FILTER = 6; 2396 public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7; 2397 public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8; 2398 public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9; 2399 public static final int MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS = 10; 2400 public static final int MSG_UPDATE_FINGERPRINT = 11; 2401 public static final int MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS = 12; 2402 public static final int MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER = 13; 2403 public static final int MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER = 14; 2404 MainHandler(Looper looper)2405 public MainHandler(Looper looper) { 2406 super(looper); 2407 } 2408 2409 @Override handleMessage(Message msg)2410 public void handleMessage(Message msg) { 2411 final int type = msg.what; 2412 switch (type) { 2413 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: { 2414 AccessibilityEvent event = (AccessibilityEvent) msg.obj; 2415 synchronized (mLock) { 2416 if (mHasInputFilter && mInputFilter != null) { 2417 mInputFilter.notifyAccessibilityEvent(event); 2418 } 2419 } 2420 event.recycle(); 2421 } break; 2422 2423 case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: { 2424 KeyEvent event = (KeyEvent) msg.obj; 2425 final int policyFlags = msg.arg1; 2426 synchronized (mLock) { 2427 if (mHasInputFilter && mInputFilter != null) { 2428 mInputFilter.sendInputEvent(event, policyFlags); 2429 } 2430 } 2431 event.recycle(); 2432 } break; 2433 2434 case MSG_SEND_STATE_TO_CLIENTS: { 2435 final int clientState = msg.arg1; 2436 final int userId = msg.arg2; 2437 sendStateToClients(clientState, mGlobalClients); 2438 sendStateToClients(clientState, getUserClientsForId(userId)); 2439 } break; 2440 2441 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: { 2442 final int userId = msg.arg1; 2443 sendStateToClients(0, getUserClientsForId(userId)); 2444 } break; 2445 2446 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: { 2447 announceNewUserIfNeeded(); 2448 } break; 2449 2450 case MSG_UPDATE_INPUT_FILTER: { 2451 UserState userState = (UserState) msg.obj; 2452 updateInputFilter(userState); 2453 } break; 2454 2455 case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: { 2456 Service service = (Service) msg.obj; 2457 showEnableTouchExplorationDialog(service); 2458 } break; 2459 2460 case MSG_CLEAR_ACCESSIBILITY_FOCUS: { 2461 final int windowId = msg.arg1; 2462 getInteractionBridge().clearAccessibilityFocusNotLocked(windowId); 2463 } break; 2464 2465 case MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS: { 2466 final int userId = msg.arg1; 2467 notifyClientsOfServicesStateChange(mGlobalClients); 2468 notifyClientsOfServicesStateChange(getUserClientsForId(userId)); 2469 } break; 2470 2471 case MSG_UPDATE_FINGERPRINT: { 2472 updateFingerprintGestureHandling((UserState) msg.obj); 2473 } break; 2474 2475 case MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS: { 2476 final int userId = msg.arg1; 2477 final int relevantEventTypes = msg.arg2; 2478 final UserState userState; 2479 synchronized (mLock) { 2480 userState = getUserStateLocked(userId); 2481 } 2482 broadcastToClients(userState, (client) -> { 2483 try { 2484 client.setRelevantEventTypes(relevantEventTypes); 2485 } catch (RemoteException re) { 2486 /* ignore */ 2487 } 2488 }); 2489 } break; 2490 2491 case MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER: { 2492 synchronized (mLock) { 2493 if (mHasInputFilter && mInputFilter != null) { 2494 mInputFilter.notifyAccessibilityButtonClicked(); 2495 } 2496 } 2497 } break; 2498 2499 case MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER: { 2500 showAccessibilityButtonTargetSelection(); 2501 } break; 2502 } 2503 } 2504 announceNewUserIfNeeded()2505 private void announceNewUserIfNeeded() { 2506 synchronized (mLock) { 2507 UserState userState = getCurrentUserStateLocked(); 2508 if (userState.isHandlingAccessibilityEvents()) { 2509 UserManager userManager = (UserManager) mContext.getSystemService( 2510 Context.USER_SERVICE); 2511 String message = mContext.getString(R.string.user_switched, 2512 userManager.getUserInfo(mCurrentUserId).name); 2513 AccessibilityEvent event = AccessibilityEvent.obtain( 2514 AccessibilityEvent.TYPE_ANNOUNCEMENT); 2515 event.getText().add(message); 2516 sendAccessibilityEvent(event, mCurrentUserId); 2517 } 2518 } 2519 } 2520 getUserClientsForId(int userId)2521 private RemoteCallbackList<IAccessibilityManagerClient> getUserClientsForId(int userId) { 2522 final UserState userState; 2523 synchronized (mLock) { 2524 userState = getUserStateLocked(userId); 2525 } 2526 return userState.mUserClients; 2527 } 2528 sendStateToClients(int clientState, RemoteCallbackList<IAccessibilityManagerClient> clients)2529 private void sendStateToClients(int clientState, 2530 RemoteCallbackList<IAccessibilityManagerClient> clients) { 2531 clients.broadcast((client) -> { 2532 try { 2533 client.setState(clientState); 2534 } catch (RemoteException re) { 2535 /* ignore */ 2536 } 2537 }); 2538 } 2539 notifyClientsOfServicesStateChange( RemoteCallbackList<IAccessibilityManagerClient> clients)2540 private void notifyClientsOfServicesStateChange( 2541 RemoteCallbackList<IAccessibilityManagerClient> clients) { 2542 try { 2543 final int userClientCount = clients.beginBroadcast(); 2544 for (int i = 0; i < userClientCount; i++) { 2545 IAccessibilityManagerClient client = clients.getBroadcastItem(i); 2546 try { 2547 client.notifyServicesStateChanged(); 2548 } catch (RemoteException re) { 2549 /* ignore */ 2550 } 2551 } 2552 } finally { 2553 clients.finishBroadcast(); 2554 } 2555 } 2556 } 2557 findWindowIdLocked(IBinder token)2558 private int findWindowIdLocked(IBinder token) { 2559 final int globalIndex = mGlobalWindowTokens.indexOfValue(token); 2560 if (globalIndex >= 0) { 2561 return mGlobalWindowTokens.keyAt(globalIndex); 2562 } 2563 UserState userState = getCurrentUserStateLocked(); 2564 final int userIndex = userState.mWindowTokens.indexOfValue(token); 2565 if (userIndex >= 0) { 2566 return userState.mWindowTokens.keyAt(userIndex); 2567 } 2568 return -1; 2569 } 2570 ensureWindowsAvailableTimed()2571 private void ensureWindowsAvailableTimed() { 2572 synchronized (mLock) { 2573 if (mSecurityPolicy.mWindows != null) { 2574 return; 2575 } 2576 // If we have no registered callback, update the state we 2577 // we may have to register one but it didn't happen yet. 2578 if (mWindowsForAccessibilityCallback == null) { 2579 UserState userState = getCurrentUserStateLocked(); 2580 onUserStateChangedLocked(userState); 2581 } 2582 // We have no windows but do not care about them, done. 2583 if (mWindowsForAccessibilityCallback == null) { 2584 return; 2585 } 2586 2587 // Wait for the windows with a timeout. 2588 final long startMillis = SystemClock.uptimeMillis(); 2589 while (mSecurityPolicy.mWindows == null) { 2590 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 2591 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; 2592 if (remainMillis <= 0) { 2593 return; 2594 } 2595 try { 2596 mLock.wait(remainMillis); 2597 } catch (InterruptedException ie) { 2598 /* ignore */ 2599 } 2600 } 2601 } 2602 } 2603 getMagnificationController()2604 MagnificationController getMagnificationController() { 2605 synchronized (mLock) { 2606 if (mMagnificationController == null) { 2607 mMagnificationController = new MagnificationController(mContext, this, mLock); 2608 mMagnificationController.setUserId(mCurrentUserId); 2609 } 2610 return mMagnificationController; 2611 } 2612 } 2613 2614 /** 2615 * This class represents an accessibility service. It stores all per service 2616 * data required for the service management, provides API for starting/stopping the 2617 * service and is responsible for adding/removing the service in the data structures 2618 * for service management. The class also exposes configuration interface that is 2619 * passed to the service it represents as soon it is bound. It also serves as the 2620 * connection for the service. 2621 */ 2622 class Service extends IAccessibilityServiceConnection.Stub 2623 implements ServiceConnection, DeathRecipient, KeyEventDispatcher.KeyEventFilter, 2624 FingerprintGestureDispatcher.FingerprintGestureClient { 2625 2626 final int mUserId; 2627 2628 int mId = 0; 2629 2630 AccessibilityServiceInfo mAccessibilityServiceInfo; 2631 2632 // The service that's bound to this instance. Whenever this value is non-null, this 2633 // object is registered as a death recipient 2634 IBinder mService; 2635 2636 IAccessibilityServiceClient mServiceInterface; 2637 2638 int mEventTypes; 2639 2640 int mFeedbackType; 2641 2642 Set<String> mPackageNames = new HashSet<>(); 2643 2644 boolean mIsDefault; 2645 2646 boolean mRequestTouchExplorationMode; 2647 2648 boolean mRequestFilterKeyEvents; 2649 2650 boolean mRetrieveInteractiveWindows; 2651 2652 boolean mCaptureFingerprintGestures; 2653 2654 boolean mRequestAccessibilityButton; 2655 2656 boolean mReceivedAccessibilityButtonCallbackSinceBind; 2657 2658 boolean mLastAccessibilityButtonCallbackState; 2659 2660 int mFetchFlags; 2661 2662 long mNotificationTimeout; 2663 2664 ComponentName mComponentName; 2665 2666 Intent mIntent; 2667 2668 boolean mIsAutomation; 2669 2670 final ResolveInfo mResolveInfo; 2671 2672 final IBinder mOverlayWindowToken = new Binder(); 2673 2674 // the events pending events to be dispatched to this service 2675 final SparseArray<AccessibilityEvent> mPendingEvents = 2676 new SparseArray<>(); 2677 2678 boolean mWasConnectedAndDied; 2679 2680 /** Whether this service relies on its {@link AccessibilityCache} being up to date */ 2681 boolean mUsesAccessibilityCache = false; 2682 2683 // Handler only for dispatching accessibility events since we use event 2684 // types as message types allowing us to remove messages per event type. 2685 public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) { 2686 @Override 2687 public void handleMessage(Message message) { 2688 final int eventType = message.what; 2689 AccessibilityEvent event = (AccessibilityEvent) message.obj; 2690 boolean serviceWantsEvent = message.arg1 != 0; 2691 notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent); 2692 } 2693 }; 2694 2695 // Handler for scheduling method invocations on the main thread. 2696 public final InvocationHandler mInvocationHandler = new InvocationHandler( 2697 mMainHandler.getLooper()); 2698 Service(int userId, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo)2699 public Service(int userId, ComponentName componentName, 2700 AccessibilityServiceInfo accessibilityServiceInfo) { 2701 mUserId = userId; 2702 mResolveInfo = accessibilityServiceInfo.getResolveInfo(); 2703 mId = sIdCounter++; 2704 mComponentName = componentName; 2705 mAccessibilityServiceInfo = accessibilityServiceInfo; 2706 mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName)); 2707 if (!mIsAutomation) { 2708 mIntent = new Intent().setComponent(mComponentName); 2709 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, 2710 com.android.internal.R.string.accessibility_binding_label); 2711 final long idendtity = Binder.clearCallingIdentity(); 2712 try { 2713 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 2714 mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); 2715 } finally { 2716 Binder.restoreCallingIdentity(idendtity); 2717 } 2718 } 2719 setDynamicallyConfigurableProperties(accessibilityServiceInfo); 2720 } 2721 2722 @Override onKeyEvent(KeyEvent keyEvent, int sequenceNumber)2723 public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) { 2724 if (!mRequestFilterKeyEvents || (mServiceInterface == null)) { 2725 return false; 2726 } 2727 if((mAccessibilityServiceInfo.getCapabilities() 2728 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { 2729 return false; 2730 } 2731 try { 2732 mServiceInterface.onKeyEvent(keyEvent, sequenceNumber); 2733 } catch (RemoteException e) { 2734 return false; 2735 } 2736 return true; 2737 } 2738 2739 @Override isCapturingFingerprintGestures()2740 public boolean isCapturingFingerprintGestures() { 2741 return (mServiceInterface != null) 2742 && mSecurityPolicy.canCaptureFingerprintGestures(this) 2743 && mCaptureFingerprintGestures; 2744 } 2745 2746 @Override onFingerprintGestureDetectionActiveChanged(boolean active)2747 public void onFingerprintGestureDetectionActiveChanged(boolean active) { 2748 if (!isCapturingFingerprintGestures()) { 2749 return; 2750 } 2751 IAccessibilityServiceClient serviceInterface; 2752 synchronized (mLock) { 2753 serviceInterface = mServiceInterface; 2754 } 2755 if (serviceInterface != null) { 2756 try { 2757 mServiceInterface.onFingerprintCapturingGesturesChanged(active); 2758 } catch (RemoteException e) { 2759 } 2760 } 2761 } 2762 2763 @Override onFingerprintGesture(int gesture)2764 public void onFingerprintGesture(int gesture) { 2765 if (!isCapturingFingerprintGestures()) { 2766 return; 2767 } 2768 IAccessibilityServiceClient serviceInterface; 2769 synchronized (mLock) { 2770 serviceInterface = mServiceInterface; 2771 } 2772 if (serviceInterface != null) { 2773 try { 2774 mServiceInterface.onFingerprintGesture(gesture); 2775 } catch (RemoteException e) { 2776 } 2777 } 2778 } 2779 setDynamicallyConfigurableProperties(AccessibilityServiceInfo info)2780 public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { 2781 mEventTypes = info.eventTypes; 2782 mFeedbackType = info.feedbackType; 2783 String[] packageNames = info.packageNames; 2784 if (packageNames != null) { 2785 mPackageNames.addAll(Arrays.asList(packageNames)); 2786 } 2787 mNotificationTimeout = info.notificationTimeout; 2788 mIsDefault = (info.flags & DEFAULT) != 0; 2789 2790 if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 2791 >= Build.VERSION_CODES.JELLY_BEAN) { 2792 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { 2793 mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 2794 } else { 2795 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 2796 } 2797 } 2798 2799 if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { 2800 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 2801 } else { 2802 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 2803 } 2804 2805 mRequestTouchExplorationMode = (info.flags 2806 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 2807 mRequestFilterKeyEvents = (info.flags 2808 & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; 2809 mRetrieveInteractiveWindows = (info.flags 2810 & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; 2811 mCaptureFingerprintGestures = (info.flags 2812 & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0; 2813 mRequestAccessibilityButton = (info.flags 2814 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; 2815 } 2816 2817 /** 2818 * Binds to the accessibility service. 2819 * 2820 * @return True if binding is successful. 2821 */ bindLocked()2822 public boolean bindLocked() { 2823 UserState userState = getUserStateLocked(mUserId); 2824 if (!mIsAutomation) { 2825 final long identity = Binder.clearCallingIdentity(); 2826 try { 2827 if (mService == null && mContext.bindServiceAsUser( 2828 mIntent, this, 2829 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 2830 new UserHandle(mUserId))) { 2831 userState.mBindingServices.add(mComponentName); 2832 } 2833 } finally { 2834 Binder.restoreCallingIdentity(identity); 2835 } 2836 } else { 2837 userState.mBindingServices.add(mComponentName); 2838 mMainHandler.post(new Runnable() { 2839 @Override 2840 public void run() { 2841 // Simulate asynchronous connection since in onServiceConnected 2842 // we may modify the state data in case of an error but bind is 2843 // called while iterating over the data and bad things can happen. 2844 onServiceConnected(mComponentName, 2845 userState.mUiAutomationServiceClient.asBinder()); 2846 } 2847 }); 2848 userState.mUiAutomationService = this; 2849 } 2850 return false; 2851 } 2852 2853 /** 2854 * Unbinds from the accessibility service and removes it from the data 2855 * structures for service management. 2856 * 2857 * @return True if unbinding is successful. 2858 */ unbindLocked()2859 public boolean unbindLocked() { 2860 UserState userState = getUserStateLocked(mUserId); 2861 getKeyEventDispatcher().flush(this); 2862 if (!mIsAutomation) { 2863 mContext.unbindService(this); 2864 } else { 2865 userState.destroyUiAutomationService(); 2866 } 2867 removeServiceLocked(this, userState); 2868 resetLocked(); 2869 return true; 2870 } 2871 2872 @Override disableSelf()2873 public void disableSelf() { 2874 synchronized(mLock) { 2875 UserState userState = getUserStateLocked(mUserId); 2876 if (userState.mEnabledServices.remove(mComponentName)) { 2877 final long identity = Binder.clearCallingIdentity(); 2878 try { 2879 persistComponentNamesToSettingLocked( 2880 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 2881 userState.mEnabledServices, mUserId); 2882 } finally { 2883 Binder.restoreCallingIdentity(identity); 2884 } 2885 onUserStateChangedLocked(userState); 2886 } 2887 } 2888 } 2889 canReceiveEventsLocked()2890 public boolean canReceiveEventsLocked() { 2891 return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); 2892 } 2893 2894 @Override setOnKeyEventResult(boolean handled, int sequence)2895 public void setOnKeyEventResult(boolean handled, int sequence) { 2896 getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); 2897 } 2898 2899 @Override getServiceInfo()2900 public AccessibilityServiceInfo getServiceInfo() { 2901 synchronized (mLock) { 2902 return mAccessibilityServiceInfo; 2903 } 2904 } 2905 canRetrieveInteractiveWindowsLocked()2906 public boolean canRetrieveInteractiveWindowsLocked() { 2907 return mSecurityPolicy.canRetrieveWindowContentLocked(this) 2908 && mRetrieveInteractiveWindows; 2909 } 2910 2911 @Override setServiceInfo(AccessibilityServiceInfo info)2912 public void setServiceInfo(AccessibilityServiceInfo info) { 2913 final long identity = Binder.clearCallingIdentity(); 2914 try { 2915 synchronized (mLock) { 2916 // If the XML manifest had data to configure the service its info 2917 // should be already set. In such a case update only the dynamically 2918 // configurable properties. 2919 AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; 2920 if (oldInfo != null) { 2921 oldInfo.updateDynamicallyConfigurableProperties(info); 2922 setDynamicallyConfigurableProperties(oldInfo); 2923 } else { 2924 setDynamicallyConfigurableProperties(info); 2925 } 2926 UserState userState = getUserStateLocked(mUserId); 2927 onUserStateChangedLocked(userState); 2928 scheduleNotifyClientsOfServicesStateChange(userState); 2929 } 2930 } finally { 2931 Binder.restoreCallingIdentity(identity); 2932 } 2933 } 2934 2935 @Override onServiceConnected(ComponentName componentName, IBinder service)2936 public void onServiceConnected(ComponentName componentName, IBinder service) { 2937 synchronized (mLock) { 2938 if (mService != service) { 2939 if (mService != null) { 2940 mService.unlinkToDeath(this, 0); 2941 } 2942 mService = service; 2943 try { 2944 mService.linkToDeath(this, 0); 2945 } catch (RemoteException re) { 2946 Slog.e(LOG_TAG, "Failed registering death link"); 2947 binderDied(); 2948 return; 2949 } 2950 } 2951 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); 2952 UserState userState = getUserStateLocked(mUserId); 2953 addServiceLocked(this, userState); 2954 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) { 2955 userState.mBindingServices.remove(mComponentName); 2956 mWasConnectedAndDied = false; 2957 try { 2958 mServiceInterface.init(this, mId, mOverlayWindowToken); 2959 onUserStateChangedLocked(userState); 2960 } catch (RemoteException re) { 2961 Slog.w(LOG_TAG, "Error while setting connection for service: " 2962 + service, re); 2963 binderDied(); 2964 } 2965 } else { 2966 binderDied(); 2967 } 2968 } 2969 } 2970 isCalledForCurrentUserLocked()2971 private boolean isCalledForCurrentUserLocked() { 2972 // We treat calls from a profile as if made by its parent as profiles 2973 // share the accessibility state of the parent. The call below 2974 // performs the current profile parent resolution. 2975 final int resolvedUserId = mSecurityPolicy 2976 .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT); 2977 return resolvedUserId == mCurrentUserId; 2978 } 2979 2980 @Override getWindows()2981 public List<AccessibilityWindowInfo> getWindows() { 2982 ensureWindowsAvailableTimed(); 2983 synchronized (mLock) { 2984 if (!isCalledForCurrentUserLocked()) { 2985 return null; 2986 } 2987 final boolean permissionGranted = 2988 mSecurityPolicy.canRetrieveWindowsLocked(this); 2989 if (!permissionGranted) { 2990 return null; 2991 } 2992 if (mSecurityPolicy.mWindows == null) { 2993 return null; 2994 } 2995 List<AccessibilityWindowInfo> windows = new ArrayList<>(); 2996 final int windowCount = mSecurityPolicy.mWindows.size(); 2997 for (int i = 0; i < windowCount; i++) { 2998 AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i); 2999 AccessibilityWindowInfo windowClone = 3000 AccessibilityWindowInfo.obtain(window); 3001 windowClone.setConnectionId(mId); 3002 windows.add(windowClone); 3003 } 3004 return windows; 3005 } 3006 } 3007 3008 @Override getWindow(int windowId)3009 public AccessibilityWindowInfo getWindow(int windowId) { 3010 ensureWindowsAvailableTimed(); 3011 synchronized (mLock) { 3012 if (!isCalledForCurrentUserLocked()) { 3013 return null; 3014 } 3015 final boolean permissionGranted = 3016 mSecurityPolicy.canRetrieveWindowsLocked(this); 3017 if (!permissionGranted) { 3018 return null; 3019 } 3020 AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId); 3021 if (window != null) { 3022 AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); 3023 windowClone.setConnectionId(mId); 3024 return windowClone; 3025 } 3026 return null; 3027 } 3028 } 3029 3030 @Override findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewIdResName, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3031 public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, 3032 long accessibilityNodeId, String viewIdResName, int interactionId, 3033 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3034 throws RemoteException { 3035 final int resolvedWindowId; 3036 IAccessibilityInteractionConnection connection = null; 3037 Region partialInteractiveRegion = Region.obtain(); 3038 MagnificationSpec spec; 3039 synchronized (mLock) { 3040 mUsesAccessibilityCache = true; 3041 if (!isCalledForCurrentUserLocked()) { 3042 return false; 3043 } 3044 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3045 final boolean permissionGranted = 3046 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3047 if (!permissionGranted) { 3048 return false; 3049 } else { 3050 connection = getConnectionLocked(resolvedWindowId); 3051 if (connection == null) { 3052 return false; 3053 } 3054 } 3055 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3056 resolvedWindowId, partialInteractiveRegion)) { 3057 partialInteractiveRegion.recycle(); 3058 partialInteractiveRegion = null; 3059 } 3060 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3061 } 3062 final int interrogatingPid = Binder.getCallingPid(); 3063 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3064 interrogatingPid, interrogatingTid); 3065 final long identityToken = Binder.clearCallingIdentity(); 3066 try { 3067 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, 3068 partialInteractiveRegion, interactionId, callback, mFetchFlags, 3069 interrogatingPid, interrogatingTid, spec); 3070 return true; 3071 } catch (RemoteException re) { 3072 if (DEBUG) { 3073 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); 3074 } 3075 } finally { 3076 Binder.restoreCallingIdentity(identityToken); 3077 // Recycle if passed to another process. 3078 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3079 partialInteractiveRegion.recycle(); 3080 } 3081 } 3082 return false; 3083 } 3084 3085 @Override findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3086 public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, 3087 long accessibilityNodeId, String text, int interactionId, 3088 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3089 throws RemoteException { 3090 final int resolvedWindowId; 3091 IAccessibilityInteractionConnection connection = null; 3092 Region partialInteractiveRegion = Region.obtain(); 3093 MagnificationSpec spec; 3094 synchronized (mLock) { 3095 mUsesAccessibilityCache = true; 3096 if (!isCalledForCurrentUserLocked()) { 3097 return false; 3098 } 3099 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3100 final boolean permissionGranted = 3101 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3102 if (!permissionGranted) { 3103 return false; 3104 } else { 3105 connection = getConnectionLocked(resolvedWindowId); 3106 if (connection == null) { 3107 return false; 3108 } 3109 } 3110 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3111 resolvedWindowId, partialInteractiveRegion)) { 3112 partialInteractiveRegion.recycle(); 3113 partialInteractiveRegion = null; 3114 } 3115 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3116 } 3117 final int interrogatingPid = Binder.getCallingPid(); 3118 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3119 interrogatingPid, interrogatingTid); 3120 final long identityToken = Binder.clearCallingIdentity(); 3121 try { 3122 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, 3123 partialInteractiveRegion, interactionId, callback, mFetchFlags, 3124 interrogatingPid, interrogatingTid, spec); 3125 return true; 3126 } catch (RemoteException re) { 3127 if (DEBUG) { 3128 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); 3129 } 3130 } finally { 3131 Binder.restoreCallingIdentity(identityToken); 3132 // Recycle if passed to another process. 3133 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3134 partialInteractiveRegion.recycle(); 3135 } 3136 } 3137 return false; 3138 } 3139 3140 @Override findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid, Bundle arguments)3141 public boolean findAccessibilityNodeInfoByAccessibilityId( 3142 int accessibilityWindowId, long accessibilityNodeId, int interactionId, 3143 IAccessibilityInteractionConnectionCallback callback, int flags, 3144 long interrogatingTid, Bundle arguments) throws RemoteException { 3145 final int resolvedWindowId; 3146 IAccessibilityInteractionConnection connection = null; 3147 Region partialInteractiveRegion = Region.obtain(); 3148 MagnificationSpec spec; 3149 synchronized (mLock) { 3150 mUsesAccessibilityCache = true; 3151 if (!isCalledForCurrentUserLocked()) { 3152 return false; 3153 } 3154 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3155 final boolean permissionGranted = 3156 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3157 if (!permissionGranted) { 3158 return false; 3159 } else { 3160 connection = getConnectionLocked(resolvedWindowId); 3161 if (connection == null) { 3162 return false; 3163 } 3164 } 3165 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3166 resolvedWindowId, partialInteractiveRegion)) { 3167 partialInteractiveRegion.recycle(); 3168 partialInteractiveRegion = null; 3169 } 3170 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3171 } 3172 final int interrogatingPid = Binder.getCallingPid(); 3173 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3174 interrogatingPid, interrogatingTid); 3175 final long identityToken = Binder.clearCallingIdentity(); 3176 try { 3177 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, 3178 partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, 3179 interrogatingPid, interrogatingTid, spec, arguments); 3180 return true; 3181 } catch (RemoteException re) { 3182 if (DEBUG) { 3183 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); 3184 } 3185 } finally { 3186 Binder.restoreCallingIdentity(identityToken); 3187 // Recycle if passed to another process. 3188 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3189 partialInteractiveRegion.recycle(); 3190 } 3191 } 3192 return false; 3193 } 3194 3195 @Override findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3196 public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, 3197 int focusType, int interactionId, 3198 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3199 throws RemoteException { 3200 final int resolvedWindowId; 3201 IAccessibilityInteractionConnection connection = null; 3202 Region partialInteractiveRegion = Region.obtain(); 3203 MagnificationSpec spec; 3204 synchronized (mLock) { 3205 if (!isCalledForCurrentUserLocked()) { 3206 return false; 3207 } 3208 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( 3209 accessibilityWindowId, focusType); 3210 final boolean permissionGranted = 3211 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3212 if (!permissionGranted) { 3213 return false; 3214 } else { 3215 connection = getConnectionLocked(resolvedWindowId); 3216 if (connection == null) { 3217 return false; 3218 } 3219 } 3220 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3221 resolvedWindowId, partialInteractiveRegion)) { 3222 partialInteractiveRegion.recycle(); 3223 partialInteractiveRegion = null; 3224 } 3225 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3226 } 3227 final int interrogatingPid = Binder.getCallingPid(); 3228 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3229 interrogatingPid, interrogatingTid); 3230 final long identityToken = Binder.clearCallingIdentity(); 3231 try { 3232 connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, 3233 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 3234 spec); 3235 return true; 3236 } catch (RemoteException re) { 3237 if (DEBUG) { 3238 Slog.e(LOG_TAG, "Error calling findFocus()"); 3239 } 3240 } finally { 3241 Binder.restoreCallingIdentity(identityToken); 3242 // Recycle if passed to another process. 3243 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3244 partialInteractiveRegion.recycle(); 3245 } 3246 } 3247 return false; 3248 } 3249 3250 @Override focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3251 public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, 3252 int direction, int interactionId, 3253 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3254 throws RemoteException { 3255 final int resolvedWindowId; 3256 IAccessibilityInteractionConnection connection = null; 3257 Region partialInteractiveRegion = Region.obtain(); 3258 MagnificationSpec spec; 3259 synchronized (mLock) { 3260 if (!isCalledForCurrentUserLocked()) { 3261 return false; 3262 } 3263 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3264 final boolean permissionGranted = 3265 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3266 if (!permissionGranted) { 3267 return false; 3268 } else { 3269 connection = getConnectionLocked(resolvedWindowId); 3270 if (connection == null) { 3271 return false; 3272 } 3273 } 3274 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3275 resolvedWindowId, partialInteractiveRegion)) { 3276 partialInteractiveRegion.recycle(); 3277 partialInteractiveRegion = null; 3278 } 3279 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3280 } 3281 final int interrogatingPid = Binder.getCallingPid(); 3282 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3283 interrogatingPid, interrogatingTid); 3284 final long identityToken = Binder.clearCallingIdentity(); 3285 try { 3286 connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, 3287 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 3288 spec); 3289 return true; 3290 } catch (RemoteException re) { 3291 if (DEBUG) { 3292 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); 3293 } 3294 } finally { 3295 Binder.restoreCallingIdentity(identityToken); 3296 // Recycle if passed to another process. 3297 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3298 partialInteractiveRegion.recycle(); 3299 } 3300 } 3301 return false; 3302 } 3303 3304 @Override sendGesture(int sequence, ParceledListSlice gestureSteps)3305 public void sendGesture(int sequence, ParceledListSlice gestureSteps) { 3306 synchronized (mLock) { 3307 if (mSecurityPolicy.canPerformGestures(this)) { 3308 final long endMillis = 3309 SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS; 3310 while ((mMotionEventInjector == null) 3311 && (SystemClock.uptimeMillis() < endMillis)) { 3312 try { 3313 mLock.wait(endMillis - SystemClock.uptimeMillis()); 3314 } catch (InterruptedException ie) { 3315 /* ignore */ 3316 } 3317 } 3318 if (mMotionEventInjector != null) { 3319 List<GestureDescription.GestureStep> steps = gestureSteps.getList(); 3320 mMotionEventInjector.injectEvents(steps, mServiceInterface, sequence); 3321 return; 3322 } else { 3323 Slog.e(LOG_TAG, "MotionEventInjector installation timed out"); 3324 } 3325 } 3326 } 3327 try { 3328 mServiceInterface.onPerformGestureResult(sequence, false); 3329 } catch (RemoteException re) { 3330 Slog.e(LOG_TAG, "Error sending motion event injection failure to " 3331 + mServiceInterface, re); 3332 } 3333 } 3334 3335 @Override performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3336 public boolean performAccessibilityAction(int accessibilityWindowId, 3337 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 3338 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3339 throws RemoteException { 3340 final int resolvedWindowId; 3341 IAccessibilityInteractionConnection connection = null; 3342 synchronized (mLock) { 3343 if (!isCalledForCurrentUserLocked()) { 3344 return false; 3345 } 3346 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3347 final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 3348 this, resolvedWindowId); 3349 if (!permissionGranted) { 3350 return false; 3351 } else { 3352 connection = getConnectionLocked(resolvedWindowId); 3353 if (connection == null) { 3354 return false; 3355 } 3356 AccessibilityWindowInfo windowInfo = 3357 mSecurityPolicy.findWindowById(resolvedWindowId); 3358 if ((windowInfo != null) && windowInfo.inPictureInPicture()) { 3359 boolean isA11yFocusAction = 3360 (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) 3361 || (action == 3362 AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 3363 if ((mPictureInPictureActionReplacingConnection != null) 3364 && !isA11yFocusAction) { 3365 connection = mPictureInPictureActionReplacingConnection.mConnection; 3366 } 3367 } 3368 } 3369 } 3370 final int interrogatingPid = Binder.getCallingPid(); 3371 final long identityToken = Binder.clearCallingIdentity(); 3372 try { 3373 // Regardless of whether or not the action succeeds, it was generated by an 3374 // accessibility service that is driven by user actions, so note user activity. 3375 mPowerManager.userActivity(SystemClock.uptimeMillis(), 3376 PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); 3377 3378 connection.performAccessibilityAction(accessibilityNodeId, action, arguments, 3379 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid); 3380 } catch (RemoteException re) { 3381 if (DEBUG) { 3382 Slog.e(LOG_TAG, "Error calling performAccessibilityAction()"); 3383 } 3384 } finally { 3385 Binder.restoreCallingIdentity(identityToken); 3386 } 3387 return true; 3388 } 3389 3390 @Override performGlobalAction(int action)3391 public boolean performGlobalAction(int action) { 3392 synchronized (mLock) { 3393 if (!isCalledForCurrentUserLocked()) { 3394 return false; 3395 } 3396 } 3397 final long identity = Binder.clearCallingIdentity(); 3398 try { 3399 mPowerManager.userActivity(SystemClock.uptimeMillis(), 3400 PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); 3401 switch (action) { 3402 case AccessibilityService.GLOBAL_ACTION_BACK: { 3403 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK); 3404 } return true; 3405 case AccessibilityService.GLOBAL_ACTION_HOME: { 3406 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME); 3407 } return true; 3408 case AccessibilityService.GLOBAL_ACTION_RECENTS: { 3409 return openRecents(); 3410 } 3411 case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: { 3412 expandNotifications(); 3413 } return true; 3414 case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: { 3415 expandQuickSettings(); 3416 } return true; 3417 case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: { 3418 showGlobalActions(); 3419 } return true; 3420 case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: { 3421 toggleSplitScreen(); 3422 } return true; 3423 } 3424 return false; 3425 } finally { 3426 Binder.restoreCallingIdentity(identity); 3427 } 3428 } 3429 3430 @Override isFingerprintGestureDetectionAvailable()3431 public boolean isFingerprintGestureDetectionAvailable() { 3432 return isCapturingFingerprintGestures() 3433 && (mFingerprintGestureDispatcher != null) 3434 && mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable(); 3435 } 3436 3437 @Override getMagnificationScale()3438 public float getMagnificationScale() { 3439 synchronized (mLock) { 3440 if (!isCalledForCurrentUserLocked()) { 3441 return 1.0f; 3442 } 3443 } 3444 final long identity = Binder.clearCallingIdentity(); 3445 try { 3446 return getMagnificationController().getScale(); 3447 } finally { 3448 Binder.restoreCallingIdentity(identity); 3449 } 3450 } 3451 3452 @Override getMagnificationRegion()3453 public Region getMagnificationRegion() { 3454 synchronized (mLock) { 3455 final Region region = Region.obtain(); 3456 if (!isCalledForCurrentUserLocked()) { 3457 return region; 3458 } 3459 MagnificationController magnificationController = getMagnificationController(); 3460 boolean forceRegistration = mSecurityPolicy.canControlMagnification(this); 3461 boolean initiallyRegistered = magnificationController.isRegisteredLocked(); 3462 if (!initiallyRegistered && forceRegistration) { 3463 magnificationController.register(); 3464 } 3465 final long identity = Binder.clearCallingIdentity(); 3466 try { 3467 magnificationController.getMagnificationRegion(region); 3468 return region; 3469 } finally { 3470 Binder.restoreCallingIdentity(identity); 3471 if (!initiallyRegistered && forceRegistration) { 3472 magnificationController.unregister(); 3473 } 3474 } 3475 } 3476 } 3477 3478 @Override getMagnificationCenterX()3479 public float getMagnificationCenterX() { 3480 synchronized (mLock) { 3481 if (!isCalledForCurrentUserLocked()) { 3482 return 0.0f; 3483 } 3484 } 3485 final long identity = Binder.clearCallingIdentity(); 3486 try { 3487 return getMagnificationController().getCenterX(); 3488 } finally { 3489 Binder.restoreCallingIdentity(identity); 3490 } 3491 } 3492 3493 @Override getMagnificationCenterY()3494 public float getMagnificationCenterY() { 3495 synchronized (mLock) { 3496 if (!isCalledForCurrentUserLocked()) { 3497 return 0.0f; 3498 } 3499 } 3500 final long identity = Binder.clearCallingIdentity(); 3501 try { 3502 return getMagnificationController().getCenterY(); 3503 } finally { 3504 Binder.restoreCallingIdentity(identity); 3505 } 3506 } 3507 3508 @Override resetMagnification(boolean animate)3509 public boolean resetMagnification(boolean animate) { 3510 synchronized (mLock) { 3511 if (!isCalledForCurrentUserLocked()) { 3512 return false; 3513 } 3514 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this); 3515 if (!permissionGranted) { 3516 return false; 3517 } 3518 } 3519 final long identity = Binder.clearCallingIdentity(); 3520 try { 3521 return getMagnificationController().reset(animate); 3522 } finally { 3523 Binder.restoreCallingIdentity(identity); 3524 } 3525 } 3526 3527 @Override setMagnificationScaleAndCenter(float scale, float centerX, float centerY, boolean animate)3528 public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY, 3529 boolean animate) { 3530 synchronized (mLock) { 3531 if (!isCalledForCurrentUserLocked()) { 3532 return false; 3533 } 3534 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this); 3535 if (!permissionGranted) { 3536 return false; 3537 } 3538 final long identity = Binder.clearCallingIdentity(); 3539 try { 3540 MagnificationController magnificationController = getMagnificationController(); 3541 if (!magnificationController.isRegisteredLocked()) { 3542 magnificationController.register(); 3543 } 3544 return magnificationController 3545 .setScaleAndCenter(scale, centerX, centerY, animate, mId); 3546 } finally { 3547 Binder.restoreCallingIdentity(identity); 3548 } 3549 } 3550 } 3551 3552 @Override setMagnificationCallbackEnabled(boolean enabled)3553 public void setMagnificationCallbackEnabled(boolean enabled) { 3554 mInvocationHandler.setMagnificationCallbackEnabled(enabled); 3555 } 3556 3557 @Override setSoftKeyboardShowMode(int showMode)3558 public boolean setSoftKeyboardShowMode(int showMode) { 3559 final UserState userState; 3560 synchronized (mLock) { 3561 if (!isCalledForCurrentUserLocked()) { 3562 return false; 3563 } 3564 3565 userState = getCurrentUserStateLocked(); 3566 } 3567 3568 final long identity = Binder.clearCallingIdentity(); 3569 try { 3570 // Keep track of the last service to request a non-default show mode. The show mode 3571 // should be restored to default should this service be disabled. 3572 if (showMode == Settings.Secure.SHOW_MODE_AUTO) { 3573 userState.mServiceChangingSoftKeyboardMode = null; 3574 } else { 3575 userState.mServiceChangingSoftKeyboardMode = mComponentName; 3576 } 3577 3578 Settings.Secure.putIntForUser(mContext.getContentResolver(), 3579 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode, 3580 userState.mUserId); 3581 } finally { 3582 Binder.restoreCallingIdentity(identity); 3583 } 3584 return true; 3585 } 3586 3587 @Override setSoftKeyboardCallbackEnabled(boolean enabled)3588 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 3589 mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled); 3590 } 3591 3592 @Override isAccessibilityButtonAvailable()3593 public boolean isAccessibilityButtonAvailable() { 3594 final UserState userState; 3595 synchronized (mLock) { 3596 if (!isCalledForCurrentUserLocked()) { 3597 return false; 3598 } 3599 userState = getCurrentUserStateLocked(); 3600 return isAccessibilityButtonAvailableLocked(userState); 3601 } 3602 } 3603 3604 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)3605 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 3606 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 3607 synchronized (mLock) { 3608 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() 3609 .loadLabel(mContext.getPackageManager())); 3610 pw.append(", feedbackType" 3611 + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); 3612 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); 3613 pw.append(", eventTypes=" 3614 + AccessibilityEvent.eventTypeToString(mEventTypes)); 3615 pw.append(", notificationTimeout=" + mNotificationTimeout); 3616 pw.append("]"); 3617 } 3618 } 3619 3620 @Override onServiceDisconnected(ComponentName componentName)3621 public void onServiceDisconnected(ComponentName componentName) { 3622 binderDied(); 3623 } 3624 onAdded()3625 public void onAdded() throws RemoteException { 3626 final long identity = Binder.clearCallingIdentity(); 3627 try { 3628 mWindowManagerService.addWindowToken(mOverlayWindowToken, 3629 TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY); 3630 } finally { 3631 Binder.restoreCallingIdentity(identity); 3632 } 3633 } 3634 onRemoved()3635 public void onRemoved() { 3636 final long identity = Binder.clearCallingIdentity(); 3637 try { 3638 mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY); 3639 } finally { 3640 Binder.restoreCallingIdentity(identity); 3641 } 3642 } 3643 resetLocked()3644 public void resetLocked() { 3645 try { 3646 // Clear the proxy in the other process so this 3647 // IAccessibilityServiceConnection can be garbage collected. 3648 if (mServiceInterface != null) { 3649 mServiceInterface.init(null, mId, null); 3650 } 3651 } catch (RemoteException re) { 3652 /* ignore */ 3653 } 3654 if (mService != null) { 3655 mService.unlinkToDeath(this, 0); 3656 mService = null; 3657 } 3658 mServiceInterface = null; 3659 mReceivedAccessibilityButtonCallbackSinceBind = false; 3660 } 3661 isConnectedLocked()3662 public boolean isConnectedLocked() { 3663 return (mService != null); 3664 } 3665 binderDied()3666 public void binderDied() { 3667 synchronized (mLock) { 3668 // It is possible that this service's package was force stopped during 3669 // whose handling the death recipient is unlinked and still get a call 3670 // on binderDied since the call was made before we unlink but was 3671 // waiting on the lock we held during the force stop handling. 3672 if (!isConnectedLocked()) { 3673 return; 3674 } 3675 mWasConnectedAndDied = true; 3676 getKeyEventDispatcher().flush(this); 3677 UserState userState = getUserStateLocked(mUserId); 3678 resetLocked(); 3679 if (mIsAutomation) { 3680 // This is typically done when unbinding, but UiAutomation isn't bound. 3681 removeServiceLocked(this, userState); 3682 // We no longer have an automation service, so restore 3683 // the state based on values in the settings database. 3684 userState.mInstalledServices.remove(mAccessibilityServiceInfo); 3685 userState.mEnabledServices.remove(mComponentName); 3686 userState.destroyUiAutomationService(); 3687 readConfigurationForUserStateLocked(userState); 3688 } 3689 if (mId == getMagnificationController().getIdOfLastServiceToMagnify()) { 3690 getMagnificationController().resetIfNeeded(true); 3691 } 3692 onUserStateChangedLocked(userState); 3693 } 3694 } 3695 3696 /** 3697 * Performs a notification for an {@link AccessibilityEvent}. 3698 * 3699 * @param event The event. 3700 * @param serviceWantsEvent whether the event should be received by 3701 * {@link AccessibilityService#onAccessibilityEvent} (true), 3702 * as opposed to just {@link AccessibilityInteractionClient#onAccessibilityEvent} (false) 3703 */ notifyAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent)3704 public void notifyAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) { 3705 synchronized (mLock) { 3706 final int eventType = event.getEventType(); 3707 // Make a copy since during dispatch it is possible the event to 3708 // be modified to remove its source if the receiving service does 3709 // not have permission to access the window content. 3710 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); 3711 Message message; 3712 if ((mNotificationTimeout > 0) 3713 && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) { 3714 // Allow at most one pending event 3715 final AccessibilityEvent oldEvent = mPendingEvents.get(eventType); 3716 mPendingEvents.put(eventType, newEvent); 3717 if (oldEvent != null) { 3718 mEventDispatchHandler.removeMessages(eventType); 3719 oldEvent.recycle(); 3720 } 3721 message = mEventDispatchHandler.obtainMessage(eventType); 3722 } else { 3723 // Send all messages, bypassing mPendingEvents 3724 message = mEventDispatchHandler.obtainMessage(eventType, newEvent); 3725 } 3726 message.arg1 = serviceWantsEvent ? 1 : 0; 3727 3728 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); 3729 } 3730 } 3731 isAccessibilityButtonAvailableLocked(UserState userState)3732 private boolean isAccessibilityButtonAvailableLocked(UserState userState) { 3733 // If the service does not request the accessibility button, it isn't available 3734 if (!mRequestAccessibilityButton) { 3735 return false; 3736 } 3737 3738 // If the accessibility button isn't currently shown, it cannot be available to services 3739 if (!mIsAccessibilityButtonShown) { 3740 return false; 3741 } 3742 3743 // If magnification is on and assigned to the accessibility button, services cannot be 3744 if (userState.mIsNavBarMagnificationEnabled 3745 && userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { 3746 return false; 3747 } 3748 3749 int requestingServices = 0; 3750 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 3751 final Service service = userState.mBoundServices.get(i); 3752 if (service.mRequestAccessibilityButton) { 3753 requestingServices++; 3754 } 3755 } 3756 3757 if (requestingServices == 1) { 3758 // If only a single service is requesting, it must be this service, and the 3759 // accessibility button is available to it 3760 return true; 3761 } else { 3762 // With more than one active service, we derive the target from the user's settings 3763 if (userState.mServiceAssignedToAccessibilityButton == null) { 3764 // If the user has not made an assignment, we treat the button as available to 3765 // all services until the user interacts with the button to make an assignment 3766 return true; 3767 } else { 3768 // If an assignment was made, it defines availability 3769 return mComponentName.equals(userState.mServiceAssignedToAccessibilityButton); 3770 } 3771 } 3772 } 3773 3774 /** 3775 * Notifies an accessibility service client for a scheduled event given the event type. 3776 * 3777 * @param eventType The type of the event to dispatch. 3778 */ notifyAccessibilityEventInternal( int eventType, AccessibilityEvent event, boolean serviceWantsEvent)3779 private void notifyAccessibilityEventInternal( 3780 int eventType, 3781 AccessibilityEvent event, 3782 boolean serviceWantsEvent) { 3783 IAccessibilityServiceClient listener; 3784 3785 synchronized (mLock) { 3786 listener = mServiceInterface; 3787 3788 // If the service died/was disabled while the message for dispatching 3789 // the accessibility event was propagating the listener may be null. 3790 if (listener == null) { 3791 return; 3792 } 3793 3794 // There are two ways we notify for events, throttled and non-throttled. If we 3795 // are not throttling, then messages come with events, which we handle with 3796 // minimal fuss. 3797 if (event == null) { 3798 // We are throttling events, so we'll send the event for this type in 3799 // mPendingEvents as long as it it's null. It can only null due to a race 3800 // condition: 3801 // 3802 // 1) A binder thread calls notifyAccessibilityServiceDelayedLocked 3803 // which posts a message for dispatching an event and stores the event 3804 // in mPendingEvents. 3805 // 2) The message is pulled from the queue by the handler on the service 3806 // thread and this method is just about to acquire the lock. 3807 // 3) Another binder thread acquires the lock in notifyAccessibilityEvent 3808 // 4) notifyAccessibilityEvent recycles the event that this method was about 3809 // to process, replaces it with a new one, and posts a second message 3810 // 5) This method grabs the new event, processes it, and removes it from 3811 // mPendingEvents 3812 // 6) The second message dispatched in (4) arrives, but the event has been 3813 // remvoved in (5). 3814 event = mPendingEvents.get(eventType); 3815 if (event == null) { 3816 return; 3817 } 3818 mPendingEvents.remove(eventType); 3819 } 3820 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { 3821 event.setConnectionId(mId); 3822 } else { 3823 event.setSource((View) null); 3824 } 3825 event.setSealed(true); 3826 } 3827 3828 try { 3829 listener.onAccessibilityEvent(event, serviceWantsEvent); 3830 if (DEBUG) { 3831 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); 3832 } 3833 } catch (RemoteException re) { 3834 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); 3835 } finally { 3836 event.recycle(); 3837 } 3838 } 3839 notifyGesture(int gestureId)3840 public void notifyGesture(int gestureId) { 3841 mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, 3842 gestureId, 0).sendToTarget(); 3843 } 3844 notifyClearAccessibilityNodeInfoCache()3845 public void notifyClearAccessibilityNodeInfoCache() { 3846 mInvocationHandler.sendEmptyMessage( 3847 InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); 3848 } 3849 notifyMagnificationChangedLocked(@onNull Region region, float scale, float centerX, float centerY)3850 public void notifyMagnificationChangedLocked(@NonNull Region region, 3851 float scale, float centerX, float centerY) { 3852 mInvocationHandler 3853 .notifyMagnificationChangedLocked(region, scale, centerX, centerY); 3854 } 3855 notifySoftKeyboardShowModeChangedLocked(int showState)3856 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 3857 mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState); 3858 } 3859 notifyAccessibilityButtonClickedLocked()3860 public void notifyAccessibilityButtonClickedLocked() { 3861 mInvocationHandler.notifyAccessibilityButtonClickedLocked(); 3862 } 3863 notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)3864 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 3865 mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available); 3866 } 3867 3868 /** 3869 * Called by the invocation handler to notify the service that the 3870 * state of magnification has changed. 3871 */ notifyMagnificationChangedInternal(@onNull Region region, float scale, float centerX, float centerY)3872 private void notifyMagnificationChangedInternal(@NonNull Region region, 3873 float scale, float centerX, float centerY) { 3874 final IAccessibilityServiceClient listener; 3875 synchronized (mLock) { 3876 listener = mServiceInterface; 3877 } 3878 if (listener != null) { 3879 try { 3880 listener.onMagnificationChanged(region, scale, centerX, centerY); 3881 } catch (RemoteException re) { 3882 Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re); 3883 } 3884 } 3885 } 3886 3887 /** 3888 * Called by the invocation handler to notify the service that the state of the soft 3889 * keyboard show mode has changed. 3890 */ notifySoftKeyboardShowModeChangedInternal(int showState)3891 private void notifySoftKeyboardShowModeChangedInternal(int showState) { 3892 final IAccessibilityServiceClient listener; 3893 synchronized (mLock) { 3894 listener = mServiceInterface; 3895 } 3896 if (listener != null) { 3897 try { 3898 listener.onSoftKeyboardShowModeChanged(showState); 3899 } catch (RemoteException re) { 3900 Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService, 3901 re); 3902 } 3903 } 3904 } 3905 notifyAccessibilityButtonClickedInternal()3906 private void notifyAccessibilityButtonClickedInternal() { 3907 final IAccessibilityServiceClient listener; 3908 synchronized (mLock) { 3909 listener = mServiceInterface; 3910 } 3911 if (listener != null) { 3912 try { 3913 listener.onAccessibilityButtonClicked(); 3914 } catch (RemoteException re) { 3915 Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re); 3916 } 3917 } 3918 } 3919 notifyAccessibilityButtonAvailabilityChangedInternal(boolean available)3920 private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) { 3921 // Only notify the service if it's not been notified or the state has changed 3922 if (mReceivedAccessibilityButtonCallbackSinceBind 3923 && (mLastAccessibilityButtonCallbackState == available)) { 3924 return; 3925 } 3926 mReceivedAccessibilityButtonCallbackSinceBind = true; 3927 mLastAccessibilityButtonCallbackState = available; 3928 final IAccessibilityServiceClient listener; 3929 synchronized (mLock) { 3930 listener = mServiceInterface; 3931 } 3932 if (listener != null) { 3933 try { 3934 listener.onAccessibilityButtonAvailabilityChanged(available); 3935 } catch (RemoteException re) { 3936 Slog.e(LOG_TAG, 3937 "Error sending accessibility button availability change to " + mService, 3938 re); 3939 } 3940 } 3941 } 3942 notifyGestureInternal(int gestureId)3943 private void notifyGestureInternal(int gestureId) { 3944 final IAccessibilityServiceClient listener; 3945 synchronized (mLock) { 3946 listener = mServiceInterface; 3947 } 3948 if (listener != null) { 3949 try { 3950 listener.onGesture(gestureId); 3951 } catch (RemoteException re) { 3952 Slog.e(LOG_TAG, "Error during sending gesture " + gestureId 3953 + " to " + mService, re); 3954 } 3955 } 3956 } 3957 notifyClearAccessibilityCacheInternal()3958 private void notifyClearAccessibilityCacheInternal() { 3959 final IAccessibilityServiceClient listener; 3960 synchronized (mLock) { 3961 listener = mServiceInterface; 3962 } 3963 if (listener != null) { 3964 try { 3965 listener.clearAccessibilityCache(); 3966 } catch (RemoteException re) { 3967 Slog.e(LOG_TAG, "Error during requesting accessibility info cache" 3968 + " to be cleared.", re); 3969 } 3970 } 3971 } 3972 sendDownAndUpKeyEvents(int keyCode)3973 private void sendDownAndUpKeyEvents(int keyCode) { 3974 final long token = Binder.clearCallingIdentity(); 3975 3976 // Inject down. 3977 final long downTime = SystemClock.uptimeMillis(); 3978 KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, 3979 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 3980 InputDevice.SOURCE_KEYBOARD, null); 3981 InputManager.getInstance().injectInputEvent(down, 3982 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 3983 down.recycle(); 3984 3985 // Inject up. 3986 final long upTime = SystemClock.uptimeMillis(); 3987 KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0, 3988 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 3989 InputDevice.SOURCE_KEYBOARD, null); 3990 InputManager.getInstance().injectInputEvent(up, 3991 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 3992 up.recycle(); 3993 3994 Binder.restoreCallingIdentity(token); 3995 } 3996 expandNotifications()3997 private void expandNotifications() { 3998 final long token = Binder.clearCallingIdentity(); 3999 4000 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 4001 android.app.Service.STATUS_BAR_SERVICE); 4002 statusBarManager.expandNotificationsPanel(); 4003 4004 Binder.restoreCallingIdentity(token); 4005 } 4006 expandQuickSettings()4007 private void expandQuickSettings() { 4008 final long token = Binder.clearCallingIdentity(); 4009 4010 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 4011 android.app.Service.STATUS_BAR_SERVICE); 4012 statusBarManager.expandSettingsPanel(); 4013 4014 Binder.restoreCallingIdentity(token); 4015 } 4016 openRecents()4017 private boolean openRecents() { 4018 final long token = Binder.clearCallingIdentity(); 4019 try { 4020 StatusBarManagerInternal statusBarService = LocalServices.getService( 4021 StatusBarManagerInternal.class); 4022 if (statusBarService == null) { 4023 return false; 4024 } 4025 statusBarService.toggleRecentApps(); 4026 } finally { 4027 Binder.restoreCallingIdentity(token); 4028 } 4029 return true; 4030 } 4031 showGlobalActions()4032 private void showGlobalActions() { 4033 mWindowManagerService.showGlobalActions(); 4034 } 4035 toggleSplitScreen()4036 private void toggleSplitScreen() { 4037 LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen(); 4038 } 4039 getConnectionLocked(int windowId)4040 private IAccessibilityInteractionConnection getConnectionLocked(int windowId) { 4041 if (DEBUG) { 4042 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); 4043 } 4044 AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId); 4045 if (wrapper == null) { 4046 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); 4047 } 4048 if (wrapper != null && wrapper.mConnection != null) { 4049 return wrapper.mConnection; 4050 } 4051 if (DEBUG) { 4052 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); 4053 } 4054 return null; 4055 } 4056 resolveAccessibilityWindowIdLocked(int accessibilityWindowId)4057 private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { 4058 if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { 4059 return mSecurityPolicy.getActiveWindowId(); 4060 } 4061 return accessibilityWindowId; 4062 } 4063 resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType)4064 private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { 4065 if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { 4066 return mSecurityPolicy.mActiveWindowId; 4067 } 4068 if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) { 4069 if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) { 4070 return mSecurityPolicy.mFocusedWindowId; 4071 } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) { 4072 return mSecurityPolicy.mAccessibilityFocusedWindowId; 4073 } 4074 } 4075 return windowId; 4076 } 4077 replaceCallbackIfNeeded( IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, int interactionId, int interrogatingPid, long interrogatingTid)4078 private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded( 4079 IAccessibilityInteractionConnectionCallback originalCallback, 4080 int resolvedWindowId, int interactionId, int interrogatingPid, 4081 long interrogatingTid) { 4082 AccessibilityWindowInfo windowInfo = mSecurityPolicy.findWindowById(resolvedWindowId); 4083 if ((windowInfo == null) || !windowInfo.inPictureInPicture() 4084 || (mPictureInPictureActionReplacingConnection == null)) { 4085 return originalCallback; 4086 } 4087 return new ActionReplacingCallback(originalCallback, 4088 mPictureInPictureActionReplacingConnection.mConnection, interactionId, 4089 interrogatingPid, interrogatingTid); 4090 } 4091 4092 private final class InvocationHandler extends Handler { 4093 public static final int MSG_ON_GESTURE = 1; 4094 public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; 4095 4096 private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; 4097 private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6; 4098 private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7; 4099 private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8; 4100 4101 private boolean mIsMagnificationCallbackEnabled = false; 4102 private boolean mIsSoftKeyboardCallbackEnabled = false; 4103 InvocationHandler(Looper looper)4104 public InvocationHandler(Looper looper) { 4105 super(looper, null, true); 4106 } 4107 4108 @Override handleMessage(Message message)4109 public void handleMessage(Message message) { 4110 final int type = message.what; 4111 switch (type) { 4112 case MSG_ON_GESTURE: { 4113 final int gestureId = message.arg1; 4114 notifyGestureInternal(gestureId); 4115 } break; 4116 4117 case MSG_CLEAR_ACCESSIBILITY_CACHE: { 4118 notifyClearAccessibilityCacheInternal(); 4119 } break; 4120 4121 case MSG_ON_MAGNIFICATION_CHANGED: { 4122 final SomeArgs args = (SomeArgs) message.obj; 4123 final Region region = (Region) args.arg1; 4124 final float scale = (float) args.arg2; 4125 final float centerX = (float) args.arg3; 4126 final float centerY = (float) args.arg4; 4127 notifyMagnificationChangedInternal(region, scale, centerX, centerY); 4128 } break; 4129 4130 case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: { 4131 final int showState = (int) message.arg1; 4132 notifySoftKeyboardShowModeChangedInternal(showState); 4133 } break; 4134 4135 case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: { 4136 notifyAccessibilityButtonClickedInternal(); 4137 } break; 4138 4139 case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: { 4140 final boolean available = (message.arg1 != 0); 4141 notifyAccessibilityButtonAvailabilityChangedInternal(available); 4142 } break; 4143 4144 default: { 4145 throw new IllegalArgumentException("Unknown message: " + type); 4146 } 4147 } 4148 } 4149 notifyMagnificationChangedLocked(@onNull Region region, float scale, float centerX, float centerY)4150 public void notifyMagnificationChangedLocked(@NonNull Region region, float scale, 4151 float centerX, float centerY) { 4152 if (!mIsMagnificationCallbackEnabled) { 4153 // Callback is disabled, don't bother packing args. 4154 return; 4155 } 4156 4157 final SomeArgs args = SomeArgs.obtain(); 4158 args.arg1 = region; 4159 args.arg2 = scale; 4160 args.arg3 = centerX; 4161 args.arg4 = centerY; 4162 4163 final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args); 4164 msg.sendToTarget(); 4165 } 4166 setMagnificationCallbackEnabled(boolean enabled)4167 public void setMagnificationCallbackEnabled(boolean enabled) { 4168 mIsMagnificationCallbackEnabled = enabled; 4169 } 4170 notifySoftKeyboardShowModeChangedLocked(int showState)4171 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 4172 if (!mIsSoftKeyboardCallbackEnabled) { 4173 return; 4174 } 4175 4176 final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0); 4177 msg.sendToTarget(); 4178 } 4179 setSoftKeyboardCallbackEnabled(boolean enabled)4180 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 4181 mIsSoftKeyboardCallbackEnabled = enabled; 4182 } 4183 notifyAccessibilityButtonClickedLocked()4184 public void notifyAccessibilityButtonClickedLocked() { 4185 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED); 4186 msg.sendToTarget(); 4187 } 4188 notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)4189 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 4190 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, 4191 (available ? 1 : 0), 0); 4192 msg.sendToTarget(); 4193 } 4194 } 4195 } 4196 4197 final class WindowsForAccessibilityCallback implements 4198 WindowManagerInternal.WindowsForAccessibilityCallback { 4199 4200 @Override onWindowsForAccessibilityChanged(List<WindowInfo> windows)4201 public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) { 4202 synchronized (mLock) { 4203 // Populate the windows to report. 4204 List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>(); 4205 final int receivedWindowCount = windows.size(); 4206 for (int i = 0; i < receivedWindowCount; i++) { 4207 WindowInfo receivedWindow = windows.get(i); 4208 AccessibilityWindowInfo reportedWindow = populateReportedWindow( 4209 receivedWindow); 4210 if (reportedWindow != null) { 4211 reportedWindows.add(reportedWindow); 4212 } 4213 } 4214 4215 if (DEBUG) { 4216 Slog.i(LOG_TAG, "Windows changed: " + reportedWindows); 4217 } 4218 4219 // Let the policy update the focused and active windows. 4220 mSecurityPolicy.updateWindowsLocked(reportedWindows); 4221 4222 // Someone may be waiting for the windows - advertise it. 4223 mLock.notifyAll(); 4224 } 4225 } 4226 populateReportedWindow(WindowInfo window)4227 private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) { 4228 final int windowId = findWindowIdLocked(window.token); 4229 if (windowId < 0) { 4230 return null; 4231 } 4232 4233 AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain(); 4234 4235 reportedWindow.setId(windowId); 4236 reportedWindow.setType(getTypeForWindowManagerWindowType(window.type)); 4237 reportedWindow.setLayer(window.layer); 4238 reportedWindow.setFocused(window.focused); 4239 reportedWindow.setBoundsInScreen(window.boundsInScreen); 4240 reportedWindow.setTitle(window.title); 4241 reportedWindow.setAnchorId(window.accessibilityIdOfAnchor); 4242 reportedWindow.setPictureInPicture(window.inPictureInPicture); 4243 4244 final int parentId = findWindowIdLocked(window.parentToken); 4245 if (parentId >= 0) { 4246 reportedWindow.setParentId(parentId); 4247 } 4248 4249 if (window.childTokens != null) { 4250 final int childCount = window.childTokens.size(); 4251 for (int i = 0; i < childCount; i++) { 4252 IBinder childToken = window.childTokens.get(i); 4253 final int childId = findWindowIdLocked(childToken); 4254 if (childId >= 0) { 4255 reportedWindow.addChild(childId); 4256 } 4257 } 4258 } 4259 4260 return reportedWindow; 4261 } 4262 getTypeForWindowManagerWindowType(int windowType)4263 private int getTypeForWindowManagerWindowType(int windowType) { 4264 switch (windowType) { 4265 case WindowManager.LayoutParams.TYPE_APPLICATION: 4266 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA: 4267 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL: 4268 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING: 4269 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL: 4270 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL: 4271 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION: 4272 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION: 4273 case WindowManager.LayoutParams.TYPE_PHONE: 4274 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE: 4275 case WindowManager.LayoutParams.TYPE_TOAST: 4276 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: { 4277 return AccessibilityWindowInfo.TYPE_APPLICATION; 4278 } 4279 4280 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 4281 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: { 4282 return AccessibilityWindowInfo.TYPE_INPUT_METHOD; 4283 } 4284 4285 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG: 4286 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 4287 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: 4288 case WindowManager.LayoutParams.TYPE_SEARCH_BAR: 4289 case WindowManager.LayoutParams.TYPE_STATUS_BAR: 4290 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL: 4291 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL: 4292 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: 4293 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT: 4294 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG: 4295 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR: 4296 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: 4297 case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY: 4298 case WindowManager.LayoutParams.TYPE_SCREENSHOT: { 4299 return AccessibilityWindowInfo.TYPE_SYSTEM; 4300 } 4301 4302 case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: { 4303 return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER; 4304 } 4305 4306 case TYPE_ACCESSIBILITY_OVERLAY: { 4307 return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY; 4308 } 4309 4310 default: { 4311 return -1; 4312 } 4313 } 4314 } 4315 } 4316 4317 private final class InteractionBridge { 4318 private final Display mDefaultDisplay; 4319 private final int mConnectionId; 4320 private final AccessibilityInteractionClient mClient; 4321 InteractionBridge()4322 public InteractionBridge() { 4323 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 4324 info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 4325 info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; 4326 info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 4327 Service service = new Service(UserHandle.USER_NULL, 4328 sFakeAccessibilityServiceComponentName, info); 4329 4330 mConnectionId = service.mId; 4331 4332 mClient = AccessibilityInteractionClient.getInstance(); 4333 mClient.addConnection(mConnectionId, service); 4334 4335 //TODO: (multi-display) We need to support multiple displays. 4336 DisplayManager displayManager = (DisplayManager) 4337 mContext.getSystemService(Context.DISPLAY_SERVICE); 4338 mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); 4339 } 4340 clearAccessibilityFocusNotLocked(int windowId)4341 public void clearAccessibilityFocusNotLocked(int windowId) { 4342 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId); 4343 if (focus != null) { 4344 focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 4345 } 4346 } 4347 4348 /** 4349 * Perform an accessibility action on the view that currently has accessibility focus. 4350 * Has no effect if no item has accessibility focus, if the item with accessibility 4351 * focus does not expose the specified action, or if the action fails. 4352 * 4353 * @param actionId The id of the action to perform. 4354 * 4355 * @return {@code true} if the action was performed. {@code false} if it was not. 4356 */ performActionOnAccessibilityFocusedItemNotLocked( AccessibilityNodeInfo.AccessibilityAction action)4357 public boolean performActionOnAccessibilityFocusedItemNotLocked( 4358 AccessibilityNodeInfo.AccessibilityAction action) { 4359 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 4360 if ((focus == null) || !focus.getActionList().contains(action)) { 4361 return false; 4362 } 4363 return focus.performAction(action.getId()); 4364 } 4365 getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint)4366 public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) { 4367 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 4368 if (focus == null) { 4369 return false; 4370 } 4371 4372 synchronized (mLock) { 4373 Rect boundsInScreen = mTempRect; 4374 focus.getBoundsInScreen(boundsInScreen); 4375 4376 // Apply magnification if needed. 4377 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId()); 4378 if (spec != null && !spec.isNop()) { 4379 boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY); 4380 boundsInScreen.scale(1 / spec.scale); 4381 } 4382 4383 // Clip to the window bounds. 4384 Rect windowBounds = mTempRect1; 4385 getWindowBounds(focus.getWindowId(), windowBounds); 4386 if (!boundsInScreen.intersect(windowBounds)) { 4387 return false; 4388 } 4389 4390 // Clip to the screen bounds. 4391 Point screenSize = mTempPoint; 4392 mDefaultDisplay.getRealSize(screenSize); 4393 if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) { 4394 return false; 4395 } 4396 4397 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY()); 4398 } 4399 4400 return true; 4401 } 4402 getAccessibilityFocusNotLocked()4403 private AccessibilityNodeInfo getAccessibilityFocusNotLocked() { 4404 final int focusedWindowId; 4405 synchronized (mLock) { 4406 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId; 4407 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) { 4408 return null; 4409 } 4410 } 4411 return getAccessibilityFocusNotLocked(focusedWindowId); 4412 } 4413 getAccessibilityFocusNotLocked(int windowId)4414 private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) { 4415 return mClient.findFocus(mConnectionId, 4416 windowId, AccessibilityNodeInfo.ROOT_NODE_ID, 4417 AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); 4418 } 4419 } 4420 4421 final class SecurityPolicy { 4422 public static final int INVALID_WINDOW_ID = -1; 4423 4424 private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = 4425 AccessibilityEvent.TYPE_VIEW_CLICKED 4426 | AccessibilityEvent.TYPE_VIEW_FOCUSED 4427 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 4428 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 4429 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 4430 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 4431 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 4432 | AccessibilityEvent.TYPE_VIEW_SELECTED 4433 | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 4434 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 4435 | AccessibilityEvent.TYPE_VIEW_SCROLLED 4436 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 4437 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED 4438 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 4439 4440 // In Z order 4441 public List<AccessibilityWindowInfo> mWindows; 4442 public SparseArray<AccessibilityWindowInfo> mWindowsById = new SparseArray<>(); 4443 4444 public int mActiveWindowId = INVALID_WINDOW_ID; 4445 public int mFocusedWindowId = INVALID_WINDOW_ID; 4446 public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 4447 public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 4448 4449 private boolean mTouchInteractionInProgress; 4450 canDispatchAccessibilityEventLocked(AccessibilityEvent event)4451 private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) { 4452 final int eventType = event.getEventType(); 4453 switch (eventType) { 4454 // All events that are for changes in a global window 4455 // state should *always* be dispatched. 4456 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: 4457 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 4458 case AccessibilityEvent.TYPE_ANNOUNCEMENT: 4459 // All events generated by the user touching the 4460 // screen should *always* be dispatched. 4461 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: 4462 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: 4463 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START: 4464 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END: 4465 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START: 4466 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: 4467 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: 4468 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: 4469 // Also always dispatch the event that assist is reading context. 4470 case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT: 4471 // Also windows changing should always be anounced. 4472 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: { 4473 return true; 4474 } 4475 // All events for changes in window content should be 4476 // dispatched *only* if this window is one of the windows 4477 // the accessibility layer reports which are windows 4478 // that a sighted user can touch. 4479 default: { 4480 return isRetrievalAllowingWindow(event.getWindowId()); 4481 } 4482 } 4483 } 4484 clearWindowsLocked()4485 public void clearWindowsLocked() { 4486 List<AccessibilityWindowInfo> windows = Collections.emptyList(); 4487 final int activeWindowId = mActiveWindowId; 4488 updateWindowsLocked(windows); 4489 mActiveWindowId = activeWindowId; 4490 mWindows = null; 4491 } 4492 updateWindowsLocked(List<AccessibilityWindowInfo> windows)4493 public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) { 4494 if (mWindows == null) { 4495 mWindows = new ArrayList<>(); 4496 } 4497 4498 final int oldWindowCount = mWindows.size(); 4499 for (int i = oldWindowCount - 1; i >= 0; i--) { 4500 mWindows.remove(i).recycle(); 4501 } 4502 mWindowsById.clear(); 4503 4504 mFocusedWindowId = INVALID_WINDOW_ID; 4505 if (!mTouchInteractionInProgress) { 4506 mActiveWindowId = INVALID_WINDOW_ID; 4507 } 4508 4509 // If the active window goes away while the user is touch exploring we 4510 // reset the active window id and wait for the next hover event from 4511 // under the user's finger to determine which one is the new one. It 4512 // is possible that the finger is not moving and the input system 4513 // filters out such events. 4514 boolean activeWindowGone = true; 4515 4516 final int windowCount = windows.size(); 4517 if (windowCount > 0) { 4518 for (int i = 0; i < windowCount; i++) { 4519 AccessibilityWindowInfo window = windows.get(i); 4520 final int windowId = window.getId(); 4521 if (window.isFocused()) { 4522 mFocusedWindowId = windowId; 4523 if (!mTouchInteractionInProgress) { 4524 mActiveWindowId = windowId; 4525 window.setActive(true); 4526 } else if (windowId == mActiveWindowId) { 4527 activeWindowGone = false; 4528 } 4529 } 4530 mWindows.add(window); 4531 mWindowsById.put(windowId, window); 4532 } 4533 4534 if (mTouchInteractionInProgress && activeWindowGone) { 4535 mActiveWindowId = mFocusedWindowId; 4536 } 4537 4538 // Focused window may change the active one, so set the 4539 // active window once we decided which it is. 4540 for (int i = 0; i < windowCount; i++) { 4541 AccessibilityWindowInfo window = mWindows.get(i); 4542 if (window.getId() == mActiveWindowId) { 4543 window.setActive(true); 4544 } 4545 if (window.getId() == mAccessibilityFocusedWindowId) { 4546 window.setAccessibilityFocused(true); 4547 } 4548 } 4549 } 4550 4551 notifyWindowsChanged(); 4552 } 4553 computePartialInteractiveRegionForWindowLocked(int windowId, Region outRegion)4554 public boolean computePartialInteractiveRegionForWindowLocked(int windowId, 4555 Region outRegion) { 4556 if (mWindows == null) { 4557 return false; 4558 } 4559 4560 // Windows are ordered in z order so start from the bottom and find 4561 // the window of interest. After that all windows that cover it should 4562 // be subtracted from the resulting region. Note that for accessibility 4563 // we are returning only interactive windows. 4564 Region windowInteractiveRegion = null; 4565 boolean windowInteractiveRegionChanged = false; 4566 4567 final int windowCount = mWindows.size(); 4568 for (int i = windowCount - 1; i >= 0; i--) { 4569 AccessibilityWindowInfo currentWindow = mWindows.get(i); 4570 if (windowInteractiveRegion == null) { 4571 if (currentWindow.getId() == windowId) { 4572 Rect currentWindowBounds = mTempRect; 4573 currentWindow.getBoundsInScreen(currentWindowBounds); 4574 outRegion.set(currentWindowBounds); 4575 windowInteractiveRegion = outRegion; 4576 continue; 4577 } 4578 } else if (currentWindow.getType() 4579 != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) { 4580 Rect currentWindowBounds = mTempRect; 4581 currentWindow.getBoundsInScreen(currentWindowBounds); 4582 if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) { 4583 windowInteractiveRegionChanged = true; 4584 } 4585 } 4586 } 4587 4588 return windowInteractiveRegionChanged; 4589 } 4590 updateEventSourceLocked(AccessibilityEvent event)4591 public void updateEventSourceLocked(AccessibilityEvent event) { 4592 if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) { 4593 event.setSource((View) null); 4594 } 4595 } 4596 updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, int eventType, int eventAction)4597 public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, 4598 int eventType, int eventAction) { 4599 // The active window is either the window that has input focus or 4600 // the window that the user is currently touching. If the user is 4601 // touching a window that does not have input focus as soon as the 4602 // the user stops touching that window the focused window becomes 4603 // the active one. Here we detect the touched window and make it 4604 // active. In updateWindowsLocked() we update the focused window 4605 // and if the user is not touching the screen, we make the focused 4606 // window the active one. 4607 switch (eventType) { 4608 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { 4609 // If no service has the capability to introspect screen, 4610 // we do not register callback in the window manager for 4611 // window changes, so we have to ask the window manager 4612 // what the focused window is to update the active one. 4613 // The active window also determined events from which 4614 // windows are delivered. 4615 synchronized (mLock) { 4616 if (mWindowsForAccessibilityCallback == null) { 4617 mFocusedWindowId = getFocusedWindowId(); 4618 if (windowId == mFocusedWindowId) { 4619 mActiveWindowId = windowId; 4620 } 4621 } 4622 } 4623 } break; 4624 4625 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: { 4626 // Do not allow delayed hover events to confuse us 4627 // which the active window is. 4628 synchronized (mLock) { 4629 if (mTouchInteractionInProgress && mActiveWindowId != windowId) { 4630 setActiveWindowLocked(windowId); 4631 } 4632 } 4633 } break; 4634 4635 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: { 4636 synchronized (mLock) { 4637 if (mAccessibilityFocusedWindowId != windowId) { 4638 mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 4639 mAccessibilityFocusedWindowId, 0).sendToTarget(); 4640 mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId); 4641 mAccessibilityFocusNodeId = nodeId; 4642 } 4643 } 4644 } break; 4645 4646 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: { 4647 synchronized (mLock) { 4648 if (mAccessibilityFocusNodeId == nodeId) { 4649 mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 4650 } 4651 // Clear the window with focus if it no longer has focus and we aren't 4652 // just moving focus from one view to the other in the same window 4653 if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) 4654 && (mAccessibilityFocusedWindowId == windowId) 4655 && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) 4656 ) { 4657 mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 4658 } 4659 } 4660 } break; 4661 } 4662 } 4663 onTouchInteractionStart()4664 public void onTouchInteractionStart() { 4665 synchronized (mLock) { 4666 mTouchInteractionInProgress = true; 4667 } 4668 } 4669 onTouchInteractionEnd()4670 public void onTouchInteractionEnd() { 4671 synchronized (mLock) { 4672 mTouchInteractionInProgress = false; 4673 // We want to set the active window to be current immediately 4674 // after the user has stopped touching the screen since if the 4675 // user types with the IME he should get a feedback for the 4676 // letter typed in the text view which is in the input focused 4677 // window. Note that we always deliver hover accessibility events 4678 // (they are a result of user touching the screen) so change of 4679 // the active window before all hover accessibility events from 4680 // the touched window are delivered is fine. 4681 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId; 4682 setActiveWindowLocked(mFocusedWindowId); 4683 4684 // If there is no service that can operate with active windows 4685 // we keep accessibility focus behavior to constrain it only in 4686 // the active window. Look at updateAccessibilityFocusBehaviorLocked 4687 // for details. 4688 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId 4689 && mAccessibilityFocusedWindowId == oldActiveWindow 4690 && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) { 4691 mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 4692 oldActiveWindow, 0).sendToTarget(); 4693 } 4694 } 4695 } 4696 getActiveWindowId()4697 public int getActiveWindowId() { 4698 if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) { 4699 mActiveWindowId = getFocusedWindowId(); 4700 } 4701 return mActiveWindowId; 4702 } 4703 setActiveWindowLocked(int windowId)4704 private void setActiveWindowLocked(int windowId) { 4705 if (mActiveWindowId != windowId) { 4706 mActiveWindowId = windowId; 4707 if (mWindows != null) { 4708 final int windowCount = mWindows.size(); 4709 for (int i = 0; i < windowCount; i++) { 4710 AccessibilityWindowInfo window = mWindows.get(i); 4711 window.setActive(window.getId() == windowId); 4712 } 4713 } 4714 notifyWindowsChanged(); 4715 } 4716 } 4717 setAccessibilityFocusedWindowLocked(int windowId)4718 private void setAccessibilityFocusedWindowLocked(int windowId) { 4719 if (mAccessibilityFocusedWindowId != windowId) { 4720 mAccessibilityFocusedWindowId = windowId; 4721 if (mWindows != null) { 4722 final int windowCount = mWindows.size(); 4723 for (int i = 0; i < windowCount; i++) { 4724 AccessibilityWindowInfo window = mWindows.get(i); 4725 window.setAccessibilityFocused(window.getId() == windowId); 4726 } 4727 } 4728 4729 notifyWindowsChanged(); 4730 } 4731 } 4732 notifyWindowsChanged()4733 public void notifyWindowsChanged() { 4734 if (mWindowsForAccessibilityCallback == null) { 4735 return; 4736 } 4737 final long identity = Binder.clearCallingIdentity(); 4738 try { 4739 // Let the client know the windows changed. 4740 AccessibilityEvent event = AccessibilityEvent.obtain( 4741 AccessibilityEvent.TYPE_WINDOWS_CHANGED); 4742 event.setEventTime(SystemClock.uptimeMillis()); 4743 sendAccessibilityEvent(event, mCurrentUserId); 4744 } finally { 4745 Binder.restoreCallingIdentity(identity); 4746 } 4747 } 4748 canGetAccessibilityNodeInfoLocked(Service service, int windowId)4749 public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) { 4750 return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId); 4751 } 4752 canRetrieveWindowsLocked(Service service)4753 public boolean canRetrieveWindowsLocked(Service service) { 4754 return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows; 4755 } 4756 canRetrieveWindowContentLocked(Service service)4757 public boolean canRetrieveWindowContentLocked(Service service) { 4758 return (service.mAccessibilityServiceInfo.getCapabilities() 4759 & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; 4760 } 4761 canControlMagnification(Service service)4762 public boolean canControlMagnification(Service service) { 4763 return (service.mAccessibilityServiceInfo.getCapabilities() 4764 & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0; 4765 } 4766 canPerformGestures(Service service)4767 public boolean canPerformGestures(Service service) { 4768 return (service.mAccessibilityServiceInfo.getCapabilities() 4769 & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0; 4770 } 4771 canCaptureFingerprintGestures(Service service)4772 public boolean canCaptureFingerprintGestures(Service service) { 4773 return (service.mAccessibilityServiceInfo.getCapabilities() 4774 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0; 4775 } 4776 resolveProfileParentLocked(int userId)4777 private int resolveProfileParentLocked(int userId) { 4778 if (userId != mCurrentUserId) { 4779 final long identity = Binder.clearCallingIdentity(); 4780 try { 4781 UserInfo parent = mUserManager.getProfileParent(userId); 4782 if (parent != null) { 4783 return parent.getUserHandle().getIdentifier(); 4784 } 4785 } finally { 4786 Binder.restoreCallingIdentity(identity); 4787 } 4788 } 4789 return userId; 4790 } 4791 resolveCallingUserIdEnforcingPermissionsLocked(int userId)4792 public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) { 4793 final int callingUid = Binder.getCallingUid(); 4794 if (callingUid == 0 4795 || callingUid == Process.SYSTEM_UID 4796 || callingUid == Process.SHELL_UID) { 4797 if (userId == UserHandle.USER_CURRENT 4798 || userId == UserHandle.USER_CURRENT_OR_SELF) { 4799 return mCurrentUserId; 4800 } 4801 return resolveProfileParentLocked(userId); 4802 } 4803 final int callingUserId = UserHandle.getUserId(callingUid); 4804 if (callingUserId == userId) { 4805 return resolveProfileParentLocked(userId); 4806 } 4807 final int callingUserParentId = resolveProfileParentLocked(callingUserId); 4808 if (callingUserParentId == mCurrentUserId && 4809 (userId == UserHandle.USER_CURRENT 4810 || userId == UserHandle.USER_CURRENT_OR_SELF)) { 4811 return mCurrentUserId; 4812 } 4813 if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS) 4814 && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { 4815 throw new SecurityException("Call from user " + callingUserId + " as user " 4816 + userId + " without permission INTERACT_ACROSS_USERS or " 4817 + "INTERACT_ACROSS_USERS_FULL not allowed."); 4818 } 4819 if (userId == UserHandle.USER_CURRENT 4820 || userId == UserHandle.USER_CURRENT_OR_SELF) { 4821 return mCurrentUserId; 4822 } 4823 throw new IllegalArgumentException("Calling user can be changed to only " 4824 + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); 4825 } 4826 isCallerInteractingAcrossUsers(int userId)4827 public boolean isCallerInteractingAcrossUsers(int userId) { 4828 final int callingUid = Binder.getCallingUid(); 4829 return (Binder.getCallingPid() == android.os.Process.myPid() 4830 || callingUid == Process.SHELL_UID 4831 || userId == UserHandle.USER_CURRENT 4832 || userId == UserHandle.USER_CURRENT_OR_SELF); 4833 } 4834 isRetrievalAllowingWindow(int windowId)4835 private boolean isRetrievalAllowingWindow(int windowId) { 4836 // The system gets to interact with any window it wants. 4837 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 4838 return true; 4839 } 4840 if (windowId == mActiveWindowId) { 4841 return true; 4842 } 4843 return findWindowById(windowId) != null; 4844 } 4845 findWindowById(int windowId)4846 private AccessibilityWindowInfo findWindowById(int windowId) { 4847 return mWindowsById.get(windowId); 4848 } 4849 getPictureInPictureWindow()4850 private AccessibilityWindowInfo getPictureInPictureWindow() { 4851 if (mWindows != null) { 4852 final int windowCount = mWindows.size(); 4853 for (int i = 0; i < windowCount; i++) { 4854 AccessibilityWindowInfo window = mWindows.get(i); 4855 if (window.inPictureInPicture()) { 4856 return window; 4857 } 4858 } 4859 } 4860 return null; 4861 } 4862 enforceCallingPermission(String permission, String function)4863 private void enforceCallingPermission(String permission, String function) { 4864 if (OWN_PROCESS_ID == Binder.getCallingPid()) { 4865 return; 4866 } 4867 if (!hasPermission(permission)) { 4868 throw new SecurityException("You do not have " + permission 4869 + " required to call " + function + " from pid=" 4870 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 4871 } 4872 } 4873 hasPermission(String permission)4874 private boolean hasPermission(String permission) { 4875 return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED; 4876 } 4877 getFocusedWindowId()4878 private int getFocusedWindowId() { 4879 IBinder token = mWindowManagerService.getFocusedWindowToken(); 4880 synchronized (mLock) { 4881 return findWindowIdLocked(token); 4882 } 4883 } 4884 } 4885 4886 private class UserState { 4887 public final int mUserId; 4888 4889 // Non-transient state. 4890 4891 public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients = 4892 new RemoteCallbackList<>(); 4893 4894 public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections = 4895 new SparseArray<>(); 4896 4897 public final SparseArray<IBinder> mWindowTokens = new SparseArray<>(); 4898 4899 // Transient state. 4900 4901 public final CopyOnWriteArrayList<Service> mBoundServices = 4902 new CopyOnWriteArrayList<>(); 4903 4904 public int mLastSentRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK; 4905 4906 public final Map<ComponentName, Service> mComponentNameToServiceMap = 4907 new HashMap<>(); 4908 4909 public final List<AccessibilityServiceInfo> mInstalledServices = 4910 new ArrayList<>(); 4911 4912 public final Set<ComponentName> mBindingServices = new HashSet<>(); 4913 4914 public final Set<ComponentName> mEnabledServices = new HashSet<>(); 4915 4916 public final Set<ComponentName> mTouchExplorationGrantedServices = 4917 new HashSet<>(); 4918 4919 public ComponentName mServiceChangingSoftKeyboardMode; 4920 4921 public ComponentName mServiceToEnableWithShortcut; 4922 4923 public int mLastSentClientState = -1; 4924 4925 public int mSoftKeyboardShowMode = 0; 4926 4927 public boolean mIsNavBarMagnificationAssignedToAccessibilityButton; 4928 public ComponentName mServiceAssignedToAccessibilityButton; 4929 4930 public boolean mIsTouchExplorationEnabled; 4931 public boolean mIsTextHighContrastEnabled; 4932 public boolean mIsDisplayMagnificationEnabled; 4933 public boolean mIsNavBarMagnificationEnabled; 4934 public boolean mIsAutoclickEnabled; 4935 public boolean mIsPerformGesturesEnabled; 4936 public boolean mIsFilterKeyEventsEnabled; 4937 public boolean mAccessibilityFocusOnlyInActiveWindow; 4938 4939 private Service mUiAutomationService; 4940 private int mUiAutomationFlags; 4941 private IAccessibilityServiceClient mUiAutomationServiceClient; 4942 4943 private IBinder mUiAutomationServiceOwner; 4944 private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient = 4945 new DeathRecipient() { 4946 @Override 4947 public void binderDied() { 4948 mUiAutomationServiceOwner.unlinkToDeath( 4949 mUiAutomationSerivceOnwerDeathRecipient, 0); 4950 mUiAutomationServiceOwner = null; 4951 if (mUiAutomationService != null) { 4952 mUiAutomationService.binderDied(); 4953 } 4954 } 4955 }; 4956 UserState(int userId)4957 public UserState(int userId) { 4958 mUserId = userId; 4959 } 4960 getClientState()4961 public int getClientState() { 4962 int clientState = 0; 4963 if (isHandlingAccessibilityEvents()) { 4964 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; 4965 } 4966 // Touch exploration relies on enabled accessibility. 4967 if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) { 4968 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; 4969 } 4970 if (mIsTextHighContrastEnabled) { 4971 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; 4972 } 4973 return clientState; 4974 } 4975 isHandlingAccessibilityEvents()4976 public boolean isHandlingAccessibilityEvents() { 4977 return !mBoundServices.isEmpty() || !mBindingServices.isEmpty(); 4978 } 4979 onSwitchToAnotherUser()4980 public void onSwitchToAnotherUser() { 4981 // Clear UI test automation state. 4982 if (mUiAutomationService != null) { 4983 mUiAutomationService.binderDied(); 4984 } 4985 4986 // Unbind all services. 4987 unbindAllServicesLocked(this); 4988 4989 // Clear service management state. 4990 mBoundServices.clear(); 4991 mBindingServices.clear(); 4992 4993 // Clear event management state. 4994 mLastSentClientState = -1; 4995 4996 // Clear state persisted in settings. 4997 mEnabledServices.clear(); 4998 mTouchExplorationGrantedServices.clear(); 4999 mIsTouchExplorationEnabled = false; 5000 mIsDisplayMagnificationEnabled = false; 5001 mIsNavBarMagnificationEnabled = false; 5002 mServiceAssignedToAccessibilityButton = null; 5003 mIsNavBarMagnificationAssignedToAccessibilityButton = false; 5004 mIsAutoclickEnabled = false; 5005 mSoftKeyboardShowMode = 0; 5006 } 5007 destroyUiAutomationService()5008 public void destroyUiAutomationService() { 5009 mUiAutomationService = null; 5010 mUiAutomationFlags = 0; 5011 mUiAutomationServiceClient = null; 5012 if (mUiAutomationServiceOwner != null) { 5013 mUiAutomationServiceOwner.unlinkToDeath( 5014 mUiAutomationSerivceOnwerDeathRecipient, 0); 5015 mUiAutomationServiceOwner = null; 5016 } 5017 } 5018 isUiAutomationSuppressingOtherServices()5019 boolean isUiAutomationSuppressingOtherServices() { 5020 return ((mUiAutomationService != null) && (mUiAutomationFlags 5021 & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0); 5022 } 5023 } 5024 5025 private final class AccessibilityContentObserver extends ContentObserver { 5026 5027 private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor( 5028 Settings.Secure.TOUCH_EXPLORATION_ENABLED); 5029 5030 private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor( 5031 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); 5032 5033 private final Uri mNavBarMagnificationEnabledUri = Settings.Secure.getUriFor( 5034 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); 5035 5036 private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor( 5037 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED); 5038 5039 private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor( 5040 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 5041 5042 private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure 5043 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); 5044 5045 private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor( 5046 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 5047 5048 private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor( 5049 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED); 5050 5051 private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor( 5052 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER); 5053 5054 private final Uri mHighTextContrastUri = Settings.Secure.getUriFor( 5055 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); 5056 5057 private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor( 5058 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE); 5059 5060 private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor( 5061 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); 5062 5063 private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( 5064 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); 5065 AccessibilityContentObserver(Handler handler)5066 public AccessibilityContentObserver(Handler handler) { 5067 super(handler); 5068 } 5069 register(ContentResolver contentResolver)5070 public void register(ContentResolver contentResolver) { 5071 contentResolver.registerContentObserver(mTouchExplorationEnabledUri, 5072 false, this, UserHandle.USER_ALL); 5073 contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri, 5074 false, this, UserHandle.USER_ALL); 5075 contentResolver.registerContentObserver(mNavBarMagnificationEnabledUri, 5076 false, this, UserHandle.USER_ALL); 5077 contentResolver.registerContentObserver(mAutoclickEnabledUri, 5078 false, this, UserHandle.USER_ALL); 5079 contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri, 5080 false, this, UserHandle.USER_ALL); 5081 contentResolver.registerContentObserver( 5082 mTouchExplorationGrantedAccessibilityServicesUri, 5083 false, this, UserHandle.USER_ALL); 5084 contentResolver.registerContentObserver( 5085 mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL); 5086 contentResolver.registerContentObserver( 5087 mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL); 5088 contentResolver.registerContentObserver( 5089 mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL); 5090 contentResolver.registerContentObserver( 5091 mHighTextContrastUri, false, this, UserHandle.USER_ALL); 5092 contentResolver.registerContentObserver( 5093 mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL); 5094 contentResolver.registerContentObserver( 5095 mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL); 5096 contentResolver.registerContentObserver( 5097 mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); 5098 } 5099 5100 @Override onChange(boolean selfChange, Uri uri)5101 public void onChange(boolean selfChange, Uri uri) { 5102 synchronized (mLock) { 5103 // Profiles share the accessibility state of the parent. Therefore, 5104 // we are checking for changes only the parent settings. 5105 UserState userState = getCurrentUserStateLocked(); 5106 5107 // If the automation service is suppressing, we will update when it dies. 5108 if (userState.isUiAutomationSuppressingOtherServices()) { 5109 return; 5110 } 5111 5112 if (mTouchExplorationEnabledUri.equals(uri)) { 5113 if (readTouchExplorationEnabledSettingLocked(userState)) { 5114 onUserStateChangedLocked(userState); 5115 } 5116 } else if (mDisplayMagnificationEnabledUri.equals(uri) 5117 || mNavBarMagnificationEnabledUri.equals(uri)) { 5118 if (readMagnificationEnabledSettingsLocked(userState)) { 5119 onUserStateChangedLocked(userState); 5120 } 5121 } else if (mAutoclickEnabledUri.equals(uri)) { 5122 if (readAutoclickEnabledSettingLocked(userState)) { 5123 onUserStateChangedLocked(userState); 5124 } 5125 } else if (mEnabledAccessibilityServicesUri.equals(uri)) { 5126 if (readEnabledAccessibilityServicesLocked(userState)) { 5127 onUserStateChangedLocked(userState); 5128 } 5129 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { 5130 if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) { 5131 onUserStateChangedLocked(userState); 5132 } 5133 } else if (mDisplayDaltonizerEnabledUri.equals(uri) 5134 || mDisplayDaltonizerUri.equals(uri)) { 5135 updateDisplayDaltonizerLocked(userState); 5136 } else if (mDisplayInversionEnabledUri.equals(uri)) { 5137 updateDisplayInversionLocked(userState); 5138 } else if (mHighTextContrastUri.equals(uri)) { 5139 if (readHighTextContrastEnabledSettingLocked(userState)) { 5140 onUserStateChangedLocked(userState); 5141 } 5142 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) { 5143 if (readSoftKeyboardShowModeChangedLocked(userState)) { 5144 notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode); 5145 onUserStateChangedLocked(userState); 5146 } 5147 } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) { 5148 if (readAccessibilityShortcutSettingLocked(userState)) { 5149 onUserStateChangedLocked(userState); 5150 } 5151 } else if (mAccessibilityButtonComponentIdUri.equals(uri)) { 5152 if (readAccessibilityButtonSettingsLocked(userState)) { 5153 onUserStateChangedLocked(userState); 5154 } 5155 } 5156 } 5157 } 5158 } 5159 } 5160