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