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