• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.accessibilityservice;
18 
19 import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
20 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
21 
22 import android.accessibilityservice.GestureDescription.MotionEventGenerator;
23 import android.annotation.CallbackExecutor;
24 import android.annotation.CheckResult;
25 import android.annotation.ColorInt;
26 import android.annotation.FlaggedApi;
27 import android.annotation.IntDef;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.annotation.RequiresPermission;
31 import android.annotation.TestApi;
32 import android.app.Service;
33 import android.compat.annotation.UnsupportedAppUsage;
34 import android.content.Context;
35 import android.content.ContextWrapper;
36 import android.content.Intent;
37 import android.content.pm.ParceledListSlice;
38 import android.graphics.Bitmap;
39 import android.graphics.ColorSpace;
40 import android.graphics.ParcelableColorSpace;
41 import android.graphics.Region;
42 import android.hardware.HardwareBuffer;
43 import android.hardware.display.DisplayManager;
44 import android.os.Build;
45 import android.os.Bundle;
46 import android.os.Handler;
47 import android.os.HandlerExecutor;
48 import android.os.IBinder;
49 import android.os.Looper;
50 import android.os.RemoteCallback;
51 import android.os.RemoteException;
52 import android.os.SystemClock;
53 import android.util.ArrayMap;
54 import android.util.Log;
55 import android.util.Slog;
56 import android.util.SparseArray;
57 import android.view.Display;
58 import android.view.InputDevice;
59 import android.view.KeyEvent;
60 import android.view.MotionEvent;
61 import android.view.SurfaceControl;
62 import android.view.WindowManager;
63 import android.view.WindowManagerImpl;
64 import android.view.accessibility.AccessibilityCache;
65 import android.view.accessibility.AccessibilityEvent;
66 import android.view.accessibility.AccessibilityInteractionClient;
67 import android.view.accessibility.AccessibilityNodeInfo;
68 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
69 import android.view.accessibility.AccessibilityWindowInfo;
70 import android.view.accessibility.Flags;
71 import android.view.inputmethod.EditorInfo;
72 
73 import com.android.internal.annotations.VisibleForTesting;
74 import com.android.internal.inputmethod.CancellationGroup;
75 import com.android.internal.inputmethod.IAccessibilityInputMethodSession;
76 import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback;
77 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
78 import com.android.internal.inputmethod.RemoteAccessibilityInputConnection;
79 import com.android.internal.util.Preconditions;
80 
81 import java.lang.annotation.Retention;
82 import java.lang.annotation.RetentionPolicy;
83 import java.util.Collections;
84 import java.util.List;
85 import java.util.concurrent.Executor;
86 import java.util.function.Consumer;
87 import java.util.function.IntConsumer;
88 
89 /**
90  * Accessibility services should only be used to assist users with disabilities in using
91  * Android devices and apps. They run in the background and receive callbacks by the system
92  * when {@link AccessibilityEvent}s are fired. Such events denote some state transition
93  * in the user interface, for example, the focus has changed, a button has been clicked,
94  * etc. Such a service can optionally request the capability for querying the content
95  * of the active window. Development of an accessibility service requires extending this
96  * class and implementing its abstract methods.
97  *
98  * <div class="special reference">
99  * <h3>Developer Guides</h3>
100  * <p>For more information about creating AccessibilityServices, read the
101  * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
102  * developer guide.</p>
103  * </div>
104  *
105  * <h3>Lifecycle</h3>
106  * <p>
107  * The lifecycle of an accessibility service is managed exclusively by the system and
108  * follows the established service life cycle. Starting an accessibility service is triggered
109  * exclusively by the user explicitly turning the service on in device settings. After the system
110  * binds to a service, it calls {@link AccessibilityService#onServiceConnected()}. This method can
111  * be overridden by clients that want to perform post binding setup.
112  * </p>
113  * <p>
114  * An accessibility service stops either when the user turns it off in device settings or when
115  * it calls {@link AccessibilityService#disableSelf()}.
116  * </p>
117  * <h3>Declaration</h3>
118  * <p>
119  * An accessibility is declared as any other service in an AndroidManifest.xml, but it
120  * must do two things:
121  * <ul>
122  *     <li>
123  *         Specify that it handles the "android.accessibilityservice.AccessibilityService"
124  *         {@link android.content.Intent}.
125  *     </li>
126  *     <li>
127  *         Request the {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission to
128  *         ensure that only the system can bind to it.
129  *     </li>
130  * </ul>
131  * If either of these items is missing, the system will ignore the accessibility service.
132  * Following is an example declaration:
133  * </p>
134  * <pre> &lt;service android:name=".MyAccessibilityService"
135  *         android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"&gt;
136  *     &lt;intent-filter&gt;
137  *         &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
138  *     &lt;/intent-filter&gt;
139  *     . . .
140  * &lt;/service&gt;</pre>
141  * <h3>Configuration</h3>
142  * <p>
143  * An accessibility service can be configured to receive specific types of accessibility events,
144  * listen only to specific packages, get events from each type only once in a given time frame,
145  * retrieve window content, specify a settings activity, etc.
146  * </p>
147  * <p>
148  * There are two approaches for configuring an accessibility service:
149  * </p>
150  * <ul>
151  * <li>
152  * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
153  * the service. A service declaration with a meta-data tag is presented below:
154  * <pre> &lt;service android:name=".MyAccessibilityService"&gt;
155  *     &lt;intent-filter&gt;
156  *         &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
157  *     &lt;/intent-filter&gt;
158  *     &lt;meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" /&gt;
159  * &lt;/service&gt;</pre>
160  * <p class="note">
161  * <strong>Note:</strong> This approach enables setting all properties.
162  * </p>
163  * <p>
164  * For more details refer to {@link #SERVICE_META_DATA} and
165  * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>.
166  * </p>
167  * </li>
168  * <li>
169  * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
170  * that this method can be called any time to dynamically change the service configuration.
171  * <p class="note">
172  * <strong>Note:</strong> This approach enables setting only dynamically configurable properties:
173  * {@link AccessibilityServiceInfo#eventTypes},
174  * {@link AccessibilityServiceInfo#feedbackType},
175  * {@link AccessibilityServiceInfo#flags},
176  * {@link AccessibilityServiceInfo#notificationTimeout},
177  * {@link AccessibilityServiceInfo#packageNames}
178  * </p>
179  * <p>
180  * For more details refer to {@link AccessibilityServiceInfo}.
181  * </p>
182  * </li>
183  * </ul>
184  * <h3>Retrieving window content</h3>
185  * <p>
186  * A service can specify in its declaration that it can retrieve window
187  * content which is represented as a tree of {@link AccessibilityWindowInfo} and
188  * {@link AccessibilityNodeInfo} objects. Note that
189  * declaring this capability requires that the service declares its configuration via
190  * an XML resource referenced by {@link #SERVICE_META_DATA}.
191  * </p>
192  * <p>
193  * Window content may be retrieved with
194  * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()},
195  * {@link AccessibilityService#findFocus(int)},
196  * {@link AccessibilityService#getWindows()}, or
197  * {@link AccessibilityService#getRootInActiveWindow()}.
198  * </p>
199  * <p class="note">
200  * <strong>Note</strong> An accessibility service may have requested to be notified for
201  * a subset of the event types, and thus be unaware when the node hierarchy has changed. It is also
202  * possible for a node to contain outdated information because the window content may change at any
203  * time.
204  * </p>
205  * <h3>Drawing Accessibility Overlays</h3>
206  * <p>Accessibility services can draw overlays on top of existing screen contents.
207  * Accessibility overlays can be used to visually highlight items on the screen
208  * e.g. indicate the current item with accessibility focus.
209  * Overlays can also offer the user a way to interact with the service directly and quickly
210  * customize the service's behavior.</p>
211  * <p>Accessibility overlays can be attached to a particular window or to the display itself.
212  * Attaching an overlay to a window allows the overly to move, grow and shrink as the window does.
213  * The overlay will maintain the same relative position within the window bounds as the window
214  * moves. The overlay will also maintain the same relative position within the window bounds if
215  * the window is resized.
216  * To attach an overlay to a window, use {@link #attachAccessibilityOverlayToWindow}.
217  * Attaching an overlay to the display means that the overlay is independent of the active
218  * windows on that display.
219  * To attach an overlay to a display, use {@link #attachAccessibilityOverlayToDisplay}. </p>
220  * <p> When positioning an overlay that is attached to a window, the service must use window
221  * coordinates. In order to position an overlay on top of an existing UI element it is necessary
222  * to know the bounds of that element in window coordinates. To find the bounds in window
223  * coordinates of an element, find the corresponding {@link AccessibilityNodeInfo} as discussed
224  * above and call {@link AccessibilityNodeInfo#getBoundsInWindow}. </p>
225  * <h3>Notification strategy</h3>
226  * <p>
227  * All accessibility services are notified of all events they have requested, regardless of their
228  * feedback type.
229  * </p>
230  * <p class="note">
231  * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
232  * events to the client too frequently since this is accomplished via an expensive
233  * interprocess call. One can think of the timeout as a criteria to determine when
234  * event generation has settled down.</p>
235  * <h3>Event types</h3>
236  * <ul>
237  * <li>{@link AccessibilityEvent#TYPE_VIEW_CLICKED}</li>
238  * <li>{@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}</li>
239  * <li>{@link AccessibilityEvent#TYPE_VIEW_FOCUSED}</li>
240  * <li>{@link AccessibilityEvent#TYPE_VIEW_SELECTED}</li>
241  * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}</li>
242  * <li>{@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}</li>
243  * <li>{@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}</li>
244  * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}</li>
245  * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}</li>
246  * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}</li>
247  * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}</li>
248  * <li>{@link AccessibilityEvent#TYPE_VIEW_SCROLLED}</li>
249  * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}</li>
250  * <li>{@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}</li>
251  * <li>{@link AccessibilityEvent#TYPE_ANNOUNCEMENT}</li>
252  * <li>{@link AccessibilityEvent#TYPE_GESTURE_DETECTION_START}</li>
253  * <li>{@link AccessibilityEvent#TYPE_GESTURE_DETECTION_END}</li>
254  * <li>{@link AccessibilityEvent#TYPE_TOUCH_INTERACTION_START}</li>
255  * <li>{@link AccessibilityEvent#TYPE_TOUCH_INTERACTION_END}</li>
256  * <li>{@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED}</li>
257  * <li>{@link AccessibilityEvent#TYPE_WINDOWS_CHANGED}</li>
258  * <li>{@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED}</li>
259  * </ul>
260  * <h3>Feedback types</h3>
261  * <ul>
262  * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}</li>
263  * <li>{@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}</li>
264  * <li>{@link AccessibilityServiceInfo#FEEDBACK_SPOKEN}</li>
265  * <li>{@link AccessibilityServiceInfo#FEEDBACK_VISUAL}</li>
266  * <li>{@link AccessibilityServiceInfo#FEEDBACK_GENERIC}</li>
267  * <li>{@link AccessibilityServiceInfo#FEEDBACK_BRAILLE}</li>
268  * </ul>
269  * @see AccessibilityEvent
270  * @see AccessibilityServiceInfo
271  * @see android.view.accessibility.AccessibilityManager
272  */
273 public abstract class AccessibilityService extends Service {
274 
275     /**
276      * The user has performed a touch-exploration gesture on the touch screen without ever
277      * triggering gesture detection. This gesture is only dispatched when {@link
278      * AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
279      *
280      * @hide
281      */
282     public static final int GESTURE_TOUCH_EXPLORATION = -2;
283 
284     /**
285      * The user has performed a passthrough gesture on the touch screen without ever triggering
286      * gesture detection. This gesture is only dispatched when {@link
287      * AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
288      * @hide
289      */
290     public static final int GESTURE_PASSTHROUGH = -1;
291 
292     /**
293      * The user has performed an unrecognized gesture on the touch screen. This gesture is only
294      * dispatched when {@link AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
295      */
296     public static final int GESTURE_UNKNOWN = 0;
297 
298     /**
299      * The user has performed a swipe up gesture on the touch screen.
300      */
301     public static final int GESTURE_SWIPE_UP = 1;
302 
303     /**
304      * The user has performed a swipe down gesture on the touch screen.
305      */
306     public static final int GESTURE_SWIPE_DOWN = 2;
307 
308     /**
309      * The user has performed a swipe left gesture on the touch screen.
310      */
311     public static final int GESTURE_SWIPE_LEFT = 3;
312 
313     /**
314      * The user has performed a swipe right gesture on the touch screen.
315      */
316     public static final int GESTURE_SWIPE_RIGHT = 4;
317 
318     /**
319      * The user has performed a swipe left and right gesture on the touch screen.
320      */
321     public static final int GESTURE_SWIPE_LEFT_AND_RIGHT = 5;
322 
323     /**
324      * The user has performed a swipe right and left gesture on the touch screen.
325      */
326     public static final int GESTURE_SWIPE_RIGHT_AND_LEFT = 6;
327 
328     /**
329      * The user has performed a swipe up and down gesture on the touch screen.
330      */
331     public static final int GESTURE_SWIPE_UP_AND_DOWN = 7;
332 
333     /**
334      * The user has performed a swipe down and up gesture on the touch screen.
335      */
336     public static final int GESTURE_SWIPE_DOWN_AND_UP = 8;
337 
338     /**
339      * The user has performed a left and up gesture on the touch screen.
340      */
341     public static final int GESTURE_SWIPE_LEFT_AND_UP = 9;
342 
343     /**
344      * The user has performed a left and down gesture on the touch screen.
345      */
346     public static final int GESTURE_SWIPE_LEFT_AND_DOWN = 10;
347 
348     /**
349      * The user has performed a right and up gesture on the touch screen.
350      */
351     public static final int GESTURE_SWIPE_RIGHT_AND_UP = 11;
352 
353     /**
354      * The user has performed a right and down gesture on the touch screen.
355      */
356     public static final int GESTURE_SWIPE_RIGHT_AND_DOWN = 12;
357 
358     /**
359      * The user has performed an up and left gesture on the touch screen.
360      */
361     public static final int GESTURE_SWIPE_UP_AND_LEFT = 13;
362 
363     /**
364      * The user has performed an up and right gesture on the touch screen.
365      */
366     public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14;
367 
368     /**
369      * The user has performed a down and left gesture on the touch screen.
370      */
371     public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15;
372 
373     /**
374      * The user has performed a down and right gesture on the touch screen.
375      */
376     public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16;
377 
378     /**
379      * The user has performed a double tap gesture on the touch screen.
380      */
381     public static final int GESTURE_DOUBLE_TAP = 17;
382 
383     /**
384      * The user has performed a double tap and hold gesture on the touch screen.
385      */
386     public static final int GESTURE_DOUBLE_TAP_AND_HOLD = 18;
387 
388     /**
389      * The user has performed a two-finger single tap gesture on the touch screen.
390      */
391     public static final int GESTURE_2_FINGER_SINGLE_TAP = 19;
392 
393     /**
394      * The user has performed a two-finger double tap gesture on the touch screen.
395      */
396     public static final int GESTURE_2_FINGER_DOUBLE_TAP = 20;
397 
398     /**
399      * The user has performed a two-finger triple tap gesture on the touch screen.
400      */
401     public static final int GESTURE_2_FINGER_TRIPLE_TAP = 21;
402 
403     /**
404      * The user has performed a three-finger single tap gesture on the touch screen.
405      */
406     public static final int GESTURE_3_FINGER_SINGLE_TAP = 22;
407 
408     /**
409      * The user has performed a three-finger double tap gesture on the touch screen.
410      */
411     public static final int GESTURE_3_FINGER_DOUBLE_TAP = 23;
412 
413     /**
414      * The user has performed a three-finger triple tap gesture on the touch screen.
415      */
416     public static final int GESTURE_3_FINGER_TRIPLE_TAP = 24;
417 
418     /**
419      * The user has performed a two-finger swipe up gesture on the touch screen.
420      */
421     public static final int GESTURE_2_FINGER_SWIPE_UP = 25;
422 
423     /**
424      * The user has performed a two-finger swipe down gesture on the touch screen.
425      */
426     public static final int GESTURE_2_FINGER_SWIPE_DOWN = 26;
427 
428     /**
429      * The user has performed a two-finger swipe left gesture on the touch screen.
430      */
431     public static final int GESTURE_2_FINGER_SWIPE_LEFT = 27;
432 
433     /**
434      * The user has performed a two-finger swipe right gesture on the touch screen.
435      */
436     public static final int GESTURE_2_FINGER_SWIPE_RIGHT = 28;
437 
438     /**
439      * The user has performed a three-finger swipe up gesture on the touch screen.
440      */
441     public static final int GESTURE_3_FINGER_SWIPE_UP = 29;
442 
443     /**
444      * The user has performed a three-finger swipe down gesture on the touch screen.
445      */
446     public static final int GESTURE_3_FINGER_SWIPE_DOWN = 30;
447 
448     /**
449      * The user has performed a three-finger swipe left gesture on the touch screen.
450      */
451     public static final int GESTURE_3_FINGER_SWIPE_LEFT = 31;
452 
453     /**
454      * The user has performed a three-finger swipe right gesture on the touch screen.
455      */
456     public static final int GESTURE_3_FINGER_SWIPE_RIGHT = 32;
457 
458     /** The user has performed a four-finger swipe up gesture on the touch screen. */
459     public static final int GESTURE_4_FINGER_SWIPE_UP = 33;
460 
461     /** The user has performed a four-finger swipe down gesture on the touch screen. */
462     public static final int GESTURE_4_FINGER_SWIPE_DOWN = 34;
463 
464     /** The user has performed a four-finger swipe left gesture on the touch screen. */
465     public static final int GESTURE_4_FINGER_SWIPE_LEFT = 35;
466 
467     /** The user has performed a four-finger swipe right gesture on the touch screen. */
468     public static final int GESTURE_4_FINGER_SWIPE_RIGHT = 36;
469 
470     /** The user has performed a four-finger single tap gesture on the touch screen. */
471     public static final int GESTURE_4_FINGER_SINGLE_TAP = 37;
472 
473     /** The user has performed a four-finger double tap gesture on the touch screen. */
474     public static final int GESTURE_4_FINGER_DOUBLE_TAP = 38;
475 
476     /** The user has performed a four-finger triple tap gesture on the touch screen. */
477     public static final int GESTURE_4_FINGER_TRIPLE_TAP = 39;
478 
479     /** The user has performed a two-finger double tap and hold gesture on the touch screen. */
480     public static final int GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD = 40;
481 
482     /** The user has performed a three-finger double tap and hold gesture on the touch screen. */
483     public static final int GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD = 41;
484 
485     /** The user has performed a two-finger  triple-tap and hold gesture on the touch screen. */
486     public static final int GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD = 43;
487 
488     /** The user has performed a three-finger  single-tap and hold gesture on the touch screen. */
489     public static final int GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD = 44;
490 
491     /** The user has performed a three-finger  triple-tap and hold gesture on the touch screen. */
492     public static final int GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD = 45;
493 
494     /** The user has performed a two-finger double tap and hold gesture on the touch screen. */
495     public static final int GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD = 42;
496 
497     /**
498      * The {@link Intent} that must be declared as handled by the service.
499      */
500     public static final String SERVICE_INTERFACE =
501         "android.accessibilityservice.AccessibilityService";
502 
503     /**
504      * Name under which an AccessibilityService component publishes information
505      * about itself. This meta-data must reference an XML resource containing an
506      * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>
507      * tag. This is a sample XML file configuring an accessibility service:
508      * <pre> &lt;accessibility-service
509      *     android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
510      *     android:packageNames="foo.bar, foo.baz"
511      *     android:accessibilityFeedbackType="feedbackSpoken"
512      *     android:notificationTimeout="100"
513      *     android:accessibilityFlags="flagDefault"
514      *     android:settingsActivity="foo.bar.TestBackActivity"
515      *     android:canRetrieveWindowContent="true"
516      *     android:canRequestTouchExplorationMode="true"
517      *     . . .
518      * /&gt;</pre>
519      */
520     public static final String SERVICE_META_DATA = "android.accessibilityservice";
521 
522     /**
523      * Action to go back.
524      */
525     public static final int GLOBAL_ACTION_BACK = 1;
526 
527     /**
528      * Action to go home.
529      */
530     public static final int GLOBAL_ACTION_HOME = 2;
531 
532     /**
533      * Action to toggle showing the overview of recent apps. Will fail on platforms that don't
534      * show recent apps.
535      */
536     public static final int GLOBAL_ACTION_RECENTS = 3;
537 
538     /**
539      * Action to open the notifications.
540      */
541     public static final int GLOBAL_ACTION_NOTIFICATIONS = 4;
542 
543     /**
544      * Action to open the quick settings.
545      */
546     public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5;
547 
548     /**
549      * Action to open the power long-press dialog.
550      */
551     public static final int GLOBAL_ACTION_POWER_DIALOG = 6;
552 
553     /**
554      * Action to toggle docking the current app's window.
555      * <p>
556      * <strong>Note:</strong>  It is effective only if it appears in {@link #getSystemActions()}.
557      */
558     public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7;
559 
560     /**
561      * Action to lock the screen
562      */
563     public static final int GLOBAL_ACTION_LOCK_SCREEN = 8;
564 
565     /**
566      * Action to take a screenshot
567      */
568     public static final int GLOBAL_ACTION_TAKE_SCREENSHOT = 9;
569 
570     /**
571      * Action to send the KEYCODE_HEADSETHOOK KeyEvent, which is used to answer and hang up calls
572      * and play and stop media. Calling takes priority. If there is an incoming call,
573      * this action can be used to answer that call, and if there is an ongoing call, to hang up on
574      * that call.
575      */
576     public static final int GLOBAL_ACTION_KEYCODE_HEADSETHOOK = 10;
577 
578     /**
579      * Action to trigger the Accessibility Button
580      */
581     public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON = 11;
582 
583     /**
584      * Action to bring up the Accessibility Button's chooser menu
585      */
586     public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON_CHOOSER = 12;
587 
588     /**
589      * Action to trigger the Accessibility Shortcut. This shortcut has a hardware trigger and can
590      * be activated by holding down the two volume keys.
591      */
592     public static final int GLOBAL_ACTION_ACCESSIBILITY_SHORTCUT = 13;
593 
594     /**
595      * Action to show Launcher's all apps.
596      */
597     public static final int GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS = 14;
598 
599     /**
600      * Action to dismiss the notification shade
601      */
602     public static final int GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE = 15;
603 
604     /**
605      * Action to trigger dpad up keyevent.
606      */
607     public static final int GLOBAL_ACTION_DPAD_UP = 16;
608 
609     /**
610      * Action to trigger dpad down keyevent.
611      */
612     public static final int GLOBAL_ACTION_DPAD_DOWN = 17;
613 
614     /**
615      * Action to trigger dpad left keyevent.
616      */
617     public static final int GLOBAL_ACTION_DPAD_LEFT = 18;
618 
619     /**
620      * Action to trigger dpad right keyevent.
621      */
622     public static final int GLOBAL_ACTION_DPAD_RIGHT = 19;
623 
624     /**
625      * Action to trigger dpad center keyevent.
626      */
627     public static final int GLOBAL_ACTION_DPAD_CENTER = 20;
628 
629     /**
630      * Action to trigger menu key event.
631      */
632     @FlaggedApi(Flags.FLAG_GLOBAL_ACTION_MENU)
633     public static final int GLOBAL_ACTION_MENU = 21;
634 
635     /**
636      * Action to trigger media play/pause key event.
637      */
638     @FlaggedApi(Flags.FLAG_GLOBAL_ACTION_MEDIA_PLAY_PAUSE)
639     public static final int GLOBAL_ACTION_MEDIA_PLAY_PAUSE = 22;
640 
641     private static final String LOG_TAG = "AccessibilityService";
642 
643     /**
644      * Interface used by IAccessibilityServiceClientWrapper to call the service from its main
645      * thread.
646      * @hide
647      */
648     public interface Callbacks {
onAccessibilityEvent(AccessibilityEvent event)649         void onAccessibilityEvent(AccessibilityEvent event);
onInterrupt()650         void onInterrupt();
onServiceConnected()651         void onServiceConnected();
init(int connectionId, IBinder windowToken)652         void init(int connectionId, IBinder windowToken);
653         /** The detected gesture information for different displays */
onGesture(AccessibilityGestureEvent gestureInfo)654         boolean onGesture(AccessibilityGestureEvent gestureInfo);
onKeyEvent(KeyEvent event)655         boolean onKeyEvent(KeyEvent event);
656         /** Magnification changed callbacks for different displays */
onMagnificationChanged(int displayId, @NonNull Region region, MagnificationConfig config)657         void onMagnificationChanged(int displayId, @NonNull Region region,
658                 MagnificationConfig config);
659         /** Callbacks for receiving motion events. */
onMotionEvent(MotionEvent event)660         void onMotionEvent(MotionEvent event);
661         /** Callback for tuch state changes. */
onTouchStateChanged(int displayId, int state)662         void onTouchStateChanged(int displayId, int state);
onSoftKeyboardShowModeChanged(int showMode)663         void onSoftKeyboardShowModeChanged(int showMode);
onPerformGestureResult(int sequence, boolean completedSuccessfully)664         void onPerformGestureResult(int sequence, boolean completedSuccessfully);
onFingerprintCapturingGesturesChanged(boolean active)665         void onFingerprintCapturingGesturesChanged(boolean active);
onFingerprintGesture(int gesture)666         void onFingerprintGesture(int gesture);
667         /** Accessbility button clicked callbacks for different displays */
onAccessibilityButtonClicked(int displayId)668         void onAccessibilityButtonClicked(int displayId);
onAccessibilityButtonAvailabilityChanged(boolean available)669         void onAccessibilityButtonAvailabilityChanged(boolean available);
670         /** This is called when the system action list is changed. */
onSystemActionsChanged()671         void onSystemActionsChanged();
672         /** This is called when an app requests ime sessions or when the service is enabled. */
createImeSession(IAccessibilityInputMethodSessionCallback callback)673         void createImeSession(IAccessibilityInputMethodSessionCallback callback);
674         /** This is called when an app starts input or when the service is enabled. */
startInput(@ullable RemoteAccessibilityInputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting)675         void startInput(@Nullable RemoteAccessibilityInputConnection inputConnection,
676                 @NonNull EditorInfo editorInfo, boolean restarting);
677     }
678 
679     /**
680      * Annotations for Soft Keyboard show modes so tools can catch invalid show modes.
681      * @hide
682      */
683     @Retention(RetentionPolicy.SOURCE)
684     @IntDef(prefix = { "SHOW_MODE_" }, value = {
685             SHOW_MODE_AUTO,
686             SHOW_MODE_HIDDEN,
687             SHOW_MODE_IGNORE_HARD_KEYBOARD
688     })
689     public @interface SoftKeyboardShowMode {}
690 
691     /**
692      * Allow the system to control when the soft keyboard is shown.
693      * @see SoftKeyboardController
694      */
695     public static final int SHOW_MODE_AUTO = 0;
696 
697     /**
698      * Never show the soft keyboard.
699      * @see SoftKeyboardController
700      */
701     public static final int SHOW_MODE_HIDDEN = 1;
702 
703     /**
704      * Allow the soft keyboard to be shown, even if a hard keyboard is connected
705      * @see SoftKeyboardController
706      */
707     public static final int SHOW_MODE_IGNORE_HARD_KEYBOARD = 2;
708 
709     /**
710      * Mask used to cover the show modes supported in public API
711      * @hide
712      */
713     public static final int SHOW_MODE_MASK = 0x03;
714 
715     /**
716      * Bit used to hold the old value of the hard IME setting to restore when a service is shut
717      * down.
718      * @hide
719      */
720     public static final int SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE = 0x20000000;
721 
722     /**
723      * Bit for show mode setting to indicate that the user has overridden the hard keyboard
724      * behavior.
725      * @hide
726      */
727     public static final int SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN = 0x40000000;
728 
729     /**
730      * Annotations for error codes of taking screenshot.
731      * @hide
732      */
733     @Retention(RetentionPolicy.SOURCE)
734     @IntDef(prefix = { "TAKE_SCREENSHOT_" }, value = {
735             ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR,
736             ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS,
737             ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT,
738             ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
739             ERROR_TAKE_SCREENSHOT_INVALID_WINDOW
740     })
741     public @interface ScreenshotErrorCode {}
742 
743     /**
744      * The status of taking screenshot is success.
745      * @hide
746      */
747     public static final int TAKE_SCREENSHOT_SUCCESS = 0;
748 
749     /**
750      * The status of taking screenshot is failure and the reason is internal error.
751      */
752     public static final int ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR = 1;
753 
754     /**
755      * The status of taking screenshot is failure and the reason is no accessibility access.
756      */
757     public static final int ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS = 2;
758 
759     /**
760      * The status of taking screenshot is failure and the reason is that too little time has
761      * elapsed since the last screenshot.
762      */
763     public static final int ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT = 3;
764 
765     /**
766      * The status of taking screenshot is failure and the reason is invalid display Id.
767      */
768     public static final int ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY = 4;
769 
770     /**
771      * The status of taking screenshot is failure and the reason is invalid accessibility window Id.
772      */
773     public static final int ERROR_TAKE_SCREENSHOT_INVALID_WINDOW = 5;
774 
775     /**
776      * The status of taking screenshot is failure and the reason is the window contains secure
777      * content.
778      * @see WindowManager.LayoutParams#FLAG_SECURE
779      */
780     public static final int ERROR_TAKE_SCREENSHOT_SECURE_WINDOW = 6;
781 
782     /**
783      * The interval time of calling
784      * {@link AccessibilityService#takeScreenshot(int, Executor, Consumer)} API.
785      * @hide
786      */
787     @TestApi
788     public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 333;
789 
790     /** @hide */
791     public static final String KEY_ACCESSIBILITY_SCREENSHOT_STATUS =
792             "screenshot_status";
793 
794     /** @hide */
795     public static final String KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER =
796             "screenshot_hardwareBuffer";
797 
798     /** @hide */
799     public static final String KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE =
800             "screenshot_colorSpace";
801 
802     /** @hide */
803     public static final String KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP =
804             "screenshot_timestamp";
805 
806 
807     /**
808      * Annotations for result codes of attaching accessibility overlays.
809      *
810      * @hide
811      */
812     @Retention(RetentionPolicy.SOURCE)
813     @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")
814     @IntDef(
815             prefix = {"OVERLAY_RESULT_"},
816             value = {
817                 OVERLAY_RESULT_SUCCESS,
818                 OVERLAY_RESULT_INTERNAL_ERROR,
819                 OVERLAY_RESULT_INVALID,
820             })
821     public @interface AttachOverlayResult {}
822 
823     /** Result code indicating the overlay was successfully attached. */
824     @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")
825     public static final int OVERLAY_RESULT_SUCCESS = 0;
826 
827     /**
828      * Result code indicating the overlay could not be attached due to an internal
829      * error and not
830      * because of problems with the input.
831      */
832     @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")
833     public static final int OVERLAY_RESULT_INTERNAL_ERROR = 1;
834 
835     /**
836      * Result code indicating the overlay could not be attached because the
837      * specified display or
838      * window id was invalid.
839      */
840     @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")
841     public static final int OVERLAY_RESULT_INVALID = 2;
842 
843     private int mConnectionId = AccessibilityInteractionClient.NO_ID;
844 
845     @UnsupportedAppUsage
846     private AccessibilityServiceInfo mInfo;
847 
848     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
849     private IBinder mWindowToken;
850 
851     private WindowManager mWindowManager;
852 
853     /** List of magnification controllers, mapping from displayId -> MagnificationController. */
854     private final SparseArray<MagnificationController> mMagnificationControllers =
855             new SparseArray<>(0);
856     /**
857      * List of touch interaction controllers, mapping from displayId -> TouchInteractionController.
858      */
859     private final SparseArray<TouchInteractionController> mTouchInteractionControllers =
860             new SparseArray<>(0);
861 
862     private SoftKeyboardController mSoftKeyboardController;
863     private InputMethod mInputMethod;
864     private boolean mInputMethodInitialized = false;
865     private final SparseArray<AccessibilityButtonController> mAccessibilityButtonControllers =
866             new SparseArray<>(0);
867     private BrailleDisplayController mBrailleDisplayController;
868 
869     private int mGestureStatusCallbackSequence;
870 
871     private SparseArray<GestureResultCallbackInfo> mGestureStatusCallbackInfos;
872 
873     private final Object mLock = new Object();
874 
875     private FingerprintGestureController mFingerprintGestureController;
876 
877     private int mMotionEventSources;
878 
879     /**
880      * Callback for {@link android.view.accessibility.AccessibilityEvent}s.
881      *
882      * @param event The new event. This event is owned by the caller and cannot be used after
883      * this method returns. Services wishing to use the event after this method returns should
884      * make a copy.
885      */
onAccessibilityEvent(AccessibilityEvent event)886     public abstract void onAccessibilityEvent(AccessibilityEvent event);
887 
888     /**
889      * Callback for interrupting the accessibility feedback.
890      */
onInterrupt()891     public abstract void onInterrupt();
892 
893     /**
894      * Dispatches service connection to internal components first, then the
895      * client code.
896      */
dispatchServiceConnected()897     private void dispatchServiceConnected() {
898         synchronized (mLock) {
899             for (int i = 0; i < mMagnificationControllers.size(); i++) {
900                 mMagnificationControllers.valueAt(i).onServiceConnectedLocked();
901             }
902             final AccessibilityServiceInfo info = getServiceInfo();
903             if (info != null) {
904                 updateInputMethod(info);
905                 mMotionEventSources = info.getMotionEventSources();
906             }
907         }
908         if (mSoftKeyboardController != null) {
909             mSoftKeyboardController.onServiceConnected();
910         }
911 
912         // The client gets to handle service connection last, after we've set
913         // up any state upon which their code may rely.
914         onServiceConnected();
915     }
916 
updateInputMethod(AccessibilityServiceInfo info)917     private void updateInputMethod(AccessibilityServiceInfo info) {
918         if (info != null) {
919             boolean requestIme = (info.flags
920                     & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0;
921             if (requestIme && !mInputMethodInitialized) {
922                 mInputMethod = onCreateInputMethod();
923                 mInputMethodInitialized = true;
924             } else if (!requestIme & mInputMethodInitialized) {
925                 mInputMethod = null;
926                 mInputMethodInitialized = false;
927             }
928         }
929     }
930 
931     /**
932      * This method is a part of the {@link AccessibilityService} lifecycle and is
933      * called after the system has successfully bound to the service. If is
934      * convenient to use this method for setting the {@link AccessibilityServiceInfo}.
935      *
936      * @see AccessibilityServiceInfo
937      * @see #setServiceInfo(AccessibilityServiceInfo)
938      */
onServiceConnected()939     protected void onServiceConnected() {
940 
941     }
942 
943     /**
944      * Called by {@link #onGesture(AccessibilityGestureEvent)} when the user performs a specific
945      * gesture on the default display.
946      *
947      * <strong>Note:</strong> To receive gestures an accessibility service must
948      * request that the device is in touch exploration mode by setting the
949      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE}
950      * flag.
951      *
952      * @param gestureId The unique id of the performed gesture.
953      *
954      * @return Whether the gesture was handled.
955      * @deprecated Override {@link #onGesture(AccessibilityGestureEvent)} instead.
956      *
957      * @see #GESTURE_SWIPE_UP
958      * @see #GESTURE_SWIPE_UP_AND_LEFT
959      * @see #GESTURE_SWIPE_UP_AND_DOWN
960      * @see #GESTURE_SWIPE_UP_AND_RIGHT
961      * @see #GESTURE_SWIPE_DOWN
962      * @see #GESTURE_SWIPE_DOWN_AND_LEFT
963      * @see #GESTURE_SWIPE_DOWN_AND_UP
964      * @see #GESTURE_SWIPE_DOWN_AND_RIGHT
965      * @see #GESTURE_SWIPE_LEFT
966      * @see #GESTURE_SWIPE_LEFT_AND_UP
967      * @see #GESTURE_SWIPE_LEFT_AND_RIGHT
968      * @see #GESTURE_SWIPE_LEFT_AND_DOWN
969      * @see #GESTURE_SWIPE_RIGHT
970      * @see #GESTURE_SWIPE_RIGHT_AND_UP
971      * @see #GESTURE_SWIPE_RIGHT_AND_LEFT
972      * @see #GESTURE_SWIPE_RIGHT_AND_DOWN
973      */
974     @Deprecated
onGesture(int gestureId)975     protected boolean onGesture(int gestureId) {
976         return false;
977     }
978 
979     /**
980      * Called by the system when the user performs a specific gesture on the
981      * specific touch screen.
982      *<p>
983      * <strong>Note:</strong> To receive gestures an accessibility service must
984      * request that the device is in touch exploration mode by setting the
985      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE}
986      * flag.
987      *<p>
988      * <strong>Note:</strong> The default implementation calls {@link #onGesture(int)} when the
989      * touch screen is default display.
990      *
991      * @param gestureEvent The information of gesture.
992      *
993      * @return Whether the gesture was handled.
994      *
995      */
onGesture(@onNull AccessibilityGestureEvent gestureEvent)996     public boolean onGesture(@NonNull AccessibilityGestureEvent gestureEvent) {
997         if (gestureEvent.getDisplayId() == Display.DEFAULT_DISPLAY) {
998             onGesture(gestureEvent.getGestureId());
999         }
1000         return false;
1001     }
1002 
1003     /**
1004      * Callback that allows an accessibility service to observe the key events
1005      * before they are passed to the rest of the system. This means that the events
1006      * are first delivered here before they are passed to the device policy, the
1007      * input method, or applications.
1008      * <p>
1009      * <strong>Note:</strong> It is important that key events are handled in such
1010      * a way that the event stream that would be passed to the rest of the system
1011      * is well-formed. For example, handling the down event but not the up event
1012      * and vice versa would generate an inconsistent event stream.
1013      * </p>
1014      * <p>
1015      * <strong>Note:</strong> The key events delivered in this method are copies
1016      * and modifying them will have no effect on the events that will be passed
1017      * to the system. This method is intended to perform purely filtering
1018      * functionality.
1019      * <p>
1020      *
1021      * @param event The event to be processed. This event is owned by the caller and cannot be used
1022      * after this method returns. Services wishing to use the event after this method returns should
1023      * make a copy.
1024      * @return If true then the event will be consumed and not delivered to
1025      *         applications, otherwise it will be delivered as usual.
1026      */
onKeyEvent(KeyEvent event)1027     protected boolean onKeyEvent(KeyEvent event) {
1028         return false;
1029     }
1030 
1031     /**
1032      * Callback that allows an accessibility service to observe generic {@link MotionEvent}s.
1033      * <p>
1034      * Prefer {@link TouchInteractionController} to observe and control touchscreen events,
1035      * including touch gestures. If this or any enabled service is using
1036      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} then
1037      * {@link #onMotionEvent} will not receive touchscreen events.
1038      * </p>
1039      * <p>
1040      * <strong>Note:</strong> The service must first request to listen to events using
1041      * {@link AccessibilityServiceInfo#setMotionEventSources}.
1042      * {@link MotionEvent}s from sources in {@link AccessibilityServiceInfo#getMotionEventSources()}
1043      * are not sent to the rest of the system. To stop listening to events from a given source, call
1044      * {@link AccessibilityServiceInfo#setMotionEventSources} with that source removed.
1045      * </p>
1046      * @param event The event to be processed.
1047      */
onMotionEvent(@onNull MotionEvent event)1048     public void onMotionEvent(@NonNull MotionEvent event) { }
1049 
1050     /**
1051      * Gets the windows on the screen of the default display. This method returns only the windows
1052      * that a sighted user can interact with, as opposed to all windows.
1053      * For example, if there is a modal dialog shown and the user cannot touch
1054      * anything behind it, then only the modal window will be reported
1055      * (assuming it is the top one). For convenience the returned windows
1056      * are ordered in a descending layer order, which is the windows that
1057      * are on top are reported first. Since the user can always
1058      * interact with the window that has input focus by typing, the focused
1059      * window is always returned (even if covered by a modal window).
1060      * <p>
1061      * <strong>Note:</strong> In order to access the windows your service has
1062      * to declare the capability to retrieve window content by setting the
1063      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
1064      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
1065      * Also the service has to opt-in to retrieve the interactive windows by
1066      * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
1067      * flag.
1068      * </p>
1069      *
1070      * @return The windows if there are windows and the service is can retrieve
1071      *         them, otherwise an empty list.
1072      */
getWindows()1073     public List<AccessibilityWindowInfo> getWindows() {
1074         return AccessibilityInteractionClient.getInstance(this).getWindows(mConnectionId);
1075     }
1076 
1077     /**
1078      * Gets the windows on the screen of all displays. This method returns only the windows
1079      * that a sighted user can interact with, as opposed to all windows.
1080      * For example, if there is a modal dialog shown and the user cannot touch
1081      * anything behind it, then only the modal window will be reported
1082      * (assuming it is the top one). For convenience the returned windows
1083      * are ordered in a descending layer order, which is the windows that
1084      * are on top are reported first. Since the user can always
1085      * interact with the window that has input focus by typing, the focused
1086      * window is always returned (even if covered by a modal window).
1087      * <p>
1088      * <strong>Note:</strong> In order to access the windows your service has
1089      * to declare the capability to retrieve window content by setting the
1090      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
1091      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
1092      * Also the service has to opt-in to retrieve the interactive windows by
1093      * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
1094      * flag.
1095      * </p>
1096      *
1097      * @return The windows of all displays if there are windows and the service is can retrieve
1098      *         them, otherwise an empty list. The key of SparseArray is display ID.
1099      */
1100     @NonNull
getWindowsOnAllDisplays()1101     public final SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
1102         return AccessibilityInteractionClient.getInstance(this).getWindowsOnAllDisplays(
1103                 mConnectionId);
1104     }
1105 
1106     /**
1107      * Gets the root node in the currently active window if this service
1108      * can retrieve window content. The active window is the one that the user
1109      * is currently touching or the window with input focus, if the user is not
1110      * touching any window. It could be from any logical display.
1111      * <p>
1112      * <strong>Note:</strong> In order to access the root node your service has
1113      * to declare the capability to retrieve window content by setting the
1114      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
1115      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
1116      * </p>
1117      *
1118      * @return The root node if this service can retrieve window content.
1119      * @see AccessibilityWindowInfo#isActive() for more explanation about the active window.
1120      */
getRootInActiveWindow()1121     public AccessibilityNodeInfo getRootInActiveWindow() {
1122         return getRootInActiveWindow(AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_HYBRID);
1123     }
1124 
1125     /**
1126      * Gets the root node in the currently active window if this service
1127      * can retrieve window content. The active window is the one that the user
1128      * is currently touching or the window with input focus, if the user is not
1129      * touching any window. It could be from any logical display.
1130      *
1131      * @param prefetchingStrategy the prefetching strategy.
1132      * @return The root node if this service can retrieve window content.
1133      *
1134      * @see #getRootInActiveWindow()
1135      * @see AccessibilityNodeInfo#getParent(int) for a description of prefetching.
1136      */
1137     @Nullable
getRootInActiveWindow( @ccessibilityNodeInfo.PrefetchingStrategy int prefetchingStrategy)1138     public AccessibilityNodeInfo getRootInActiveWindow(
1139             @AccessibilityNodeInfo.PrefetchingStrategy int prefetchingStrategy) {
1140         return AccessibilityInteractionClient.getInstance(this).getRootInActiveWindow(
1141                 mConnectionId, prefetchingStrategy);
1142     }
1143 
1144     /**
1145      * Disables the service. After calling this method, the service will be disabled and settings
1146      * will show that it is turned off.
1147      */
disableSelf()1148     public final void disableSelf() {
1149         final IAccessibilityServiceConnection connection =
1150                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
1151         if (connection != null) {
1152             try {
1153                 connection.disableSelf();
1154             } catch (RemoteException re) {
1155                 throw new RuntimeException(re);
1156             }
1157         }
1158     }
1159 
1160     @NonNull
1161     @Override
createDisplayContext(Display display)1162     public Context createDisplayContext(Display display) {
1163         return new AccessibilityContext(super.createDisplayContext(display), mConnectionId);
1164     }
1165 
1166     @NonNull
1167     @Override
createWindowContext(int type, @Nullable Bundle options)1168     public Context createWindowContext(int type, @Nullable Bundle options) {
1169         final Context context = super.createWindowContext(type, options);
1170         if (type != TYPE_ACCESSIBILITY_OVERLAY) {
1171             return context;
1172         }
1173         return new AccessibilityContext(context, mConnectionId);
1174     }
1175 
1176     @NonNull
1177     @Override
createWindowContext(@onNull Display display, int type, @Nullable Bundle options)1178     public Context createWindowContext(@NonNull Display display, int type,
1179             @Nullable Bundle options) {
1180         final Context context = super.createWindowContext(display, type, options);
1181         if (type != TYPE_ACCESSIBILITY_OVERLAY) {
1182             return context;
1183         }
1184         return new AccessibilityContext(context, mConnectionId);
1185     }
1186 
1187     /**
1188      * Returns the magnification controller, which may be used to query and
1189      * modify the state of display magnification.
1190      * <p>
1191      * <strong>Note:</strong> In order to control magnification, your service
1192      * must declare the capability by setting the
1193      * {@link android.R.styleable#AccessibilityService_canControlMagnification}
1194      * property in its meta-data. For more information, see
1195      * {@link #SERVICE_META_DATA}.
1196      *
1197      * @return the magnification controller
1198      */
1199     @NonNull
getMagnificationController()1200     public final MagnificationController getMagnificationController() {
1201         return getMagnificationController(Display.DEFAULT_DISPLAY);
1202     }
1203 
1204     /**
1205      * Returns the magnification controller of specified logical display, which may be used to
1206      * query and modify the state of display magnification.
1207      * <p>
1208      * <strong>Note:</strong> In order to control magnification, your service
1209      * must declare the capability by setting the
1210      * {@link android.R.styleable#AccessibilityService_canControlMagnification}
1211      * property in its meta-data. For more information, see
1212      * {@link #SERVICE_META_DATA}.
1213      *
1214      * @param displayId The logic display id, use {@link Display#DEFAULT_DISPLAY} for
1215      *                  default display.
1216      * @return the magnification controller
1217      *
1218      * @hide
1219      */
1220     @NonNull
getMagnificationController(int displayId)1221     public final MagnificationController getMagnificationController(int displayId) {
1222         synchronized (mLock) {
1223             MagnificationController controller = mMagnificationControllers.get(displayId);
1224             if (controller == null) {
1225                 controller = new MagnificationController(this, mLock, displayId);
1226                 mMagnificationControllers.put(displayId, controller);
1227             }
1228             return controller;
1229         }
1230     }
1231 
1232     /**
1233      * Get the controller for fingerprint gestures. This feature requires {@link
1234      * AccessibilityServiceInfo#CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES}.
1235      *
1236      *<strong>Note: </strong> The service must be connected before this method is called.
1237      *
1238      * @return The controller for fingerprint gestures, or {@code null} if gestures are unavailable.
1239      */
1240     @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT)
getFingerprintGestureController()1241     public final @NonNull FingerprintGestureController getFingerprintGestureController() {
1242         if (mFingerprintGestureController == null) {
1243             mFingerprintGestureController = new FingerprintGestureController(
1244                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId));
1245         }
1246         return mFingerprintGestureController;
1247     }
1248 
1249     /**
1250      * Dispatch a gesture to the touch screen. Any gestures currently in progress, whether from
1251      * the user, this service, or another service, will be cancelled.
1252      * <p>
1253      * The gesture will be dispatched as if it were performed directly on the screen by a user, so
1254      * the events may be affected by features such as magnification and explore by touch.
1255      * </p>
1256      * <p>
1257      * <strong>Note:</strong> In order to dispatch gestures, your service
1258      * must declare the capability by setting the
1259      * {@link android.R.styleable#AccessibilityService_canPerformGestures}
1260      * property in its meta-data. For more information, see
1261      * {@link #SERVICE_META_DATA}.
1262      * </p>
1263      * <p>Since many apps do not appropriately support {@link AccessibilityAction#ACTION_CLICK},
1264      * if this action fails on an element that should be clickable, a service that is not a screen
1265      * reader may send a tap directly to the element as a fallback. The example below
1266      * demonstrates this fallback using the gesture dispatch APIs:
1267      *
1268      * <pre class="prettyprint"><code>
1269      *     private void tap(PointF point) {
1270      *         StrokeDescription tap =  new StrokeDescription(path(point), 0,
1271      *         ViewConfiguration.getTapTimeout());
1272      *         GestureDescription.Builder builder = new GestureDescription.Builder();
1273      *         builder.addStroke(tap);
1274      *         dispatchGesture(builder.build(), null, null);
1275      *     }
1276      *</code>
1277      * </pre>
1278      * @param gesture The gesture to dispatch
1279      * @param callback The object to call back when the status of the gesture is known. If
1280      * {@code null}, no status is reported.
1281      * @param handler The handler on which to call back the {@code callback} object. If
1282      * {@code null}, the object is called back on the service's main thread.
1283      *
1284      * @return {@code true} if the gesture is dispatched, {@code false} if not.
1285      */
dispatchGesture(@onNull GestureDescription gesture, @Nullable GestureResultCallback callback, @Nullable Handler handler)1286     public final boolean dispatchGesture(@NonNull GestureDescription gesture,
1287             @Nullable GestureResultCallback callback,
1288             @Nullable Handler handler) {
1289         final IAccessibilityServiceConnection connection =
1290                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
1291         if (connection == null) {
1292             return false;
1293         }
1294         int sampleTimeMs = calculateGestureSampleTimeMs(gesture.getDisplayId());
1295         List<GestureDescription.GestureStep> steps =
1296                 MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, sampleTimeMs);
1297         try {
1298             synchronized (mLock) {
1299                 mGestureStatusCallbackSequence++;
1300                 if (callback != null) {
1301                     if (mGestureStatusCallbackInfos == null) {
1302                         mGestureStatusCallbackInfos = new SparseArray<>();
1303                     }
1304                     GestureResultCallbackInfo callbackInfo = new GestureResultCallbackInfo(gesture,
1305                             callback, handler);
1306                     mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo);
1307                 }
1308                 connection.dispatchGesture(mGestureStatusCallbackSequence,
1309                         new ParceledListSlice<>(steps), gesture.getDisplayId());
1310             }
1311         } catch (RemoteException re) {
1312             throw new RuntimeException(re);
1313         }
1314         return true;
1315     }
1316 
1317     /**
1318      * Returns the sample time in millis of gesture steps for the current display.
1319      *
1320      * <p>For gestures to be smooth they should line up with the refresh rate of the display.
1321      * On versions of Android before R, the sample time was fixed to 100ms.
1322      */
calculateGestureSampleTimeMs(int displayId)1323     private int calculateGestureSampleTimeMs(int displayId) {
1324         if (getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.Q) {
1325             return 100;
1326         }
1327         Display display = getSystemService(DisplayManager.class).getDisplay(
1328                 displayId);
1329         if (display == null) {
1330             return 100;
1331         }
1332         int msPerSecond = 1000;
1333         int sampleTimeMs = (int) (msPerSecond / display.getRefreshRate());
1334         if (sampleTimeMs < 1) {
1335             // Should be impossible, but do not return 0.
1336             return 100;
1337         }
1338         return sampleTimeMs;
1339     }
1340 
onPerformGestureResult(int sequence, final boolean completedSuccessfully)1341     void onPerformGestureResult(int sequence, final boolean completedSuccessfully) {
1342         if (mGestureStatusCallbackInfos == null) {
1343             return;
1344         }
1345         GestureResultCallbackInfo callbackInfo;
1346         synchronized (mLock) {
1347             callbackInfo = mGestureStatusCallbackInfos.get(sequence);
1348             mGestureStatusCallbackInfos.remove(sequence);
1349         }
1350         final GestureResultCallbackInfo finalCallbackInfo = callbackInfo;
1351         if ((callbackInfo != null) && (callbackInfo.gestureDescription != null)
1352                 && (callbackInfo.callback != null)) {
1353             if (callbackInfo.handler != null) {
1354                 callbackInfo.handler.post(new Runnable() {
1355                     @Override
1356                     public void run() {
1357                         if (completedSuccessfully) {
1358                             finalCallbackInfo.callback
1359                                     .onCompleted(finalCallbackInfo.gestureDescription);
1360                         } else {
1361                             finalCallbackInfo.callback
1362                                     .onCancelled(finalCallbackInfo.gestureDescription);
1363                         }
1364                     }
1365                 });
1366                 return;
1367             }
1368             if (completedSuccessfully) {
1369                 callbackInfo.callback.onCompleted(callbackInfo.gestureDescription);
1370             } else {
1371                 callbackInfo.callback.onCancelled(callbackInfo.gestureDescription);
1372             }
1373         }
1374     }
1375 
onMagnificationChanged(int displayId, @NonNull Region region, MagnificationConfig config)1376     private void onMagnificationChanged(int displayId, @NonNull Region region,
1377             MagnificationConfig config) {
1378         MagnificationController controller;
1379         synchronized (mLock) {
1380             controller = mMagnificationControllers.get(displayId);
1381         }
1382         if (controller != null) {
1383             controller.dispatchMagnificationChanged(region, config);
1384         }
1385     }
1386 
1387     /**
1388      * Callback for fingerprint gesture handling
1389      * @param active If gesture detection is active
1390      */
onFingerprintCapturingGesturesChanged(boolean active)1391     private void onFingerprintCapturingGesturesChanged(boolean active) {
1392         getFingerprintGestureController().onGestureDetectionActiveChanged(active);
1393     }
1394 
1395     /**
1396      * Callback for fingerprint gesture handling
1397      * @param gesture The identifier for the gesture performed
1398      */
onFingerprintGesture(int gesture)1399     private void onFingerprintGesture(int gesture) {
1400         getFingerprintGestureController().onGesture(gesture);
1401     }
1402 
1403     /** @hide */
1404     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
getConnectionId()1405     public int getConnectionId() {
1406         return mConnectionId;
1407     }
1408 
1409     /**
1410      * Used to control and query the state of display magnification.
1411      */
1412     public static final class MagnificationController {
1413         private final AccessibilityService mService;
1414         private final int mDisplayId;
1415 
1416         /**
1417          * Map of listeners to their handlers. Lazily created when adding the
1418          * first magnification listener.
1419          */
1420         private ArrayMap<OnMagnificationChangedListener, Handler> mListeners;
1421         private final Object mLock;
1422 
MagnificationController(@onNull AccessibilityService service, @NonNull Object lock, int displayId)1423         MagnificationController(@NonNull AccessibilityService service, @NonNull Object lock,
1424                 int displayId) {
1425             mService = service;
1426             mLock = lock;
1427             mDisplayId = displayId;
1428         }
1429 
1430         /**
1431          * Called when the service is connected.
1432          */
onServiceConnectedLocked()1433         void onServiceConnectedLocked() {
1434             if (mListeners != null && !mListeners.isEmpty()) {
1435                 setMagnificationCallbackEnabled(true);
1436             }
1437         }
1438 
1439         /**
1440          * Adds the specified change listener to the list of magnification
1441          * change listeners. The callback will occur on the service's main
1442          * thread.
1443          *
1444          * @param listener the listener to add, must be non-{@code null}
1445          */
addListener(@onNull OnMagnificationChangedListener listener)1446         public void addListener(@NonNull OnMagnificationChangedListener listener) {
1447             addListener(listener, null);
1448         }
1449 
1450         /**
1451          * Adds the specified change listener to the list of magnification
1452          * change listeners. The callback will occur on the specified
1453          * {@link Handler}'s thread, or on the service's main thread if the
1454          * handler is {@code null}.
1455          *
1456          * @param listener the listener to add, must be non-null
1457          * @param handler the handler on which the callback should execute, or
1458          *        {@code null} to execute on the service's main thread
1459          */
addListener(@onNull OnMagnificationChangedListener listener, @Nullable Handler handler)1460         public void addListener(@NonNull OnMagnificationChangedListener listener,
1461                 @Nullable Handler handler) {
1462             synchronized (mLock) {
1463                 if (mListeners == null) {
1464                     mListeners = new ArrayMap<>();
1465                 }
1466 
1467                 final boolean shouldEnableCallback = mListeners.isEmpty();
1468                 mListeners.put(listener, handler);
1469 
1470                 if (shouldEnableCallback) {
1471                     // This may fail if the service is not connected yet, but if we
1472                     // still have listeners when it connects then we can try again.
1473                     setMagnificationCallbackEnabled(true);
1474                 }
1475             }
1476         }
1477 
1478         /**
1479          * Removes the specified change listener from the list of magnification change listeners.
1480          *
1481          * @param listener the listener to remove, must be non-null
1482          * @return {@code true} if the listener was removed, {@code false} otherwise
1483          */
removeListener(@onNull OnMagnificationChangedListener listener)1484         public boolean removeListener(@NonNull OnMagnificationChangedListener listener) {
1485             if (mListeners == null) {
1486                 return false;
1487             }
1488 
1489             synchronized (mLock) {
1490                 final int keyIndex = mListeners.indexOfKey(listener);
1491                 final boolean hasKey = keyIndex >= 0;
1492                 if (hasKey) {
1493                     mListeners.removeAt(keyIndex);
1494                 }
1495 
1496                 if (hasKey && mListeners.isEmpty()) {
1497                     // We just removed the last listener, so we don't need
1498                     // callbacks from the service anymore.
1499                     setMagnificationCallbackEnabled(false);
1500                 }
1501 
1502                 return hasKey;
1503             }
1504         }
1505 
setMagnificationCallbackEnabled(boolean enabled)1506         private void setMagnificationCallbackEnabled(boolean enabled) {
1507             final IAccessibilityServiceConnection connection =
1508                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1509                             mService.mConnectionId);
1510             if (connection != null) {
1511                 try {
1512                     connection.setMagnificationCallbackEnabled(mDisplayId, enabled);
1513                 } catch (RemoteException re) {
1514                     throw new RuntimeException(re);
1515                 }
1516             }
1517         }
1518 
1519         /**
1520          * Dispatches magnification changes to any registered listeners. This
1521          * should be called on the service's main thread.
1522          */
dispatchMagnificationChanged(final @NonNull Region region, final MagnificationConfig config)1523         void dispatchMagnificationChanged(final @NonNull Region region,
1524                 final MagnificationConfig config) {
1525             final ArrayMap<OnMagnificationChangedListener, Handler> entries;
1526             synchronized (mLock) {
1527                 if (mListeners == null || mListeners.isEmpty()) {
1528                     Slog.d(LOG_TAG, "Received magnification changed "
1529                             + "callback with no listeners registered!");
1530                     setMagnificationCallbackEnabled(false);
1531                     return;
1532                 }
1533 
1534                 // Listeners may remove themselves. Perform a shallow copy to avoid concurrent
1535                 // modification.
1536                 entries = new ArrayMap<>(mListeners);
1537             }
1538 
1539             for (int i = 0, count = entries.size(); i < count; i++) {
1540                 final OnMagnificationChangedListener listener = entries.keyAt(i);
1541                 final Handler handler = entries.valueAt(i);
1542                 if (handler != null) {
1543                     handler.post(() -> {
1544                         listener.onMagnificationChanged(MagnificationController.this,
1545                                 region, config);
1546                     });
1547                 } else {
1548                     // We're already on the main thread, just run the listener.
1549                     listener.onMagnificationChanged(this, region, config);
1550                 }
1551             }
1552         }
1553 
1554         /**
1555          * Gets the {@link MagnificationConfig} of the controlling magnifier on the display.
1556          * <p>
1557          * <strong>Note:</strong> If the service is not yet connected (e.g.
1558          * {@link AccessibilityService#onServiceConnected()} has not yet been
1559          * called) or the service has been disconnected, this method will
1560          * return null.
1561          * </p>
1562          *
1563          * @return the magnification config that the service controls
1564          */
getMagnificationConfig()1565         public @Nullable MagnificationConfig getMagnificationConfig() {
1566             final IAccessibilityServiceConnection connection =
1567                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1568                             mService.mConnectionId);
1569             if (connection != null) {
1570                 try {
1571                     return connection.getMagnificationConfig(mDisplayId);
1572                 } catch (RemoteException re) {
1573                     Log.w(LOG_TAG, "Failed to obtain magnification config", re);
1574                     re.rethrowFromSystemServer();
1575                 }
1576             }
1577             return null;
1578         }
1579 
1580         /**
1581          * Returns the current magnification scale.
1582          * <p>
1583          * <strong>Note:</strong> If the service is not yet connected (e.g.
1584          * {@link AccessibilityService#onServiceConnected()} has not yet been
1585          * called) or the service has been disconnected, this method will
1586          * return a default value of {@code 1.0f}.
1587          * </p>
1588          * <p>
1589          * <strong>Note:</strong> This legacy API gets the scale of full-screen
1590          * magnification. To get the scale of the current controlling magnifier,
1591          * use {@link #getMagnificationConfig} instead.
1592          * </p>
1593          *
1594          * @return the current magnification scale
1595          * @deprecated Use {@link #getMagnificationConfig()} instead
1596          */
1597         @Deprecated
getScale()1598         public float getScale() {
1599             final IAccessibilityServiceConnection connection =
1600                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1601                             mService.mConnectionId);
1602             if (connection != null) {
1603                 try {
1604                     return connection.getMagnificationScale(mDisplayId);
1605                 } catch (RemoteException re) {
1606                     Log.w(LOG_TAG, "Failed to obtain scale", re);
1607                     re.rethrowFromSystemServer();
1608                 }
1609             }
1610             return 1.0f;
1611         }
1612 
1613         /**
1614          * Returns the unscaled screen-relative X coordinate of the focal
1615          * center of the magnified region. This is the point around which
1616          * zooming occurs and is guaranteed to lie within the magnified
1617          * region.
1618          * <p>
1619          * <strong>Note:</strong> If the service is not yet connected (e.g.
1620          * {@link AccessibilityService#onServiceConnected()} has not yet been
1621          * called) or the service has been disconnected, this method will
1622          * return a default value of {@code 0.0f}.
1623          * </p>
1624          * <p>
1625          * <strong>Note:</strong> This legacy API gets the center position of full-screen
1626          * magnification. To get the magnification center of the current controlling magnifier,
1627          * use {@link #getMagnificationConfig} instead.
1628          * </p>
1629          *
1630          * @return the unscaled screen-relative X coordinate of the center of
1631          *         the magnified region
1632          * @deprecated Use {@link #getMagnificationConfig()} instead
1633          */
1634         @Deprecated
getCenterX()1635         public float getCenterX() {
1636             final IAccessibilityServiceConnection connection =
1637                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1638                             mService.mConnectionId);
1639             if (connection != null) {
1640                 try {
1641                     return connection.getMagnificationCenterX(mDisplayId);
1642                 } catch (RemoteException re) {
1643                     Log.w(LOG_TAG, "Failed to obtain center X", re);
1644                     re.rethrowFromSystemServer();
1645                 }
1646             }
1647             return 0.0f;
1648         }
1649 
1650         /**
1651          * Returns the unscaled screen-relative Y coordinate of the focal
1652          * center of the magnified region. This is the point around which
1653          * zooming occurs and is guaranteed to lie within the magnified
1654          * region.
1655          * <p>
1656          * <strong>Note:</strong> If the service is not yet connected (e.g.
1657          * {@link AccessibilityService#onServiceConnected()} has not yet been
1658          * called) or the service has been disconnected, this method will
1659          * return a default value of {@code 0.0f}.
1660          * </p>
1661          * <p>
1662          * <strong>Note:</strong> This legacy API gets the center position of full-screen
1663          * magnification. To get the magnification center of the current controlling magnifier,
1664          * use {@link #getMagnificationConfig} instead.
1665          * </p>
1666          *
1667          * @return the unscaled screen-relative Y coordinate of the center of
1668          *         the magnified region
1669          * @deprecated Use {@link #getMagnificationConfig()} instead
1670          */
1671         @Deprecated
getCenterY()1672         public float getCenterY() {
1673             final IAccessibilityServiceConnection connection =
1674                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1675                             mService.mConnectionId);
1676             if (connection != null) {
1677                 try {
1678                     return connection.getMagnificationCenterY(mDisplayId);
1679                 } catch (RemoteException re) {
1680                     Log.w(LOG_TAG, "Failed to obtain center Y", re);
1681                     re.rethrowFromSystemServer();
1682                 }
1683             }
1684             return 0.0f;
1685         }
1686 
1687         /**
1688          * Returns the region of the screen currently active for magnification. Changes to
1689          * magnification scale and center only affect this portion of the screen. The rest of the
1690          * screen, for example input methods, cannot be magnified. This region is relative to the
1691          * unscaled screen and is independent of the scale and center point.
1692          * <p>
1693          * The returned region will be empty if magnification is not active. Magnification is active
1694          * if magnification gestures are enabled or if a service is running that can control
1695          * magnification.
1696          * <p>
1697          * <strong>Note:</strong> If the service is not yet connected (e.g.
1698          * {@link AccessibilityService#onServiceConnected()} has not yet been
1699          * called) or the service has been disconnected, this method will
1700          * return an empty region.
1701          * </p>
1702          * <p>
1703          * <strong>Note:</strong> This legacy API gets the magnification region of full-screen
1704          * magnification. To get the magnification region of the current controlling magnifier,
1705          * use {@link #getCurrentMagnificationRegion()} instead.
1706          * </p>
1707          *
1708          * @return the region of the screen currently active for magnification, or an empty region
1709          * if magnification is not active.
1710          * @deprecated Use {@link #getCurrentMagnificationRegion()} instead
1711          */
1712         @Deprecated
1713         @NonNull
getMagnificationRegion()1714         public Region getMagnificationRegion() {
1715             final IAccessibilityServiceConnection connection =
1716                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1717                             mService.mConnectionId);
1718             if (connection != null) {
1719                 try {
1720                     return connection.getMagnificationRegion(mDisplayId);
1721                 } catch (RemoteException re) {
1722                     Log.w(LOG_TAG, "Failed to obtain magnified region", re);
1723                     re.rethrowFromSystemServer();
1724                 }
1725             }
1726             return Region.obtain();
1727         }
1728 
1729         /**
1730          * Returns the region of the screen currently active for magnification if the
1731          * controlling magnification is {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN}.
1732          * Returns the region of screen projected on the magnification window if the
1733          * controlling magnification is {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW}.
1734          *
1735          * <p>
1736          * If the controlling mode is {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN},
1737          * the returned region will be empty if the magnification is
1738          * not active. And the magnification is active if magnification gestures are enabled
1739          * or if a service is running that can control magnification.
1740          * </p><p>
1741          * If the controlling mode is {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW},
1742          * the returned region will be empty if the magnification is not activated.
1743          * </p><p>
1744          * <strong>Note:</strong> If the service is not yet connected (e.g.
1745          * {@link AccessibilityService#onServiceConnected()} has not yet been
1746          * called) or the service has been disconnected, this method will
1747          * return an empty region.
1748          * </p>
1749          *
1750          * @return the magnification region of the currently controlling magnification
1751          */
1752         @NonNull
getCurrentMagnificationRegion()1753         public Region getCurrentMagnificationRegion() {
1754             final IAccessibilityServiceConnection connection =
1755                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1756                             mService.mConnectionId);
1757             if (connection != null) {
1758                 try {
1759                     return connection.getCurrentMagnificationRegion(mDisplayId);
1760                 } catch (RemoteException re) {
1761                     Log.w(LOG_TAG, "Failed to obtain the current magnified region", re);
1762                     re.rethrowFromSystemServer();
1763                 }
1764             }
1765             return Region.obtain();
1766         }
1767 
1768         /**
1769          * Resets magnification scale and center to their default (e.g. no
1770          * magnification) values.
1771          * <p>
1772          * <strong>Note:</strong> If the service is not yet connected (e.g.
1773          * {@link AccessibilityService#onServiceConnected()} has not yet been
1774          * called) or the service has been disconnected, this method will have
1775          * no effect and return {@code false}.
1776          * <p>
1777          * <strong>Note:</strong> This legacy API reset full-screen magnification.
1778          * To reset the current controlling magnifier, use
1779          * {@link #resetCurrentMagnification(boolean)} ()} instead.
1780          * </p>
1781          *
1782          * @param animate {@code true} to animate from the current scale and
1783          *                center or {@code false} to reset the scale and center
1784          *                immediately
1785          * @return {@code true} on success, {@code false} on failure
1786          */
reset(boolean animate)1787         public boolean reset(boolean animate) {
1788             final IAccessibilityServiceConnection connection =
1789                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1790                             mService.mConnectionId);
1791             if (connection != null) {
1792                 try {
1793                     return connection.resetMagnification(mDisplayId, animate);
1794                 } catch (RemoteException re) {
1795                     Log.w(LOG_TAG, "Failed to reset", re);
1796                     re.rethrowFromSystemServer();
1797                 }
1798             }
1799             return false;
1800         }
1801 
1802         /**
1803          * Resets magnification scale and center of the controlling magnification
1804          * to their default (e.g. no magnification) values.
1805          * <p>
1806          * <strong>Note:</strong> If the service is not yet connected (e.g.
1807          * {@link AccessibilityService#onServiceConnected()} has not yet been
1808          * called) or the service has been disconnected, this method will have
1809          * no effect and return {@code false}.
1810          * </p>
1811          *
1812          * @param animate {@code true} to animate from the current scale and
1813          *                center or {@code false} to reset the scale and center
1814          *                immediately
1815          * @return {@code true} on success, {@code false} on failure
1816          */
resetCurrentMagnification(boolean animate)1817         public boolean resetCurrentMagnification(boolean animate) {
1818             final IAccessibilityServiceConnection connection =
1819                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1820                             mService.mConnectionId);
1821             if (connection != null) {
1822                 try {
1823                     return connection.resetCurrentMagnification(mDisplayId, animate);
1824                 } catch (RemoteException re) {
1825                     Log.w(LOG_TAG, "Failed to reset", re);
1826                     re.rethrowFromSystemServer();
1827                 }
1828             }
1829             return false;
1830         }
1831 
1832         /**
1833          * Sets the {@link MagnificationConfig}. The service controls the magnification by
1834          * setting the config.
1835          * <p>
1836          * <strong>Note:</strong> If the service is not yet connected (e.g.
1837          * {@link AccessibilityService#onServiceConnected()} has not yet been
1838          * called) or the service has been disconnected, this method will have
1839          * no effect and return {@code false}.
1840          * </p>
1841          *
1842          * @param config the magnification config
1843          * @param animate {@code true} to animate from the current spec or
1844          *                {@code false} to set the spec immediately
1845          * @return {@code true} on success, {@code false} on failure
1846          */
setMagnificationConfig(@onNull MagnificationConfig config, boolean animate)1847         public boolean setMagnificationConfig(@NonNull MagnificationConfig config,
1848                 boolean animate) {
1849             final IAccessibilityServiceConnection connection =
1850                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1851                             mService.mConnectionId);
1852             if (connection != null) {
1853                 try {
1854                     return connection.setMagnificationConfig(mDisplayId, config, animate);
1855                 } catch (RemoteException re) {
1856                     Log.w(LOG_TAG, "Failed to set magnification config", re);
1857                     re.rethrowFromSystemServer();
1858                 }
1859             }
1860             return false;
1861         }
1862 
1863         /**
1864          * Sets the magnification scale.
1865          * <p>
1866          * <strong>Note:</strong> If the service is not yet connected (e.g.
1867          * {@link AccessibilityService#onServiceConnected()} has not yet been
1868          * called) or the service has been disconnected, this method will have
1869          * no effect and return {@code false}.
1870          * <p>
1871          * <strong>Note:</strong> This legacy API sets the scale of full-screen
1872          * magnification. To set the scale of the specified magnifier,
1873          * use {@link #setMagnificationConfig} instead.
1874          * </p>
1875          *
1876          * @param scale the magnification scale to set, must be >= 1 and <= 8
1877          * @param animate {@code true} to animate from the current scale or
1878          *                {@code false} to set the scale immediately
1879          * @return {@code true} on success, {@code false} on failure
1880          * @deprecated Use {@link #setMagnificationConfig(MagnificationConfig, boolean)} instead
1881          */
1882         @Deprecated
setScale(float scale, boolean animate)1883         public boolean setScale(float scale, boolean animate) {
1884             final IAccessibilityServiceConnection connection =
1885                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1886                             mService.mConnectionId);
1887             if (connection != null) {
1888                 try {
1889                     final MagnificationConfig config = new MagnificationConfig.Builder()
1890                             .setMode(MAGNIFICATION_MODE_FULLSCREEN)
1891                             .setScale(scale).build();
1892                     return connection.setMagnificationConfig(mDisplayId, config, animate);
1893                 } catch (RemoteException re) {
1894                     Log.w(LOG_TAG, "Failed to set scale", re);
1895                     re.rethrowFromSystemServer();
1896                 }
1897             }
1898             return false;
1899         }
1900 
1901         /**
1902          * Sets the center of the magnified viewport.
1903          * <p>
1904          * <strong>Note:</strong> If the service is not yet connected (e.g.
1905          * {@link AccessibilityService#onServiceConnected()} has not yet been
1906          * called) or the service has been disconnected, this method will have
1907          * no effect and return {@code false}.
1908          * </p>
1909          * <p>
1910          * <strong>Note:</strong> This legacy API sets the center of full-screen
1911          * magnification. To set the center of the specified magnifier,
1912          * use {@link #setMagnificationConfig} instead.
1913          * </p>
1914          *
1915          * @param centerX the unscaled screen-relative X coordinate on which to
1916          *                center the viewport
1917          * @param centerY the unscaled screen-relative Y coordinate on which to
1918          *                center the viewport
1919          * @param animate {@code true} to animate from the current viewport
1920          *                center or {@code false} to set the center immediately
1921          * @return {@code true} on success, {@code false} on failure
1922          * @deprecated Use {@link #setMagnificationConfig(MagnificationConfig, boolean)} instead
1923          */
1924         @Deprecated
setCenter(float centerX, float centerY, boolean animate)1925         public boolean setCenter(float centerX, float centerY, boolean animate) {
1926             final IAccessibilityServiceConnection connection =
1927                     AccessibilityInteractionClient.getInstance(mService).getConnection(
1928                             mService.mConnectionId);
1929             if (connection != null) {
1930                 try {
1931                     final MagnificationConfig config = new MagnificationConfig.Builder()
1932                             .setMode(MAGNIFICATION_MODE_FULLSCREEN)
1933                             .setCenterX(centerX).setCenterY(centerY).build();
1934                     return connection.setMagnificationConfig(mDisplayId, config, animate);
1935                 } catch (RemoteException re) {
1936                     Log.w(LOG_TAG, "Failed to set center", re);
1937                     re.rethrowFromSystemServer();
1938                 }
1939             }
1940             return false;
1941         }
1942 
1943         /**
1944          * Listener for changes in the state of magnification.
1945          */
1946         public interface OnMagnificationChangedListener {
1947             /**
1948              * Called when the magnified region, scale, or center changes.
1949              * <p>
1950              * <strong>Note:</strong> This legacy callback notifies only full-screen
1951              * magnification change.
1952              * </p>
1953              *
1954              * @param controller the magnification controller
1955              * @param region the magnification region
1956              * @param scale the new scale
1957              * @param centerX the new X coordinate, in unscaled coordinates, around which
1958              * magnification is focused
1959              * @param centerY the new Y coordinate, in unscaled coordinates, around which
1960              * magnification is focused
1961              * @deprecated Override
1962              * {@link #onMagnificationChanged(MagnificationController, Region, MagnificationConfig)}
1963              * instead
1964              */
1965             @Deprecated
onMagnificationChanged(@onNull MagnificationController controller, @NonNull Region region, float scale, float centerX, float centerY)1966             void onMagnificationChanged(@NonNull MagnificationController controller,
1967                     @NonNull Region region, float scale, float centerX, float centerY);
1968 
1969             /**
1970              * Called when the magnified region, mode, scale, or center changes of
1971              * all magnification modes.
1972              * <p>
1973              * <strong>Note:</strong> This method can be overridden to listen to the
1974              * magnification changes of all magnification modes then the legacy callback
1975              * would not receive the notifications.
1976              * Skipping calling super when overriding this method results in
1977              * {@link #onMagnificationChanged(MagnificationController, Region, float, float, float)}
1978              * not getting called.
1979              * </p>
1980              *
1981              * @param controller the magnification controller
1982              * @param region the magnification region
1983              *               If the config mode is
1984              *               {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN},
1985              *               it is the region of the screen currently active for magnification.
1986              *               that is the same region as {@link #getMagnificationRegion()}.
1987              *               If the config mode is
1988              *               {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW},
1989              *               it is the region of screen projected on the magnification window.
1990              * @param config The magnification config. That has the controlling magnification
1991              *               mode, the new scale and the new screen-relative center position
1992              */
onMagnificationChanged(@onNull MagnificationController controller, @NonNull Region region, @NonNull MagnificationConfig config)1993             default void onMagnificationChanged(@NonNull MagnificationController controller,
1994                     @NonNull Region region, @NonNull MagnificationConfig config) {
1995                 if (config.getMode() == MAGNIFICATION_MODE_FULLSCREEN) {
1996                     onMagnificationChanged(controller, region,
1997                             config.getScale(), config.getCenterX(), config.getCenterY());
1998                 }
1999             }
2000         }
2001     }
2002 
2003     /**
2004      * Returns the soft keyboard controller, which may be used to query and modify the soft keyboard
2005      * show mode.
2006      *
2007      * @return the soft keyboard controller
2008      */
2009     @NonNull
getSoftKeyboardController()2010     public final SoftKeyboardController getSoftKeyboardController() {
2011         synchronized (mLock) {
2012             if (mSoftKeyboardController == null) {
2013                 mSoftKeyboardController = new SoftKeyboardController(this, mLock);
2014             }
2015             return mSoftKeyboardController;
2016         }
2017     }
2018 
2019     /**
2020      * The default implementation returns our default {@link InputMethod}. Subclasses can override
2021      * it to provide their own customized version. Accessibility services need to set the
2022      * {@link AccessibilityServiceInfo#FLAG_INPUT_METHOD_EDITOR} flag to use input method APIs.
2023      *
2024      * @return the InputMethod.
2025      */
2026     @NonNull
onCreateInputMethod()2027     public InputMethod onCreateInputMethod() {
2028         return new InputMethod(this);
2029     }
2030 
2031     /**
2032      * Returns the InputMethod instance after the system calls {@link #onCreateInputMethod()},
2033      * which may be used to input text or get editable text selection change notifications. It will
2034      * return null if the accessibility service doesn't set the
2035      * {@link AccessibilityServiceInfo#FLAG_INPUT_METHOD_EDITOR} flag or the system doesn't call
2036      * {@link #onCreateInputMethod()}.
2037      *
2038      * @return the InputMethod instance
2039      */
2040     @Nullable
getInputMethod()2041     public final InputMethod getInputMethod() {
2042         return mInputMethod;
2043     }
2044 
onSoftKeyboardShowModeChanged(int showMode)2045     private void onSoftKeyboardShowModeChanged(int showMode) {
2046         if (mSoftKeyboardController != null) {
2047             mSoftKeyboardController.dispatchSoftKeyboardShowModeChanged(showMode);
2048         }
2049     }
2050 
2051     /**
2052      * Used to control, query, and listen for changes to the soft keyboard show mode.
2053      * <p>
2054      * Accessibility services may request to override the decisions normally made about whether or
2055      * not the soft keyboard is shown.
2056      * <p>
2057      * If multiple services make conflicting requests, the last request is honored. A service may
2058      * register a listener to find out if the mode has changed under it.
2059      * <p>
2060      * If the user takes action to override the behavior behavior requested by an accessibility
2061      * service, the user's request takes precendence, the show mode will be reset to
2062      * {@link AccessibilityService#SHOW_MODE_AUTO}, and services will no longer be able to control
2063      * that aspect of the soft keyboard's behavior.
2064      * <p>
2065      * Note: Because soft keyboards are independent apps, the framework does not have total control
2066      * over their behavior. They may choose to show themselves, or not, without regard to requests
2067      * made here. So the framework will make a best effort to deliver the behavior requested, but
2068      * cannot guarantee success.
2069      *
2070      * @see AccessibilityService#SHOW_MODE_AUTO
2071      * @see AccessibilityService#SHOW_MODE_HIDDEN
2072      * @see AccessibilityService#SHOW_MODE_IGNORE_HARD_KEYBOARD
2073      */
2074     public static final class SoftKeyboardController {
2075         private final AccessibilityService mService;
2076 
2077         /**
2078          * Map of listeners to their handlers. Lazily created when adding the first
2079          * soft keyboard change listener.
2080          */
2081         private ArrayMap<OnShowModeChangedListener, Handler> mListeners;
2082         private final Object mLock;
2083 
2084         /** @hide */
2085         @Retention(RetentionPolicy.SOURCE)
2086         @IntDef({
2087                 ENABLE_IME_SUCCESS,
2088                 ENABLE_IME_FAIL_BY_ADMIN,
2089                 ENABLE_IME_FAIL_UNKNOWN
2090         })
2091         public @interface EnableImeResult {}
2092         /**
2093          * Return value for {@link #setInputMethodEnabled(String, boolean)}. The action succeeded.
2094          */
2095         public static final int ENABLE_IME_SUCCESS = 0;
2096         /**
2097          * Return value for {@link #setInputMethodEnabled(String, boolean)}. The action failed
2098          * because the InputMethod is not permitted by device policy manager.
2099          */
2100         public static final int ENABLE_IME_FAIL_BY_ADMIN = 1;
2101         /**
2102          * Return value for {@link #setInputMethodEnabled(String, boolean)}. The action failed
2103          * and the reason is unknown.
2104          */
2105         public static final int ENABLE_IME_FAIL_UNKNOWN = 2;
2106 
SoftKeyboardController(@onNull AccessibilityService service, @NonNull Object lock)2107         SoftKeyboardController(@NonNull AccessibilityService service, @NonNull Object lock) {
2108             mService = service;
2109             mLock = lock;
2110         }
2111 
2112         /**
2113          * Called when the service is connected.
2114          */
onServiceConnected()2115         void onServiceConnected() {
2116             synchronized(mLock) {
2117                 if (mListeners != null && !mListeners.isEmpty()) {
2118                     setSoftKeyboardCallbackEnabled(true);
2119                 }
2120             }
2121         }
2122 
2123         /**
2124          * Adds the specified change listener to the list of show mode change listeners. The
2125          * callback will occur on the service's main thread. Listener is not called on registration.
2126          */
addOnShowModeChangedListener(@onNull OnShowModeChangedListener listener)2127         public void addOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
2128             addOnShowModeChangedListener(listener, null);
2129         }
2130 
2131         /**
2132          * Adds the specified change listener to the list of soft keyboard show mode change
2133          * listeners. The callback will occur on the specified {@link Handler}'s thread, or on the
2134          * services's main thread if the handler is {@code null}.
2135          *
2136          * @param listener the listener to add, must be non-null
2137          * @param handler the handler on which to callback should execute, or {@code null} to
2138          *        execute on the service's main thread
2139          */
addOnShowModeChangedListener(@onNull OnShowModeChangedListener listener, @Nullable Handler handler)2140         public void addOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener,
2141                 @Nullable Handler handler) {
2142             synchronized (mLock) {
2143                 if (mListeners == null) {
2144                     mListeners = new ArrayMap<>();
2145                 }
2146 
2147                 final boolean shouldEnableCallback = mListeners.isEmpty();
2148                 mListeners.put(listener, handler);
2149 
2150                 if (shouldEnableCallback) {
2151                     // This may fail if the service is not connected yet, but if we still have
2152                     // listeners when it connects, we can try again.
2153                     setSoftKeyboardCallbackEnabled(true);
2154                 }
2155             }
2156         }
2157 
2158         /**
2159          * Removes the specified change listener from the list of keyboard show mode change
2160          * listeners.
2161          *
2162          * @param listener the listener to remove, must be non-null
2163          * @return {@code true} if the listener was removed, {@code false} otherwise
2164          */
removeOnShowModeChangedListener( @onNull OnShowModeChangedListener listener)2165         public boolean removeOnShowModeChangedListener(
2166                 @NonNull OnShowModeChangedListener listener) {
2167             if (mListeners == null) {
2168                 return false;
2169             }
2170 
2171             synchronized (mLock) {
2172                 final int keyIndex = mListeners.indexOfKey(listener);
2173                 final boolean hasKey = keyIndex >= 0;
2174                 if (hasKey) {
2175                     mListeners.removeAt(keyIndex);
2176                 }
2177 
2178                 if (hasKey && mListeners.isEmpty()) {
2179                     // We just removed the last listener, so we don't need callbacks from the
2180                     // service anymore.
2181                     setSoftKeyboardCallbackEnabled(false);
2182                 }
2183 
2184                 return hasKey;
2185             }
2186         }
2187 
setSoftKeyboardCallbackEnabled(boolean enabled)2188         private void setSoftKeyboardCallbackEnabled(boolean enabled) {
2189             final IAccessibilityServiceConnection connection =
2190                     AccessibilityInteractionClient.getInstance(mService).getConnection(
2191                             mService.mConnectionId);
2192             if (connection != null) {
2193                 try {
2194                     connection.setSoftKeyboardCallbackEnabled(enabled);
2195                 } catch (RemoteException re) {
2196                     throw new RuntimeException(re);
2197                 }
2198             }
2199         }
2200 
2201         /**
2202          * Dispatches the soft keyboard show mode change to any registered listeners. This should
2203          * be called on the service's main thread.
2204          */
dispatchSoftKeyboardShowModeChanged(final int showMode)2205         void dispatchSoftKeyboardShowModeChanged(final int showMode) {
2206             final ArrayMap<OnShowModeChangedListener, Handler> entries;
2207             synchronized (mLock) {
2208                 if (mListeners == null || mListeners.isEmpty()) {
2209                     Slog.w(LOG_TAG, "Received soft keyboard show mode changed callback"
2210                             + " with no listeners registered!");
2211                     setSoftKeyboardCallbackEnabled(false);
2212                     return;
2213                 }
2214 
2215                 // Listeners may remove themselves. Perform a shallow copy to avoid concurrent
2216                 // modification.
2217                 entries = new ArrayMap<>(mListeners);
2218             }
2219 
2220             for (int i = 0, count = entries.size(); i < count; i++) {
2221                 final OnShowModeChangedListener listener = entries.keyAt(i);
2222                 final Handler handler = entries.valueAt(i);
2223                 if (handler != null) {
2224                     handler.post(new Runnable() {
2225                         @Override
2226                         public void run() {
2227                             listener.onShowModeChanged(SoftKeyboardController.this, showMode);
2228                         }
2229                     });
2230                 } else {
2231                     // We're already on the main thread, just run the listener.
2232                     listener.onShowModeChanged(this, showMode);
2233                 }
2234             }
2235         }
2236 
2237         /**
2238          * Returns the show mode of the soft keyboard.
2239          *
2240          * @return the current soft keyboard show mode
2241          *
2242          * @see AccessibilityService#SHOW_MODE_AUTO
2243          * @see AccessibilityService#SHOW_MODE_HIDDEN
2244          * @see AccessibilityService#SHOW_MODE_IGNORE_HARD_KEYBOARD
2245          */
2246         @SoftKeyboardShowMode
getShowMode()2247         public int getShowMode() {
2248             final IAccessibilityServiceConnection connection =
2249                     AccessibilityInteractionClient.getInstance(mService).getConnection(
2250                             mService.mConnectionId);
2251             if (connection != null) {
2252                 try {
2253                     return connection.getSoftKeyboardShowMode();
2254                 } catch (RemoteException re) {
2255                     Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
2256                     re.rethrowFromSystemServer();
2257                 }
2258             }
2259             return SHOW_MODE_AUTO;
2260         }
2261 
2262         /**
2263          * Sets the soft keyboard show mode.
2264          * <p>
2265          * <strong>Note:</strong> If the service is not yet connected (e.g.
2266          * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
2267          * service has been disconnected, this method will have no effect and return {@code false}.
2268          *
2269          * @param showMode the new show mode for the soft keyboard
2270          * @return {@code true} on success
2271          *
2272          * @see AccessibilityService#SHOW_MODE_AUTO
2273          * @see AccessibilityService#SHOW_MODE_HIDDEN
2274          * @see AccessibilityService#SHOW_MODE_IGNORE_HARD_KEYBOARD
2275          */
setShowMode(@oftKeyboardShowMode int showMode)2276         public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
2277            final IAccessibilityServiceConnection connection =
2278                    AccessibilityInteractionClient.getInstance(mService).getConnection(
2279                            mService.mConnectionId);
2280            if (connection != null) {
2281                try {
2282                    return connection.setSoftKeyboardShowMode(showMode);
2283                } catch (RemoteException re) {
2284                    Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
2285                    re.rethrowFromSystemServer();
2286                }
2287            }
2288            return false;
2289         }
2290 
2291         /**
2292          * Listener for changes in the soft keyboard show mode.
2293          */
2294         public interface OnShowModeChangedListener {
2295            /**
2296             * Called when the soft keyboard behavior changes. The default show mode is
2297             * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
2298             * focused. An AccessibilityService can also request the show mode
2299             * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
2300             *
2301             * @param controller the soft keyboard controller
2302             * @param showMode the current soft keyboard show mode
2303             */
onShowModeChanged(@onNull SoftKeyboardController controller, @SoftKeyboardShowMode int showMode)2304             void onShowModeChanged(@NonNull SoftKeyboardController controller,
2305                     @SoftKeyboardShowMode int showMode);
2306         }
2307 
2308         /**
2309          * Switches the current IME for the user for whom the service is enabled. The change will
2310          * persist until the current IME is explicitly changed again, and may persist beyond the
2311          * life cycle of the requesting service.
2312          *
2313          * @param imeId The ID of the input method to make current. This IME must be installed and
2314          *              enabled.
2315          * @return {@code true} if the current input method was successfully switched to the input
2316          *         method by {@code imeId},
2317          *         {@code false} if the input method specified is not installed, not enabled, or
2318          *         otherwise not available to become the current IME
2319          *
2320          * @see android.view.inputmethod.InputMethodInfo#getId()
2321          */
switchToInputMethod(@onNull String imeId)2322         public boolean switchToInputMethod(@NonNull String imeId) {
2323             final IAccessibilityServiceConnection connection =
2324                     AccessibilityInteractionClient.getInstance(mService).getConnection(
2325                             mService.mConnectionId);
2326             if (connection != null) {
2327                 try {
2328                     return connection.switchToInputMethod(imeId);
2329                 } catch (RemoteException re) {
2330                     throw new RuntimeException(re);
2331                 }
2332             }
2333             return false;
2334         }
2335 
2336         /**
2337          * Enable or disable the specified IME for the user for whom the service is activated. The
2338          * IME needs to be in the same package as the service and needs to be allowed by device
2339          * policy, if there is one. The change will persist until the specified IME is next
2340          * explicitly enabled or disabled by whatever means, such as user choice, and may persist
2341          * beyond the life cycle of the requesting service.
2342          *
2343          * @param imeId The ID of the input method to enable or disable. This IME must be installed.
2344          * @param enabled {@code true} if the input method associated with {@code imeId} should be
2345          *                enabled.
2346          * @return status code for the result of enabling/disabling the input method associated
2347          *         with {@code imeId}.
2348          * @throws SecurityException if the input method is not in the same package as the service.
2349          *
2350          * @see android.view.inputmethod.InputMethodInfo#getId()
2351          */
2352         @CheckResult
2353         @EnableImeResult
setInputMethodEnabled(@onNull String imeId, boolean enabled)2354         public int setInputMethodEnabled(@NonNull String imeId, boolean enabled)
2355                 throws SecurityException {
2356             final IAccessibilityServiceConnection connection =
2357                     AccessibilityInteractionClient.getInstance(mService).getConnection(
2358                             mService.mConnectionId);
2359             if (connection != null) {
2360                 try {
2361                     return connection.setInputMethodEnabled(imeId, enabled);
2362                 } catch (RemoteException re) {
2363                     throw new RuntimeException(re);
2364                 }
2365             }
2366             return ENABLE_IME_FAIL_UNKNOWN;
2367         }
2368     }
2369 
2370     /**
2371      * Returns the controller for the accessibility button within the system's navigation area.
2372      * This instance may be used to query the accessibility button's state and register listeners
2373      * for interactions with and state changes for the accessibility button when
2374      * {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} is set.
2375      * <p>
2376      * <strong>Note:</strong> Not all devices are capable of displaying the accessibility button
2377      * within a navigation area, and as such, use of this class should be considered only as an
2378      * optional feature or shortcut on supported device implementations.
2379      * </p>
2380      *
2381      * @return the accessibility button controller for this {@link AccessibilityService}
2382      */
2383     @NonNull
getAccessibilityButtonController()2384     public final AccessibilityButtonController getAccessibilityButtonController() {
2385         return getAccessibilityButtonController(Display.DEFAULT_DISPLAY);
2386     }
2387 
2388     /**
2389      * Returns the controller of specified logical display for the accessibility button within the
2390      * system's navigation area. This instance may be used to query the accessibility button's
2391      * state and register listeners for interactions with and state changes for the accessibility
2392      * button when {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} is set.
2393      * <p>
2394      * <strong>Note:</strong> Not all devices are capable of displaying the accessibility button
2395      * within a navigation area, and as such, use of this class should be considered only as an
2396      * optional feature or shortcut on supported device implementations.
2397      * </p>
2398      *
2399      * @param displayId The logic display id, use {@link Display#DEFAULT_DISPLAY} for default
2400      *                  display.
2401      * @return the accessibility button controller for this {@link AccessibilityService}
2402      */
2403     @NonNull
getAccessibilityButtonController(int displayId)2404     public final AccessibilityButtonController getAccessibilityButtonController(int displayId) {
2405         synchronized (mLock) {
2406             AccessibilityButtonController controller = mAccessibilityButtonControllers.get(
2407                     displayId);
2408             if (controller == null) {
2409                 controller = new AccessibilityButtonController(
2410                     AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId));
2411                 mAccessibilityButtonControllers.put(displayId, controller);
2412             }
2413             return controller;
2414         }
2415     }
2416 
onAccessibilityButtonClicked(int displayId)2417     private void onAccessibilityButtonClicked(int displayId) {
2418         getAccessibilityButtonController(displayId).dispatchAccessibilityButtonClicked();
2419     }
2420 
onAccessibilityButtonAvailabilityChanged(boolean available)2421     private void onAccessibilityButtonAvailabilityChanged(boolean available) {
2422         getAccessibilityButtonController().dispatchAccessibilityButtonAvailabilityChanged(
2423                 available);
2424     }
2425 
2426     /** Sets the cache status.
2427      *
2428      * <p>If {@code enabled}, enable the cache and prefetching. Otherwise, disable the cache
2429      * and prefetching.
2430      * Note: By default the cache is enabled.
2431      * @param enabled whether to enable or disable the cache.
2432      * @return {@code true} if the cache and connection are not null, so the cache status is set.
2433      */
setCacheEnabled(boolean enabled)2434     public boolean setCacheEnabled(boolean enabled) {
2435         AccessibilityCache cache =
2436                 AccessibilityInteractionClient.getCache(mConnectionId);
2437         if (cache == null) {
2438             return false;
2439         }
2440         final IAccessibilityServiceConnection connection =
2441                 AccessibilityInteractionClient.getConnection(mConnectionId);
2442         if (connection == null) {
2443             return false;
2444         }
2445         try {
2446             connection.setCacheEnabled(enabled);
2447             cache.setEnabled(enabled);
2448             return true;
2449         } catch (RemoteException re) {
2450             Log.w(LOG_TAG, "Error while setting status of cache", re);
2451             re.rethrowFromSystemServer();
2452         }
2453         return false;
2454     }
2455 
2456     /** Invalidates {@code node} and its subtree in the cache.
2457      * @param node the node to invalidate.
2458      * @return {@code true} if the subtree rooted at {@code node} was invalidated.
2459      */
clearCachedSubtree(@onNull AccessibilityNodeInfo node)2460     public boolean clearCachedSubtree(@NonNull AccessibilityNodeInfo node) {
2461         AccessibilityCache cache =
2462                 AccessibilityInteractionClient.getCache(mConnectionId);
2463         if (cache == null) {
2464             return false;
2465         }
2466         return cache.clearSubTree(node);
2467     }
2468 
2469     /** Clears the cache.
2470      * @return {@code true} if the cache was cleared
2471      */
clearCache()2472     public boolean clearCache() {
2473         AccessibilityCache cache =
2474                 AccessibilityInteractionClient.getCache(mConnectionId);
2475         if (cache == null) {
2476             return false;
2477         }
2478         cache.clear();
2479         return true;
2480     }
2481 
2482     /** Checks if {@code node} is in the cache.
2483      * @param node the node to check.
2484      * @return {@code true} if {@code node} is in the cache.
2485      */
isNodeInCache(@onNull AccessibilityNodeInfo node)2486     public boolean isNodeInCache(@NonNull AccessibilityNodeInfo node) {
2487         AccessibilityCache cache =
2488                 AccessibilityInteractionClient.getCache(mConnectionId);
2489         if (cache == null) {
2490             return false;
2491         }
2492         return cache.isNodeInCache(node);
2493     }
2494 
2495     /** Returns {@code true} if the cache is enabled. */
isCacheEnabled()2496     public boolean isCacheEnabled() {
2497         AccessibilityCache cache =
2498                 AccessibilityInteractionClient.getCache(mConnectionId);
2499         if (cache == null) {
2500             return false;
2501         }
2502         return cache.isEnabled();
2503     }
2504 
2505     /** This is called when the system action list is changed. */
onSystemActionsChanged()2506     public void onSystemActionsChanged() {
2507     }
2508 
2509     /**
2510      * Returns a list of system actions available in the system right now.
2511      * <p>
2512      * System actions that correspond to the global action constants will have matching action IDs.
2513      * For example, an with id {@link #GLOBAL_ACTION_BACK} will perform the back action.
2514      * </p>
2515      * <p>
2516      * These actions should be called by {@link #performGlobalAction}.
2517      * </p>
2518      *
2519      * @return A list of available system actions.
2520      */
getSystemActions()2521     public final @NonNull List<AccessibilityAction> getSystemActions() {
2522         IAccessibilityServiceConnection connection =
2523                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
2524         if (connection != null) {
2525             try {
2526                 return connection.getSystemActions();
2527             } catch (RemoteException re) {
2528                 Log.w(LOG_TAG, "Error while calling getSystemActions", re);
2529                 re.rethrowFromSystemServer();
2530             }
2531         }
2532         return Collections.emptyList();
2533     }
2534 
2535     /**
2536      * Performs a global action. Such an action can be performed
2537      * at any moment regardless of the current application or user
2538      * location in that application. For example going back, going
2539      * home, opening recents, etc.
2540      *
2541      * <p>
2542      * Note: The global action ids themselves give no information about the current availability
2543      * of their corresponding actions. To determine if a global action is available, use
2544      * {@link #getSystemActions()}
2545      *
2546      * @param action The action to perform.
2547      * @return Whether the action was successfully performed.
2548      *
2549      * Perform actions using ids like the id constants referenced below:
2550      * @see #GLOBAL_ACTION_BACK
2551      * @see #GLOBAL_ACTION_HOME
2552      * @see #GLOBAL_ACTION_NOTIFICATIONS
2553      * @see #GLOBAL_ACTION_RECENTS
2554      * @see #GLOBAL_ACTION_DPAD_UP
2555      * @see #GLOBAL_ACTION_DPAD_DOWN
2556      * @see #GLOBAL_ACTION_DPAD_LEFT
2557      * @see #GLOBAL_ACTION_DPAD_RIGHT
2558      * @see #GLOBAL_ACTION_DPAD_CENTER
2559      */
performGlobalAction(int action)2560     public final boolean performGlobalAction(int action) {
2561         IAccessibilityServiceConnection connection =
2562                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
2563         if (connection != null) {
2564             try {
2565                 return connection.performGlobalAction(action);
2566             } catch (RemoteException re) {
2567                 Log.w(LOG_TAG, "Error while calling performGlobalAction", re);
2568                 re.rethrowFromSystemServer();
2569             }
2570         }
2571         return false;
2572     }
2573 
2574     /**
2575      * Find the view that has the specified focus type. The search is performed
2576      * across all windows.
2577      * <p>
2578      * <strong>Note:</strong> In order to access the windows your service has
2579      * to declare the capability to retrieve window content by setting the
2580      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
2581      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
2582      * Also the service has to opt-in to retrieve the interactive windows by
2583      * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
2584      * flag. Otherwise, the search will be performed only in the active window.
2585      * </p>
2586      * <p>
2587      * <strong>Note:</strong> If the view with {@link AccessibilityNodeInfo#FOCUS_INPUT}
2588      * is on an embedded view hierarchy which is embedded in a {@link android.view.SurfaceView} via
2589      * {@link android.view.SurfaceView#setChildSurfacePackage}, there is a limitation that this API
2590      * won't be able to find the node for the view. It's because views don't know about
2591      * the embedded hierarchies. Instead, you could traverse all the nodes to find the
2592      * focus.
2593      * </p>
2594      *
2595      * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
2596      *         {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
2597      * @return The node info of the focused view or null.
2598      *
2599      * @see AccessibilityNodeInfo#FOCUS_INPUT
2600      * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
2601      */
findFocus(int focus)2602     public AccessibilityNodeInfo findFocus(int focus) {
2603         return AccessibilityInteractionClient.getInstance(this).findFocus(mConnectionId,
2604                 AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
2605     }
2606 
2607     /**
2608      * Gets the an {@link AccessibilityServiceInfo} describing this
2609      * {@link AccessibilityService}. This method is useful if one wants
2610      * to change some of the dynamically configurable properties at
2611      * runtime.
2612      *
2613      * @return The accessibility service info.
2614      *
2615      * @see AccessibilityServiceInfo
2616      */
getServiceInfo()2617     public final AccessibilityServiceInfo getServiceInfo() {
2618         IAccessibilityServiceConnection connection =
2619                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
2620         if (connection != null) {
2621             try {
2622                 return connection.getServiceInfo();
2623             } catch (RemoteException re) {
2624                 Log.w(LOG_TAG, "Error while getting AccessibilityServiceInfo", re);
2625                 re.rethrowFromSystemServer();
2626             }
2627         }
2628         return null;
2629     }
2630 
2631     /**
2632      * Sets the {@link AccessibilityServiceInfo} that describes this service.
2633      * <p>
2634      * Note: You can call this method any time but the info will be picked up after
2635      *       the system has bound to this service and when this method is called thereafter.
2636      *
2637      * @param info The info.
2638      */
setServiceInfo(AccessibilityServiceInfo info)2639     public final void setServiceInfo(AccessibilityServiceInfo info) {
2640         mInfo = info;
2641         updateInputMethod(info);
2642         mMotionEventSources = info.getMotionEventSources();
2643         sendServiceInfo();
2644     }
2645 
2646     /**
2647      * Sets the {@link AccessibilityServiceInfo} for this service if the latter is
2648      * properly set and there is an {@link IAccessibilityServiceConnection} to the
2649      * AccessibilityManagerService.
2650      */
sendServiceInfo()2651     private void sendServiceInfo() {
2652         IAccessibilityServiceConnection connection =
2653                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
2654         if (mInfo != null && connection != null) {
2655             try {
2656                 connection.setServiceInfo(mInfo);
2657                 mInfo = null;
2658                 AccessibilityInteractionClient.getInstance(this).clearCache(mConnectionId);
2659             } catch (RemoteException re) {
2660                 Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
2661                 re.rethrowFromSystemServer();
2662             }
2663         }
2664     }
2665 
2666     @Override
getSystemService(@erviceName @onNull String name)2667     public Object getSystemService(@ServiceName @NonNull String name) {
2668         if (getBaseContext() == null) {
2669             throw new IllegalStateException(
2670                     "System services not available to Activities before onCreate()");
2671         }
2672 
2673         // Guarantee that we always return the same window manager instance.
2674         if (WINDOW_SERVICE.equals(name)) {
2675             if (mWindowManager == null) {
2676                 mWindowManager = (WindowManager) getBaseContext().getSystemService(name);
2677                 final WindowManagerImpl wm = (WindowManagerImpl) mWindowManager;
2678                 // Set e default token obtained from the connection to ensure client could use
2679                 // accessibility overlay.
2680                 wm.setDefaultToken(mWindowToken);
2681             }
2682             return mWindowManager;
2683         }
2684         return super.getSystemService(name);
2685     }
2686 
2687     /**
2688      * Takes a screenshot of the specified display and returns it via an
2689      * {@link AccessibilityService.ScreenshotResult}. You can use {@link Bitmap#wrapHardwareBuffer}
2690      * to construct the bitmap from the ScreenshotResult's payload.
2691      * <p>
2692      * <strong>Note:</strong> In order to take screenshot your service has
2693      * to declare the capability to take screenshot by setting the
2694      * {@link android.R.styleable#AccessibilityService_canTakeScreenshot}
2695      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
2696      * </p>
2697      *
2698      * @param displayId The logic display id, must be {@link Display#DEFAULT_DISPLAY} for
2699      *                  default display.
2700      * @param executor Executor on which to run the callback.
2701      * @param callback The callback invoked when taking screenshot has succeeded or failed.
2702      *                 See {@link TakeScreenshotCallback} for details.
2703      * @see #takeScreenshotOfWindow
2704      */
takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor, @NonNull TakeScreenshotCallback callback)2705     public void takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor,
2706             @NonNull TakeScreenshotCallback callback) {
2707         Preconditions.checkNotNull(executor, "executor cannot be null");
2708         Preconditions.checkNotNull(callback, "callback cannot be null");
2709         final IAccessibilityServiceConnection connection =
2710                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
2711         if (connection == null) {
2712             sendScreenshotFailure(ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, executor, callback);
2713             return;
2714         }
2715         try {
2716             connection.takeScreenshot(displayId, new RemoteCallback((result) -> {
2717                 final int status = result.getInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS);
2718                 if (status != TAKE_SCREENSHOT_SUCCESS) {
2719                     sendScreenshotFailure(status, executor, callback);
2720                     return;
2721                 }
2722                 final HardwareBuffer hardwareBuffer =
2723                         result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER, android.hardware.HardwareBuffer.class);
2724                 final ParcelableColorSpace colorSpace =
2725                         result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE,
2726                                 android.graphics.ParcelableColorSpace.class);
2727                 final ScreenshotResult screenshot = new ScreenshotResult(hardwareBuffer,
2728                         colorSpace.getColorSpace(),
2729                         result.getLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP));
2730                 sendScreenshotSuccess(screenshot, executor, callback);
2731             }));
2732         } catch (RemoteException re) {
2733             throw new RuntimeException(re);
2734         }
2735     }
2736 
2737     /**
2738      * Takes a screenshot of the specified window and returns it via an
2739      * {@link AccessibilityService.ScreenshotResult}. You can use {@link Bitmap#wrapHardwareBuffer}
2740      * to construct the bitmap from the ScreenshotResult's payload.
2741      * <p>
2742      * <strong>Note:</strong> In order to take screenshots your service has
2743      * to declare the capability to take screenshot by setting the
2744      * {@link android.R.styleable#AccessibilityService_canTakeScreenshot}
2745      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
2746      * </p>
2747      * <p>
2748      * Both this method and {@link #takeScreenshot} can be used for machine learning-based visual
2749      * screen understanding. Use <code>takeScreenshotOfWindow</code> if your target window might be
2750      * visually underneath an accessibility overlay (from your or another accessibility service) in
2751      * order to capture the window contents without the screenshot being covered by the overlay
2752      * contents drawn on the screen.
2753      * </p>
2754      *
2755      * @param accessibilityWindowId The window id, from {@link AccessibilityWindowInfo#getId()}.
2756      * @param executor Executor on which to run the callback.
2757      * @param callback The callback invoked when taking screenshot has succeeded or failed.
2758      *                 See {@link TakeScreenshotCallback} for details.
2759      * @see #takeScreenshot
2760      */
takeScreenshotOfWindow(int accessibilityWindowId, @NonNull @CallbackExecutor Executor executor, @NonNull TakeScreenshotCallback callback)2761     public void takeScreenshotOfWindow(int accessibilityWindowId,
2762             @NonNull @CallbackExecutor Executor executor,
2763             @NonNull TakeScreenshotCallback callback) {
2764         AccessibilityInteractionClient.getInstance(this).takeScreenshotOfWindow(
2765                         mConnectionId, accessibilityWindowId, executor, callback);
2766     }
2767 
2768     /**
2769      * Sets the strokeWidth and color of the accessibility focus rectangle.
2770      * <p>
2771      * <strong>Note:</strong> This setting persists until this or another active
2772      * AccessibilityService changes it or the device reboots.
2773      * </p>
2774      *
2775      * @param strokeWidth The stroke width of the rectangle in pixels.
2776      *                    Setting this value to zero results in no focus rectangle being drawn.
2777      * @param color The color of the rectangle.
2778      */
setAccessibilityFocusAppearance(int strokeWidth, @ColorInt int color)2779     public void setAccessibilityFocusAppearance(int strokeWidth, @ColorInt int color) {
2780         IAccessibilityServiceConnection connection =
2781                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
2782         if (connection != null) {
2783             try {
2784                 connection.setFocusAppearance(strokeWidth, color);
2785             } catch (RemoteException re) {
2786                 Log.w(LOG_TAG, "Error while setting the strokeWidth and color of the "
2787                         + "accessibility focus rectangle", re);
2788                 re.rethrowFromSystemServer();
2789             }
2790         }
2791     }
2792 
2793     /**
2794      * Implement to return the implementation of the internal accessibility
2795      * service interface.
2796      */
2797     @Override
onBind(Intent intent)2798     public final IBinder onBind(Intent intent) {
2799         return new IAccessibilityServiceClientWrapper(this, getMainExecutor(), new Callbacks() {
2800             @Override
2801             public void onServiceConnected() {
2802                 AccessibilityService.this.dispatchServiceConnected();
2803             }
2804 
2805             @Override
2806             public void onInterrupt() {
2807                 AccessibilityService.this.onInterrupt();
2808             }
2809 
2810             @Override
2811             public void onAccessibilityEvent(AccessibilityEvent event) {
2812                 AccessibilityService.this.onAccessibilityEvent(event);
2813             }
2814 
2815             @Override
2816             public void init(int connectionId, IBinder windowToken) {
2817                 mConnectionId = connectionId;
2818                 mWindowToken = windowToken;
2819 
2820                 // The client may have already obtained the window manager, so
2821                 // update the default token on whatever manager we gave them.
2822                 if (mWindowManager != null) {
2823                     final WindowManagerImpl wm = (WindowManagerImpl) mWindowManager;
2824                     wm.setDefaultToken(mWindowToken);
2825                 }
2826             }
2827 
2828             @Override
2829             public boolean onGesture(AccessibilityGestureEvent gestureEvent) {
2830                 return AccessibilityService.this.onGesture(gestureEvent);
2831             }
2832 
2833             @Override
2834             public boolean onKeyEvent(KeyEvent event) {
2835                 return AccessibilityService.this.onKeyEvent(event);
2836             }
2837 
2838             @Override
2839             public void onMagnificationChanged(int displayId, @NonNull Region region,
2840                     MagnificationConfig config) {
2841                 AccessibilityService.this.onMagnificationChanged(displayId, region, config);
2842             }
2843 
2844             @Override
2845             public void onMotionEvent(MotionEvent event) {
2846                 AccessibilityService.this.sendMotionEventToCallback(event);
2847             }
2848 
2849             @Override
2850             public void onTouchStateChanged(int displayId, int state) {
2851                 AccessibilityService.this.onTouchStateChanged(displayId, state);
2852             }
2853 
2854             @Override
2855             public void onSoftKeyboardShowModeChanged(int showMode) {
2856                 AccessibilityService.this.onSoftKeyboardShowModeChanged(showMode);
2857             }
2858 
2859             @Override
2860             public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
2861                 AccessibilityService.this.onPerformGestureResult(sequence, completedSuccessfully);
2862             }
2863 
2864             @Override
2865             public void onFingerprintCapturingGesturesChanged(boolean active) {
2866                 AccessibilityService.this.onFingerprintCapturingGesturesChanged(active);
2867             }
2868 
2869             @Override
2870             public void onFingerprintGesture(int gesture) {
2871                 AccessibilityService.this.onFingerprintGesture(gesture);
2872             }
2873 
2874             @Override
2875             public void onAccessibilityButtonClicked(int displayId) {
2876                 AccessibilityService.this.onAccessibilityButtonClicked(displayId);
2877             }
2878 
2879             @Override
2880             public void onAccessibilityButtonAvailabilityChanged(boolean available) {
2881                 AccessibilityService.this.onAccessibilityButtonAvailabilityChanged(available);
2882             }
2883 
2884             @Override
2885             public void onSystemActionsChanged() {
2886                 AccessibilityService.this.onSystemActionsChanged();
2887             }
2888 
2889             @Override
2890             public void createImeSession(IAccessibilityInputMethodSessionCallback callback) {
2891                 if (mInputMethod != null) {
2892                     mInputMethod.createImeSession(callback);
2893                 }
2894             }
2895 
2896             @Override
2897             public void startInput(@Nullable RemoteAccessibilityInputConnection connection,
2898                     @NonNull EditorInfo editorInfo, boolean restarting) {
2899                 if (mInputMethod != null) {
2900                     if (restarting) {
2901                         mInputMethod.restartInput(connection, editorInfo);
2902                     } else {
2903                         mInputMethod.startInput(connection, editorInfo);
2904                     }
2905                 }
2906             }
2907         });
2908     }
2909 
2910     /**
2911      * Implements the internal {@link IAccessibilityServiceClient} interface to convert
2912      * incoming calls to it back to calls on an {@link AccessibilityService}.
2913      *
2914      * @hide
2915      */
2916     public static class IAccessibilityServiceClientWrapper extends
2917             IAccessibilityServiceClient.Stub {
2918 
2919         private final Callbacks mCallback;
2920         private final Context mContext;
2921         private final Executor mExecutor;
2922 
2923         private int mConnectionId = AccessibilityInteractionClient.NO_ID;
2924 
2925         /**
2926          * This is not {@code null} only between {@link #bindInput()} and {@link #unbindInput()} so
2927          * that {@link RemoteAccessibilityInputConnection} can query if {@link #unbindInput()} has
2928          * already been called or not, mainly to avoid unnecessary blocking operations.
2929          *
2930          * <p>This field must be set and cleared only from the binder thread(s), where the system
2931          * guarantees that {@link #bindInput()},
2932          * {@link #startInput(IRemoteAccessibilityInputConnection, EditorInfo, boolean)},
2933          * and {@link #unbindInput()} are called with the same order as the original calls
2934          * in {@link com.android.server.inputmethod.InputMethodManagerService}.
2935          * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p>
2936          */
2937         @Nullable
2938         CancellationGroup mCancellationGroup = null;
2939 
2940         public IAccessibilityServiceClientWrapper(Context context, Executor executor,
2941                 Callbacks callback) {
2942             mCallback = callback;
2943             mContext = context;
2944             mExecutor = executor;
2945         }
2946 
2947         public IAccessibilityServiceClientWrapper(Context context, Looper looper,
2948                 Callbacks callback) {
2949             this(context, new HandlerExecutor(new Handler(looper)), callback);
2950         }
2951 
2952         public void init(IAccessibilityServiceConnection connection, int connectionId,
2953                 IBinder windowToken) {
2954             mExecutor.execute(() -> {
2955                 mConnectionId = connectionId;
2956                 if (connection != null) {
2957                     AccessibilityInteractionClient.getInstance(mContext).addConnection(
2958                             mConnectionId, connection, /*initializeCache=*/true);
2959                     if (mContext != null) {
2960                         try {
2961                             connection.setAttributionTag(mContext.getAttributionTag());
2962                         } catch (RemoteException re) {
2963                             Log.w(LOG_TAG, "Error while setting attributionTag", re);
2964                             re.rethrowFromSystemServer();
2965                         }
2966                     }
2967                     mCallback.init(mConnectionId, windowToken);
2968                     mCallback.onServiceConnected();
2969                 } else {
2970                     AccessibilityInteractionClient.getInstance(mContext)
2971                             .clearCache(mConnectionId);
2972                     AccessibilityInteractionClient.getInstance(mContext).removeConnection(
2973                             mConnectionId);
2974                     mConnectionId = AccessibilityInteractionClient.NO_ID;
2975                     mCallback.init(AccessibilityInteractionClient.NO_ID, null);
2976                 }
2977                 return;
2978             });
2979         }
2980 
2981         public void onInterrupt() {
2982             mExecutor.execute(() -> {
2983                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
2984                     mCallback.onInterrupt();
2985                 }
2986             });
2987         }
2988 
2989         public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) {
2990             mExecutor.execute(() -> {
2991                 if (event != null) {
2992                     // Send the event to AccessibilityCache via AccessibilityInteractionClient
2993                     AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
2994                             event, mConnectionId);
2995                     if (serviceWantsEvent
2996                             && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
2997                         // Send the event to AccessibilityService
2998                         mCallback.onAccessibilityEvent(event);
2999                     }
3000                 }
3001                 return;
3002             });
3003         }
3004 
3005         @Override
3006         public void onGesture(AccessibilityGestureEvent gestureInfo) {
3007             mExecutor.execute(() -> {
3008                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3009                     mCallback.onGesture(gestureInfo);
3010                 }
3011                 return;
3012             });
3013         }
3014 
3015         public void clearAccessibilityCache() {
3016             mExecutor.execute(() -> {
3017                 AccessibilityInteractionClient.getInstance(mContext).clearCache(mConnectionId);
3018                 return;
3019             });
3020         }
3021 
3022         @Override
3023         public void onKeyEvent(KeyEvent event, int sequence) {
3024             mExecutor.execute(() -> {
3025                 try {
3026                     IAccessibilityServiceConnection connection = AccessibilityInteractionClient
3027                             .getInstance(mContext).getConnection(mConnectionId);
3028                     if (connection != null) {
3029                         final boolean result = mCallback.onKeyEvent(event);
3030                         try {
3031                             connection.setOnKeyEventResult(result, sequence);
3032                         } catch (RemoteException re) {
3033                             /* ignore */
3034                         }
3035                     }
3036                 } finally {
3037                     // Make sure the event is recycled.
3038                     try {
3039                         event.recycle();
3040                     } catch (IllegalStateException ise) {
3041                         /* ignore - best effort */
3042                     }
3043                 }
3044                 return;
3045             });
3046         }
3047 
3048         /** Magnification changed callbacks for different displays */
3049         public void onMagnificationChanged(int displayId, @NonNull Region region,
3050                 MagnificationConfig config) {
3051             mExecutor.execute(() -> {
3052                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3053                     mCallback.onMagnificationChanged(displayId, region, config);
3054                 }
3055                 return;
3056             });
3057         }
3058 
3059         public void onSoftKeyboardShowModeChanged(int showMode) {
3060             mExecutor.execute(() -> {
3061                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3062                     mCallback.onSoftKeyboardShowModeChanged(showMode);
3063                 }
3064                 return;
3065             });
3066         }
3067 
3068         public void onPerformGestureResult(int sequence, boolean successfully) {
3069             mExecutor.execute(() -> {
3070                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3071                     mCallback.onPerformGestureResult(sequence, successfully);
3072                 }
3073                 return;
3074             });
3075         }
3076 
3077         public void onFingerprintCapturingGesturesChanged(boolean active) {
3078             mExecutor.execute(() -> {
3079                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3080                     mCallback.onFingerprintCapturingGesturesChanged(active);
3081                 }
3082                 return;
3083             });
3084         }
3085 
3086         public void onFingerprintGesture(int gesture) {
3087             mExecutor.execute(() -> {
3088                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3089                     mCallback.onFingerprintGesture(gesture);
3090                 }
3091                 return;
3092             });
3093         }
3094 
3095         /** Accessibility button clicked callbacks for different displays */
3096         public void onAccessibilityButtonClicked(int displayId) {
3097             mExecutor.execute(() -> {
3098                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3099                     mCallback.onAccessibilityButtonClicked(displayId);
3100                 }
3101                 return;
3102             });
3103         }
3104 
3105         public void onAccessibilityButtonAvailabilityChanged(boolean available) {
3106             mExecutor.execute(() -> {
3107                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3108                     mCallback.onAccessibilityButtonAvailabilityChanged(available);
3109                 }
3110                 return;
3111             });
3112         }
3113 
3114         /** This is called when the system action list is changed. */
3115         public void onSystemActionsChanged() {
3116             mExecutor.execute(() -> {
3117                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3118                     mCallback.onSystemActionsChanged();
3119                 }
3120                 return;
3121             });
3122         }
3123 
3124         /** This is called when an app requests ime sessions or when the service is enabled. */
3125         public void createImeSession(IAccessibilityInputMethodSessionCallback callback) {
3126             mExecutor.execute(() -> {
3127                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3128                     mCallback.createImeSession(callback);
3129                 }
3130             });
3131         }
3132 
3133         /**
3134          * This is called when InputMethodManagerService requests to set the session enabled or
3135          * disabled
3136          */
3137         public void setImeSessionEnabled(IAccessibilityInputMethodSession session,
3138                 boolean enabled) {
3139             try {
3140                 AccessibilityInputMethodSession ls =
3141                         ((AccessibilityInputMethodSessionWrapper) session).getSession();
3142                 if (ls == null) {
3143                     Log.w(LOG_TAG, "Session is already finished: " + session);
3144                     return;
3145                 }
3146                 mExecutor.execute(() -> {
3147                     if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3148                         ls.setEnabled(enabled);
3149                     }
3150                     return;
3151                 });
3152             } catch (ClassCastException e) {
3153                 Log.w(LOG_TAG, "Incoming session not of correct type: " + session, e);
3154             }
3155         }
3156 
3157         /** This is called when an app binds input or when the service is enabled. */
3158         public void bindInput() {
3159             if (mCancellationGroup != null) {
3160                 Log.e(LOG_TAG, "bindInput must be paired with unbindInput.");
3161             }
3162             mCancellationGroup = new CancellationGroup();
3163         }
3164 
3165         /** This is called when an app unbinds input or when the service is disabled. */
3166         public void unbindInput() {
3167             if (mCancellationGroup != null) {
3168                 // Signal the flag then forget it.
3169                 mCancellationGroup.cancelAll();
3170                 mCancellationGroup = null;
3171             } else {
3172                 Log.e(LOG_TAG, "unbindInput must be paired with bindInput.");
3173             }
3174         }
3175 
3176         /** This is called when an app starts input or when the service is enabled. */
3177         public void startInput(IRemoteAccessibilityInputConnection connection,
3178                 EditorInfo editorInfo, boolean restarting) {
3179             if (mCancellationGroup == null) {
3180                 Log.e(LOG_TAG, "startInput must be called after bindInput.");
3181                 mCancellationGroup = new CancellationGroup();
3182             }
3183             mExecutor.execute(() -> {
3184                 if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
3185                     final RemoteAccessibilityInputConnection ic = connection == null ? null
3186                             : new RemoteAccessibilityInputConnection(
3187                                     connection, mCancellationGroup);
3188                     editorInfo.makeCompatible(mContext.getApplicationInfo().targetSdkVersion);
3189                     mCallback.startInput(ic, editorInfo, restarting);
3190                 }
3191             });
3192         }
3193 
3194         @Override
3195         public void onMotionEvent(MotionEvent event) {
3196             mExecutor.execute(() -> {
3197                 mCallback.onMotionEvent(event);
3198             });
3199         }
3200 
3201         @Override
3202         public void onTouchStateChanged(int displayId, int state) {
3203             mExecutor.execute(() -> {
3204                 mCallback.onTouchStateChanged(displayId, state);
3205             });
3206         }
3207     }
3208 
3209     /**
3210      * Class used to report status of dispatched gestures
3211      */
3212     public static abstract class GestureResultCallback {
3213         /** Called when the gesture has completed successfully
3214          *
3215          * @param gestureDescription The description of the gesture that completed.
3216          */
3217         public void onCompleted(GestureDescription gestureDescription) {
3218         }
3219 
3220         /** Called when the gesture was cancelled
3221          *
3222          * @param gestureDescription The description of the gesture that was cancelled.
3223          */
3224         public void onCancelled(GestureDescription gestureDescription) {
3225         }
3226     }
3227 
3228     /* Object to keep track of gesture result callbacks */
3229     private static class GestureResultCallbackInfo {
3230         GestureDescription gestureDescription;
3231         GestureResultCallback callback;
3232         Handler handler;
3233 
3234         GestureResultCallbackInfo(GestureDescription gestureDescription,
3235                 GestureResultCallback callback, Handler handler) {
3236             this.gestureDescription = gestureDescription;
3237             this.callback = callback;
3238             this.handler = handler;
3239         }
3240     }
3241 
3242     private void sendScreenshotSuccess(ScreenshotResult screenshot, Executor executor,
3243             TakeScreenshotCallback callback) {
3244         executor.execute(() -> callback.onSuccess(screenshot));
3245     }
3246 
3247     private void sendScreenshotFailure(@ScreenshotErrorCode int errorCode, Executor executor,
3248             TakeScreenshotCallback callback) {
3249         executor.execute(() -> callback.onFailure(errorCode));
3250     }
3251 
3252     /**
3253      * Interface used to report status of taking screenshot.
3254      */
3255     public interface TakeScreenshotCallback {
3256         /** Called when taking screenshot has completed successfully.
3257          *
3258          * @param screenshot The content of screenshot.
3259          */
3260         void onSuccess(@NonNull ScreenshotResult screenshot);
3261 
3262         /** Called when taking screenshot has failed. {@code errorCode} will identify the
3263          * reason of failure.
3264          *
3265          * @param errorCode The error code of this operation.
3266          */
3267         void onFailure(@ScreenshotErrorCode int errorCode);
3268     }
3269 
3270     /**
3271      * Can be used to construct a bitmap of the screenshot or any other operations for
3272      * {@link AccessibilityService#takeScreenshot} API.
3273      */
3274     public static final class ScreenshotResult {
3275         private final @NonNull HardwareBuffer mHardwareBuffer;
3276         private final @NonNull ColorSpace mColorSpace;
3277         private final long mTimestamp;
3278 
3279         /** @hide */
3280         public ScreenshotResult(@NonNull HardwareBuffer hardwareBuffer,
3281                 @NonNull ColorSpace colorSpace, long timestamp) {
3282             Preconditions.checkNotNull(hardwareBuffer, "hardwareBuffer cannot be null");
3283             Preconditions.checkNotNull(colorSpace, "colorSpace cannot be null");
3284             mHardwareBuffer = hardwareBuffer;
3285             mColorSpace = colorSpace;
3286             mTimestamp = timestamp;
3287         }
3288 
3289         /**
3290          * Gets the {@link ColorSpace} identifying a specific organization of colors of the
3291          * screenshot.
3292          *
3293          * @return the color space
3294          */
3295         @NonNull
3296         public ColorSpace getColorSpace() {
3297             return mColorSpace;
3298         }
3299 
3300         /**
3301          * Gets the {@link HardwareBuffer} representing a memory buffer of the screenshot.
3302          * <p>
3303          * <strong>Note:</strong> The application should call {@link HardwareBuffer#close()} when
3304          * the buffer is no longer needed to free the underlying resources.
3305          * </p>
3306          *
3307          * @return the hardware buffer
3308          */
3309         @NonNull
3310         public HardwareBuffer getHardwareBuffer() {
3311             return mHardwareBuffer;
3312         }
3313 
3314         /**
3315          * Gets the timestamp of taking the screenshot.
3316          *
3317          * @return milliseconds of non-sleep uptime before screenshot since boot and it's from
3318          * {@link SystemClock#uptimeMillis()}
3319          */
3320         public long getTimestamp() {
3321             return mTimestamp;
3322         };
3323     }
3324 
3325     /**
3326      * When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
3327      * function requests that touch interactions starting in the specified region of the screen
3328      * bypass the gesture detector. There can only be one gesture detection passthrough region per
3329      * display. Requesting a new gesture detection passthrough region clears the existing one. To
3330      * disable this passthrough and return to the original behavior, pass in an empty region. When
3331      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this
3332      * function has no effect.
3333      *
3334      * @param displayId The display on which to set this region.
3335      * @param region the region of the screen.
3336      */
3337     public void setGestureDetectionPassthroughRegion(int displayId, @NonNull Region region) {
3338         Preconditions.checkNotNull(region, "region cannot be null");
3339         final IAccessibilityServiceConnection connection =
3340                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
3341         if (connection != null) {
3342             try {
3343                 connection.setGestureDetectionPassthroughRegion(displayId, region);
3344             } catch (RemoteException re) {
3345                 throw new RuntimeException(re);
3346             }
3347         }
3348     }
3349 
3350     /**
3351      * When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
3352      * function requests that touch interactions starting in the specified region of the screen
3353      * bypass the touch explorer and go straight to the view hierarchy. There can only be one touch
3354      * exploration passthrough region per display. Requesting a new touch explorationpassthrough
3355      * region clears the existing one. To disable this passthrough and return to the original
3356      * behavior, pass in an empty region. When {@link
3357      * AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this function has
3358      * no effect.
3359      *
3360      * @param displayId The display on which to set this region.
3361      * @param region the region of the screen .
3362      */
3363     public void setTouchExplorationPassthroughRegion(int displayId, @NonNull Region region) {
3364         Preconditions.checkNotNull(region, "region cannot be null");
3365         final IAccessibilityServiceConnection connection =
3366                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
3367         if (connection != null) {
3368             try {
3369                 connection.setTouchExplorationPassthroughRegion(displayId, region);
3370             } catch (RemoteException re) {
3371                 throw new RuntimeException(re);
3372             }
3373         }
3374     }
3375 
3376     /**
3377      * Sets the system settings values that control the scaling factor for animations. The scale
3378      * controls the animation playback speed for animations that respect these settings. Animations
3379      * that do not respect the settings values will not be affected by this function. A lower scale
3380      * value results in a faster speed. A value of <code>0</code> disables animations entirely. When
3381      * animations are disabled services receive window change events more quickly which can reduce
3382      * the potential by confusion by reducing the time during which windows are in transition.
3383      *
3384      * @see AccessibilityEvent#TYPE_WINDOWS_CHANGED
3385      * @see AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
3386      * @see android.provider.Settings.Global#WINDOW_ANIMATION_SCALE
3387      * @see android.provider.Settings.Global#TRANSITION_ANIMATION_SCALE
3388      * @see android.provider.Settings.Global#ANIMATOR_DURATION_SCALE
3389      * @param scale The scaling factor for all animations.
3390      */
3391     public void setAnimationScale(float scale) {
3392         final IAccessibilityServiceConnection connection =
3393                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
3394         if (connection != null) {
3395             try {
3396                 connection.setAnimationScale(scale);
3397             } catch (RemoteException re) {
3398                 throw new RuntimeException(re);
3399             }
3400         }
3401     }
3402 
3403     private static class AccessibilityContext extends ContextWrapper {
3404         private final int mConnectionId;
3405 
3406         private AccessibilityContext(Context base, int connectionId) {
3407             super(base);
3408             mConnectionId = connectionId;
3409             setDefaultTokenInternal(this, getDisplayId());
3410         }
3411 
3412         @NonNull
3413         @Override
3414         public Context createDisplayContext(Display display) {
3415             return new AccessibilityContext(super.createDisplayContext(display), mConnectionId);
3416         }
3417 
3418         @NonNull
3419         @Override
3420         public Context createWindowContext(int type, @Nullable Bundle options) {
3421             final Context context = super.createWindowContext(type, options);
3422             if (type != TYPE_ACCESSIBILITY_OVERLAY) {
3423                 return context;
3424             }
3425             return new AccessibilityContext(context, mConnectionId);
3426         }
3427 
3428         @NonNull
3429         @Override
3430         public Context createWindowContext(@NonNull Display display, int type,
3431                 @Nullable Bundle options) {
3432             final Context context = super.createWindowContext(display, type, options);
3433             if (type != TYPE_ACCESSIBILITY_OVERLAY) {
3434                 return context;
3435             }
3436             return new AccessibilityContext(context, mConnectionId);
3437         }
3438 
3439         private void setDefaultTokenInternal(Context context, int displayId) {
3440             final WindowManagerImpl wm = (WindowManagerImpl) context.getSystemService(
3441                     WINDOW_SERVICE);
3442             final IAccessibilityServiceConnection connection =
3443                     AccessibilityInteractionClient.getConnection(mConnectionId);
3444             IBinder token = null;
3445             if (connection != null) {
3446                 try {
3447                     token = connection.getOverlayWindowToken(displayId);
3448                 } catch (RemoteException re) {
3449                     Log.w(LOG_TAG, "Failed to get window token", re);
3450                     re.rethrowFromSystemServer();
3451                 }
3452                 wm.setDefaultToken(token);
3453             }
3454         }
3455     }
3456 
3457     /**
3458      * Returns the touch interaction controller for the specified logical display, which may be used
3459      * to detect gestures and otherwise control touch interactions. If
3460      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled the
3461      * controller's methods will have no effect.
3462      *
3463      * @param displayId The logical display id, use {@link Display#DEFAULT_DISPLAY} for default
3464      *                      display.
3465      * @return the TouchExploration controller
3466      */
3467     @NonNull
3468     public final TouchInteractionController getTouchInteractionController(int displayId) {
3469         synchronized (mLock) {
3470             TouchInteractionController controller = mTouchInteractionControllers.get(displayId);
3471             if (controller == null) {
3472                 controller = new TouchInteractionController(this, mLock, displayId);
3473                 mTouchInteractionControllers.put(displayId, controller);
3474             }
3475             return controller;
3476         }
3477     }
3478 
3479     void sendMotionEventToCallback(MotionEvent event) {
3480         boolean sendingTouchEventToTouchInteractionController = false;
3481         if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) {
3482             TouchInteractionController controller;
3483             synchronized (mLock) {
3484                 int displayId = event.getDisplayId();
3485                 controller = mTouchInteractionControllers.get(displayId);
3486             }
3487             if (controller != null) {
3488                 sendingTouchEventToTouchInteractionController = true;
3489                 controller.onMotionEvent(event);
3490             }
3491         }
3492         final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK;
3493         if ((mMotionEventSources & eventSourceWithoutClass) != 0
3494                 && !sendingTouchEventToTouchInteractionController) {
3495             onMotionEvent(event);
3496         }
3497     }
3498 
3499     void onTouchStateChanged(int displayId, int state) {
3500         TouchInteractionController controller;
3501         synchronized (mLock) {
3502             controller = mTouchInteractionControllers.get(displayId);
3503         }
3504         if (controller != null) {
3505             controller.onStateChanged(state);
3506         }
3507     }
3508 
3509     /**
3510      * Attaches a {@link android.view.SurfaceControl} containing an accessibility overlay to the
3511      * specified display. This type of overlay should be used for content that does not need to
3512      * track the location and size of Views in the currently active app e.g. service configuration
3513      * or general service UI.
3514      *
3515      * <p>Generally speaking, an accessibility overlay will be a {@link android.view.View}. To embed
3516      * the View into a {@link android.view.SurfaceControl}, create a {@link
3517      * android.view.SurfaceControlViewHost} and attach the View using {@link
3518      * android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by calling
3519      * <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.
3520      *
3521      * <p>To remove this overlay and free the associated resources, use <code>
3522      *  new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
3523      *
3524      * <p>If the specified overlay has already been attached to the specified display this method
3525      * does nothing. If the specified overlay has already been attached to a previous display this
3526      * function will transfer the overlay to the new display. Services can attach multiple overlays.
3527      * Use <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>. to
3528      * coordinate the order of the overlays on screen.
3529      *
3530      * @param displayId the display to which the SurfaceControl should be attached.
3531      * @param sc the SurfaceControl containing the overlay content
3532      *
3533      */
3534     public void attachAccessibilityOverlayToDisplay(int displayId, @NonNull SurfaceControl sc) {
3535         Preconditions.checkNotNull(sc, "SurfaceControl cannot be null");
3536         AccessibilityInteractionClient.getInstance(this)
3537                 .attachAccessibilityOverlayToDisplay(mConnectionId, displayId, sc, null, null);
3538     }
3539 
3540     /**
3541      * Attaches a {@link android.view.SurfaceControl} containing an accessibility overlay to the
3542      * specified display. This type of overlay should be used for content that does not need to
3543      * track the location and size of Views in the currently active app e.g. service configuration
3544      * or general service UI.
3545      *
3546      * <p>Generally speaking, an accessibility overlay will be a {@link android.view.View}. To embed
3547      * the View into a {@link android.view.SurfaceControl}, create a {@link
3548      * android.view.SurfaceControlViewHost} and attach the View using {@link
3549      * android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by calling
3550      * <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.
3551      *
3552      * <p>To remove this overlay and free the associated resources, use <code>
3553      *  new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
3554      *
3555      * <p>If the specified overlay has already been attached to the specified display this method
3556      * does nothing. If the specified overlay has already been attached to a previous display this
3557      * function will transfer the overlay to the new display. Services can attach multiple overlays.
3558      * Use <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>. to
3559      * coordinate the order of the overlays on screen.
3560      *
3561      * @param displayId the display to which the SurfaceControl should be attached.
3562      * @param sc the SurfaceControl containing the overlay content
3563      * @param executor Executor on which to run the callback.
3564      * @param callback The callback invoked when attaching the overlay has succeeded or failed. The
3565      *     callback is a {@link java.util.function.IntConsumer} of the result status code.
3566      * @see #OVERLAY_RESULT_SUCCESS
3567      * @see #OVERLAY_RESULT_INVALID
3568      * @see #OVERLAY_RESULT_INTERNAL_ERROR
3569      */
3570     @FlaggedApi(android.view.accessibility.Flags.FLAG_A11Y_OVERLAY_CALLBACKS)
3571     public final void attachAccessibilityOverlayToDisplay(
3572             int displayId,
3573             @NonNull SurfaceControl sc,
3574             @NonNull @CallbackExecutor Executor executor,
3575             @NonNull IntConsumer callback) {
3576         Preconditions.checkNotNull(sc, "SurfaceControl cannot be null");
3577         AccessibilityInteractionClient.getInstance(this)
3578                 .attachAccessibilityOverlayToDisplay(
3579                         mConnectionId, displayId, sc, executor, callback);
3580     }
3581 
3582     /**
3583      * Attaches an accessibility overlay {@link android.view.SurfaceControl} to the specified
3584      * window. This method should be used when you want the overlay to move and resize as the parent
3585      * window moves and resizes.
3586      *
3587      * <p>Generally speaking, an accessibility overlay will be a {@link android.view.View}. To embed
3588      * the View into a {@link android.view.SurfaceControl}, create a {@link
3589      * android.view.SurfaceControlViewHost} and attach the View using {@link
3590      * android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by calling
3591      * <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.
3592      *
3593      * <p>To remove this overlay and free the associated resources, use <code>
3594      *  new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
3595      *
3596      * <p>If the specified overlay has already been attached to the specified window this method
3597      * does nothing. If the specified overlay has already been attached to a previous window this
3598      * function will transfer the overlay to the new window. Services can attach multiple overlays.
3599      * Use <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>. to
3600      * coordinate the order of the overlays on screen.
3601      *
3602      * @param accessibilityWindowId The window id, from {@link AccessibilityWindowInfo#getId()}.
3603      * @param sc the SurfaceControl containing the overlay content
3604      *
3605      */
3606     public void attachAccessibilityOverlayToWindow(
3607             int accessibilityWindowId, @NonNull SurfaceControl sc) {
3608         Preconditions.checkNotNull(sc, "SurfaceControl cannot be null");
3609         AccessibilityInteractionClient.getInstance(this)
3610                 .attachAccessibilityOverlayToWindow(
3611                         mConnectionId, accessibilityWindowId, sc, null, null);
3612     }
3613 
3614     /**
3615      * Attaches an accessibility overlay {@link android.view.SurfaceControl} to the specified
3616      * window. This method should be used when you want the overlay to move and resize as the parent
3617      * window moves and resizes.
3618      *
3619      * <p>Generally speaking, an accessibility overlay will be a {@link android.view.View}. To embed
3620      * the View into a {@link android.view.SurfaceControl}, create a {@link
3621      * android.view.SurfaceControlViewHost} and attach the View using {@link
3622      * android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by calling
3623      * <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.
3624      *
3625      * <p>To remove this overlay and free the associated resources, use <code>
3626      *  new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
3627      *
3628      * <p>If the specified overlay has already been attached to the specified window this method
3629      * does nothing. If the specified overlay has already been attached to a previous window this
3630      * function will transfer the overlay to the new window. Services can attach multiple overlays.
3631      * Use <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>. to
3632      * coordinate the order of the overlays on screen.
3633      *
3634      * @param accessibilityWindowId The window id, from {@link AccessibilityWindowInfo#getId()}.
3635      * @param sc the SurfaceControl containing the overlay content
3636      * @param executor Executor on which to run the callback.
3637      * @param callback The callback invoked when attaching the overlay has succeeded or failed. The
3638      *     callback is a {@link java.util.function.IntConsumer} of the result status code.
3639      * @see #OVERLAY_RESULT_SUCCESS
3640      * @see #OVERLAY_RESULT_INVALID
3641      * @see #OVERLAY_RESULT_INTERNAL_ERROR
3642      */
3643     @FlaggedApi(android.view.accessibility.Flags.FLAG_A11Y_OVERLAY_CALLBACKS)
3644     public final void attachAccessibilityOverlayToWindow(
3645             int accessibilityWindowId,
3646             @NonNull SurfaceControl sc,
3647             @NonNull @CallbackExecutor Executor executor,
3648             @NonNull IntConsumer callback) {
3649         Preconditions.checkNotNull(sc, "SurfaceControl cannot be null");
3650         AccessibilityInteractionClient.getInstance(this)
3651                 .attachAccessibilityOverlayToWindow(
3652                         mConnectionId, accessibilityWindowId, sc, executor, callback);
3653     }
3654 
3655     /**
3656      * Returns the {@link BrailleDisplayController} which may be used to communicate with
3657      * refreshable Braille displays that provide USB or Bluetooth Braille display HID support.
3658      */
3659     @FlaggedApi(android.view.accessibility.Flags.FLAG_BRAILLE_DISPLAY_HID)
3660     @NonNull
3661     public final BrailleDisplayController getBrailleDisplayController() {
3662         BrailleDisplayController.checkApiFlagIsEnabled();
3663         synchronized (mLock) {
3664             if (mBrailleDisplayController == null) {
3665                 mBrailleDisplayController = new BrailleDisplayControllerImpl(this, mLock);
3666             }
3667             return mBrailleDisplayController;
3668         }
3669     }
3670 }
3671