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