1 /* 2 ** Copyright 2017, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 package com.android.server.accessibility; 18 19 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE; 20 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER; 21 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_STATUS; 22 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP; 23 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; 24 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION; 25 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CLIENT; 26 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CONNECTION; 27 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL; 28 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 29 import static android.view.accessibility.AccessibilityInteractionClient.CALL_STACK; 30 import static android.view.accessibility.AccessibilityInteractionClient.IGNORE_CALL_STACK; 31 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS; 32 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS; 33 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; 34 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; 35 36 import android.accessibilityservice.AccessibilityGestureEvent; 37 import android.accessibilityservice.AccessibilityService; 38 import android.accessibilityservice.AccessibilityServiceInfo; 39 import android.accessibilityservice.AccessibilityTrace; 40 import android.accessibilityservice.IAccessibilityServiceClient; 41 import android.accessibilityservice.IAccessibilityServiceConnection; 42 import android.annotation.NonNull; 43 import android.annotation.Nullable; 44 import android.app.PendingIntent; 45 import android.content.ComponentName; 46 import android.content.Context; 47 import android.content.Intent; 48 import android.content.ServiceConnection; 49 import android.content.pm.PackageManager; 50 import android.content.pm.ParceledListSlice; 51 import android.graphics.ParcelableColorSpace; 52 import android.graphics.Region; 53 import android.hardware.HardwareBuffer; 54 import android.hardware.display.DisplayManager; 55 import android.hardware.display.DisplayManagerInternal; 56 import android.os.Binder; 57 import android.os.Build; 58 import android.os.Bundle; 59 import android.os.Handler; 60 import android.os.IBinder; 61 import android.os.Looper; 62 import android.os.Message; 63 import android.os.PowerManager; 64 import android.os.RemoteCallback; 65 import android.os.RemoteException; 66 import android.os.ServiceManager; 67 import android.os.SystemClock; 68 import android.util.Slog; 69 import android.util.SparseArray; 70 import android.view.Display; 71 import android.view.KeyEvent; 72 import android.view.MagnificationSpec; 73 import android.view.SurfaceControl.ScreenshotHardwareBuffer; 74 import android.view.View; 75 import android.view.WindowInfo; 76 import android.view.accessibility.AccessibilityCache; 77 import android.view.accessibility.AccessibilityEvent; 78 import android.view.accessibility.AccessibilityNodeInfo; 79 import android.view.accessibility.AccessibilityWindowInfo; 80 import android.view.accessibility.IAccessibilityInteractionConnectionCallback; 81 82 import com.android.internal.annotations.GuardedBy; 83 import com.android.internal.compat.IPlatformCompat; 84 import com.android.internal.os.SomeArgs; 85 import com.android.internal.util.DumpUtils; 86 import com.android.internal.util.function.pooled.PooledLambda; 87 import com.android.server.LocalServices; 88 import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection; 89 import com.android.server.accessibility.magnification.FullScreenMagnificationController; 90 import com.android.server.wm.ActivityTaskManagerInternal; 91 import com.android.server.wm.WindowManagerInternal; 92 93 import java.io.FileDescriptor; 94 import java.io.PrintWriter; 95 import java.util.ArrayList; 96 import java.util.Arrays; 97 import java.util.Collections; 98 import java.util.HashSet; 99 import java.util.List; 100 import java.util.NoSuchElementException; 101 import java.util.Set; 102 103 /** 104 * This class represents an accessibility client - either an AccessibilityService or a UiAutomation. 105 * It is responsible for behavior common to both types of clients. 106 */ 107 abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServiceConnection.Stub 108 implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter, 109 FingerprintGestureDispatcher.FingerprintGestureClient { 110 private static final boolean DEBUG = false; 111 private static final String LOG_TAG = "AbstractAccessibilityServiceConnection"; 112 private static final String TRACE_SVC_CONN = LOG_TAG + ".IAccessibilityServiceConnection"; 113 private static final String TRACE_SVC_CLIENT = LOG_TAG + ".IAccessibilityServiceClient"; 114 private static final String TRACE_WM = "WindowManagerInternal"; 115 private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000; 116 117 protected static final String TAKE_SCREENSHOT = "takeScreenshot"; 118 protected final Context mContext; 119 protected final SystemSupport mSystemSupport; 120 protected final WindowManagerInternal mWindowManagerService; 121 private final SystemActionPerformer mSystemActionPerformer; 122 private final AccessibilityWindowManager mA11yWindowManager; 123 private final DisplayManager mDisplayManager; 124 private final PowerManager mPowerManager; 125 private final IPlatformCompat mIPlatformCompat; 126 127 private final Handler mMainHandler; 128 129 // Handler for scheduling method invocations on the main thread. 130 public final InvocationHandler mInvocationHandler; 131 132 final int mId; 133 134 protected final AccessibilityServiceInfo mAccessibilityServiceInfo; 135 136 // Lock must match the one used by AccessibilityManagerService 137 protected final Object mLock; 138 139 protected final AccessibilitySecurityPolicy mSecurityPolicy; 140 protected final AccessibilityTrace mTrace; 141 142 // The service that's bound to this instance. Whenever this value is non-null, this 143 // object is registered as a death recipient 144 IBinder mService; 145 146 IAccessibilityServiceClient mServiceInterface; 147 148 int mEventTypes; 149 150 int mFeedbackType; 151 152 Set<String> mPackageNames = new HashSet<>(); 153 154 boolean mIsDefault; 155 156 boolean mRequestTouchExplorationMode; 157 158 private boolean mServiceHandlesDoubleTap; 159 160 private boolean mRequestMultiFingerGestures; 161 162 private boolean mRequestTwoFingerPassthrough; 163 164 private boolean mSendMotionEvents; 165 166 boolean mRequestFilterKeyEvents; 167 168 boolean mRetrieveInteractiveWindows; 169 170 boolean mCaptureFingerprintGestures; 171 172 boolean mRequestAccessibilityButton; 173 174 boolean mReceivedAccessibilityButtonCallbackSinceBind; 175 176 boolean mLastAccessibilityButtonCallbackState; 177 178 int mFetchFlags; 179 180 long mNotificationTimeout; 181 182 final ComponentName mComponentName; 183 184 // the events pending events to be dispatched to this service 185 final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>(); 186 187 /** Whether this service relies on its {@link AccessibilityCache} being up to date */ 188 boolean mUsesAccessibilityCache = false; 189 190 // Handler only for dispatching accessibility events since we use event 191 // types as message types allowing us to remove messages per event type. 192 public Handler mEventDispatchHandler; 193 194 final SparseArray<IBinder> mOverlayWindowTokens = new SparseArray(); 195 196 /** The timestamp of requesting to take screenshot in milliseconds */ 197 private long mRequestTakeScreenshotTimestampMs; 198 199 public interface SystemSupport { 200 /** 201 * @return The current dispatcher for key events 202 */ getKeyEventDispatcher()203 @NonNull KeyEventDispatcher getKeyEventDispatcher(); 204 205 /** 206 * @param windowId The id of the window of interest 207 * @return The magnification spec for the window, or {@code null} if none is available 208 */ getCompatibleMagnificationSpecLocked(int windowId)209 @Nullable MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId); 210 211 /** 212 * @param displayId The display id. 213 * @return The current injector of motion events used on the display, if one exists. 214 */ getMotionEventInjectorForDisplayLocked(int displayId)215 @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId); 216 217 /** 218 * @return The current dispatcher for fingerprint gestures, if one exists 219 */ getFingerprintGestureDispatcher()220 @Nullable FingerprintGestureDispatcher getFingerprintGestureDispatcher(); 221 222 /** 223 * @return The magnification controller 224 */ 225 @NonNull getFullScreenMagnificationController()226 FullScreenMagnificationController getFullScreenMagnificationController(); 227 228 /** 229 * Called back to notify system that the client has changed 230 * @param serviceInfoChanged True if the service's AccessibilityServiceInfo changed. 231 */ onClientChangeLocked(boolean serviceInfoChanged)232 void onClientChangeLocked(boolean serviceInfoChanged); 233 getCurrentUserIdLocked()234 int getCurrentUserIdLocked(); 235 isAccessibilityButtonShown()236 boolean isAccessibilityButtonShown(); 237 238 /** 239 * Persists the component names in the specified setting in a 240 * colon separated fashion. 241 * 242 * @param settingName The setting name. 243 * @param componentNames The component names. 244 * @param userId The user id to persist the setting for. 245 */ persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)246 void persistComponentNamesToSettingLocked(String settingName, 247 Set<ComponentName> componentNames, int userId); 248 249 /* This is exactly PendingIntent.getActivity, separated out for testability */ getPendingIntentActivity(Context context, int requestCode, Intent intent, int flags)250 PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent, 251 int flags); 252 setGestureDetectionPassthroughRegion(int displayId, Region region)253 void setGestureDetectionPassthroughRegion(int displayId, Region region); 254 setTouchExplorationPassthroughRegion(int displayId, Region region)255 void setTouchExplorationPassthroughRegion(int displayId, Region region); 256 } 257 AbstractAccessibilityServiceConnection(Context context, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport, AccessibilityTrace trace, WindowManagerInternal windowManagerInternal, SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager a11yWindowManager)258 public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName, 259 AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, 260 Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport, 261 AccessibilityTrace trace, WindowManagerInternal windowManagerInternal, 262 SystemActionPerformer systemActionPerfomer, 263 AccessibilityWindowManager a11yWindowManager) { 264 mContext = context; 265 mWindowManagerService = windowManagerInternal; 266 mId = id; 267 mComponentName = componentName; 268 mAccessibilityServiceInfo = accessibilityServiceInfo; 269 mLock = lock; 270 mSecurityPolicy = securityPolicy; 271 mSystemActionPerformer = systemActionPerfomer; 272 mSystemSupport = systemSupport; 273 mTrace = trace; 274 mMainHandler = mainHandler; 275 mInvocationHandler = new InvocationHandler(mainHandler.getLooper()); 276 mA11yWindowManager = a11yWindowManager; 277 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 278 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 279 mIPlatformCompat = IPlatformCompat.Stub.asInterface( 280 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); 281 mEventDispatchHandler = new Handler(mainHandler.getLooper()) { 282 @Override 283 public void handleMessage(Message message) { 284 final int eventType = message.what; 285 AccessibilityEvent event = (AccessibilityEvent) message.obj; 286 boolean serviceWantsEvent = message.arg1 != 0; 287 notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent); 288 } 289 }; 290 setDynamicallyConfigurableProperties(accessibilityServiceInfo); 291 } 292 293 @Override onKeyEvent(KeyEvent keyEvent, int sequenceNumber)294 public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) { 295 if (!mRequestFilterKeyEvents || (mServiceInterface == null)) { 296 return false; 297 } 298 if((mAccessibilityServiceInfo.getCapabilities() 299 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { 300 return false; 301 } 302 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 303 return false; 304 } 305 try { 306 if (svcClientTracingEnabled()) { 307 logTraceSvcClient("onKeyEvent", keyEvent + ", " + sequenceNumber); 308 } 309 mServiceInterface.onKeyEvent(keyEvent, sequenceNumber); 310 } catch (RemoteException e) { 311 return false; 312 } 313 return true; 314 } 315 setDynamicallyConfigurableProperties(AccessibilityServiceInfo info)316 public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { 317 mEventTypes = info.eventTypes; 318 mFeedbackType = info.feedbackType; 319 String[] packageNames = info.packageNames; 320 mPackageNames.clear(); 321 if (packageNames != null) { 322 mPackageNames.addAll(Arrays.asList(packageNames)); 323 } 324 mNotificationTimeout = info.notificationTimeout; 325 mIsDefault = (info.flags & DEFAULT) != 0; 326 327 if (supportsFlagForNotImportantViews(info)) { 328 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { 329 mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 330 } else { 331 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 332 } 333 } 334 335 if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { 336 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 337 } else { 338 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 339 } 340 341 mRequestTouchExplorationMode = (info.flags 342 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 343 mServiceHandlesDoubleTap = (info.flags 344 & AccessibilityServiceInfo.FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0; 345 mRequestMultiFingerGestures = (info.flags 346 & AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0; 347 mRequestTwoFingerPassthrough = 348 (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0; 349 mSendMotionEvents = 350 (info.flags & AccessibilityServiceInfo.FLAG_SEND_MOTION_EVENTS) != 0; 351 mRequestFilterKeyEvents = 352 (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; 353 mRetrieveInteractiveWindows = (info.flags 354 & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; 355 mCaptureFingerprintGestures = (info.flags 356 & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0; 357 mRequestAccessibilityButton = (info.flags 358 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; 359 } 360 supportsFlagForNotImportantViews(AccessibilityServiceInfo info)361 protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) { 362 return info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 363 >= Build.VERSION_CODES.JELLY_BEAN; 364 } 365 canReceiveEventsLocked()366 public boolean canReceiveEventsLocked() { 367 return (mEventTypes != 0 && mService != null); 368 } 369 370 @Override setOnKeyEventResult(boolean handled, int sequence)371 public void setOnKeyEventResult(boolean handled, int sequence) { 372 if (svcConnTracingEnabled()) { 373 logTraceSvcConn("setOnKeyEventResult", "handled=" + handled + ";sequence=" + sequence); 374 } 375 mSystemSupport.getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); 376 } 377 378 @Override getServiceInfo()379 public AccessibilityServiceInfo getServiceInfo() { 380 if (svcConnTracingEnabled()) { 381 logTraceSvcConn("getServiceInfo", ""); 382 } 383 synchronized (mLock) { 384 return mAccessibilityServiceInfo; 385 } 386 } 387 getCapabilities()388 public int getCapabilities() { 389 return mAccessibilityServiceInfo.getCapabilities(); 390 } 391 getRelevantEventTypes()392 int getRelevantEventTypes() { 393 return (mUsesAccessibilityCache ? AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK 394 : AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) | mEventTypes; 395 } 396 397 @Override setServiceInfo(AccessibilityServiceInfo info)398 public void setServiceInfo(AccessibilityServiceInfo info) { 399 if (svcConnTracingEnabled()) { 400 logTraceSvcConn("setServiceInfo", "info=" + info); 401 } 402 final long identity = Binder.clearCallingIdentity(); 403 try { 404 synchronized (mLock) { 405 // If the XML manifest had data to configure the service its info 406 // should be already set. In such a case update only the dynamically 407 // configurable properties. 408 AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; 409 if (oldInfo != null) { 410 oldInfo.updateDynamicallyConfigurableProperties(mIPlatformCompat, info); 411 setDynamicallyConfigurableProperties(oldInfo); 412 } else { 413 setDynamicallyConfigurableProperties(info); 414 } 415 mSystemSupport.onClientChangeLocked(true); 416 } 417 } finally { 418 Binder.restoreCallingIdentity(identity); 419 } 420 } 421 hasRightsToCurrentUserLocked()422 protected abstract boolean hasRightsToCurrentUserLocked(); 423 424 @Nullable 425 @Override getWindows()426 public AccessibilityWindowInfo.WindowListSparseArray getWindows() { 427 if (svcConnTracingEnabled()) { 428 logTraceSvcConn("getWindows", ""); 429 } 430 synchronized (mLock) { 431 if (!hasRightsToCurrentUserLocked()) { 432 return null; 433 } 434 final boolean permissionGranted = 435 mSecurityPolicy.canRetrieveWindowsLocked(this); 436 if (!permissionGranted) { 437 return null; 438 } 439 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 440 return null; 441 } 442 final AccessibilityWindowInfo.WindowListSparseArray allWindows = 443 new AccessibilityWindowInfo.WindowListSparseArray(); 444 final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked(); 445 final int displayListCounts = displayList.size(); 446 if (displayListCounts > 0) { 447 for (int i = 0; i < displayListCounts; i++) { 448 final int displayId = displayList.get(i); 449 ensureWindowsAvailableTimedLocked(displayId); 450 451 final List<AccessibilityWindowInfo> windowList = getWindowsByDisplayLocked( 452 displayId); 453 if (windowList != null) { 454 allWindows.put(displayId, windowList); 455 } 456 } 457 } 458 return allWindows; 459 } 460 } 461 462 @Override getWindow(int windowId)463 public AccessibilityWindowInfo getWindow(int windowId) { 464 if (svcConnTracingEnabled()) { 465 logTraceSvcConn("getWindow", "windowId=" + windowId); 466 } 467 synchronized (mLock) { 468 int displayId = Display.INVALID_DISPLAY; 469 if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) { 470 displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked( 471 mSystemSupport.getCurrentUserIdLocked(), windowId); 472 } 473 ensureWindowsAvailableTimedLocked(displayId); 474 475 if (!hasRightsToCurrentUserLocked()) { 476 return null; 477 } 478 final boolean permissionGranted = 479 mSecurityPolicy.canRetrieveWindowsLocked(this); 480 if (!permissionGranted) { 481 return null; 482 } 483 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 484 return null; 485 } 486 AccessibilityWindowInfo window = 487 mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId); 488 if (window != null) { 489 AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); 490 windowClone.setConnectionId(mId); 491 return windowClone; 492 } 493 return null; 494 } 495 } 496 497 @Override findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewIdResName, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)498 public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId, 499 long accessibilityNodeId, String viewIdResName, int interactionId, 500 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 501 throws RemoteException { 502 if (svcConnTracingEnabled()) { 503 logTraceSvcConn("findAccessibilityNodeInfosByViewId", 504 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 505 + accessibilityNodeId + ";viewIdResName=" + viewIdResName + ";interactionId=" 506 + interactionId + ";callback=" + callback + ";interrogatingTid=" 507 + interrogatingTid); 508 } 509 final int resolvedWindowId; 510 RemoteAccessibilityConnection connection; 511 Region partialInteractiveRegion = Region.obtain(); 512 MagnificationSpec spec; 513 synchronized (mLock) { 514 mUsesAccessibilityCache = true; 515 if (!hasRightsToCurrentUserLocked()) { 516 return null; 517 } 518 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 519 final boolean permissionGranted = 520 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 521 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 522 if (!permissionGranted) { 523 return null; 524 } else { 525 connection = mA11yWindowManager.getConnectionLocked( 526 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 527 if (connection == null) { 528 return null; 529 } 530 } 531 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 532 resolvedWindowId, partialInteractiveRegion)) { 533 partialInteractiveRegion.recycle(); 534 partialInteractiveRegion = null; 535 } 536 spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); 537 } 538 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 539 return null; 540 } 541 final int interrogatingPid = Binder.getCallingPid(); 542 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 543 interrogatingPid, interrogatingTid); 544 final long identityToken = Binder.clearCallingIdentity(); 545 if (intConnTracingEnabled()) { 546 logTraceIntConn("findAccessibilityNodeInfosByViewId", 547 accessibilityNodeId + ";" + viewIdResName + ";" + partialInteractiveRegion + ";" 548 + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid 549 + ";" + interrogatingTid + ";" + spec); 550 } 551 try { 552 connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId, 553 viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags, 554 interrogatingPid, interrogatingTid, spec); 555 return mSecurityPolicy.computeValidReportedPackages( 556 connection.getPackageName(), connection.getUid()); 557 } catch (RemoteException re) { 558 if (DEBUG) { 559 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); 560 } 561 } finally { 562 Binder.restoreCallingIdentity(identityToken); 563 // Recycle if passed to another process. 564 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 565 partialInteractiveRegion.recycle(); 566 } 567 } 568 return null; 569 } 570 571 @Override findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)572 public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, 573 long accessibilityNodeId, String text, int interactionId, 574 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 575 throws RemoteException { 576 if (svcConnTracingEnabled()) { 577 logTraceSvcConn("findAccessibilityNodeInfosByText", 578 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 579 + accessibilityNodeId + ";text=" + text + ";interactionId=" + interactionId 580 + ";callback=" + callback + ";interrogatingTid=" + interrogatingTid); 581 } 582 final int resolvedWindowId; 583 RemoteAccessibilityConnection connection; 584 Region partialInteractiveRegion = Region.obtain(); 585 MagnificationSpec spec; 586 synchronized (mLock) { 587 mUsesAccessibilityCache = true; 588 if (!hasRightsToCurrentUserLocked()) { 589 return null; 590 } 591 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 592 final boolean permissionGranted = 593 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 594 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 595 if (!permissionGranted) { 596 return null; 597 } else { 598 connection = mA11yWindowManager.getConnectionLocked( 599 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 600 if (connection == null) { 601 return null; 602 } 603 } 604 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 605 resolvedWindowId, partialInteractiveRegion)) { 606 partialInteractiveRegion.recycle(); 607 partialInteractiveRegion = null; 608 } 609 spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); 610 } 611 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 612 return null; 613 } 614 final int interrogatingPid = Binder.getCallingPid(); 615 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 616 interrogatingPid, interrogatingTid); 617 final long identityToken = Binder.clearCallingIdentity(); 618 if (intConnTracingEnabled()) { 619 logTraceIntConn("findAccessibilityNodeInfosByText", 620 accessibilityNodeId + ";" + text + ";" + partialInteractiveRegion + ";" 621 + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid 622 + ";" + interrogatingTid + ";" + spec); 623 } 624 try { 625 connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId, 626 text, partialInteractiveRegion, interactionId, callback, mFetchFlags, 627 interrogatingPid, interrogatingTid, spec); 628 return mSecurityPolicy.computeValidReportedPackages( 629 connection.getPackageName(), connection.getUid()); 630 } catch (RemoteException re) { 631 if (DEBUG) { 632 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); 633 } 634 } finally { 635 Binder.restoreCallingIdentity(identityToken); 636 // Recycle if passed to another process. 637 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 638 partialInteractiveRegion.recycle(); 639 } 640 } 641 return null; 642 } 643 644 @Override findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid, Bundle arguments)645 public String[] findAccessibilityNodeInfoByAccessibilityId( 646 int accessibilityWindowId, long accessibilityNodeId, int interactionId, 647 IAccessibilityInteractionConnectionCallback callback, int flags, 648 long interrogatingTid, Bundle arguments) throws RemoteException { 649 if (svcConnTracingEnabled()) { 650 logTraceSvcConn("findAccessibilityNodeInfoByAccessibilityId", 651 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 652 + accessibilityNodeId + ";interactionId=" + interactionId + ";callback=" 653 + callback + ";flags=" + flags + ";interrogatingTid=" + interrogatingTid 654 + ";arguments=" + arguments); 655 } 656 final int resolvedWindowId; 657 RemoteAccessibilityConnection connection; 658 Region partialInteractiveRegion = Region.obtain(); 659 MagnificationSpec spec; 660 synchronized (mLock) { 661 mUsesAccessibilityCache = true; 662 if (!hasRightsToCurrentUserLocked()) { 663 return null; 664 } 665 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 666 final boolean permissionGranted = 667 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 668 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 669 if (!permissionGranted) { 670 return null; 671 } else { 672 connection = mA11yWindowManager.getConnectionLocked( 673 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 674 if (connection == null) { 675 return null; 676 } 677 } 678 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 679 resolvedWindowId, partialInteractiveRegion)) { 680 partialInteractiveRegion.recycle(); 681 partialInteractiveRegion = null; 682 } 683 spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); 684 } 685 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 686 return null; 687 } 688 final int interrogatingPid = Binder.getCallingPid(); 689 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 690 interrogatingPid, interrogatingTid); 691 final long identityToken = Binder.clearCallingIdentity(); 692 if (intConnTracingEnabled()) { 693 logTraceIntConn("findAccessibilityNodeInfoByAccessibilityId", 694 accessibilityNodeId + ";" + partialInteractiveRegion + ";" + interactionId + ";" 695 + callback + ";" + (mFetchFlags | flags) + ";" + interrogatingPid + ";" 696 + interrogatingTid + ";" + spec + ";" + arguments); 697 } 698 try { 699 connection.getRemote().findAccessibilityNodeInfoByAccessibilityId( 700 accessibilityNodeId, partialInteractiveRegion, interactionId, callback, 701 mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, arguments); 702 return mSecurityPolicy.computeValidReportedPackages( 703 connection.getPackageName(), connection.getUid()); 704 } catch (RemoteException re) { 705 if (DEBUG) { 706 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); 707 } 708 } finally { 709 Binder.restoreCallingIdentity(identityToken); 710 // Recycle if passed to another process. 711 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 712 partialInteractiveRegion.recycle(); 713 } 714 } 715 return null; 716 } 717 718 @Override findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)719 public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, 720 int focusType, int interactionId, 721 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 722 throws RemoteException { 723 if (svcConnTracingEnabled()) { 724 logTraceSvcConn("findFocus", 725 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 726 + accessibilityNodeId + ";focusType=" + focusType + ";interactionId=" 727 + interactionId + ";callback=" + callback + ";interrogatingTid=" 728 + interrogatingTid); 729 } 730 final int resolvedWindowId; 731 RemoteAccessibilityConnection connection; 732 Region partialInteractiveRegion = Region.obtain(); 733 MagnificationSpec spec; 734 synchronized (mLock) { 735 if (!hasRightsToCurrentUserLocked()) { 736 return null; 737 } 738 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( 739 accessibilityWindowId, focusType); 740 final boolean permissionGranted = 741 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 742 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 743 if (!permissionGranted) { 744 return null; 745 } else { 746 connection = mA11yWindowManager.getConnectionLocked( 747 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 748 if (connection == null) { 749 return null; 750 } 751 } 752 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 753 resolvedWindowId, partialInteractiveRegion)) { 754 partialInteractiveRegion.recycle(); 755 partialInteractiveRegion = null; 756 } 757 spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); 758 } 759 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 760 return null; 761 } 762 final int interrogatingPid = Binder.getCallingPid(); 763 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 764 interrogatingPid, interrogatingTid); 765 final long identityToken = Binder.clearCallingIdentity(); 766 if (intConnTracingEnabled()) { 767 logTraceIntConn("findFocus", 768 accessibilityNodeId + ";" + focusType + ";" + partialInteractiveRegion + ";" 769 + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid 770 + ";" + interrogatingTid + ";" + spec); 771 } 772 try { 773 connection.getRemote().findFocus(accessibilityNodeId, focusType, 774 partialInteractiveRegion, interactionId, callback, mFetchFlags, 775 interrogatingPid, interrogatingTid, spec); 776 return mSecurityPolicy.computeValidReportedPackages( 777 connection.getPackageName(), connection.getUid()); 778 } catch (RemoteException re) { 779 if (DEBUG) { 780 Slog.e(LOG_TAG, "Error calling findFocus()"); 781 } 782 } finally { 783 Binder.restoreCallingIdentity(identityToken); 784 // Recycle if passed to another process. 785 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 786 partialInteractiveRegion.recycle(); 787 } 788 } 789 return null; 790 } 791 792 @Override focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)793 public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, 794 int direction, int interactionId, 795 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 796 throws RemoteException { 797 if (svcConnTracingEnabled()) { 798 logTraceSvcConn("focusSearch", 799 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 800 + accessibilityNodeId + ";direction=" + direction + ";interactionId=" 801 + interactionId + ";callback=" + callback + ";interrogatingTid=" 802 + interrogatingTid); 803 } 804 final int resolvedWindowId; 805 RemoteAccessibilityConnection connection; 806 Region partialInteractiveRegion = Region.obtain(); 807 MagnificationSpec spec; 808 synchronized (mLock) { 809 if (!hasRightsToCurrentUserLocked()) { 810 return null; 811 } 812 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 813 final boolean permissionGranted = 814 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 815 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 816 if (!permissionGranted) { 817 return null; 818 } else { 819 connection = mA11yWindowManager.getConnectionLocked( 820 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 821 if (connection == null) { 822 return null; 823 } 824 } 825 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 826 resolvedWindowId, partialInteractiveRegion)) { 827 partialInteractiveRegion.recycle(); 828 partialInteractiveRegion = null; 829 } 830 spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); 831 } 832 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 833 return null; 834 } 835 final int interrogatingPid = Binder.getCallingPid(); 836 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 837 interrogatingPid, interrogatingTid); 838 final long identityToken = Binder.clearCallingIdentity(); 839 if (intConnTracingEnabled()) { 840 logTraceIntConn("focusSearch", 841 accessibilityNodeId + ";" + direction + ";" + partialInteractiveRegion 842 + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";" 843 + interrogatingPid + ";" + interrogatingTid + ";" + spec); 844 } 845 try { 846 connection.getRemote().focusSearch(accessibilityNodeId, direction, 847 partialInteractiveRegion, interactionId, callback, mFetchFlags, 848 interrogatingPid, interrogatingTid, spec); 849 return mSecurityPolicy.computeValidReportedPackages( 850 connection.getPackageName(), connection.getUid()); 851 } catch (RemoteException re) { 852 if (DEBUG) { 853 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); 854 } 855 } finally { 856 Binder.restoreCallingIdentity(identityToken); 857 // Recycle if passed to another process. 858 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 859 partialInteractiveRegion.recycle(); 860 } 861 } 862 return null; 863 } 864 865 @Override sendGesture(int sequence, ParceledListSlice gestureSteps)866 public void sendGesture(int sequence, ParceledListSlice gestureSteps) { 867 if (svcConnTracingEnabled()) { 868 logTraceSvcConn( 869 "sendGesture", "sequence=" + sequence + ";gestureSteps=" + gestureSteps); 870 } 871 } 872 873 @Override dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId)874 public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) { 875 if (svcConnTracingEnabled()) { 876 logTraceSvcConn("dispatchGesture", "sequence=" + sequence + ";gestureSteps=" 877 + gestureSteps + ";displayId=" + displayId); 878 } 879 } 880 881 @Override performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)882 public boolean performAccessibilityAction(int accessibilityWindowId, 883 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 884 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 885 throws RemoteException { 886 if (svcConnTracingEnabled()) { 887 logTraceSvcConn("performAccessibilityAction", 888 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 889 + accessibilityNodeId + ";action=" + action + ";arguments=" + arguments 890 + ";interactionId=" + interactionId + ";callback=" + callback 891 + ";interrogatingTid=" + interrogatingTid); 892 } 893 final int resolvedWindowId; 894 synchronized (mLock) { 895 if (!hasRightsToCurrentUserLocked()) { 896 return false; 897 } 898 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 899 if (!mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 900 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId)) { 901 return false; 902 } 903 } 904 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 905 return false; 906 } 907 return performAccessibilityActionInternal( 908 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId, accessibilityNodeId, 909 action, arguments, interactionId, callback, mFetchFlags, interrogatingTid); 910 } 911 912 @Override performGlobalAction(int action)913 public boolean performGlobalAction(int action) { 914 if (svcConnTracingEnabled()) { 915 logTraceSvcConn("performGlobalAction", "action=" + action); 916 } 917 synchronized (mLock) { 918 if (!hasRightsToCurrentUserLocked()) { 919 return false; 920 } 921 } 922 return mSystemActionPerformer.performSystemAction(action); 923 } 924 925 @Override getSystemActions()926 public @NonNull List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions() { 927 if (svcConnTracingEnabled()) { 928 logTraceSvcConn("getSystemActions", ""); 929 } 930 synchronized (mLock) { 931 if (!hasRightsToCurrentUserLocked()) { 932 return Collections.emptyList(); 933 } 934 } 935 return mSystemActionPerformer.getSystemActions(); 936 } 937 938 @Override isFingerprintGestureDetectionAvailable()939 public boolean isFingerprintGestureDetectionAvailable() { 940 if (svcConnTracingEnabled()) { 941 logTraceSvcConn("isFingerprintGestureDetectionAvailable", ""); 942 } 943 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 944 return false; 945 } 946 if (isCapturingFingerprintGestures()) { 947 FingerprintGestureDispatcher dispatcher = 948 mSystemSupport.getFingerprintGestureDispatcher(); 949 return (dispatcher != null) && dispatcher.isFingerprintGestureDetectionAvailable(); 950 } 951 return false; 952 } 953 954 @Override getMagnificationScale(int displayId)955 public float getMagnificationScale(int displayId) { 956 if (svcConnTracingEnabled()) { 957 logTraceSvcConn("getMagnificationScale", "displayId=" + displayId); 958 } 959 synchronized (mLock) { 960 if (!hasRightsToCurrentUserLocked()) { 961 return 1.0f; 962 } 963 } 964 final long identity = Binder.clearCallingIdentity(); 965 try { 966 return mSystemSupport.getFullScreenMagnificationController().getScale(displayId); 967 } finally { 968 Binder.restoreCallingIdentity(identity); 969 } 970 } 971 972 @Override getMagnificationRegion(int displayId)973 public Region getMagnificationRegion(int displayId) { 974 if (svcConnTracingEnabled()) { 975 logTraceSvcConn("getMagnificationRegion", "displayId=" + displayId); 976 } 977 synchronized (mLock) { 978 final Region region = Region.obtain(); 979 if (!hasRightsToCurrentUserLocked()) { 980 return region; 981 } 982 FullScreenMagnificationController magnificationController = 983 mSystemSupport.getFullScreenMagnificationController(); 984 boolean registeredJustForThisCall = 985 registerMagnificationIfNeeded(displayId, magnificationController); 986 final long identity = Binder.clearCallingIdentity(); 987 try { 988 magnificationController.getMagnificationRegion(displayId, region); 989 return region; 990 } finally { 991 Binder.restoreCallingIdentity(identity); 992 if (registeredJustForThisCall) { 993 magnificationController.unregister(displayId); 994 } 995 } 996 } 997 } 998 999 @Override getMagnificationCenterX(int displayId)1000 public float getMagnificationCenterX(int displayId) { 1001 if (svcConnTracingEnabled()) { 1002 logTraceSvcConn("getMagnificationCenterX", "displayId=" + displayId); 1003 } 1004 synchronized (mLock) { 1005 if (!hasRightsToCurrentUserLocked()) { 1006 return 0.0f; 1007 } 1008 FullScreenMagnificationController magnificationController = 1009 mSystemSupport.getFullScreenMagnificationController(); 1010 boolean registeredJustForThisCall = 1011 registerMagnificationIfNeeded(displayId, magnificationController); 1012 final long identity = Binder.clearCallingIdentity(); 1013 try { 1014 return magnificationController.getCenterX(displayId); 1015 } finally { 1016 Binder.restoreCallingIdentity(identity); 1017 if (registeredJustForThisCall) { 1018 magnificationController.unregister(displayId); 1019 } 1020 } 1021 } 1022 } 1023 1024 @Override getMagnificationCenterY(int displayId)1025 public float getMagnificationCenterY(int displayId) { 1026 if (svcConnTracingEnabled()) { 1027 logTraceSvcConn("getMagnificationCenterY", "displayId=" + displayId); 1028 } 1029 synchronized (mLock) { 1030 if (!hasRightsToCurrentUserLocked()) { 1031 return 0.0f; 1032 } 1033 FullScreenMagnificationController magnificationController = 1034 mSystemSupport.getFullScreenMagnificationController(); 1035 boolean registeredJustForThisCall = 1036 registerMagnificationIfNeeded(displayId, magnificationController); 1037 final long identity = Binder.clearCallingIdentity(); 1038 try { 1039 return magnificationController.getCenterY(displayId); 1040 } finally { 1041 Binder.restoreCallingIdentity(identity); 1042 if (registeredJustForThisCall) { 1043 magnificationController.unregister(displayId); 1044 } 1045 } 1046 } 1047 } 1048 registerMagnificationIfNeeded(int displayId, FullScreenMagnificationController magnificationController)1049 private boolean registerMagnificationIfNeeded(int displayId, 1050 FullScreenMagnificationController magnificationController) { 1051 if (!magnificationController.isRegistered(displayId) 1052 && mSecurityPolicy.canControlMagnification(this)) { 1053 magnificationController.register(displayId); 1054 return true; 1055 } 1056 return false; 1057 } 1058 1059 @Override resetMagnification(int displayId, boolean animate)1060 public boolean resetMagnification(int displayId, boolean animate) { 1061 if (svcConnTracingEnabled()) { 1062 logTraceSvcConn("resetMagnification", "displayId=" + displayId + ";animate=" + animate); 1063 } 1064 synchronized (mLock) { 1065 if (!hasRightsToCurrentUserLocked()) { 1066 return false; 1067 } 1068 if (!mSecurityPolicy.canControlMagnification(this)) { 1069 return false; 1070 } 1071 } 1072 final long identity = Binder.clearCallingIdentity(); 1073 try { 1074 FullScreenMagnificationController magnificationController = 1075 mSystemSupport.getFullScreenMagnificationController(); 1076 return (magnificationController.reset(displayId, animate) 1077 || !magnificationController.isMagnifying(displayId)); 1078 } finally { 1079 Binder.restoreCallingIdentity(identity); 1080 } 1081 } 1082 1083 @Override setMagnificationScaleAndCenter(int displayId, float scale, float centerX, float centerY, boolean animate)1084 public boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX, 1085 float centerY, boolean animate) { 1086 if (svcConnTracingEnabled()) { 1087 logTraceSvcConn("setMagnificationScaleAndCenter", 1088 "displayId=" + displayId + ";scale=" + scale + ";centerX=" + centerX 1089 + ";centerY=" + centerY + ";animate=" + animate); 1090 } 1091 synchronized (mLock) { 1092 if (!hasRightsToCurrentUserLocked()) { 1093 return false; 1094 } 1095 if (!mSecurityPolicy.canControlMagnification(this)) { 1096 return false; 1097 } 1098 final long identity = Binder.clearCallingIdentity(); 1099 try { 1100 FullScreenMagnificationController magnificationController = 1101 mSystemSupport.getFullScreenMagnificationController(); 1102 if (!magnificationController.isRegistered(displayId)) { 1103 magnificationController.register(displayId); 1104 } 1105 return magnificationController 1106 .setScaleAndCenter(displayId, scale, centerX, centerY, animate, mId); 1107 } finally { 1108 Binder.restoreCallingIdentity(identity); 1109 } 1110 } 1111 } 1112 1113 @Override setMagnificationCallbackEnabled(int displayId, boolean enabled)1114 public void setMagnificationCallbackEnabled(int displayId, boolean enabled) { 1115 if (svcConnTracingEnabled()) { 1116 logTraceSvcConn("setMagnificationCallbackEnabled", 1117 "displayId=" + displayId + ";enabled=" + enabled); 1118 } 1119 mInvocationHandler.setMagnificationCallbackEnabled(displayId, enabled); 1120 } 1121 isMagnificationCallbackEnabled(int displayId)1122 public boolean isMagnificationCallbackEnabled(int displayId) { 1123 return mInvocationHandler.isMagnificationCallbackEnabled(displayId); 1124 } 1125 1126 @Override setSoftKeyboardCallbackEnabled(boolean enabled)1127 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 1128 if (svcConnTracingEnabled()) { 1129 logTraceSvcConn("setSoftKeyboardCallbackEnabled", "enabled=" + enabled); 1130 } 1131 mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled); 1132 } 1133 1134 @Override takeScreenshot(int displayId, RemoteCallback callback)1135 public void takeScreenshot(int displayId, RemoteCallback callback) { 1136 if (svcConnTracingEnabled()) { 1137 logTraceSvcConn("takeScreenshot", "displayId=" + displayId + ";callback=" + callback); 1138 } 1139 final long currentTimestamp = SystemClock.uptimeMillis(); 1140 if (mRequestTakeScreenshotTimestampMs != 0 1141 && (currentTimestamp - mRequestTakeScreenshotTimestampMs) 1142 <= AccessibilityService.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) { 1143 sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, 1144 callback); 1145 return; 1146 } 1147 mRequestTakeScreenshotTimestampMs = currentTimestamp; 1148 1149 synchronized (mLock) { 1150 if (!hasRightsToCurrentUserLocked()) { 1151 sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, 1152 callback); 1153 return; 1154 } 1155 1156 if (!mSecurityPolicy.canTakeScreenshotLocked(this)) { 1157 throw new SecurityException("Services don't have the capability of taking" 1158 + " the screenshot."); 1159 } 1160 } 1161 1162 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 1163 sendScreenshotFailure( 1164 AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, 1165 callback); 1166 return; 1167 } 1168 1169 // Private virtual displays are created by the ap and is not allowed to access by other 1170 // aps. We assume the contents on this display should not be captured. 1171 final DisplayManager displayManager = 1172 (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); 1173 final Display display = displayManager.getDisplay(displayId); 1174 if ((display == null) || (display.getType() == Display.TYPE_VIRTUAL 1175 && (display.getFlags() & Display.FLAG_PRIVATE) != 0)) { 1176 sendScreenshotFailure( 1177 AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback); 1178 return; 1179 } 1180 1181 final long identity = Binder.clearCallingIdentity(); 1182 try { 1183 mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { 1184 final ScreenshotHardwareBuffer screenshotBuffer = LocalServices 1185 .getService(DisplayManagerInternal.class).userScreenshot(displayId); 1186 if (screenshotBuffer != null) { 1187 sendScreenshotSuccess(screenshotBuffer, callback); 1188 } else { 1189 sendScreenshotFailure( 1190 AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback); 1191 } 1192 }, null).recycleOnUse()); 1193 } finally { 1194 Binder.restoreCallingIdentity(identity); 1195 } 1196 } 1197 sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer, RemoteCallback callback)1198 private void sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer, 1199 RemoteCallback callback) { 1200 final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); 1201 final ParcelableColorSpace colorSpace = 1202 new ParcelableColorSpace(screenshotBuffer.getColorSpace()); 1203 1204 final Bundle payload = new Bundle(); 1205 payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, 1206 AccessibilityService.TAKE_SCREENSHOT_SUCCESS); 1207 payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER, 1208 hardwareBuffer); 1209 payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace); 1210 payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP, 1211 SystemClock.uptimeMillis()); 1212 1213 // Send back the result. 1214 callback.sendResult(payload); 1215 hardwareBuffer.close(); 1216 } 1217 sendScreenshotFailure(@ccessibilityService.ScreenshotErrorCode int errorCode, RemoteCallback callback)1218 private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode, 1219 RemoteCallback callback) { 1220 mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { 1221 final Bundle payload = new Bundle(); 1222 payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, errorCode); 1223 // Send back the result. 1224 callback.sendResult(payload); 1225 }, null).recycleOnUse()); 1226 } 1227 1228 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)1229 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1230 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 1231 synchronized (mLock) { 1232 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() 1233 .loadLabel(mContext.getPackageManager())); 1234 pw.append(", feedbackType" 1235 + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); 1236 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); 1237 pw.append(", eventTypes=" 1238 + AccessibilityEvent.eventTypeToString(mEventTypes)); 1239 pw.append(", notificationTimeout=" + mNotificationTimeout); 1240 pw.append(", requestA11yBtn=" + mRequestAccessibilityButton); 1241 pw.append("]"); 1242 } 1243 } 1244 onAdded()1245 public void onAdded() { 1246 final Display[] displays = mDisplayManager.getDisplays(); 1247 for (int i = 0; i < displays.length; i++) { 1248 final int displayId = displays[i].getDisplayId(); 1249 onDisplayAdded(displayId); 1250 } 1251 } 1252 1253 /** 1254 * Called whenever a logical display has been added to the system. Add a window token for adding 1255 * an accessibility overlay. 1256 * 1257 * @param displayId The id of the logical display that was added. 1258 */ onDisplayAdded(int displayId)1259 public void onDisplayAdded(int displayId) { 1260 final long identity = Binder.clearCallingIdentity(); 1261 try { 1262 final IBinder overlayWindowToken = new Binder(); 1263 if (wmTracingEnabled()) { 1264 logTraceWM("addWindowToken", 1265 overlayWindowToken + ";TYPE_ACCESSIBILITY_OVERLAY;" + displayId + ";null"); 1266 } 1267 mWindowManagerService.addWindowToken(overlayWindowToken, TYPE_ACCESSIBILITY_OVERLAY, 1268 displayId, null /* options */); 1269 synchronized (mLock) { 1270 mOverlayWindowTokens.put(displayId, overlayWindowToken); 1271 } 1272 } finally { 1273 Binder.restoreCallingIdentity(identity); 1274 } 1275 } 1276 onRemoved()1277 public void onRemoved() { 1278 final Display[] displays = mDisplayManager.getDisplays(); 1279 for (int i = 0; i < displays.length; i++) { 1280 final int displayId = displays[i].getDisplayId(); 1281 onDisplayRemoved(displayId); 1282 } 1283 } 1284 1285 /** 1286 * Called whenever a logical display has been removed from the system. Remove a window token for 1287 * removing an accessibility overlay. 1288 * 1289 * @param displayId The id of the logical display that was added. 1290 */ onDisplayRemoved(int displayId)1291 public void onDisplayRemoved(int displayId) { 1292 final long identity = Binder.clearCallingIdentity(); 1293 if (wmTracingEnabled()) { 1294 logTraceWM( 1295 "addWindowToken", mOverlayWindowTokens.get(displayId) + ";true;" + displayId); 1296 } 1297 try { 1298 mWindowManagerService.removeWindowToken(mOverlayWindowTokens.get(displayId), true, 1299 displayId); 1300 synchronized (mLock) { 1301 mOverlayWindowTokens.remove(displayId); 1302 } 1303 } finally { 1304 Binder.restoreCallingIdentity(identity); 1305 } 1306 } 1307 1308 /** 1309 * Gets overlay window token by the display Id. 1310 * 1311 * @param displayId The id of the logical display that was added. 1312 * @return window token. 1313 */ 1314 @Override getOverlayWindowToken(int displayId)1315 public IBinder getOverlayWindowToken(int displayId) { 1316 if (svcConnTracingEnabled()) { 1317 logTraceSvcConn("getOverlayWindowToken", "displayId=" + displayId); 1318 } 1319 synchronized (mLock) { 1320 return mOverlayWindowTokens.get(displayId); 1321 } 1322 } 1323 1324 /** 1325 * Gets windowId of given token. 1326 * 1327 * @param token The token 1328 * @return window id 1329 */ 1330 @Override getWindowIdForLeashToken(@onNull IBinder token)1331 public int getWindowIdForLeashToken(@NonNull IBinder token) { 1332 if (svcConnTracingEnabled()) { 1333 logTraceSvcConn("getWindowIdForLeashToken", "token=" + token); 1334 } 1335 synchronized (mLock) { 1336 return mA11yWindowManager.getWindowIdLocked(token); 1337 } 1338 } 1339 resetLocked()1340 public void resetLocked() { 1341 mSystemSupport.getKeyEventDispatcher().flush(this); 1342 try { 1343 // Clear the proxy in the other process so this 1344 // IAccessibilityServiceConnection can be garbage collected. 1345 if (mServiceInterface != null) { 1346 if (svcClientTracingEnabled()) { 1347 logTraceSvcClient("init", "null, " + mId + ", null"); 1348 } 1349 mServiceInterface.init(null, mId, null); 1350 } 1351 } catch (RemoteException re) { 1352 /* ignore */ 1353 } 1354 if (mService != null) { 1355 try { 1356 mService.unlinkToDeath(this, 0); 1357 } catch (NoSuchElementException e) { 1358 Slog.e(LOG_TAG, "Failed unregistering death link"); 1359 } 1360 mService = null; 1361 } 1362 1363 mServiceInterface = null; 1364 mReceivedAccessibilityButtonCallbackSinceBind = false; 1365 } 1366 isConnectedLocked()1367 public boolean isConnectedLocked() { 1368 return (mService != null); 1369 } 1370 notifyAccessibilityEvent(AccessibilityEvent event)1371 public void notifyAccessibilityEvent(AccessibilityEvent event) { 1372 synchronized (mLock) { 1373 final int eventType = event.getEventType(); 1374 1375 final boolean serviceWantsEvent = wantsEventLocked(event); 1376 final boolean requiredForCacheConsistency = mUsesAccessibilityCache 1377 && ((AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK & eventType) != 0); 1378 if (!serviceWantsEvent && !requiredForCacheConsistency) { 1379 return; 1380 } 1381 1382 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 1383 return; 1384 } 1385 // Make a copy since during dispatch it is possible the event to 1386 // be modified to remove its source if the receiving service does 1387 // not have permission to access the window content. 1388 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); 1389 Message message; 1390 if ((mNotificationTimeout > 0) 1391 && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) { 1392 // Allow at most one pending event 1393 final AccessibilityEvent oldEvent = mPendingEvents.get(eventType); 1394 mPendingEvents.put(eventType, newEvent); 1395 if (oldEvent != null) { 1396 mEventDispatchHandler.removeMessages(eventType); 1397 oldEvent.recycle(); 1398 } 1399 message = mEventDispatchHandler.obtainMessage(eventType); 1400 } else { 1401 // Send all messages, bypassing mPendingEvents 1402 message = mEventDispatchHandler.obtainMessage(eventType, newEvent); 1403 } 1404 message.arg1 = serviceWantsEvent ? 1 : 0; 1405 1406 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); 1407 } 1408 } 1409 1410 /** 1411 * Determines if given event can be dispatched to a service based on the package of the 1412 * event source. Specifically, a service is notified if it is interested in events from the 1413 * package. 1414 * 1415 * @param event The event. 1416 * @return True if the listener should be notified, false otherwise. 1417 */ wantsEventLocked(AccessibilityEvent event)1418 private boolean wantsEventLocked(AccessibilityEvent event) { 1419 1420 if (!canReceiveEventsLocked()) { 1421 return false; 1422 } 1423 1424 if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) 1425 && !event.isImportantForAccessibility() 1426 && (mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) { 1427 return false; 1428 } 1429 1430 int eventType = event.getEventType(); 1431 if ((mEventTypes & eventType) != eventType) { 1432 return false; 1433 } 1434 1435 Set<String> packageNames = mPackageNames; 1436 String packageName = (event.getPackageName() != null) 1437 ? event.getPackageName().toString() : null; 1438 1439 return (packageNames.isEmpty() || packageNames.contains(packageName)); 1440 } 1441 1442 /** 1443 * Notifies an accessibility service client for a scheduled event given the event type. 1444 * 1445 * @param eventType The type of the event to dispatch. 1446 */ notifyAccessibilityEventInternal( int eventType, AccessibilityEvent event, boolean serviceWantsEvent)1447 private void notifyAccessibilityEventInternal( 1448 int eventType, 1449 AccessibilityEvent event, 1450 boolean serviceWantsEvent) { 1451 IAccessibilityServiceClient listener; 1452 1453 synchronized (mLock) { 1454 listener = mServiceInterface; 1455 1456 // If the service died/was disabled while the message for dispatching 1457 // the accessibility event was propagating the listener may be null. 1458 if (listener == null) { 1459 return; 1460 } 1461 1462 // There are two ways we notify for events, throttled AND non-throttled. If we 1463 // are not throttling, then messages come with events, which we handle with 1464 // minimal fuss. 1465 if (event == null) { 1466 // We are throttling events, so we'll send the event for this type in 1467 // mPendingEvents as long as it it's null. It can only null due to a race 1468 // condition: 1469 // 1470 // 1) A binder thread calls notifyAccessibilityServiceDelayedLocked 1471 // which posts a message for dispatching an event and stores the event 1472 // in mPendingEvents. 1473 // 2) The message is pulled from the queue by the handler on the service 1474 // thread and this method is just about to acquire the lock. 1475 // 3) Another binder thread acquires the lock in notifyAccessibilityEvent 1476 // 4) notifyAccessibilityEvent recycles the event that this method was about 1477 // to process, replaces it with a new one, and posts a second message 1478 // 5) This method grabs the new event, processes it, and removes it from 1479 // mPendingEvents 1480 // 6) The second message dispatched in (4) arrives, but the event has been 1481 // remvoved in (5). 1482 event = mPendingEvents.get(eventType); 1483 if (event == null) { 1484 return; 1485 } 1486 mPendingEvents.remove(eventType); 1487 } 1488 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { 1489 event.setConnectionId(mId); 1490 } else { 1491 event.setSource((View) null); 1492 } 1493 event.setSealed(true); 1494 } 1495 1496 try { 1497 if (svcClientTracingEnabled()) { 1498 logTraceSvcClient("onAccessibilityEvent", event + ";" + serviceWantsEvent); 1499 } 1500 listener.onAccessibilityEvent(event, serviceWantsEvent); 1501 if (DEBUG) { 1502 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); 1503 } 1504 } catch (RemoteException re) { 1505 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); 1506 } finally { 1507 event.recycle(); 1508 } 1509 } 1510 notifyGesture(AccessibilityGestureEvent gestureEvent)1511 public void notifyGesture(AccessibilityGestureEvent gestureEvent) { 1512 mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, 1513 gestureEvent).sendToTarget(); 1514 } 1515 notifySystemActionsChangedLocked()1516 public void notifySystemActionsChangedLocked() { 1517 mInvocationHandler.sendEmptyMessage( 1518 InvocationHandler.MSG_ON_SYSTEM_ACTIONS_CHANGED); 1519 } 1520 notifyClearAccessibilityNodeInfoCache()1521 public void notifyClearAccessibilityNodeInfoCache() { 1522 mInvocationHandler.sendEmptyMessage( 1523 InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); 1524 } 1525 notifyMagnificationChangedLocked(int displayId, @NonNull Region region, float scale, float centerX, float centerY)1526 public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region, 1527 float scale, float centerX, float centerY) { 1528 mInvocationHandler 1529 .notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY); 1530 } 1531 notifySoftKeyboardShowModeChangedLocked(int showState)1532 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 1533 mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState); 1534 } 1535 notifyAccessibilityButtonClickedLocked(int displayId)1536 public void notifyAccessibilityButtonClickedLocked(int displayId) { 1537 mInvocationHandler.notifyAccessibilityButtonClickedLocked(displayId); 1538 } 1539 notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)1540 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 1541 mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available); 1542 } 1543 1544 /** 1545 * Called by the invocation handler to notify the service that the 1546 * state of magnification has changed. 1547 */ notifyMagnificationChangedInternal(int displayId, @NonNull Region region, float scale, float centerX, float centerY)1548 private void notifyMagnificationChangedInternal(int displayId, @NonNull Region region, 1549 float scale, float centerX, float centerY) { 1550 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1551 if (listener != null) { 1552 try { 1553 if (svcClientTracingEnabled()) { 1554 logTraceSvcClient("onMagnificationChanged", displayId + ", " + region + ", " 1555 + scale + ", " + centerX + ", " + centerY); 1556 } 1557 listener.onMagnificationChanged(displayId, region, scale, centerX, centerY); 1558 } catch (RemoteException re) { 1559 Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re); 1560 } 1561 } 1562 } 1563 1564 /** 1565 * Called by the invocation handler to notify the service that the state of the soft 1566 * keyboard show mode has changed. 1567 */ notifySoftKeyboardShowModeChangedInternal(int showState)1568 private void notifySoftKeyboardShowModeChangedInternal(int showState) { 1569 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1570 if (listener != null) { 1571 try { 1572 if (svcClientTracingEnabled()) { 1573 logTraceSvcClient("onSoftKeyboardShowModeChanged", String.valueOf(showState)); 1574 } 1575 listener.onSoftKeyboardShowModeChanged(showState); 1576 } catch (RemoteException re) { 1577 Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService, 1578 re); 1579 } 1580 } 1581 } 1582 notifyAccessibilityButtonClickedInternal(int displayId)1583 private void notifyAccessibilityButtonClickedInternal(int displayId) { 1584 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1585 if (listener != null) { 1586 try { 1587 if (svcClientTracingEnabled()) { 1588 logTraceSvcClient("onAccessibilityButtonClicked", String.valueOf(displayId)); 1589 } 1590 listener.onAccessibilityButtonClicked(displayId); 1591 } catch (RemoteException re) { 1592 Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re); 1593 } 1594 } 1595 } 1596 notifyAccessibilityButtonAvailabilityChangedInternal(boolean available)1597 private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) { 1598 // Only notify the service if it's not been notified or the state has changed 1599 if (mReceivedAccessibilityButtonCallbackSinceBind 1600 && (mLastAccessibilityButtonCallbackState == available)) { 1601 return; 1602 } 1603 mReceivedAccessibilityButtonCallbackSinceBind = true; 1604 mLastAccessibilityButtonCallbackState = available; 1605 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1606 if (listener != null) { 1607 try { 1608 if (svcClientTracingEnabled()) { 1609 logTraceSvcClient("onAccessibilityButtonAvailabilityChanged", 1610 String.valueOf(available)); 1611 } 1612 listener.onAccessibilityButtonAvailabilityChanged(available); 1613 } catch (RemoteException re) { 1614 Slog.e(LOG_TAG, 1615 "Error sending accessibility button availability change to " + mService, 1616 re); 1617 } 1618 } 1619 } 1620 notifyGestureInternal(AccessibilityGestureEvent gestureInfo)1621 private void notifyGestureInternal(AccessibilityGestureEvent gestureInfo) { 1622 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1623 if (listener != null) { 1624 try { 1625 if (svcClientTracingEnabled()) { 1626 logTraceSvcClient("onGesture", gestureInfo.toString()); 1627 } 1628 listener.onGesture(gestureInfo); 1629 } catch (RemoteException re) { 1630 Slog.e(LOG_TAG, "Error during sending gesture " + gestureInfo 1631 + " to " + mService, re); 1632 } 1633 } 1634 } 1635 notifySystemActionsChangedInternal()1636 private void notifySystemActionsChangedInternal() { 1637 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1638 if (listener != null) { 1639 try { 1640 if (svcClientTracingEnabled()) { 1641 logTraceSvcClient("onSystemActionsChanged", ""); 1642 } 1643 listener.onSystemActionsChanged(); 1644 } catch (RemoteException re) { 1645 Slog.e(LOG_TAG, "Error sending system actions change to " + mService, 1646 re); 1647 } 1648 } 1649 } 1650 notifyClearAccessibilityCacheInternal()1651 private void notifyClearAccessibilityCacheInternal() { 1652 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1653 if (listener != null) { 1654 try { 1655 if (svcClientTracingEnabled()) { 1656 logTraceSvcClient("clearAccessibilityCache", ""); 1657 } 1658 listener.clearAccessibilityCache(); 1659 } catch (RemoteException re) { 1660 Slog.e(LOG_TAG, "Error during requesting accessibility info cache" 1661 + " to be cleared.", re); 1662 } 1663 } 1664 } 1665 getServiceInterfaceSafely()1666 private IAccessibilityServiceClient getServiceInterfaceSafely() { 1667 synchronized (mLock) { 1668 return mServiceInterface; 1669 } 1670 } 1671 resolveAccessibilityWindowIdLocked(int accessibilityWindowId)1672 private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { 1673 if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { 1674 return mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked()); 1675 } 1676 return accessibilityWindowId; 1677 } 1678 resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType)1679 private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { 1680 if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { 1681 return mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked()); 1682 } 1683 if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) { 1684 return mA11yWindowManager.getFocusedWindowId(focusType); 1685 } 1686 return windowId; 1687 } 1688 1689 /** 1690 * Request that the system make sure windows are available to interrogate. 1691 * 1692 * @param displayId The logical display id. 1693 */ ensureWindowsAvailableTimedLocked(int displayId)1694 private void ensureWindowsAvailableTimedLocked(int displayId) { 1695 if (mA11yWindowManager.getWindowListLocked(displayId) != null) { 1696 return; 1697 } 1698 // If we have no registered callback, update the state we 1699 // we may have to register one but it didn't happen yet. 1700 if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) { 1701 // Invokes client change to make sure tracking window enabled. 1702 mSystemSupport.onClientChangeLocked(false); 1703 } 1704 // We have no windows but do not care about them, done. 1705 if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) { 1706 return; 1707 } 1708 1709 // Wait for the windows with a timeout. 1710 final long startMillis = SystemClock.uptimeMillis(); 1711 while (mA11yWindowManager.getWindowListLocked(displayId) == null) { 1712 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 1713 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; 1714 if (remainMillis <= 0) { 1715 return; 1716 } 1717 try { 1718 mLock.wait(remainMillis); 1719 } catch (InterruptedException ie) { 1720 /* ignore */ 1721 } 1722 } 1723 } 1724 1725 /** 1726 * Perform the specified accessibility action 1727 * 1728 * @param resolvedWindowId The window ID 1729 * [Other parameters match the method on IAccessibilityServiceConnection] 1730 * 1731 * @return Whether or not the action could be sent to the app process 1732 */ performAccessibilityActionInternal(int userId, int resolvedWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, int fetchFlags, long interrogatingTid)1733 private boolean performAccessibilityActionInternal(int userId, int resolvedWindowId, 1734 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 1735 IAccessibilityInteractionConnectionCallback callback, int fetchFlags, 1736 long interrogatingTid) { 1737 RemoteAccessibilityConnection connection; 1738 IBinder activityToken = null; 1739 synchronized (mLock) { 1740 connection = mA11yWindowManager.getConnectionLocked(userId, resolvedWindowId); 1741 if (connection == null) { 1742 return false; 1743 } 1744 final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS) 1745 || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS); 1746 if (!isA11yFocusAction) { 1747 final WindowInfo windowInfo = 1748 mA11yWindowManager.findWindowInfoByIdLocked(resolvedWindowId); 1749 if (windowInfo != null) activityToken = windowInfo.activityToken; 1750 } 1751 final AccessibilityWindowInfo a11yWindowInfo = 1752 mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId); 1753 if (a11yWindowInfo != null && a11yWindowInfo.isInPictureInPictureMode() 1754 && mA11yWindowManager.getPictureInPictureActionReplacingConnection() != null 1755 && !isA11yFocusAction) { 1756 connection = mA11yWindowManager.getPictureInPictureActionReplacingConnection(); 1757 } 1758 } 1759 final int interrogatingPid = Binder.getCallingPid(); 1760 final long identityToken = Binder.clearCallingIdentity(); 1761 try { 1762 // Regardless of whether or not the action succeeds, it was generated by an 1763 // accessibility service that is driven by user actions, so note user activity. 1764 mPowerManager.userActivity(SystemClock.uptimeMillis(), 1765 PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); 1766 1767 if (action == ACTION_CLICK || action == ACTION_LONG_CLICK) { 1768 mA11yWindowManager.notifyOutsideTouch(userId, resolvedWindowId); 1769 } 1770 if (activityToken != null) { 1771 LocalServices.getService(ActivityTaskManagerInternal.class) 1772 .setFocusedActivity(activityToken); 1773 } 1774 if (intConnTracingEnabled()) { 1775 logTraceIntConn("performAccessibilityAction", 1776 accessibilityNodeId + ";" + action + ";" + arguments + ";" + interactionId 1777 + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid + ";" 1778 + interrogatingTid); 1779 } 1780 connection.getRemote().performAccessibilityAction(accessibilityNodeId, action, 1781 arguments, interactionId, callback, fetchFlags, interrogatingPid, 1782 interrogatingTid); 1783 } catch (RemoteException re) { 1784 if (DEBUG) { 1785 Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re); 1786 } 1787 return false; 1788 } finally { 1789 Binder.restoreCallingIdentity(identityToken); 1790 } 1791 return true; 1792 } 1793 1794 /** 1795 * Replace the interaction callback if needed, for example if the window is in picture- 1796 * in-picture mode and needs its nodes replaced. 1797 * 1798 * @param originalCallback The callback we were planning to use 1799 * @param resolvedWindowId The ID of the window we're calling 1800 * @param interactionId The id for the original callback 1801 * @param interrogatingPid Process ID of requester 1802 * @param interrogatingTid Thread ID of requester 1803 * 1804 * @return The callback to use, which may be the original one. 1805 */ replaceCallbackIfNeeded( IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, int interactionId, int interrogatingPid, long interrogatingTid)1806 private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded( 1807 IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, 1808 int interactionId, int interrogatingPid, long interrogatingTid) { 1809 final RemoteAccessibilityConnection pipActionReplacingConnection = 1810 mA11yWindowManager.getPictureInPictureActionReplacingConnection(); 1811 synchronized (mLock) { 1812 final AccessibilityWindowInfo windowInfo = 1813 mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId); 1814 if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode() 1815 || (pipActionReplacingConnection == null)) { 1816 return originalCallback; 1817 } 1818 } 1819 return new ActionReplacingCallback(originalCallback, 1820 pipActionReplacingConnection.getRemote(), interactionId, 1821 interrogatingPid, interrogatingTid); 1822 } 1823 getWindowsByDisplayLocked(int displayId)1824 private List<AccessibilityWindowInfo> getWindowsByDisplayLocked(int displayId) { 1825 final List<AccessibilityWindowInfo> internalWindowList = 1826 mA11yWindowManager.getWindowListLocked(displayId); 1827 if (internalWindowList == null) { 1828 return null; 1829 } 1830 final List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>(); 1831 final int windowCount = internalWindowList.size(); 1832 for (int i = 0; i < windowCount; i++) { 1833 AccessibilityWindowInfo window = internalWindowList.get(i); 1834 AccessibilityWindowInfo windowClone = 1835 AccessibilityWindowInfo.obtain(window); 1836 windowClone.setConnectionId(mId); 1837 returnedWindowList.add(windowClone); 1838 } 1839 return returnedWindowList; 1840 } 1841 getComponentName()1842 public ComponentName getComponentName() { 1843 return mComponentName; 1844 } 1845 1846 private final class InvocationHandler extends Handler { 1847 public static final int MSG_ON_GESTURE = 1; 1848 public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; 1849 1850 private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; 1851 private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6; 1852 private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7; 1853 private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8; 1854 private static final int MSG_ON_SYSTEM_ACTIONS_CHANGED = 9; 1855 1856 /** List of magnification callback states, mapping from displayId -> Boolean */ 1857 @GuardedBy("mlock") 1858 private final SparseArray<Boolean> mMagnificationCallbackState = new SparseArray<>(0); 1859 private boolean mIsSoftKeyboardCallbackEnabled = false; 1860 InvocationHandler(Looper looper)1861 public InvocationHandler(Looper looper) { 1862 super(looper, null, true); 1863 } 1864 1865 @Override handleMessage(Message message)1866 public void handleMessage(Message message) { 1867 final int type = message.what; 1868 switch (type) { 1869 case MSG_ON_GESTURE: { 1870 notifyGestureInternal((AccessibilityGestureEvent) message.obj); 1871 } break; 1872 1873 case MSG_CLEAR_ACCESSIBILITY_CACHE: { 1874 notifyClearAccessibilityCacheInternal(); 1875 } break; 1876 1877 case MSG_ON_MAGNIFICATION_CHANGED: { 1878 final SomeArgs args = (SomeArgs) message.obj; 1879 final Region region = (Region) args.arg1; 1880 final float scale = (float) args.arg2; 1881 final float centerX = (float) args.arg3; 1882 final float centerY = (float) args.arg4; 1883 final int displayId = args.argi1; 1884 notifyMagnificationChangedInternal(displayId, region, scale, centerX, centerY); 1885 args.recycle(); 1886 } break; 1887 1888 case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: { 1889 final int showState = (int) message.arg1; 1890 notifySoftKeyboardShowModeChangedInternal(showState); 1891 } break; 1892 1893 case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: { 1894 final int displayId = (int) message.arg1; 1895 notifyAccessibilityButtonClickedInternal(displayId); 1896 } break; 1897 1898 case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: { 1899 final boolean available = (message.arg1 != 0); 1900 notifyAccessibilityButtonAvailabilityChangedInternal(available); 1901 } break; 1902 case MSG_ON_SYSTEM_ACTIONS_CHANGED: { 1903 notifySystemActionsChangedInternal(); 1904 break; 1905 } 1906 default: { 1907 throw new IllegalArgumentException("Unknown message: " + type); 1908 } 1909 } 1910 } 1911 notifyMagnificationChangedLocked(int displayId, @NonNull Region region, float scale, float centerX, float centerY)1912 public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region, 1913 float scale, float centerX, float centerY) { 1914 synchronized (mLock) { 1915 if (mMagnificationCallbackState.get(displayId) == null) { 1916 return; 1917 } 1918 } 1919 1920 final SomeArgs args = SomeArgs.obtain(); 1921 args.arg1 = region; 1922 args.arg2 = scale; 1923 args.arg3 = centerX; 1924 args.arg4 = centerY; 1925 args.argi1 = displayId; 1926 1927 final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args); 1928 msg.sendToTarget(); 1929 } 1930 setMagnificationCallbackEnabled(int displayId, boolean enabled)1931 public void setMagnificationCallbackEnabled(int displayId, boolean enabled) { 1932 synchronized (mLock) { 1933 if (enabled) { 1934 mMagnificationCallbackState.put(displayId, true); 1935 } else { 1936 mMagnificationCallbackState.remove(displayId); 1937 } 1938 } 1939 } 1940 isMagnificationCallbackEnabled(int displayId)1941 public boolean isMagnificationCallbackEnabled(int displayId) { 1942 synchronized (mLock) { 1943 return mMagnificationCallbackState.get(displayId) != null; 1944 } 1945 } 1946 notifySoftKeyboardShowModeChangedLocked(int showState)1947 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 1948 if (!mIsSoftKeyboardCallbackEnabled) { 1949 return; 1950 } 1951 1952 final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0); 1953 msg.sendToTarget(); 1954 } 1955 setSoftKeyboardCallbackEnabled(boolean enabled)1956 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 1957 mIsSoftKeyboardCallbackEnabled = enabled; 1958 } 1959 notifyAccessibilityButtonClickedLocked(int displayId)1960 public void notifyAccessibilityButtonClickedLocked(int displayId) { 1961 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED, displayId, 0); 1962 msg.sendToTarget(); 1963 } 1964 notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)1965 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 1966 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, 1967 (available ? 1 : 0), 0); 1968 msg.sendToTarget(); 1969 } 1970 } 1971 isServiceHandlesDoubleTapEnabled()1972 public boolean isServiceHandlesDoubleTapEnabled() { 1973 return mServiceHandlesDoubleTap; 1974 } 1975 isMultiFingerGesturesEnabled()1976 public boolean isMultiFingerGesturesEnabled() { 1977 return mRequestMultiFingerGestures; 1978 } 1979 isTwoFingerPassthroughEnabled()1980 public boolean isTwoFingerPassthroughEnabled() { 1981 return mRequestTwoFingerPassthrough; 1982 } 1983 isSendMotionEventsEnabled()1984 public boolean isSendMotionEventsEnabled() { 1985 return mSendMotionEvents; 1986 } 1987 1988 @Override setGestureDetectionPassthroughRegion(int displayId, Region region)1989 public void setGestureDetectionPassthroughRegion(int displayId, Region region) { 1990 if (svcConnTracingEnabled()) { 1991 logTraceSvcConn("setGestureDetectionPassthroughRegion", 1992 "displayId=" + displayId + ";region=" + region); 1993 } 1994 mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region); 1995 } 1996 1997 @Override setTouchExplorationPassthroughRegion(int displayId, Region region)1998 public void setTouchExplorationPassthroughRegion(int displayId, Region region) { 1999 if (svcConnTracingEnabled()) { 2000 logTraceSvcConn("setTouchExplorationPassthroughRegion", 2001 "displayId=" + displayId + ";region=" + region); 2002 } 2003 mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region); 2004 } 2005 2006 @Override setFocusAppearance(int strokeWidth, int color)2007 public void setFocusAppearance(int strokeWidth, int color) { 2008 if (svcConnTracingEnabled()) { 2009 logTraceSvcConn("setFocusAppearance", "strokeWidth=" + strokeWidth + ";color=" + color); 2010 } 2011 } 2012 2013 @Override logTrace(long timestamp, String where, long loggingTypes, String callingParams, int processId, long threadId, int callingUid, Bundle callingStack)2014 public void logTrace(long timestamp, String where, long loggingTypes, String callingParams, 2015 int processId, long threadId, int callingUid, Bundle callingStack) { 2016 if (mTrace.isA11yTracingEnabledForTypes(loggingTypes)) { 2017 ArrayList<StackTraceElement> list = 2018 (ArrayList<StackTraceElement>) callingStack.getSerializable(CALL_STACK); 2019 HashSet<String> ignoreList = 2020 (HashSet<String>) callingStack.getSerializable(IGNORE_CALL_STACK); 2021 mTrace.logTrace(timestamp, where, loggingTypes, callingParams, processId, threadId, 2022 callingUid, list.toArray(new StackTraceElement[list.size()]), ignoreList); 2023 } 2024 } 2025 svcClientTracingEnabled()2026 protected boolean svcClientTracingEnabled() { 2027 return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CLIENT); 2028 } 2029 logTraceSvcClient(String methodName, String params)2030 protected void logTraceSvcClient(String methodName, String params) { 2031 mTrace.logTrace(TRACE_SVC_CLIENT + "." + methodName, 2032 FLAGS_ACCESSIBILITY_SERVICE_CLIENT, params); 2033 } 2034 svcConnTracingEnabled()2035 protected boolean svcConnTracingEnabled() { 2036 return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CONNECTION); 2037 } 2038 logTraceSvcConn(String methodName, String params)2039 protected void logTraceSvcConn(String methodName, String params) { 2040 mTrace.logTrace(TRACE_SVC_CONN + "." + methodName, 2041 FLAGS_ACCESSIBILITY_SERVICE_CONNECTION, params); 2042 } 2043 intConnTracingEnabled()2044 protected boolean intConnTracingEnabled() { 2045 return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION); 2046 } 2047 logTraceIntConn(String methodName, String params)2048 protected void logTraceIntConn(String methodName, String params) { 2049 mTrace.logTrace(LOG_TAG + "." + methodName, 2050 FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION, params); 2051 } 2052 wmTracingEnabled()2053 protected boolean wmTracingEnabled() { 2054 return mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL); 2055 } 2056 logTraceWM(String methodName, String params)2057 protected void logTraceWM(String methodName, String params) { 2058 mTrace.logTrace(TRACE_WM + "." + methodName, FLAGS_WINDOW_MANAGER_INTERNAL, params); 2059 } 2060 } 2061