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.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS; 20 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE; 21 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER; 22 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_STATUS; 23 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP; 24 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; 25 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION; 26 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CLIENT; 27 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CONNECTION; 28 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL; 29 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 30 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 31 import static android.view.accessibility.AccessibilityInteractionClient.CALL_STACK; 32 import static android.view.accessibility.AccessibilityInteractionClient.IGNORE_CALL_STACK; 33 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS; 34 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS; 35 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; 36 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; 37 38 import android.accessibilityservice.AccessibilityGestureEvent; 39 import android.accessibilityservice.AccessibilityService; 40 import android.accessibilityservice.AccessibilityServiceInfo; 41 import android.accessibilityservice.AccessibilityTrace; 42 import android.accessibilityservice.IAccessibilityServiceClient; 43 import android.accessibilityservice.IAccessibilityServiceConnection; 44 import android.accessibilityservice.MagnificationConfig; 45 import android.annotation.IntDef; 46 import android.annotation.NonNull; 47 import android.annotation.Nullable; 48 import android.app.PendingIntent; 49 import android.content.ComponentName; 50 import android.content.Context; 51 import android.content.Intent; 52 import android.content.ServiceConnection; 53 import android.content.pm.PackageManager; 54 import android.content.pm.ParceledListSlice; 55 import android.graphics.ParcelableColorSpace; 56 import android.graphics.Region; 57 import android.hardware.HardwareBuffer; 58 import android.hardware.display.DisplayManager; 59 import android.hardware.display.DisplayManagerInternal; 60 import android.os.Binder; 61 import android.os.Build; 62 import android.os.Bundle; 63 import android.os.Handler; 64 import android.os.IBinder; 65 import android.os.Looper; 66 import android.os.Message; 67 import android.os.PowerManager; 68 import android.os.RemoteCallback; 69 import android.os.RemoteException; 70 import android.os.ServiceManager; 71 import android.os.SystemClock; 72 import android.os.Trace; 73 import android.provider.Settings; 74 import android.util.Pair; 75 import android.util.Slog; 76 import android.util.SparseArray; 77 import android.view.Display; 78 import android.view.InputDevice; 79 import android.view.KeyEvent; 80 import android.view.MagnificationSpec; 81 import android.view.MotionEvent; 82 import android.view.SurfaceControl; 83 import android.view.View; 84 import android.view.accessibility.AccessibilityCache; 85 import android.view.accessibility.AccessibilityEvent; 86 import android.view.accessibility.AccessibilityNodeInfo; 87 import android.view.accessibility.AccessibilityWindowInfo; 88 import android.view.accessibility.IAccessibilityInteractionConnectionCallback; 89 import android.view.inputmethod.EditorInfo; 90 import android.window.ScreenCapture; 91 import android.window.ScreenCapture.ScreenshotHardwareBuffer; 92 93 import com.android.internal.annotations.GuardedBy; 94 import com.android.internal.compat.IPlatformCompat; 95 import com.android.internal.inputmethod.IAccessibilityInputMethodSession; 96 import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; 97 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; 98 import com.android.internal.os.SomeArgs; 99 import com.android.internal.util.DumpUtils; 100 import com.android.internal.util.function.pooled.PooledLambda; 101 import com.android.server.LocalServices; 102 import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection; 103 import com.android.server.accessibility.magnification.MagnificationProcessor; 104 import com.android.server.inputmethod.InputMethodManagerInternal; 105 import com.android.server.wm.WindowManagerInternal; 106 107 import java.io.FileDescriptor; 108 import java.io.PrintWriter; 109 import java.lang.annotation.Retention; 110 import java.lang.annotation.RetentionPolicy; 111 import java.util.ArrayList; 112 import java.util.Arrays; 113 import java.util.Collections; 114 import java.util.HashSet; 115 import java.util.List; 116 import java.util.NoSuchElementException; 117 import java.util.Set; 118 119 /** 120 * This class represents an accessibility client - either an AccessibilityService or a UiAutomation. 121 * It is responsible for behavior common to both types of clients. 122 */ 123 abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServiceConnection.Stub 124 implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter, 125 FingerprintGestureDispatcher.FingerprintGestureClient { 126 private static final boolean DEBUG = false; 127 private static final String LOG_TAG = "AbstractAccessibilityServiceConnection"; 128 private static final String TRACE_SVC_CONN = LOG_TAG + ".IAccessibilityServiceConnection"; 129 private static final String TRACE_SVC_CLIENT = LOG_TAG + ".IAccessibilityServiceClient"; 130 private static final String TRACE_WM = "WindowManagerInternal"; 131 private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000; 132 133 /** Display type for displays associated with the default user of the device. */ 134 public static final int DISPLAY_TYPE_DEFAULT = 1 << 0; 135 /** Display type for displays associated with an AccessibilityDisplayProxy user. */ 136 public static final int DISPLAY_TYPE_PROXY = 1 << 1; 137 138 protected static final String TAKE_SCREENSHOT = "takeScreenshot"; 139 protected final Context mContext; 140 protected final SystemSupport mSystemSupport; 141 protected final WindowManagerInternal mWindowManagerService; 142 private final SystemActionPerformer mSystemActionPerformer; 143 final AccessibilityWindowManager mA11yWindowManager; 144 private final DisplayManager mDisplayManager; 145 private final PowerManager mPowerManager; 146 private final IPlatformCompat mIPlatformCompat; 147 148 private final Handler mMainHandler; 149 150 // Handler for scheduling method invocations on the main thread. 151 public final InvocationHandler mInvocationHandler; 152 153 final int mId; 154 155 protected final AccessibilityServiceInfo mAccessibilityServiceInfo; 156 157 // Lock must match the one used by AccessibilityManagerService 158 protected final Object mLock; 159 160 protected final AccessibilitySecurityPolicy mSecurityPolicy; 161 protected final AccessibilityTrace mTrace; 162 163 // The attribution tag set by the service that is bound to this instance 164 protected String mAttributionTag; 165 166 protected int mDisplayTypes = DISPLAY_TYPE_DEFAULT; 167 168 // The service that's bound to this instance. Whenever this value is non-null, this 169 // object is registered as a death recipient 170 IBinder mService; 171 172 IAccessibilityServiceClient mServiceInterface; 173 174 int mEventTypes; 175 176 int mFeedbackType; 177 178 Set<String> mPackageNames = new HashSet<>(); 179 180 boolean mIsDefault; 181 182 boolean mRequestTouchExplorationMode; 183 184 private boolean mServiceHandlesDoubleTap; 185 186 private boolean mRequestMultiFingerGestures; 187 188 private boolean mRequestTwoFingerPassthrough; 189 190 private boolean mSendMotionEvents; 191 192 private SparseArray<Boolean> mServiceDetectsGestures = new SparseArray<>(0); 193 boolean mRequestFilterKeyEvents; 194 195 boolean mRetrieveInteractiveWindows; 196 197 boolean mCaptureFingerprintGestures; 198 199 boolean mRequestAccessibilityButton; 200 201 boolean mReceivedAccessibilityButtonCallbackSinceBind; 202 203 boolean mLastAccessibilityButtonCallbackState; 204 205 boolean mRequestImeApis; 206 207 int mFetchFlags; 208 209 long mNotificationTimeout; 210 211 final ComponentName mComponentName; 212 213 int mGenericMotionEventSources; 214 215 // the events pending events to be dispatched to this service 216 final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>(); 217 218 /** Whether this service relies on its {@link AccessibilityCache} being up to date */ 219 boolean mUsesAccessibilityCache = false; 220 221 // Handler only for dispatching accessibility events since we use event 222 // types as message types allowing us to remove messages per event type. 223 public Handler mEventDispatchHandler; 224 225 final SparseArray<IBinder> mOverlayWindowTokens = new SparseArray(); 226 227 /** The timestamp of requesting to take screenshot in milliseconds */ 228 private long mRequestTakeScreenshotTimestampMs; 229 /** 230 * The timestamps of requesting to take a window screenshot in milliseconds, 231 * mapping from accessibility window id -> timestamp. 232 */ 233 private SparseArray<Long> mRequestTakeScreenshotOfWindowTimestampMs = new SparseArray<>(); 234 235 /** @hide */ 236 @Retention(RetentionPolicy.SOURCE) 237 @IntDef(flag = true, prefix = { "DISPLAY_TYPE_" }, value = { 238 DISPLAY_TYPE_DEFAULT, 239 DISPLAY_TYPE_PROXY 240 }) 241 public @interface DisplayTypes {} 242 243 public interface SystemSupport { 244 /** 245 * @return The current dispatcher for key events 246 */ getKeyEventDispatcher()247 @NonNull KeyEventDispatcher getKeyEventDispatcher(); 248 249 /** 250 * @param displayId The display id. 251 * @return The current injector of motion events used on the display, if one exists. 252 */ getMotionEventInjectorForDisplayLocked(int displayId)253 @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId); 254 255 /** 256 * @return The current dispatcher for fingerprint gestures, if one exists 257 */ getFingerprintGestureDispatcher()258 @Nullable FingerprintGestureDispatcher getFingerprintGestureDispatcher(); 259 260 /** 261 * @return The magnification processor 262 */ 263 @NonNull getMagnificationProcessor()264 MagnificationProcessor getMagnificationProcessor(); 265 266 /** 267 * Called back to notify system that the client has changed 268 * @param serviceInfoChanged True if the service's AccessibilityServiceInfo changed. 269 */ onClientChangeLocked(boolean serviceInfoChanged)270 void onClientChangeLocked(boolean serviceInfoChanged); 271 272 /** 273 * Called back to notify the system the proxy client for a device has changed. 274 * 275 * Changes include if the proxy is unregistered, if its service info list has changed, or if 276 * its focus appearance has changed. 277 */ onProxyChanged(int deviceId)278 void onProxyChanged(int deviceId); 279 getCurrentUserIdLocked()280 int getCurrentUserIdLocked(); 281 getWindowTransformationMatrixAndMagnificationSpec( int windowId)282 Pair<float[], MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec( 283 int windowId); 284 isAccessibilityButtonShown()285 boolean isAccessibilityButtonShown(); 286 287 /** 288 * Persists the component names in the specified setting in a 289 * colon separated fashion. 290 * 291 * @param settingName The setting name. 292 * @param componentNames The component names. 293 * @param userId The user id to persist the setting for. 294 */ persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)295 void persistComponentNamesToSettingLocked(String settingName, 296 Set<ComponentName> componentNames, int userId); 297 298 /* This is exactly PendingIntent.getActivity, separated out for testability */ getPendingIntentActivity(Context context, int requestCode, Intent intent, int flags)299 PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent, 300 int flags); 301 setGestureDetectionPassthroughRegion(int displayId, Region region)302 void setGestureDetectionPassthroughRegion(int displayId, Region region); 303 setTouchExplorationPassthroughRegion(int displayId, Region region)304 void setTouchExplorationPassthroughRegion(int displayId, Region region); 305 setServiceDetectsGesturesEnabled(int displayId, boolean mode)306 void setServiceDetectsGesturesEnabled(int displayId, boolean mode); 307 requestTouchExploration(int displayId)308 void requestTouchExploration(int displayId); 309 requestDragging(int displayId, int pointerId)310 void requestDragging(int displayId, int pointerId); 311 requestDelegating(int displayId)312 void requestDelegating(int displayId); 313 onDoubleTap(int displayId)314 void onDoubleTap(int displayId); 315 onDoubleTapAndHold(int displayId)316 void onDoubleTapAndHold(int displayId); 317 requestImeLocked(AbstractAccessibilityServiceConnection connection)318 void requestImeLocked(AbstractAccessibilityServiceConnection connection); 319 unbindImeLocked(AbstractAccessibilityServiceConnection connection)320 void unbindImeLocked(AbstractAccessibilityServiceConnection connection); 321 attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc)322 void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc); 323 324 } 325 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)326 public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName, 327 AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, 328 Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport, 329 AccessibilityTrace trace, WindowManagerInternal windowManagerInternal, 330 SystemActionPerformer systemActionPerfomer, 331 AccessibilityWindowManager a11yWindowManager) { 332 mContext = context; 333 mWindowManagerService = windowManagerInternal; 334 mId = id; 335 mComponentName = componentName; 336 mAccessibilityServiceInfo = accessibilityServiceInfo; 337 mLock = lock; 338 mSecurityPolicy = securityPolicy; 339 mSystemActionPerformer = systemActionPerfomer; 340 mSystemSupport = systemSupport; 341 mTrace = trace; 342 mMainHandler = mainHandler; 343 mInvocationHandler = new InvocationHandler(mainHandler.getLooper()); 344 mA11yWindowManager = a11yWindowManager; 345 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 346 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 347 mIPlatformCompat = IPlatformCompat.Stub.asInterface( 348 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); 349 mEventDispatchHandler = new Handler(mainHandler.getLooper()) { 350 @Override 351 public void handleMessage(Message message) { 352 final int eventType = message.what; 353 AccessibilityEvent event = (AccessibilityEvent) message.obj; 354 boolean serviceWantsEvent = message.arg1 != 0; 355 notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent); 356 } 357 }; 358 setDynamicallyConfigurableProperties(accessibilityServiceInfo); 359 } 360 361 @Override onKeyEvent(KeyEvent keyEvent, int sequenceNumber)362 public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) { 363 if (!mRequestFilterKeyEvents || (mServiceInterface == null)) { 364 return false; 365 } 366 if((mAccessibilityServiceInfo.getCapabilities() 367 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { 368 return false; 369 } 370 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 371 return false; 372 } 373 try { 374 if (svcClientTracingEnabled()) { 375 logTraceSvcClient("onKeyEvent", keyEvent + ", " + sequenceNumber); 376 } 377 mServiceInterface.onKeyEvent(keyEvent, sequenceNumber); 378 } catch (RemoteException e) { 379 return false; 380 } 381 return true; 382 } 383 setDynamicallyConfigurableProperties(AccessibilityServiceInfo info)384 public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { 385 mEventTypes = info.eventTypes; 386 mFeedbackType = info.feedbackType; 387 String[] packageNames = info.packageNames; 388 mPackageNames.clear(); 389 if (packageNames != null) { 390 mPackageNames.addAll(Arrays.asList(packageNames)); 391 } 392 mNotificationTimeout = info.notificationTimeout; 393 mIsDefault = (info.flags & DEFAULT) != 0; 394 mGenericMotionEventSources = info.getMotionEventSources(); 395 396 if (supportsFlagForNotImportantViews(info)) { 397 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { 398 mFetchFlags |= 399 AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS; 400 } else { 401 mFetchFlags &= 402 ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS; 403 } 404 } 405 406 if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { 407 mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS; 408 } else { 409 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS; 410 } 411 412 if (mAccessibilityServiceInfo.isAccessibilityTool()) { 413 mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL; 414 } else { 415 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL; 416 } 417 418 mRequestTouchExplorationMode = (info.flags 419 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 420 mServiceHandlesDoubleTap = (info.flags 421 & AccessibilityServiceInfo.FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0; 422 mRequestMultiFingerGestures = (info.flags 423 & AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0; 424 mRequestTwoFingerPassthrough = 425 (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0; 426 mSendMotionEvents = 427 (info.flags & AccessibilityServiceInfo.FLAG_SEND_MOTION_EVENTS) != 0; 428 mRequestFilterKeyEvents = 429 (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; 430 mRetrieveInteractiveWindows = (info.flags 431 & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; 432 mCaptureFingerprintGestures = (info.flags 433 & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0; 434 mRequestAccessibilityButton = (info.flags 435 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; 436 mRequestImeApis = (info.flags 437 & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0; 438 } 439 supportsFlagForNotImportantViews(AccessibilityServiceInfo info)440 protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) { 441 return info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 442 >= Build.VERSION_CODES.JELLY_BEAN; 443 } 444 canReceiveEventsLocked()445 public boolean canReceiveEventsLocked() { 446 return (mEventTypes != 0 && mService != null); 447 } 448 449 @Override setOnKeyEventResult(boolean handled, int sequence)450 public void setOnKeyEventResult(boolean handled, int sequence) { 451 if (svcConnTracingEnabled()) { 452 logTraceSvcConn("setOnKeyEventResult", "handled=" + handled + ";sequence=" + sequence); 453 } 454 mSystemSupport.getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); 455 } 456 457 @Override getServiceInfo()458 public AccessibilityServiceInfo getServiceInfo() { 459 if (svcConnTracingEnabled()) { 460 logTraceSvcConn("getServiceInfo", ""); 461 } 462 synchronized (mLock) { 463 return mAccessibilityServiceInfo; 464 } 465 } 466 getCapabilities()467 public int getCapabilities() { 468 return mAccessibilityServiceInfo.getCapabilities(); 469 } 470 getRelevantEventTypes()471 int getRelevantEventTypes() { 472 return (mUsesAccessibilityCache ? AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK 473 : AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) | mEventTypes; 474 } 475 476 @Override setServiceInfo(AccessibilityServiceInfo info)477 public void setServiceInfo(AccessibilityServiceInfo info) { 478 if (svcConnTracingEnabled()) { 479 logTraceSvcConn("setServiceInfo", "info=" + info); 480 } 481 final long identity = Binder.clearCallingIdentity(); 482 try { 483 synchronized (mLock) { 484 // If the XML manifest had data to configure the service its info 485 // should be already set. In such a case update only the dynamically 486 // configurable properties. 487 boolean oldRequestIme = mRequestImeApis; 488 AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; 489 if (oldInfo != null) { 490 oldInfo.updateDynamicallyConfigurableProperties(mIPlatformCompat, info); 491 setDynamicallyConfigurableProperties(oldInfo); 492 } else { 493 setDynamicallyConfigurableProperties(info); 494 } 495 mSystemSupport.onClientChangeLocked(true); 496 if (!oldRequestIme && mRequestImeApis) { 497 mSystemSupport.requestImeLocked(this); 498 } else if (oldRequestIme && !mRequestImeApis) { 499 mSystemSupport.unbindImeLocked(this); 500 } 501 } 502 } finally { 503 Binder.restoreCallingIdentity(identity); 504 } 505 } 506 507 @Override setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos)508 public void setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos) { 509 return; 510 } 511 512 @Override getInstalledAndEnabledServices()513 public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() { 514 return null; 515 } 516 517 @Override setAttributionTag(String attributionTag)518 public void setAttributionTag(String attributionTag) { 519 mAttributionTag = attributionTag; 520 } 521 getAttributionTag()522 String getAttributionTag() { 523 return mAttributionTag; 524 } 525 hasRightsToCurrentUserLocked()526 protected abstract boolean hasRightsToCurrentUserLocked(); 527 528 @Nullable 529 @Override getWindows()530 public AccessibilityWindowInfo.WindowListSparseArray getWindows() { 531 if (svcConnTracingEnabled()) { 532 logTraceSvcConn("getWindows", ""); 533 } 534 synchronized (mLock) { 535 if (!hasRightsToCurrentUserLocked()) { 536 return null; 537 } 538 final boolean permissionGranted = 539 mSecurityPolicy.canRetrieveWindowsLocked(this); 540 if (!permissionGranted) { 541 return null; 542 } 543 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 544 return null; 545 } 546 final AccessibilityWindowInfo.WindowListSparseArray allWindows = 547 new AccessibilityWindowInfo.WindowListSparseArray(); 548 final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked( 549 mDisplayTypes); 550 final int displayListCounts = displayList.size(); 551 if (displayListCounts > 0) { 552 for (int i = 0; i < displayListCounts; i++) { 553 final int displayId = displayList.get(i); 554 ensureWindowsAvailableTimedLocked(displayId); 555 556 final List<AccessibilityWindowInfo> windowList = getWindowsByDisplayLocked( 557 displayId); 558 if (windowList != null) { 559 allWindows.put(displayId, windowList); 560 } 561 } 562 } 563 return allWindows; 564 } 565 } 566 setDisplayTypes(@isplayTypes int displayTypes)567 protected void setDisplayTypes(@DisplayTypes int displayTypes) { 568 mDisplayTypes = displayTypes; 569 } 570 571 @Override getWindow(int windowId)572 public AccessibilityWindowInfo getWindow(int windowId) { 573 if (svcConnTracingEnabled()) { 574 logTraceSvcConn("getWindow", "windowId=" + windowId); 575 } 576 synchronized (mLock) { 577 int displayId = Display.INVALID_DISPLAY; 578 if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) { 579 displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked( 580 mSystemSupport.getCurrentUserIdLocked(), windowId); 581 } 582 ensureWindowsAvailableTimedLocked(displayId); 583 584 if (!hasRightsToCurrentUserLocked()) { 585 return null; 586 } 587 final boolean permissionGranted = 588 mSecurityPolicy.canRetrieveWindowsLocked(this); 589 if (!permissionGranted) { 590 return null; 591 } 592 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 593 return null; 594 } 595 AccessibilityWindowInfo window = 596 mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId); 597 if (window != null) { 598 AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); 599 windowClone.setConnectionId(mId); 600 return windowClone; 601 } 602 return null; 603 } 604 } 605 606 @Override findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewIdResName, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)607 public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId, 608 long accessibilityNodeId, String viewIdResName, int interactionId, 609 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 610 throws RemoteException { 611 if (svcConnTracingEnabled()) { 612 logTraceSvcConn("findAccessibilityNodeInfosByViewId", 613 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 614 + accessibilityNodeId + ";viewIdResName=" + viewIdResName + ";interactionId=" 615 + interactionId + ";callback=" + callback + ";interrogatingTid=" 616 + interrogatingTid); 617 } 618 final int resolvedWindowId; 619 RemoteAccessibilityConnection connection; 620 Region partialInteractiveRegion = Region.obtain(); 621 synchronized (mLock) { 622 mUsesAccessibilityCache = true; 623 if (!hasRightsToCurrentUserLocked()) { 624 return null; 625 } 626 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 627 final boolean permissionGranted = 628 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 629 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 630 if (!permissionGranted) { 631 return null; 632 } else { 633 connection = mA11yWindowManager.getConnectionLocked( 634 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 635 if (connection == null) { 636 return null; 637 } 638 } 639 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 640 resolvedWindowId, partialInteractiveRegion)) { 641 partialInteractiveRegion.recycle(); 642 partialInteractiveRegion = null; 643 } 644 } 645 final Pair<float[], MagnificationSpec> transformMatrixAndSpec = 646 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId); 647 final float[] transformMatrix = transformMatrixAndSpec.first; 648 final MagnificationSpec spec = transformMatrixAndSpec.second; 649 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 650 return null; 651 } 652 final int interrogatingPid = Binder.getCallingPid(); 653 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 654 interrogatingPid, interrogatingTid); 655 final long identityToken = Binder.clearCallingIdentity(); 656 if (intConnTracingEnabled()) { 657 logTraceIntConn("findAccessibilityNodeInfosByViewId", 658 accessibilityNodeId + ";" + viewIdResName + ";" + partialInteractiveRegion + ";" 659 + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid 660 + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix)); 661 } 662 try { 663 connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId, 664 viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags, 665 interrogatingPid, interrogatingTid, spec, transformMatrix); 666 return mSecurityPolicy.computeValidReportedPackages( 667 connection.getPackageName(), connection.getUid()); 668 } catch (RemoteException re) { 669 if (DEBUG) { 670 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); 671 } 672 } finally { 673 Binder.restoreCallingIdentity(identityToken); 674 // Recycle if passed to another process. 675 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 676 partialInteractiveRegion.recycle(); 677 } 678 } 679 return null; 680 } 681 682 @Override findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)683 public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, 684 long accessibilityNodeId, String text, int interactionId, 685 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 686 throws RemoteException { 687 if (svcConnTracingEnabled()) { 688 logTraceSvcConn("findAccessibilityNodeInfosByText", 689 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 690 + accessibilityNodeId + ";text=" + text + ";interactionId=" + interactionId 691 + ";callback=" + callback + ";interrogatingTid=" + interrogatingTid); 692 } 693 final int resolvedWindowId; 694 RemoteAccessibilityConnection connection; 695 Region partialInteractiveRegion = Region.obtain(); 696 synchronized (mLock) { 697 mUsesAccessibilityCache = true; 698 if (!hasRightsToCurrentUserLocked()) { 699 return null; 700 } 701 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 702 final boolean permissionGranted = 703 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 704 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 705 if (!permissionGranted) { 706 return null; 707 } else { 708 connection = mA11yWindowManager.getConnectionLocked( 709 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 710 if (connection == null) { 711 return null; 712 } 713 } 714 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 715 resolvedWindowId, partialInteractiveRegion)) { 716 partialInteractiveRegion.recycle(); 717 partialInteractiveRegion = null; 718 } 719 } 720 final Pair<float[], MagnificationSpec> transformMatrixAndSpec = 721 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId); 722 final float[] transformMatrix = transformMatrixAndSpec.first; 723 final MagnificationSpec spec = transformMatrixAndSpec.second; 724 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 725 return null; 726 } 727 final int interrogatingPid = Binder.getCallingPid(); 728 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 729 interrogatingPid, interrogatingTid); 730 final long identityToken = Binder.clearCallingIdentity(); 731 if (intConnTracingEnabled()) { 732 logTraceIntConn("findAccessibilityNodeInfosByText", 733 accessibilityNodeId + ";" + text + ";" + partialInteractiveRegion + ";" 734 + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid 735 + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix)); 736 } 737 try { 738 connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId, 739 text, partialInteractiveRegion, interactionId, callback, mFetchFlags, 740 interrogatingPid, interrogatingTid, spec, transformMatrix); 741 return mSecurityPolicy.computeValidReportedPackages( 742 connection.getPackageName(), connection.getUid()); 743 } catch (RemoteException re) { 744 if (DEBUG) { 745 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); 746 } 747 } finally { 748 Binder.restoreCallingIdentity(identityToken); 749 // Recycle if passed to another process. 750 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 751 partialInteractiveRegion.recycle(); 752 } 753 } 754 return null; 755 } 756 757 @Override findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid, Bundle arguments)758 public String[] findAccessibilityNodeInfoByAccessibilityId( 759 int accessibilityWindowId, long accessibilityNodeId, int interactionId, 760 IAccessibilityInteractionConnectionCallback callback, int flags, 761 long interrogatingTid, Bundle arguments) throws RemoteException { 762 if (svcConnTracingEnabled()) { 763 logTraceSvcConn("findAccessibilityNodeInfoByAccessibilityId", 764 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 765 + accessibilityNodeId + ";interactionId=" + interactionId + ";callback=" 766 + callback + ";flags=" + flags + ";interrogatingTid=" + interrogatingTid 767 + ";arguments=" + arguments); 768 } 769 final int resolvedWindowId; 770 RemoteAccessibilityConnection connection; 771 Region partialInteractiveRegion = Region.obtain(); 772 synchronized (mLock) { 773 mUsesAccessibilityCache = true; 774 if (!hasRightsToCurrentUserLocked()) { 775 return null; 776 } 777 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 778 final boolean permissionGranted = 779 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 780 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 781 if (!permissionGranted) { 782 return null; 783 } else { 784 connection = mA11yWindowManager.getConnectionLocked( 785 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 786 if (connection == null) { 787 return null; 788 } 789 } 790 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 791 resolvedWindowId, partialInteractiveRegion)) { 792 partialInteractiveRegion.recycle(); 793 partialInteractiveRegion = null; 794 } 795 } 796 final Pair<float[], MagnificationSpec> transformMatrixAndSpec = 797 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId); 798 final float[] transformMatrix = transformMatrixAndSpec.first; 799 final MagnificationSpec spec = transformMatrixAndSpec.second; 800 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 801 return null; 802 } 803 final int interrogatingPid = Binder.getCallingPid(); 804 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 805 interrogatingPid, interrogatingTid); 806 final long identityToken = Binder.clearCallingIdentity(); 807 if (intConnTracingEnabled()) { 808 logTraceIntConn("findAccessibilityNodeInfoByAccessibilityId", 809 accessibilityNodeId + ";" + partialInteractiveRegion + ";" + interactionId + ";" 810 + callback + ";" + (mFetchFlags | flags) + ";" + interrogatingPid + ";" 811 + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix) 812 + ";" + arguments); 813 } 814 try { 815 connection.getRemote().findAccessibilityNodeInfoByAccessibilityId( 816 accessibilityNodeId, partialInteractiveRegion, interactionId, callback, 817 mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, transformMatrix, 818 arguments); 819 return mSecurityPolicy.computeValidReportedPackages( 820 connection.getPackageName(), connection.getUid()); 821 } catch (RemoteException re) { 822 if (DEBUG) { 823 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); 824 } 825 } finally { 826 Binder.restoreCallingIdentity(identityToken); 827 // Recycle if passed to another process. 828 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 829 partialInteractiveRegion.recycle(); 830 } 831 } 832 return null; 833 } 834 835 @Override findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)836 public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, 837 int focusType, int interactionId, 838 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 839 throws RemoteException { 840 if (svcConnTracingEnabled()) { 841 logTraceSvcConn("findFocus", 842 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 843 + accessibilityNodeId + ";focusType=" + focusType + ";interactionId=" 844 + interactionId + ";callback=" + callback + ";interrogatingTid=" 845 + interrogatingTid); 846 } 847 final int resolvedWindowId; 848 RemoteAccessibilityConnection connection; 849 Region partialInteractiveRegion = Region.obtain(); 850 synchronized (mLock) { 851 if (!hasRightsToCurrentUserLocked()) { 852 return null; 853 } 854 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( 855 accessibilityWindowId, focusType); 856 final boolean permissionGranted = 857 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 858 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 859 if (!permissionGranted) { 860 return null; 861 } else { 862 connection = mA11yWindowManager.getConnectionLocked( 863 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 864 if (connection == null) { 865 return null; 866 } 867 } 868 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 869 resolvedWindowId, partialInteractiveRegion)) { 870 partialInteractiveRegion.recycle(); 871 partialInteractiveRegion = null; 872 } 873 } 874 final Pair<float[], MagnificationSpec> transformMatrixAndSpec = 875 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId); 876 final float[] transformMatrix = transformMatrixAndSpec.first; 877 final MagnificationSpec spec = transformMatrixAndSpec.second; 878 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 879 return null; 880 } 881 final int interrogatingPid = Binder.getCallingPid(); 882 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 883 interrogatingPid, interrogatingTid); 884 final long identityToken = Binder.clearCallingIdentity(); 885 if (intConnTracingEnabled()) { 886 logTraceIntConn("findFocus", 887 accessibilityNodeId + ";" + focusType + ";" + partialInteractiveRegion + ";" 888 + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid 889 + ";" + interrogatingTid + ";" + spec + ";" 890 + Arrays.toString(transformMatrix)); 891 } 892 try { 893 connection.getRemote().findFocus(accessibilityNodeId, focusType, 894 partialInteractiveRegion, interactionId, callback, mFetchFlags, 895 interrogatingPid, interrogatingTid, spec, transformMatrix); 896 return mSecurityPolicy.computeValidReportedPackages( 897 connection.getPackageName(), connection.getUid()); 898 } catch (RemoteException re) { 899 if (DEBUG) { 900 Slog.e(LOG_TAG, "Error calling findFocus()"); 901 } 902 } finally { 903 Binder.restoreCallingIdentity(identityToken); 904 // Recycle if passed to another process. 905 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 906 partialInteractiveRegion.recycle(); 907 } 908 } 909 return null; 910 } 911 912 @Override focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)913 public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, 914 int direction, int interactionId, 915 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 916 throws RemoteException { 917 if (svcConnTracingEnabled()) { 918 logTraceSvcConn("focusSearch", 919 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 920 + accessibilityNodeId + ";direction=" + direction + ";interactionId=" 921 + interactionId + ";callback=" + callback + ";interrogatingTid=" 922 + interrogatingTid); 923 } 924 final int resolvedWindowId; 925 RemoteAccessibilityConnection connection; 926 Region partialInteractiveRegion = Region.obtain(); 927 synchronized (mLock) { 928 if (!hasRightsToCurrentUserLocked()) { 929 return null; 930 } 931 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 932 final boolean permissionGranted = 933 mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 934 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId); 935 if (!permissionGranted) { 936 return null; 937 } else { 938 connection = mA11yWindowManager.getConnectionLocked( 939 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId); 940 if (connection == null) { 941 return null; 942 } 943 } 944 if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked( 945 resolvedWindowId, partialInteractiveRegion)) { 946 partialInteractiveRegion.recycle(); 947 partialInteractiveRegion = null; 948 } 949 } 950 final Pair<float[], MagnificationSpec> transformMatrixAndSpec = 951 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId); 952 final float[] transformMatrix = transformMatrixAndSpec.first; 953 final MagnificationSpec spec = transformMatrixAndSpec.second; 954 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 955 return null; 956 } 957 final int interrogatingPid = Binder.getCallingPid(); 958 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 959 interrogatingPid, interrogatingTid); 960 final long identityToken = Binder.clearCallingIdentity(); 961 if (intConnTracingEnabled()) { 962 logTraceIntConn("focusSearch", 963 accessibilityNodeId + ";" + direction + ";" + partialInteractiveRegion 964 + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";" 965 + interrogatingPid + ";" + interrogatingTid + ";" + spec + ";" 966 + Arrays.toString(transformMatrix)); 967 } 968 try { 969 connection.getRemote().focusSearch(accessibilityNodeId, direction, 970 partialInteractiveRegion, interactionId, callback, mFetchFlags, 971 interrogatingPid, interrogatingTid, spec, transformMatrix); 972 return mSecurityPolicy.computeValidReportedPackages( 973 connection.getPackageName(), connection.getUid()); 974 } catch (RemoteException re) { 975 if (DEBUG) { 976 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); 977 } 978 } finally { 979 Binder.restoreCallingIdentity(identityToken); 980 // Recycle if passed to another process. 981 if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { 982 partialInteractiveRegion.recycle(); 983 } 984 } 985 return null; 986 } 987 988 @Override sendGesture(int sequence, ParceledListSlice gestureSteps)989 public void sendGesture(int sequence, ParceledListSlice gestureSteps) { 990 if (svcConnTracingEnabled()) { 991 logTraceSvcConn( 992 "sendGesture", "sequence=" + sequence + ";gestureSteps=" + gestureSteps); 993 } 994 } 995 996 @Override dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId)997 public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) { 998 if (svcConnTracingEnabled()) { 999 logTraceSvcConn("dispatchGesture", "sequence=" + sequence + ";gestureSteps=" 1000 + gestureSteps + ";displayId=" + displayId); 1001 } 1002 } 1003 1004 @Override performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)1005 public boolean performAccessibilityAction(int accessibilityWindowId, 1006 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 1007 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 1008 throws RemoteException { 1009 if (svcConnTracingEnabled()) { 1010 logTraceSvcConn("performAccessibilityAction", 1011 "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId=" 1012 + accessibilityNodeId + ";action=" + action + ";arguments=" + arguments 1013 + ";interactionId=" + interactionId + ";callback=" + callback 1014 + ";interrogatingTid=" + interrogatingTid); 1015 } 1016 final int resolvedWindowId; 1017 synchronized (mLock) { 1018 if (!hasRightsToCurrentUserLocked()) { 1019 return false; 1020 } 1021 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 1022 if (!mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 1023 mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId)) { 1024 return false; 1025 } 1026 } 1027 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 1028 return false; 1029 } 1030 return performAccessibilityActionInternal( 1031 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId, accessibilityNodeId, 1032 action, arguments, interactionId, callback, mFetchFlags, interrogatingTid); 1033 } 1034 1035 @Override performGlobalAction(int action)1036 public boolean performGlobalAction(int action) { 1037 if (svcConnTracingEnabled()) { 1038 logTraceSvcConn("performGlobalAction", "action=" + action); 1039 } 1040 synchronized (mLock) { 1041 if (!hasRightsToCurrentUserLocked()) { 1042 return false; 1043 } 1044 } 1045 return mSystemActionPerformer.performSystemAction(action); 1046 } 1047 1048 @Override getSystemActions()1049 public @NonNull List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions() { 1050 if (svcConnTracingEnabled()) { 1051 logTraceSvcConn("getSystemActions", ""); 1052 } 1053 synchronized (mLock) { 1054 if (!hasRightsToCurrentUserLocked()) { 1055 return Collections.emptyList(); 1056 } 1057 } 1058 return mSystemActionPerformer.getSystemActions(); 1059 } 1060 1061 @Override isFingerprintGestureDetectionAvailable()1062 public boolean isFingerprintGestureDetectionAvailable() { 1063 if (svcConnTracingEnabled()) { 1064 logTraceSvcConn("isFingerprintGestureDetectionAvailable", ""); 1065 } 1066 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 1067 return false; 1068 } 1069 if (isCapturingFingerprintGestures()) { 1070 FingerprintGestureDispatcher dispatcher = 1071 mSystemSupport.getFingerprintGestureDispatcher(); 1072 return (dispatcher != null) && dispatcher.isFingerprintGestureDetectionAvailable(); 1073 } 1074 return false; 1075 } 1076 1077 @Nullable 1078 @Override getMagnificationConfig(int displayId)1079 public MagnificationConfig getMagnificationConfig(int displayId) { 1080 if (svcConnTracingEnabled()) { 1081 logTraceSvcConn("getMagnificationConfig", "displayId=" + displayId); 1082 } 1083 synchronized (mLock) { 1084 if (!hasRightsToCurrentUserLocked()) { 1085 return null; 1086 } 1087 } 1088 final long identity = Binder.clearCallingIdentity(); 1089 try { 1090 return mSystemSupport.getMagnificationProcessor().getMagnificationConfig(displayId); 1091 } finally { 1092 Binder.restoreCallingIdentity(identity); 1093 } 1094 } 1095 1096 @Override getMagnificationScale(int displayId)1097 public float getMagnificationScale(int displayId) { 1098 if (svcConnTracingEnabled()) { 1099 logTraceSvcConn("getMagnificationScale", "displayId=" + displayId); 1100 } 1101 synchronized (mLock) { 1102 if (!hasRightsToCurrentUserLocked()) { 1103 return 1.0f; 1104 } 1105 } 1106 final long identity = Binder.clearCallingIdentity(); 1107 try { 1108 return mSystemSupport.getMagnificationProcessor().getScale(displayId); 1109 } finally { 1110 Binder.restoreCallingIdentity(identity); 1111 } 1112 } 1113 1114 @Override getMagnificationRegion(int displayId)1115 public Region getMagnificationRegion(int displayId) { 1116 if (svcConnTracingEnabled()) { 1117 logTraceSvcConn("getMagnificationRegion", "displayId=" + displayId); 1118 } 1119 synchronized (mLock) { 1120 final Region region = Region.obtain(); 1121 if (!hasRightsToCurrentUserLocked()) { 1122 return region; 1123 } 1124 MagnificationProcessor magnificationProcessor = 1125 mSystemSupport.getMagnificationProcessor(); 1126 final long identity = Binder.clearCallingIdentity(); 1127 try { 1128 magnificationProcessor.getFullscreenMagnificationRegion(displayId, 1129 region, mSecurityPolicy.canControlMagnification(this)); 1130 return region; 1131 } finally { 1132 Binder.restoreCallingIdentity(identity); 1133 } 1134 } 1135 } 1136 1137 1138 @Override getCurrentMagnificationRegion(int displayId)1139 public Region getCurrentMagnificationRegion(int displayId) { 1140 if (svcConnTracingEnabled()) { 1141 logTraceSvcConn("getCurrentMagnificationRegion", "displayId=" + displayId); 1142 } 1143 synchronized (mLock) { 1144 final Region region = Region.obtain(); 1145 if (!hasRightsToCurrentUserLocked()) { 1146 return region; 1147 } 1148 MagnificationProcessor magnificationProcessor = 1149 mSystemSupport.getMagnificationProcessor(); 1150 final long identity = Binder.clearCallingIdentity(); 1151 try { 1152 magnificationProcessor.getCurrentMagnificationRegion(displayId, 1153 region, mSecurityPolicy.canControlMagnification(this)); 1154 return region; 1155 } finally { 1156 Binder.restoreCallingIdentity(identity); 1157 } 1158 } 1159 } 1160 1161 @Override getMagnificationCenterX(int displayId)1162 public float getMagnificationCenterX(int displayId) { 1163 if (svcConnTracingEnabled()) { 1164 logTraceSvcConn("getMagnificationCenterX", "displayId=" + displayId); 1165 } 1166 synchronized (mLock) { 1167 if (!hasRightsToCurrentUserLocked()) { 1168 return 0.0f; 1169 } 1170 MagnificationProcessor magnificationProcessor = 1171 mSystemSupport.getMagnificationProcessor(); 1172 final long identity = Binder.clearCallingIdentity(); 1173 try { 1174 return magnificationProcessor.getCenterX(displayId, 1175 mSecurityPolicy.canControlMagnification(this)); 1176 } finally { 1177 Binder.restoreCallingIdentity(identity); 1178 } 1179 } 1180 } 1181 1182 @Override getMagnificationCenterY(int displayId)1183 public float getMagnificationCenterY(int displayId) { 1184 if (svcConnTracingEnabled()) { 1185 logTraceSvcConn("getMagnificationCenterY", "displayId=" + displayId); 1186 } 1187 synchronized (mLock) { 1188 if (!hasRightsToCurrentUserLocked()) { 1189 return 0.0f; 1190 } 1191 MagnificationProcessor magnificationProcessor = 1192 mSystemSupport.getMagnificationProcessor(); 1193 final long identity = Binder.clearCallingIdentity(); 1194 try { 1195 return magnificationProcessor.getCenterY(displayId, 1196 mSecurityPolicy.canControlMagnification(this)); 1197 } finally { 1198 Binder.restoreCallingIdentity(identity); 1199 } 1200 } 1201 } 1202 1203 @Override resetMagnification(int displayId, boolean animate)1204 public boolean resetMagnification(int displayId, boolean animate) { 1205 if (svcConnTracingEnabled()) { 1206 logTraceSvcConn("resetMagnification", "displayId=" + displayId + ";animate=" + animate); 1207 } 1208 synchronized (mLock) { 1209 if (!hasRightsToCurrentUserLocked()) { 1210 return false; 1211 } 1212 if (!mSecurityPolicy.canControlMagnification(this)) { 1213 return false; 1214 } 1215 } 1216 final long identity = Binder.clearCallingIdentity(); 1217 try { 1218 MagnificationProcessor magnificationProcessor = 1219 mSystemSupport.getMagnificationProcessor(); 1220 return (magnificationProcessor.resetFullscreenMagnification(displayId, animate) 1221 || !magnificationProcessor.isMagnifying(displayId)); 1222 } finally { 1223 Binder.restoreCallingIdentity(identity); 1224 } 1225 } 1226 1227 @Override resetCurrentMagnification(int displayId, boolean animate)1228 public boolean resetCurrentMagnification(int displayId, boolean animate) { 1229 if (svcConnTracingEnabled()) { 1230 logTraceSvcConn("resetCurrentMagnification", 1231 "displayId=" + displayId + ";animate=" + animate); 1232 } 1233 synchronized (mLock) { 1234 if (!hasRightsToCurrentUserLocked()) { 1235 return false; 1236 } 1237 if (!mSecurityPolicy.canControlMagnification(this)) { 1238 return false; 1239 } 1240 } 1241 final long identity = Binder.clearCallingIdentity(); 1242 try { 1243 MagnificationProcessor magnificationProcessor = 1244 mSystemSupport.getMagnificationProcessor(); 1245 return (magnificationProcessor.resetCurrentMagnification(displayId, animate) 1246 || !magnificationProcessor.isMagnifying(displayId)); 1247 } finally { 1248 Binder.restoreCallingIdentity(identity); 1249 } 1250 } 1251 1252 @Override setMagnificationConfig(int displayId, @NonNull MagnificationConfig config, boolean animate)1253 public boolean setMagnificationConfig(int displayId, 1254 @NonNull MagnificationConfig config, boolean animate) { 1255 if (svcConnTracingEnabled()) { 1256 logTraceSvcConn("setMagnificationSpec", 1257 "displayId=" + displayId + ", config=" + config.toString()); 1258 } 1259 synchronized (mLock) { 1260 if (!hasRightsToCurrentUserLocked()) { 1261 return false; 1262 } 1263 if (!mSecurityPolicy.canControlMagnification(this)) { 1264 return false; 1265 } 1266 final long identity = Binder.clearCallingIdentity(); 1267 try { 1268 MagnificationProcessor magnificationProcessor = 1269 mSystemSupport.getMagnificationProcessor(); 1270 return magnificationProcessor.setMagnificationConfig(displayId, config, animate, 1271 mId); 1272 } finally { 1273 Binder.restoreCallingIdentity(identity); 1274 } 1275 } 1276 } 1277 1278 @Override setMagnificationCallbackEnabled(int displayId, boolean enabled)1279 public void setMagnificationCallbackEnabled(int displayId, boolean enabled) { 1280 if (svcConnTracingEnabled()) { 1281 logTraceSvcConn("setMagnificationCallbackEnabled", 1282 "displayId=" + displayId + ";enabled=" + enabled); 1283 } 1284 mInvocationHandler.setMagnificationCallbackEnabled(displayId, enabled); 1285 } 1286 isMagnificationCallbackEnabled(int displayId)1287 public boolean isMagnificationCallbackEnabled(int displayId) { 1288 return mInvocationHandler.isMagnificationCallbackEnabled(displayId); 1289 } 1290 1291 @Override setSoftKeyboardCallbackEnabled(boolean enabled)1292 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 1293 if (svcConnTracingEnabled()) { 1294 logTraceSvcConn("setSoftKeyboardCallbackEnabled", "enabled=" + enabled); 1295 } 1296 mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled); 1297 } 1298 1299 @Override takeScreenshotOfWindow(int accessibilityWindowId, int interactionId, ScreenCapture.ScreenCaptureListener listener, IAccessibilityInteractionConnectionCallback callback)1300 public void takeScreenshotOfWindow(int accessibilityWindowId, int interactionId, 1301 ScreenCapture.ScreenCaptureListener listener, 1302 IAccessibilityInteractionConnectionCallback callback) throws RemoteException { 1303 final long currentTimestamp = SystemClock.uptimeMillis(); 1304 if ((currentTimestamp 1305 - mRequestTakeScreenshotOfWindowTimestampMs.get(accessibilityWindowId, 0L)) 1306 <= ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) { 1307 callback.sendTakeScreenshotOfWindowError( 1308 AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, interactionId); 1309 return; 1310 } 1311 mRequestTakeScreenshotOfWindowTimestampMs.put(accessibilityWindowId, currentTimestamp); 1312 1313 synchronized (mLock) { 1314 if (!hasRightsToCurrentUserLocked()) { 1315 callback.sendTakeScreenshotOfWindowError( 1316 AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, interactionId); 1317 return; 1318 } 1319 if (!mSecurityPolicy.canTakeScreenshotLocked(this)) { 1320 callback.sendTakeScreenshotOfWindowError( 1321 AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, 1322 interactionId); 1323 return; 1324 } 1325 } 1326 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 1327 callback.sendTakeScreenshotOfWindowError( 1328 AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, 1329 interactionId); 1330 return; 1331 } 1332 1333 RemoteAccessibilityConnection connection = mA11yWindowManager.getConnectionLocked( 1334 mSystemSupport.getCurrentUserIdLocked(), 1335 resolveAccessibilityWindowIdLocked(accessibilityWindowId)); 1336 if (connection == null) { 1337 callback.sendTakeScreenshotOfWindowError( 1338 AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_WINDOW, interactionId); 1339 return; 1340 } 1341 connection.getRemote().takeScreenshotOfWindow(interactionId, listener, callback); 1342 } 1343 1344 @Override takeScreenshot(int displayId, RemoteCallback callback)1345 public void takeScreenshot(int displayId, RemoteCallback callback) { 1346 if (svcConnTracingEnabled()) { 1347 logTraceSvcConn("takeScreenshot", "displayId=" + displayId + ";callback=" + callback); 1348 } 1349 final long currentTimestamp = SystemClock.uptimeMillis(); 1350 if (mRequestTakeScreenshotTimestampMs != 0 1351 && (currentTimestamp - mRequestTakeScreenshotTimestampMs) 1352 <= AccessibilityService.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) { 1353 sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, 1354 callback); 1355 return; 1356 } 1357 mRequestTakeScreenshotTimestampMs = currentTimestamp; 1358 1359 synchronized (mLock) { 1360 if (!hasRightsToCurrentUserLocked()) { 1361 sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, 1362 callback); 1363 return; 1364 } 1365 1366 if (!mSecurityPolicy.canTakeScreenshotLocked(this)) { 1367 throw new SecurityException("Services don't have the capability of taking" 1368 + " the screenshot."); 1369 } 1370 } 1371 1372 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 1373 sendScreenshotFailure( 1374 AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, 1375 callback); 1376 return; 1377 } 1378 1379 // Private virtual displays are created by the ap and is not allowed to access by other 1380 // aps. We assume the contents on this display should not be captured. 1381 final DisplayManager displayManager = 1382 (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); 1383 final Display display = displayManager.getDisplay(displayId); 1384 if ((display == null) || (display.getType() == Display.TYPE_VIRTUAL 1385 && (display.getFlags() & Display.FLAG_PRIVATE) != 0)) { 1386 sendScreenshotFailure( 1387 AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback); 1388 return; 1389 } 1390 1391 final long identity = Binder.clearCallingIdentity(); 1392 try { 1393 mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { 1394 final ScreenshotHardwareBuffer screenshotBuffer = LocalServices 1395 .getService(DisplayManagerInternal.class).userScreenshot(displayId); 1396 if (screenshotBuffer != null) { 1397 sendScreenshotSuccess(screenshotBuffer, callback); 1398 } else { 1399 sendScreenshotFailure( 1400 AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback); 1401 } 1402 }, null).recycleOnUse()); 1403 } finally { 1404 Binder.restoreCallingIdentity(identity); 1405 } 1406 } 1407 sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer, RemoteCallback callback)1408 private void sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer, 1409 RemoteCallback callback) { 1410 final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); 1411 final ParcelableColorSpace colorSpace = 1412 new ParcelableColorSpace(screenshotBuffer.getColorSpace()); 1413 1414 final Bundle payload = new Bundle(); 1415 payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, 1416 AccessibilityService.TAKE_SCREENSHOT_SUCCESS); 1417 payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER, 1418 hardwareBuffer); 1419 payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace); 1420 payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP, 1421 SystemClock.uptimeMillis()); 1422 1423 // Send back the result. 1424 callback.sendResult(payload); 1425 hardwareBuffer.close(); 1426 } 1427 sendScreenshotFailure(@ccessibilityService.ScreenshotErrorCode int errorCode, RemoteCallback callback)1428 private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode, 1429 RemoteCallback callback) { 1430 mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { 1431 final Bundle payload = new Bundle(); 1432 payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, errorCode); 1433 // Send back the result. 1434 callback.sendResult(payload); 1435 }, null).recycleOnUse()); 1436 } 1437 1438 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)1439 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1440 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 1441 synchronized (mLock) { 1442 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() 1443 .loadLabel(mContext.getPackageManager())); 1444 pw.append(", feedbackType" 1445 + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); 1446 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); 1447 pw.append(", eventTypes=" 1448 + AccessibilityEvent.eventTypeToString(mEventTypes)); 1449 pw.append(", notificationTimeout=" + mNotificationTimeout); 1450 pw.append(", requestA11yBtn=" + mRequestAccessibilityButton); 1451 pw.append("]"); 1452 } 1453 } 1454 onAdded()1455 public void onAdded() { 1456 final Display[] displays = mDisplayManager.getDisplays(); 1457 for (int i = 0; i < displays.length; i++) { 1458 final int displayId = displays[i].getDisplayId(); 1459 onDisplayAdded(displayId); 1460 } 1461 } 1462 1463 /** 1464 * Called whenever a logical display has been added to the system. Add a window token for adding 1465 * an accessibility overlay. 1466 * 1467 * @param displayId The id of the logical display that was added. 1468 */ onDisplayAdded(int displayId)1469 public void onDisplayAdded(int displayId) { 1470 final long identity = Binder.clearCallingIdentity(); 1471 try { 1472 final IBinder overlayWindowToken = new Binder(); 1473 if (wmTracingEnabled()) { 1474 logTraceWM("addWindowToken", 1475 overlayWindowToken + ";TYPE_ACCESSIBILITY_OVERLAY;" + displayId + ";null"); 1476 } 1477 mWindowManagerService.addWindowToken(overlayWindowToken, TYPE_ACCESSIBILITY_OVERLAY, 1478 displayId, null /* options */); 1479 synchronized (mLock) { 1480 mOverlayWindowTokens.put(displayId, overlayWindowToken); 1481 } 1482 } finally { 1483 Binder.restoreCallingIdentity(identity); 1484 } 1485 } 1486 onRemoved()1487 public void onRemoved() { 1488 final Display[] displays = mDisplayManager.getDisplays(); 1489 for (int i = 0; i < displays.length; i++) { 1490 final int displayId = displays[i].getDisplayId(); 1491 onDisplayRemoved(displayId); 1492 } 1493 } 1494 1495 /** 1496 * Called whenever a logical display has been removed from the system. Remove a window token for 1497 * removing an accessibility overlay. 1498 * 1499 * @param displayId The id of the logical display that was added. 1500 */ onDisplayRemoved(int displayId)1501 public void onDisplayRemoved(int displayId) { 1502 final long identity = Binder.clearCallingIdentity(); 1503 if (wmTracingEnabled()) { 1504 logTraceWM( 1505 "addWindowToken", mOverlayWindowTokens.get(displayId) + ";true;" + displayId); 1506 } 1507 try { 1508 mWindowManagerService.removeWindowToken(mOverlayWindowTokens.get(displayId), true, 1509 displayId); 1510 synchronized (mLock) { 1511 mOverlayWindowTokens.remove(displayId); 1512 } 1513 } finally { 1514 Binder.restoreCallingIdentity(identity); 1515 } 1516 } 1517 1518 /** 1519 * Gets overlay window token by the display Id. 1520 * 1521 * @param displayId The id of the logical display that was added. 1522 * @return window token. 1523 */ 1524 @Override getOverlayWindowToken(int displayId)1525 public IBinder getOverlayWindowToken(int displayId) { 1526 if (svcConnTracingEnabled()) { 1527 logTraceSvcConn("getOverlayWindowToken", "displayId=" + displayId); 1528 } 1529 synchronized (mLock) { 1530 return mOverlayWindowTokens.get(displayId); 1531 } 1532 } 1533 1534 /** 1535 * Gets windowId of given token. 1536 * 1537 * @param token The token 1538 * @return window id 1539 */ 1540 @Override getWindowIdForLeashToken(@onNull IBinder token)1541 public int getWindowIdForLeashToken(@NonNull IBinder token) { 1542 if (svcConnTracingEnabled()) { 1543 logTraceSvcConn("getWindowIdForLeashToken", "token=" + token); 1544 } 1545 synchronized (mLock) { 1546 return mA11yWindowManager.getWindowIdLocked(token); 1547 } 1548 } 1549 resetLocked()1550 public void resetLocked() { 1551 mSystemSupport.getKeyEventDispatcher().flush(this); 1552 try { 1553 // Clear the proxy in the other process so this 1554 // IAccessibilityServiceConnection can be garbage collected. 1555 if (mServiceInterface != null) { 1556 if (svcClientTracingEnabled()) { 1557 logTraceSvcClient("init", "null, " + mId + ", null"); 1558 } 1559 mServiceInterface.init(null, mId, null); 1560 } 1561 } catch (RemoteException re) { 1562 /* ignore */ 1563 } 1564 if (mService != null) { 1565 try { 1566 mService.unlinkToDeath(this, 0); 1567 } catch (NoSuchElementException e) { 1568 Slog.e(LOG_TAG, "Failed unregistering death link"); 1569 } 1570 mService = null; 1571 } 1572 1573 mServiceInterface = null; 1574 mReceivedAccessibilityButtonCallbackSinceBind = false; 1575 } 1576 isConnectedLocked()1577 public boolean isConnectedLocked() { 1578 return (mService != null); 1579 } 1580 notifyAccessibilityEvent(AccessibilityEvent event)1581 public void notifyAccessibilityEvent(AccessibilityEvent event) { 1582 synchronized (mLock) { 1583 final int eventType = event.getEventType(); 1584 1585 final boolean serviceWantsEvent = wantsEventLocked(event); 1586 final boolean requiredForCacheConsistency = mUsesAccessibilityCache 1587 && ((AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK & eventType) != 0); 1588 if (!serviceWantsEvent && !requiredForCacheConsistency) { 1589 return; 1590 } 1591 1592 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 1593 return; 1594 } 1595 // Make a copy since during dispatch it is possible the event to 1596 // be modified to remove its source if the receiving service does 1597 // not have permission to access the window content. 1598 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); 1599 Message message; 1600 if ((mNotificationTimeout > 0) 1601 && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) { 1602 // Allow at most one pending event 1603 final AccessibilityEvent oldEvent = mPendingEvents.get(eventType); 1604 mPendingEvents.put(eventType, newEvent); 1605 if (oldEvent != null) { 1606 mEventDispatchHandler.removeMessages(eventType); 1607 oldEvent.recycle(); 1608 } 1609 message = mEventDispatchHandler.obtainMessage(eventType); 1610 } else { 1611 // Send all messages, bypassing mPendingEvents 1612 message = mEventDispatchHandler.obtainMessage(eventType, newEvent); 1613 } 1614 message.arg1 = serviceWantsEvent ? 1 : 0; 1615 1616 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); 1617 } 1618 } 1619 1620 /** 1621 * Determines if given event can be dispatched to a service based on the package of the 1622 * event source. Specifically, a service is notified if it is interested in events from the 1623 * package. 1624 * 1625 * @param event The event. 1626 * @return True if the listener should be notified, false otherwise. 1627 */ wantsEventLocked(AccessibilityEvent event)1628 private boolean wantsEventLocked(AccessibilityEvent event) { 1629 1630 if (!canReceiveEventsLocked()) { 1631 return false; 1632 } 1633 1634 final boolean includeNotImportantViews = (mFetchFlags 1635 & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0; 1636 if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) 1637 && !event.isImportantForAccessibility() 1638 && !includeNotImportantViews) { 1639 return false; 1640 } 1641 1642 if (event.isAccessibilityDataSensitive() 1643 && (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) { 1644 return false; 1645 } 1646 1647 int eventType = event.getEventType(); 1648 if ((mEventTypes & eventType) != eventType) { 1649 return false; 1650 } 1651 1652 Set<String> packageNames = mPackageNames; 1653 String packageName = (event.getPackageName() != null) 1654 ? event.getPackageName().toString() : null; 1655 1656 return (packageNames.isEmpty() || packageNames.contains(packageName)); 1657 } 1658 1659 /** 1660 * Notifies an accessibility service client for a scheduled event given the event type. 1661 * 1662 * @param eventType The type of the event to dispatch. 1663 */ notifyAccessibilityEventInternal( int eventType, AccessibilityEvent event, boolean serviceWantsEvent)1664 private void notifyAccessibilityEventInternal( 1665 int eventType, 1666 AccessibilityEvent event, 1667 boolean serviceWantsEvent) { 1668 IAccessibilityServiceClient listener; 1669 1670 synchronized (mLock) { 1671 listener = mServiceInterface; 1672 1673 // If the service died/was disabled while the message for dispatching 1674 // the accessibility event was propagating the listener may be null. 1675 if (listener == null) { 1676 return; 1677 } 1678 1679 // There are two ways we notify for events, throttled AND non-throttled. If we 1680 // are not throttling, then messages come with events, which we handle with 1681 // minimal fuss. 1682 if (event == null) { 1683 // We are throttling events, so we'll send the event for this type in 1684 // mPendingEvents as long as it it's null. It can only null due to a race 1685 // condition: 1686 // 1687 // 1) A binder thread calls notifyAccessibilityServiceDelayedLocked 1688 // which posts a message for dispatching an event and stores the event 1689 // in mPendingEvents. 1690 // 2) The message is pulled from the queue by the handler on the service 1691 // thread and this method is just about to acquire the lock. 1692 // 3) Another binder thread acquires the lock in notifyAccessibilityEvent 1693 // 4) notifyAccessibilityEvent recycles the event that this method was about 1694 // to process, replaces it with a new one, and posts a second message 1695 // 5) This method grabs the new event, processes it, and removes it from 1696 // mPendingEvents 1697 // 6) The second message dispatched in (4) arrives, but the event has been 1698 // remvoved in (5). 1699 event = mPendingEvents.get(eventType); 1700 if (event == null) { 1701 return; 1702 } 1703 mPendingEvents.remove(eventType); 1704 } 1705 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { 1706 event.setConnectionId(mId); 1707 } else { 1708 event.setSource((View) null); 1709 } 1710 event.setSealed(true); 1711 } 1712 1713 try { 1714 if (svcClientTracingEnabled()) { 1715 logTraceSvcClient("onAccessibilityEvent", event + ";" + serviceWantsEvent); 1716 } 1717 listener.onAccessibilityEvent(event, serviceWantsEvent); 1718 if (DEBUG) { 1719 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); 1720 } 1721 } catch (RemoteException re) { 1722 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); 1723 } finally { 1724 event.recycle(); 1725 } 1726 } 1727 notifyGesture(AccessibilityGestureEvent gestureEvent)1728 public void notifyGesture(AccessibilityGestureEvent gestureEvent) { 1729 mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, 1730 gestureEvent).sendToTarget(); 1731 } 1732 notifySystemActionsChangedLocked()1733 public void notifySystemActionsChangedLocked() { 1734 mInvocationHandler.sendEmptyMessage( 1735 InvocationHandler.MSG_ON_SYSTEM_ACTIONS_CHANGED); 1736 } 1737 notifyClearAccessibilityNodeInfoCache()1738 public void notifyClearAccessibilityNodeInfoCache() { 1739 mInvocationHandler.sendEmptyMessage( 1740 InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); 1741 } 1742 notifyMagnificationChangedLocked(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)1743 public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region, 1744 @NonNull MagnificationConfig config) { 1745 mInvocationHandler 1746 .notifyMagnificationChangedLocked(displayId, region, config); 1747 } 1748 notifySoftKeyboardShowModeChangedLocked(int showState)1749 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 1750 mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState); 1751 } 1752 notifyAccessibilityButtonClickedLocked(int displayId)1753 public void notifyAccessibilityButtonClickedLocked(int displayId) { 1754 mInvocationHandler.notifyAccessibilityButtonClickedLocked(displayId); 1755 } 1756 notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)1757 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 1758 mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available); 1759 } 1760 createImeSessionLocked()1761 public void createImeSessionLocked() { 1762 mInvocationHandler.createImeSessionLocked(); 1763 } 1764 setImeSessionEnabledLocked(IAccessibilityInputMethodSession session, boolean enabled)1765 public void setImeSessionEnabledLocked(IAccessibilityInputMethodSession session, 1766 boolean enabled) { 1767 mInvocationHandler.setImeSessionEnabledLocked(session, enabled); 1768 } 1769 bindInputLocked()1770 public void bindInputLocked() { 1771 mInvocationHandler.bindInputLocked(); 1772 } 1773 unbindInputLocked()1774 public void unbindInputLocked() { 1775 mInvocationHandler.unbindInputLocked(); 1776 } 1777 startInputLocked(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)1778 public void startInputLocked(IRemoteAccessibilityInputConnection connection, 1779 EditorInfo editorInfo, boolean restarting) { 1780 mInvocationHandler.startInputLocked(connection, editorInfo, restarting); 1781 } 1782 1783 @Nullable getWindowTransformationMatrixAndMagnificationSpec( int resolvedWindowId)1784 private Pair<float[], MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec( 1785 int resolvedWindowId) { 1786 return mSystemSupport.getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId); 1787 } 1788 wantsGenericMotionEvent(MotionEvent event)1789 public boolean wantsGenericMotionEvent(MotionEvent event) { 1790 final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK; 1791 return (mGenericMotionEventSources & eventSourceWithoutClass) != 0; 1792 } 1793 1794 /** 1795 * Called by the invocation handler to notify the service that the 1796 * state of magnification has changed. 1797 */ notifyMagnificationChangedInternal(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)1798 private void notifyMagnificationChangedInternal(int displayId, @NonNull Region region, 1799 @NonNull MagnificationConfig config) { 1800 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1801 if (listener != null) { 1802 try { 1803 if (svcClientTracingEnabled()) { 1804 logTraceSvcClient("onMagnificationChanged", displayId + ", " + region + ", " 1805 + config.toString()); 1806 } 1807 listener.onMagnificationChanged(displayId, region, config); 1808 } catch (RemoteException re) { 1809 Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re); 1810 } 1811 } 1812 } 1813 1814 /** 1815 * Called by the invocation handler to notify the service that the state of the soft 1816 * keyboard show mode has changed. 1817 */ notifySoftKeyboardShowModeChangedInternal(int showState)1818 private void notifySoftKeyboardShowModeChangedInternal(int showState) { 1819 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1820 if (listener != null) { 1821 try { 1822 if (svcClientTracingEnabled()) { 1823 logTraceSvcClient("onSoftKeyboardShowModeChanged", String.valueOf(showState)); 1824 } 1825 listener.onSoftKeyboardShowModeChanged(showState); 1826 } catch (RemoteException re) { 1827 Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService, 1828 re); 1829 } 1830 } 1831 } 1832 notifyAccessibilityButtonClickedInternal(int displayId)1833 private void notifyAccessibilityButtonClickedInternal(int displayId) { 1834 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1835 if (listener != null) { 1836 try { 1837 if (svcClientTracingEnabled()) { 1838 logTraceSvcClient("onAccessibilityButtonClicked", String.valueOf(displayId)); 1839 } 1840 listener.onAccessibilityButtonClicked(displayId); 1841 } catch (RemoteException re) { 1842 Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re); 1843 } 1844 } 1845 } 1846 notifyAccessibilityButtonAvailabilityChangedInternal(boolean available)1847 private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) { 1848 // Only notify the service if it's not been notified or the state has changed 1849 if (mReceivedAccessibilityButtonCallbackSinceBind 1850 && (mLastAccessibilityButtonCallbackState == available)) { 1851 return; 1852 } 1853 mReceivedAccessibilityButtonCallbackSinceBind = true; 1854 mLastAccessibilityButtonCallbackState = available; 1855 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1856 if (listener != null) { 1857 try { 1858 if (svcClientTracingEnabled()) { 1859 logTraceSvcClient("onAccessibilityButtonAvailabilityChanged", 1860 String.valueOf(available)); 1861 } 1862 listener.onAccessibilityButtonAvailabilityChanged(available); 1863 } catch (RemoteException re) { 1864 Slog.e(LOG_TAG, 1865 "Error sending accessibility button availability change to " + mService, 1866 re); 1867 } 1868 } 1869 } 1870 notifyGestureInternal(AccessibilityGestureEvent gestureInfo)1871 private void notifyGestureInternal(AccessibilityGestureEvent gestureInfo) { 1872 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1873 if (listener != null) { 1874 try { 1875 if (svcClientTracingEnabled()) { 1876 logTraceSvcClient("onGesture", gestureInfo.toString()); 1877 } 1878 listener.onGesture(gestureInfo); 1879 } catch (RemoteException re) { 1880 Slog.e(LOG_TAG, "Error during sending gesture " + gestureInfo 1881 + " to " + mService, re); 1882 } 1883 } 1884 } 1885 notifySystemActionsChangedInternal()1886 private void notifySystemActionsChangedInternal() { 1887 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1888 if (listener != null) { 1889 try { 1890 if (svcClientTracingEnabled()) { 1891 logTraceSvcClient("onSystemActionsChanged", ""); 1892 } 1893 listener.onSystemActionsChanged(); 1894 } catch (RemoteException re) { 1895 Slog.e(LOG_TAG, "Error sending system actions change to " + mService, 1896 re); 1897 } 1898 } 1899 } 1900 notifyClearAccessibilityCacheInternal()1901 private void notifyClearAccessibilityCacheInternal() { 1902 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1903 if (listener != null) { 1904 try { 1905 if (svcClientTracingEnabled()) { 1906 logTraceSvcClient("clearAccessibilityCache", ""); 1907 } 1908 listener.clearAccessibilityCache(); 1909 } catch (RemoteException re) { 1910 Slog.e(LOG_TAG, "Error during requesting accessibility info cache" 1911 + " to be cleared.", re); 1912 } 1913 } 1914 } 1915 createImeSessionInternal()1916 private void createImeSessionInternal() { 1917 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1918 if (listener != null) { 1919 try { 1920 if (svcClientTracingEnabled()) { 1921 logTraceSvcClient("createImeSession", ""); 1922 } 1923 AccessibilityCallback callback = new AccessibilityCallback(); 1924 listener.createImeSession(callback); 1925 } catch (RemoteException re) { 1926 Slog.e(LOG_TAG, 1927 "Error requesting IME session from " + mService, re); 1928 } 1929 } 1930 } 1931 setImeSessionEnabledInternal(IAccessibilityInputMethodSession session, boolean enabled)1932 private void setImeSessionEnabledInternal(IAccessibilityInputMethodSession session, 1933 boolean enabled) { 1934 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1935 if (listener != null && session != null) { 1936 try { 1937 if (svcClientTracingEnabled()) { 1938 logTraceSvcClient("createImeSession", ""); 1939 } 1940 listener.setImeSessionEnabled(session, enabled); 1941 } catch (RemoteException re) { 1942 Slog.e(LOG_TAG, 1943 "Error requesting IME session from " + mService, re); 1944 } 1945 } 1946 } 1947 bindInputInternal()1948 private void bindInputInternal() { 1949 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1950 if (listener != null) { 1951 try { 1952 if (svcClientTracingEnabled()) { 1953 logTraceSvcClient("bindInput", ""); 1954 } 1955 listener.bindInput(); 1956 } catch (RemoteException re) { 1957 Slog.e(LOG_TAG, 1958 "Error binding input to " + mService, re); 1959 } 1960 } 1961 } 1962 unbindInputInternal()1963 private void unbindInputInternal() { 1964 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1965 if (listener != null) { 1966 try { 1967 if (svcClientTracingEnabled()) { 1968 logTraceSvcClient("unbindInput", ""); 1969 } 1970 listener.unbindInput(); 1971 } catch (RemoteException re) { 1972 Slog.e(LOG_TAG, 1973 "Error unbinding input to " + mService, re); 1974 } 1975 } 1976 } 1977 startInputInternal(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)1978 private void startInputInternal(IRemoteAccessibilityInputConnection connection, 1979 EditorInfo editorInfo, boolean restarting) { 1980 final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); 1981 if (listener != null) { 1982 try { 1983 if (svcClientTracingEnabled()) { 1984 logTraceSvcClient("startInput", "editorInfo=" + editorInfo 1985 + " restarting=" + restarting); 1986 } 1987 listener.startInput(connection, editorInfo, restarting); 1988 } catch (RemoteException re) { 1989 Slog.e(LOG_TAG, 1990 "Error starting input to " + mService, re); 1991 } 1992 } 1993 } 1994 getServiceInterfaceSafely()1995 protected IAccessibilityServiceClient getServiceInterfaceSafely() { 1996 synchronized (mLock) { 1997 return mServiceInterface; 1998 } 1999 } 2000 resolveAccessibilityWindowIdLocked(int accessibilityWindowId)2001 private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { 2002 if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { 2003 final int focusedWindowId = 2004 mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked()); 2005 if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) { 2006 return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; 2007 } 2008 return focusedWindowId; 2009 } 2010 return accessibilityWindowId; 2011 } 2012 resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType)2013 int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { 2014 if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) { 2015 final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType); 2016 // If the caller is a proxy and the found window doesn't belong to a proxy display 2017 // (or vice versa), then return null. This doesn't work if there are multiple active 2018 // proxys, but in the future this code shouldn't be needed if input focus are 2019 // properly split. (so we will deal with the issues if we see them). 2020 //TODO(254545943): Remove this when there is user and proxy separation of input focus 2021 if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) { 2022 return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; 2023 } 2024 return focusedWindowId; 2025 } 2026 return windowId; 2027 } 2028 2029 /** 2030 * Request that the system make sure windows are available to interrogate. 2031 * 2032 * @param displayId The logical display id. 2033 */ ensureWindowsAvailableTimedLocked(int displayId)2034 private void ensureWindowsAvailableTimedLocked(int displayId) { 2035 if (displayId == Display.INVALID_DISPLAY) { 2036 return; 2037 } 2038 2039 if (mA11yWindowManager.getWindowListLocked(displayId) != null) { 2040 return; 2041 } 2042 // If we have no registered callback, update the state we 2043 // we may have to register one but it didn't happen yet. 2044 if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) { 2045 // Invokes client change to make sure tracking window enabled. 2046 mSystemSupport.onClientChangeLocked(false); 2047 } 2048 // We have no windows but do not care about them, done. 2049 if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) { 2050 return; 2051 } 2052 2053 // Wait for the windows with a timeout. 2054 final long startMillis = SystemClock.uptimeMillis(); 2055 while (mA11yWindowManager.getWindowListLocked(displayId) == null) { 2056 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 2057 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; 2058 if (remainMillis <= 0) { 2059 return; 2060 } 2061 try { 2062 mLock.wait(remainMillis); 2063 } catch (InterruptedException ie) { 2064 /* ignore */ 2065 } 2066 } 2067 } 2068 2069 /** 2070 * Perform the specified accessibility action 2071 * 2072 * @param resolvedWindowId The window ID 2073 * [Other parameters match the method on IAccessibilityServiceConnection] 2074 * 2075 * @return Whether or not the action could be sent to the app process 2076 */ performAccessibilityActionInternal(int userId, int resolvedWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, int fetchFlags, long interrogatingTid)2077 private boolean performAccessibilityActionInternal(int userId, int resolvedWindowId, 2078 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 2079 IAccessibilityInteractionConnectionCallback callback, int fetchFlags, 2080 long interrogatingTid) { 2081 RemoteAccessibilityConnection connection; 2082 IBinder windowToken = null; 2083 synchronized (mLock) { 2084 connection = mA11yWindowManager.getConnectionLocked(userId, resolvedWindowId); 2085 if (connection == null) { 2086 return false; 2087 } 2088 final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS) 2089 || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS); 2090 if (!isA11yFocusAction) { 2091 windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked( 2092 userId, resolvedWindowId); 2093 } 2094 final AccessibilityWindowInfo a11yWindowInfo = 2095 mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId); 2096 if (a11yWindowInfo != null && a11yWindowInfo.isInPictureInPictureMode() 2097 && mA11yWindowManager.getPictureInPictureActionReplacingConnection() != null 2098 && !isA11yFocusAction) { 2099 connection = mA11yWindowManager.getPictureInPictureActionReplacingConnection(); 2100 } 2101 } 2102 final int interrogatingPid = Binder.getCallingPid(); 2103 final long identityToken = Binder.clearCallingIdentity(); 2104 try { 2105 // Regardless of whether or not the action succeeds, it was generated by an 2106 // accessibility service that is driven by user actions, so note user activity. 2107 mPowerManager.userActivity(SystemClock.uptimeMillis(), 2108 PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); 2109 2110 if (action == ACTION_CLICK || action == ACTION_LONG_CLICK) { 2111 mA11yWindowManager.notifyOutsideTouch(userId, resolvedWindowId); 2112 } 2113 if (windowToken != null) { 2114 mWindowManagerService.requestWindowFocus(windowToken); 2115 } 2116 if (intConnTracingEnabled()) { 2117 logTraceIntConn("performAccessibilityAction", 2118 accessibilityNodeId + ";" + action + ";" + arguments + ";" + interactionId 2119 + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid + ";" 2120 + interrogatingTid); 2121 } 2122 connection.getRemote().performAccessibilityAction(accessibilityNodeId, action, 2123 arguments, interactionId, callback, fetchFlags, interrogatingPid, 2124 interrogatingTid); 2125 } catch (RemoteException re) { 2126 if (DEBUG) { 2127 Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re); 2128 } 2129 return false; 2130 } finally { 2131 Binder.restoreCallingIdentity(identityToken); 2132 } 2133 return true; 2134 } 2135 2136 /** 2137 * Replace the interaction callback if needed, for example if the window is in picture- 2138 * in-picture mode and needs its nodes replaced. 2139 * 2140 * @param originalCallback The callback we were planning to use 2141 * @param resolvedWindowId The ID of the window we're calling 2142 * @param interactionId The id for the original callback 2143 * @param interrogatingPid Process ID of requester 2144 * @param interrogatingTid Thread ID of requester 2145 * 2146 * @return The callback to use, which may be the original one. 2147 */ replaceCallbackIfNeeded( IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, int interactionId, int interrogatingPid, long interrogatingTid)2148 private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded( 2149 IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, 2150 int interactionId, int interrogatingPid, long interrogatingTid) { 2151 final RemoteAccessibilityConnection pipActionReplacingConnection = 2152 mA11yWindowManager.getPictureInPictureActionReplacingConnection(); 2153 synchronized (mLock) { 2154 final AccessibilityWindowInfo windowInfo = 2155 mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId); 2156 if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode() 2157 || (pipActionReplacingConnection == null)) { 2158 return originalCallback; 2159 } 2160 } 2161 return new ActionReplacingCallback(originalCallback, 2162 pipActionReplacingConnection.getRemote(), interactionId, 2163 interrogatingPid, interrogatingTid); 2164 } 2165 getWindowsByDisplayLocked(int displayId)2166 private List<AccessibilityWindowInfo> getWindowsByDisplayLocked(int displayId) { 2167 final List<AccessibilityWindowInfo> internalWindowList = 2168 mA11yWindowManager.getWindowListLocked(displayId); 2169 if (internalWindowList == null) { 2170 return null; 2171 } 2172 final List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>(); 2173 final int windowCount = internalWindowList.size(); 2174 for (int i = 0; i < windowCount; i++) { 2175 AccessibilityWindowInfo window = internalWindowList.get(i); 2176 AccessibilityWindowInfo windowClone = 2177 AccessibilityWindowInfo.obtain(window); 2178 windowClone.setConnectionId(mId); 2179 returnedWindowList.add(windowClone); 2180 } 2181 return returnedWindowList; 2182 } 2183 getComponentName()2184 public ComponentName getComponentName() { 2185 return mComponentName; 2186 } 2187 2188 private final class InvocationHandler extends Handler { 2189 public static final int MSG_ON_GESTURE = 1; 2190 public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; 2191 2192 private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; 2193 private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6; 2194 private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7; 2195 private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8; 2196 private static final int MSG_ON_SYSTEM_ACTIONS_CHANGED = 9; 2197 private static final int MSG_CREATE_IME_SESSION = 10; 2198 private static final int MSG_SET_IME_SESSION_ENABLED = 11; 2199 private static final int MSG_BIND_INPUT = 12; 2200 private static final int MSG_UNBIND_INPUT = 13; 2201 private static final int MSG_START_INPUT = 14; 2202 2203 /** List of magnification callback states, mapping from displayId -> Boolean */ 2204 @GuardedBy("mlock") 2205 private final SparseArray<Boolean> mMagnificationCallbackState = new SparseArray<>(0); 2206 private boolean mIsSoftKeyboardCallbackEnabled = false; 2207 InvocationHandler(Looper looper)2208 public InvocationHandler(Looper looper) { 2209 super(looper, null, true); 2210 } 2211 2212 @Override handleMessage(Message message)2213 public void handleMessage(Message message) { 2214 final int type = message.what; 2215 switch (type) { 2216 case MSG_ON_GESTURE: { 2217 notifyGestureInternal((AccessibilityGestureEvent) message.obj); 2218 } break; 2219 2220 case MSG_CLEAR_ACCESSIBILITY_CACHE: { 2221 notifyClearAccessibilityCacheInternal(); 2222 } break; 2223 2224 case MSG_ON_MAGNIFICATION_CHANGED: { 2225 final SomeArgs args = (SomeArgs) message.obj; 2226 final Region region = (Region) args.arg1; 2227 final MagnificationConfig config = (MagnificationConfig) args.arg2; 2228 final int displayId = args.argi1; 2229 notifyMagnificationChangedInternal(displayId, region, config); 2230 args.recycle(); 2231 } break; 2232 2233 case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: { 2234 final int showState = (int) message.arg1; 2235 notifySoftKeyboardShowModeChangedInternal(showState); 2236 } break; 2237 2238 case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: { 2239 final int displayId = (int) message.arg1; 2240 notifyAccessibilityButtonClickedInternal(displayId); 2241 } break; 2242 2243 case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: { 2244 final boolean available = (message.arg1 != 0); 2245 notifyAccessibilityButtonAvailabilityChangedInternal(available); 2246 } break; 2247 case MSG_ON_SYSTEM_ACTIONS_CHANGED: { 2248 notifySystemActionsChangedInternal(); 2249 break; 2250 } 2251 case MSG_CREATE_IME_SESSION: 2252 createImeSessionInternal(); 2253 break; 2254 case MSG_SET_IME_SESSION_ENABLED: 2255 final boolean enabled = (message.arg1 != 0); 2256 final IAccessibilityInputMethodSession session = 2257 (IAccessibilityInputMethodSession) message.obj; 2258 setImeSessionEnabledInternal(session, enabled); 2259 break; 2260 case MSG_BIND_INPUT: 2261 bindInputInternal(); 2262 break; 2263 case MSG_UNBIND_INPUT: 2264 unbindInputInternal(); 2265 break; 2266 case MSG_START_INPUT: 2267 final boolean restarting = (message.arg1 != 0); 2268 final SomeArgs args = (SomeArgs) message.obj; 2269 final IRemoteAccessibilityInputConnection connection = 2270 (IRemoteAccessibilityInputConnection) args.arg1; 2271 final EditorInfo editorInfo = (EditorInfo) args.arg2; 2272 startInputInternal(connection, editorInfo, restarting); 2273 args.recycle(); 2274 break; 2275 default: { 2276 throw new IllegalArgumentException("Unknown message: " + type); 2277 } 2278 } 2279 } 2280 notifyMagnificationChangedLocked(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)2281 public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region, 2282 @NonNull MagnificationConfig config) { 2283 synchronized (mLock) { 2284 if (mMagnificationCallbackState.get(displayId) == null) { 2285 return; 2286 } 2287 } 2288 2289 final SomeArgs args = SomeArgs.obtain(); 2290 args.arg1 = region; 2291 args.arg2 = config; 2292 args.argi1 = displayId; 2293 2294 final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args); 2295 msg.sendToTarget(); 2296 } 2297 setMagnificationCallbackEnabled(int displayId, boolean enabled)2298 public void setMagnificationCallbackEnabled(int displayId, boolean enabled) { 2299 synchronized (mLock) { 2300 if (enabled) { 2301 mMagnificationCallbackState.put(displayId, true); 2302 } else { 2303 mMagnificationCallbackState.remove(displayId); 2304 } 2305 } 2306 } 2307 isMagnificationCallbackEnabled(int displayId)2308 public boolean isMagnificationCallbackEnabled(int displayId) { 2309 synchronized (mLock) { 2310 return mMagnificationCallbackState.get(displayId) != null; 2311 } 2312 } 2313 notifySoftKeyboardShowModeChangedLocked(int showState)2314 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 2315 if (!mIsSoftKeyboardCallbackEnabled) { 2316 return; 2317 } 2318 2319 final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0); 2320 msg.sendToTarget(); 2321 } 2322 setSoftKeyboardCallbackEnabled(boolean enabled)2323 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 2324 mIsSoftKeyboardCallbackEnabled = enabled; 2325 } 2326 notifyAccessibilityButtonClickedLocked(int displayId)2327 public void notifyAccessibilityButtonClickedLocked(int displayId) { 2328 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED, displayId, 0); 2329 msg.sendToTarget(); 2330 } 2331 notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)2332 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 2333 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, 2334 (available ? 1 : 0), 0); 2335 msg.sendToTarget(); 2336 } 2337 createImeSessionLocked()2338 public void createImeSessionLocked() { 2339 final Message msg = obtainMessage(MSG_CREATE_IME_SESSION); 2340 msg.sendToTarget(); 2341 } 2342 setImeSessionEnabledLocked(IAccessibilityInputMethodSession session, boolean enabled)2343 public void setImeSessionEnabledLocked(IAccessibilityInputMethodSession session, 2344 boolean enabled) { 2345 final Message msg = obtainMessage(MSG_SET_IME_SESSION_ENABLED, (enabled ? 1 : 0), 2346 0, session); 2347 msg.sendToTarget(); 2348 } 2349 bindInputLocked()2350 public void bindInputLocked() { 2351 final Message msg = obtainMessage(MSG_BIND_INPUT); 2352 msg.sendToTarget(); 2353 } 2354 unbindInputLocked()2355 public void unbindInputLocked() { 2356 final Message msg = obtainMessage(MSG_UNBIND_INPUT); 2357 msg.sendToTarget(); 2358 } 2359 startInputLocked( IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)2360 public void startInputLocked( 2361 IRemoteAccessibilityInputConnection connection, 2362 EditorInfo editorInfo, boolean restarting) { 2363 final SomeArgs args = SomeArgs.obtain(); 2364 args.arg1 = connection; 2365 args.arg2 = editorInfo; 2366 final Message msg = obtainMessage(MSG_START_INPUT, restarting ? 1 : 0, 0, args); 2367 msg.sendToTarget(); 2368 } 2369 } 2370 isServiceHandlesDoubleTapEnabled()2371 public boolean isServiceHandlesDoubleTapEnabled() { 2372 return mServiceHandlesDoubleTap; 2373 } 2374 isMultiFingerGesturesEnabled()2375 public boolean isMultiFingerGesturesEnabled() { 2376 return mRequestMultiFingerGestures; 2377 } 2378 isTwoFingerPassthroughEnabled()2379 public boolean isTwoFingerPassthroughEnabled() { 2380 return mRequestTwoFingerPassthrough; 2381 } 2382 isSendMotionEventsEnabled()2383 public boolean isSendMotionEventsEnabled() { 2384 return mSendMotionEvents; 2385 } 2386 2387 @Override setGestureDetectionPassthroughRegion(int displayId, Region region)2388 public void setGestureDetectionPassthroughRegion(int displayId, Region region) { 2389 if (svcConnTracingEnabled()) { 2390 logTraceSvcConn("setGestureDetectionPassthroughRegion", 2391 "displayId=" + displayId + ";region=" + region); 2392 } 2393 mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region); 2394 } 2395 2396 @Override setTouchExplorationPassthroughRegion(int displayId, Region region)2397 public void setTouchExplorationPassthroughRegion(int displayId, Region region) { 2398 if (svcConnTracingEnabled()) { 2399 logTraceSvcConn("setTouchExplorationPassthroughRegion", 2400 "displayId=" + displayId + ";region=" + region); 2401 } 2402 mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region); 2403 } 2404 2405 @Override setFocusAppearance(int strokeWidth, int color)2406 public void setFocusAppearance(int strokeWidth, int color) { 2407 if (svcConnTracingEnabled()) { 2408 logTraceSvcConn("setFocusAppearance", "strokeWidth=" + strokeWidth + ";color=" + color); 2409 } 2410 } 2411 2412 @Override setCacheEnabled(boolean enabled)2413 public void setCacheEnabled(boolean enabled) { 2414 if (svcConnTracingEnabled()) { 2415 logTraceSvcConn("setCacheEnabled", "enabled=" + enabled); 2416 } 2417 final long identity = Binder.clearCallingIdentity(); 2418 try { 2419 synchronized (mLock) { 2420 mUsesAccessibilityCache = enabled; 2421 mSystemSupport.onClientChangeLocked(true); 2422 } 2423 } finally { 2424 Binder.restoreCallingIdentity(identity); 2425 } 2426 } 2427 2428 @Override logTrace(long timestamp, String where, long loggingTypes, String callingParams, int processId, long threadId, int callingUid, Bundle callingStack)2429 public void logTrace(long timestamp, String where, long loggingTypes, String callingParams, 2430 int processId, long threadId, int callingUid, Bundle callingStack) { 2431 if (mTrace.isA11yTracingEnabledForTypes(loggingTypes)) { 2432 ArrayList<StackTraceElement> list = 2433 (ArrayList<StackTraceElement>) callingStack.getSerializable(CALL_STACK, java.util.ArrayList.class); 2434 HashSet<String> ignoreList = 2435 (HashSet<String>) callingStack.getSerializable(IGNORE_CALL_STACK, java.util.HashSet.class); 2436 mTrace.logTrace(timestamp, where, loggingTypes, callingParams, processId, threadId, 2437 callingUid, list.toArray(new StackTraceElement[list.size()]), ignoreList); 2438 } 2439 } 2440 svcClientTracingEnabled()2441 protected boolean svcClientTracingEnabled() { 2442 return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CLIENT); 2443 } 2444 logTraceSvcClient(String methodName, String params)2445 protected void logTraceSvcClient(String methodName, String params) { 2446 mTrace.logTrace(TRACE_SVC_CLIENT + "." + methodName, 2447 FLAGS_ACCESSIBILITY_SERVICE_CLIENT, params); 2448 } 2449 svcConnTracingEnabled()2450 protected boolean svcConnTracingEnabled() { 2451 return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CONNECTION); 2452 } 2453 logTraceSvcConn(String methodName, String params)2454 protected void logTraceSvcConn(String methodName, String params) { 2455 mTrace.logTrace(TRACE_SVC_CONN + "." + methodName, 2456 FLAGS_ACCESSIBILITY_SERVICE_CONNECTION, params); 2457 } 2458 intConnTracingEnabled()2459 protected boolean intConnTracingEnabled() { 2460 return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION); 2461 } 2462 logTraceIntConn(String methodName, String params)2463 protected void logTraceIntConn(String methodName, String params) { 2464 mTrace.logTrace(LOG_TAG + "." + methodName, 2465 FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION, params); 2466 } 2467 wmTracingEnabled()2468 protected boolean wmTracingEnabled() { 2469 return mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL); 2470 } 2471 logTraceWM(String methodName, String params)2472 protected void logTraceWM(String methodName, String params) { 2473 mTrace.logTrace(TRACE_WM + "." + methodName, FLAGS_WINDOW_MANAGER_INTERNAL, params); 2474 } 2475 setServiceDetectsGesturesEnabled(int displayId, boolean mode)2476 public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) { 2477 mServiceDetectsGestures.put(displayId, mode); 2478 mSystemSupport.setServiceDetectsGesturesEnabled(displayId, mode); 2479 } 2480 isServiceDetectsGesturesEnabled(int displayId)2481 public boolean isServiceDetectsGesturesEnabled(int displayId) { 2482 if (mServiceDetectsGestures.contains(displayId)) { 2483 return mServiceDetectsGestures.get(displayId); 2484 } 2485 return false; 2486 } 2487 requestTouchExploration(int displayId)2488 public void requestTouchExploration(int displayId) { 2489 mSystemSupport.requestTouchExploration(displayId); 2490 } 2491 requestDragging(int displayId, int pointerId)2492 public void requestDragging(int displayId, int pointerId) { 2493 mSystemSupport.requestDragging(displayId, pointerId); 2494 } 2495 requestDelegating(int displayId)2496 public void requestDelegating(int displayId) { 2497 mSystemSupport.requestDelegating(displayId); 2498 } 2499 onDoubleTap(int displayId)2500 public void onDoubleTap(int displayId) { 2501 mSystemSupport.onDoubleTap(displayId); 2502 } 2503 onDoubleTapAndHold(int displayId)2504 public void onDoubleTapAndHold(int displayId) { 2505 mSystemSupport.onDoubleTapAndHold(displayId); 2506 } 2507 2508 /** 2509 * Sets the scaling factor for animations. 2510 */ setAnimationScale(float scale)2511 public void setAnimationScale(float scale) { 2512 final long identity = Binder.clearCallingIdentity(); 2513 try { 2514 Settings.Global.putFloat( 2515 mContext.getContentResolver(), Settings.Global.WINDOW_ANIMATION_SCALE, scale); 2516 Settings.Global.putFloat( 2517 mContext.getContentResolver(), 2518 Settings.Global.TRANSITION_ANIMATION_SCALE, 2519 scale); 2520 Settings.Global.putFloat( 2521 mContext.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, scale); 2522 } finally { 2523 Binder.restoreCallingIdentity(identity); 2524 } 2525 } 2526 2527 private static final class AccessibilityCallback 2528 extends IAccessibilityInputMethodSessionCallback.Stub { 2529 @Override sessionCreated(IAccessibilityInputMethodSession session, int id)2530 public void sessionCreated(IAccessibilityInputMethodSession session, int id) { 2531 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AACS.sessionCreated"); 2532 final long ident = Binder.clearCallingIdentity(); 2533 try { 2534 InputMethodManagerInternal.get().onSessionForAccessibilityCreated(id, session); 2535 } finally { 2536 Binder.restoreCallingIdentity(ident); 2537 } 2538 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2539 } 2540 } 2541 2542 @Override attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc)2543 public void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc) { 2544 mSystemSupport.attachAccessibilityOverlayToDisplay(displayId, sc); 2545 } 2546 2547 @Override attachAccessibilityOverlayToWindow(int accessibilityWindowId, SurfaceControl sc)2548 public void attachAccessibilityOverlayToWindow(int accessibilityWindowId, SurfaceControl sc) 2549 throws RemoteException { 2550 SurfaceControl.Transaction t = new SurfaceControl.Transaction(); 2551 t.setTrustedOverlay(sc, true).apply(); 2552 t.close(); 2553 synchronized (mLock) { 2554 RemoteAccessibilityConnection connection = 2555 mA11yWindowManager.getConnectionLocked( 2556 mSystemSupport.getCurrentUserIdLocked(), 2557 resolveAccessibilityWindowIdLocked(accessibilityWindowId)); 2558 if (connection == null) { 2559 Slog.e(LOG_TAG, "unable to get remote accessibility connection."); 2560 return; 2561 } 2562 connection.getRemote().attachAccessibilityOverlayToWindow(sc); 2563 } 2564 } 2565 }