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.util.AccessibilityUtils.getFilteredHtmlText;
20 import static android.accessibilityservice.util.AccessibilityUtils.loadSafeAnimatedImage;
21 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
22 
23 import android.annotation.FlaggedApi;
24 import android.annotation.IntDef;
25 import android.annotation.IntRange;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.SystemApi;
29 import android.annotation.TestApi;
30 import android.compat.annotation.ChangeId;
31 import android.compat.annotation.EnabledAfter;
32 import android.compat.annotation.UnsupportedAppUsage;
33 import android.content.ComponentName;
34 import android.content.Context;
35 import android.content.pm.PackageManager;
36 import android.content.pm.PackageManager.NameNotFoundException;
37 import android.content.pm.ResolveInfo;
38 import android.content.pm.ServiceInfo;
39 import android.content.res.Resources;
40 import android.content.res.TypedArray;
41 import android.content.res.XmlResourceParser;
42 import android.graphics.drawable.Drawable;
43 import android.hardware.fingerprint.FingerprintManager;
44 import android.os.Build;
45 import android.os.IBinder;
46 import android.os.Parcel;
47 import android.os.Parcelable;
48 import android.os.RemoteException;
49 import android.util.AttributeSet;
50 import android.util.SparseArray;
51 import android.util.TypedValue;
52 import android.util.Xml;
53 import android.view.InputDevice;
54 import android.view.View;
55 import android.view.accessibility.AccessibilityEvent;
56 import android.view.accessibility.AccessibilityNodeInfo;
57 import android.view.accessibility.Flags;
58 
59 import com.android.internal.R;
60 import com.android.internal.compat.IPlatformCompat;
61 
62 import org.xmlpull.v1.XmlPullParser;
63 import org.xmlpull.v1.XmlPullParserException;
64 
65 import java.io.IOException;
66 import java.lang.annotation.Retention;
67 import java.lang.annotation.RetentionPolicy;
68 import java.util.ArrayList;
69 import java.util.Collections;
70 import java.util.List;
71 
72 /**
73  * This class describes an {@link AccessibilityService}. The system notifies an
74  * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s
75  * according to the information encapsulated in this class.
76  *
77  * <div class="special reference">
78  * <h3>Developer Guides</h3>
79  * <p>For more information about creating AccessibilityServices, read the
80  * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
81  * developer guide.</p>
82  * </div>
83  *
84  * @attr ref android.R.styleable#AccessibilityService_accessibilityEventTypes
85  * @attr ref android.R.styleable#AccessibilityService_accessibilityFeedbackType
86  * @attr ref android.R.styleable#AccessibilityService_accessibilityFlags
87  * @attr ref android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
88  * @attr ref android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
89  * @attr ref android.R.styleable#AccessibilityService_canRetrieveWindowContent
90  * @attr ref android.R.styleable#AccessibilityService_intro
91  * @attr ref android.R.styleable#AccessibilityService_description
92  * @attr ref android.R.styleable#AccessibilityService_summary
93  * @attr ref android.R.styleable#AccessibilityService_notificationTimeout
94  * @attr ref android.R.styleable#AccessibilityService_packageNames
95  * @attr ref android.R.styleable#AccessibilityService_settingsActivity
96  * @attr ref android.R.styleable#AccessibilityService_tileService
97  * @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
98  * @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout
99  * @attr ref android.R.styleable#AccessibilityService_canTakeScreenshot
100  * @see AccessibilityService
101  * @see android.view.accessibility.AccessibilityEvent
102  * @see android.view.accessibility.AccessibilityManager
103  */
104 public class AccessibilityServiceInfo implements Parcelable {
105 
106     private static final String TAG_ACCESSIBILITY_SERVICE = "accessibility-service";
107 
108     /**
109      * Capability: This accessibility service can retrieve the active window content.
110      * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
111      */
112     public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1 /* << 0 */;
113 
114     /**
115      * Capability: This accessibility service can request touch exploration mode in which
116      * touched items are spoken aloud and the UI can be explored via gestures.
117      * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
118      */
119     public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 1 << 1;
120 
121     /**
122      * @deprecated No longer used
123      */
124     @Deprecated
125     public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 1 << 2;
126 
127     /**
128      * Capability: This accessibility service can request to filter the key event stream.
129      * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
130      */
131     public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 1 << 3;
132 
133     /**
134      * Capability: This accessibility service can control display magnification.
135      * @see android.R.styleable#AccessibilityService_canControlMagnification
136      */
137     public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 1 << 4;
138 
139     /**
140      * Capability: This accessibility service can perform gestures.
141      * @see android.R.styleable#AccessibilityService_canPerformGestures
142      */
143     public static final int CAPABILITY_CAN_PERFORM_GESTURES = 1 << 5;
144 
145     /**
146      * Capability: This accessibility service can capture gestures from the fingerprint sensor
147      * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
148      */
149     public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 1 << 6;
150 
151     /**
152      * Capability: This accessibility service can take screenshot.
153      * @see android.R.styleable#AccessibilityService_canTakeScreenshot
154      */
155     public static final int CAPABILITY_CAN_TAKE_SCREENSHOT = 1 << 7;
156 
157     private static SparseArray<CapabilityInfo> sAvailableCapabilityInfos;
158 
159     /**
160      * Denotes spoken feedback.
161      */
162     public static final int FEEDBACK_SPOKEN = 1 /* << 0 */;
163 
164     /**
165      * Denotes haptic feedback.
166      */
167     public static final int FEEDBACK_HAPTIC =  1 << 1;
168 
169     /**
170      * Denotes audible (not spoken) feedback.
171      */
172     public static final int FEEDBACK_AUDIBLE = 1 << 2;
173 
174     /**
175      * Denotes visual feedback.
176      */
177     public static final int FEEDBACK_VISUAL = 1 << 3;
178 
179     /**
180      * Denotes generic feedback.
181      */
182     public static final int FEEDBACK_GENERIC = 1 << 4;
183 
184     /**
185      * Denotes braille feedback.
186      */
187     public static final int FEEDBACK_BRAILLE = 1 << 5;
188 
189     /**
190      * Mask for all feedback types.
191      *
192      * @see #FEEDBACK_SPOKEN
193      * @see #FEEDBACK_HAPTIC
194      * @see #FEEDBACK_AUDIBLE
195      * @see #FEEDBACK_VISUAL
196      * @see #FEEDBACK_GENERIC
197      * @see #FEEDBACK_BRAILLE
198      */
199     public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
200 
201     /**
202      * If an {@link AccessibilityService} is the default for a given type.
203      * Default service is invoked only if no package specific one exists. In case of
204      * more than one package specific service only the earlier registered is notified.
205      */
206     public static final int DEFAULT = 1 /* << 0 */;
207 
208     /**
209      * If this flag is set the system will regard views that are not important
210      * for accessibility in addition to the ones that are important for accessibility.
211      * That is, views that are marked as not important for accessibility via
212      * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or
213      * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are
214      * marked as potentially important for accessibility via
215      * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined
216      * that are not important for accessibility, are reported while querying the window
217      * content and also the accessibility service will receive accessibility events from
218      * them.
219      * <p>
220      * <strong>Note:</strong> For accessibility services targeting Android 4.1 (API level 16) or
221      * higher, this flag has to be explicitly set for the system to regard views that are not
222      * important for accessibility. For accessibility services targeting Android 4.0.4 (API level
223      * 15) or lower, this flag is ignored and all views are regarded for accessibility purposes.
224      * </p>
225      * <p>
226      * Usually views not important for accessibility are layout managers that do not
227      * react to user actions, do not draw any content, and do not have any special
228      * semantics in the context of the screen content. For example, a three by three
229      * grid can be implemented as three horizontal linear layouts and one vertical,
230      * or three vertical linear layouts and one horizontal, or one grid layout, etc.
231      * In this context, the actual layout managers used to achieve the grid configuration
232      * are not important; rather it is important that there are nine evenly distributed
233      * elements.
234      * </p>
235      */
236     public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 1 << 1;
237 
238     /**
239      * This flag requests that the system gets into touch exploration mode.
240      * In this mode a single finger moving on the screen behaves as a mouse
241      * pointer hovering over the user interface. The system will also detect
242      * certain gestures performed on the touch screen and notify this service.
243      * The system will enable touch exploration mode if there is at least one
244      * accessibility service that has this flag set. Hence, clearing this
245      * flag does not guarantee that the device will not be in touch exploration
246      * mode since there may be another enabled service that requested it.
247      * <p>
248      * For accessibility services targeting Android 4.3 (API level 18) or higher
249      * that want to set this flag have to declare this capability in their
250      * meta-data by setting the attribute
251      * {@link android.R.attr#canRequestTouchExplorationMode
252      * canRequestTouchExplorationMode} to true. Otherwise, this flag will
253      * be ignored. For how to declare the meta-data of a service refer to
254      * {@value AccessibilityService#SERVICE_META_DATA}.
255      * </p>
256      * <p>
257      * Services targeting Android 4.2.2 (API level 17) or lower will work
258      * normally. In other words, the first time they are run, if this flag is
259      * specified, a dialog is shown to the user to confirm enabling explore by
260      * touch.
261      * </p>
262      * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
263      */
264     public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 1 << 2;
265 
266     /**
267      * @deprecated No longer used
268      */
269     @Deprecated
270     public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 1 << 3;
271 
272     /**
273      * This flag requests that the {@link AccessibilityNodeInfo}s obtained
274      * by an {@link AccessibilityService} contain the id of the source view.
275      * The source view id will be a fully qualified resource name of the
276      * form "package:id/name", for example "foo.bar:id/my_list", and it is
277      * useful for UI test automation. This flag is not set by default.
278      */
279     public static final int FLAG_REPORT_VIEW_IDS = 1 << 4;
280 
281     /**
282      * This flag requests from the system to filter key events. If this flag
283      * is set the accessibility service will receive the key events before
284      * applications allowing it implement global shortcuts.
285      * <p>
286      * Services that want to set this flag have to declare this capability
287      * in their meta-data by setting the attribute {@link android.R.attr
288      * #canRequestFilterKeyEvents canRequestFilterKeyEvents} to true,
289      * otherwise this flag will be ignored. For how to declare the meta-data
290      * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
291      * </p>
292      * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
293      */
294     public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 1 << 5;
295 
296     /**
297      * This flag indicates to the system that the accessibility service wants
298      * to access content of all interactive windows. An interactive window is a
299      * window that has input focus or can be touched by a sighted user when explore
300      * by touch is not enabled. If this flag is not set your service will not receive
301      * {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED}
302      * events, calling AccessibilityService{@link AccessibilityService#getWindows()
303      * AccessibilityService.getWindows()} will return an empty list, and {@link
304      * AccessibilityNodeInfo#getWindow() AccessibilityNodeInfo.getWindow()} will
305      * return null.
306      * <p>
307      * Services that want to set this flag have to declare the capability
308      * to retrieve window content in their meta-data by setting the attribute
309      * {@link android.R.attr#canRetrieveWindowContent canRetrieveWindowContent} to
310      * true, otherwise this flag will be ignored. For how to declare the meta-data
311      * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
312      * </p>
313      * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
314      */
315     public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 1 << 6;
316 
317     /**
318      * This flag requests that all audio tracks system-wide with
319      * {@link android.media.AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY} be controlled by the
320      * {@link android.media.AudioManager#STREAM_ACCESSIBILITY} volume.
321      */
322     public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 1 << 7;
323 
324      /**
325      * This flag indicates to the system that the accessibility service requests that an
326      * accessibility button be shown within the system's navigation area, if available.
327       * <p>
328       *   <strong>Note:</strong> For accessibility services targeting APIs greater than
329       *   {@link Build.VERSION_CODES#Q API 29}, this flag must be specified in the
330       *   accessibility service metadata file. Otherwise, it will be ignored.
331       * </p>
332      */
333     public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 1 << 8;
334 
335     /**
336      * This flag requests that all fingerprint gestures be sent to the accessibility service.
337      * <p>
338      * Services that want to set this flag have to declare the capability
339      * to retrieve window content in their meta-data by setting the attribute
340      * {@link android.R.attr#canRequestFingerprintGestures} to
341      * true, otherwise this flag will be ignored. For how to declare the meta-data
342      * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
343      * </p>
344      *
345      * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
346      * @see AccessibilityService#getFingerprintGestureController()
347      */
348     public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 1 << 9;
349 
350     /**
351      * This flag requests that accessibility shortcut warning dialog has spoken feedback when
352      * dialog is shown.
353      */
354     public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1 << 10;
355 
356     /**
357      * This flag requests that when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
358      * double tap and double tap and hold gestures are dispatched to the service rather than being
359      * handled by the framework. If {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this
360      * flag has no effect.
361      *
362      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
363      */
364     public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 1 << 11;
365 
366     /**
367      * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
368      * multi-finger gestures are also enabled. As a consequence, two-finger bypass gestures will be
369      * disabled. If {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this flag has no
370      * effect.
371      *
372      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
373      */
374     public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 1 << 12;
375 
376     /**
377      * This flag requests that when when {@link #FLAG_REQUEST_MULTI_FINGER_GESTURES} is enabled,
378      * two-finger passthrough gestures are re-enabled. Two-finger swipe gestures are not detected,
379      * but instead passed through as one-finger gestures. In addition, three-finger swipes from the
380      * bottom of the screen are not detected, and instead are passed through unchanged. If {@link
381      * #FLAG_REQUEST_MULTI_FINGER_GESTURES} is disabled this flag has no effect.
382      *
383      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
384      */
385     public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 1 << 13;
386 
387     /**
388      * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, a
389      * service will receive the motion events for each successfully-detected gesture. The service
390      * will also receive an AccessibilityGestureEvent of type GESTURE_INVALID for each cancelled
391      * gesture along with its motion events. A service will receive a gesture of type
392      * GESTURE_PASSTHROUGH and accompanying motion events for every passthrough gesture that does
393      * not start gesture detection. This information can be used to collect instances of improper
394      * gesture detection behavior and relay that information to framework developers. If {@link
395      * #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this flag has no effect.
396      *
397      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
398      */
399     public static final int FLAG_SEND_MOTION_EVENTS = 1 << 14;
400 
401     /**
402      * This flag makes the AccessibilityService an input method editor with a subset of input
403      * method editor capabilities: get the {@link android.view.inputmethod.InputConnection} and get
404      * text selection change notifications.
405      *
406      * @see AccessibilityService#getInputMethod()
407      */
408     public static final int FLAG_INPUT_METHOD_EDITOR = 1 << 15;
409 
410     /** {@hide} */
411     public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 1 << 16;
412 
413     /**
414      * The event types an {@link AccessibilityService} is interested in.
415      * <p>
416      *   <strong>Can be dynamically set at runtime.</strong>
417      * </p>
418      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED
419      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED
420      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED
421      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED
422      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
423      * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
424      * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
425      * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START
426      * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END
427      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER
428      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT
429      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED
430      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED
431      * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
432      * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_START
433      * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_END
434      * @see android.view.accessibility.AccessibilityEvent#TYPE_ANNOUNCEMENT
435      * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_START
436      * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_END
437      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED
438      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
439      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
440      * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED
441      */
442     public int eventTypes;
443 
444     /**
445      * The package names an {@link AccessibilityService} is interested in. Setting
446      * to <code>null</code> is equivalent to all packages.
447      * <p>
448      *   <strong>Can be dynamically set at runtime.</strong>
449      * </p>
450      */
451     public String[] packageNames;
452 
453 
454     /** @hide */
455     @IntDef(flag = true, prefix = { "FEEDBACK_" }, value = {
456             FEEDBACK_AUDIBLE,
457             FEEDBACK_GENERIC,
458             FEEDBACK_HAPTIC,
459             FEEDBACK_SPOKEN,
460             FEEDBACK_VISUAL,
461             FEEDBACK_BRAILLE
462     })
463     @Retention(RetentionPolicy.SOURCE)
464     public @interface FeedbackType {}
465 
466     /**
467      * The feedback type an {@link AccessibilityService} provides.
468      * <p>
469      *   <strong>Can be dynamically set at runtime.</strong>
470      * </p>
471      * @see #FEEDBACK_AUDIBLE
472      * @see #FEEDBACK_GENERIC
473      * @see #FEEDBACK_HAPTIC
474      * @see #FEEDBACK_SPOKEN
475      * @see #FEEDBACK_VISUAL
476      * @see #FEEDBACK_BRAILLE
477      */
478     @FeedbackType
479     public int feedbackType;
480 
481     /**
482      * The timeout, in milliseconds, after the most recent event of a given type before an
483      * {@link AccessibilityService} is notified.
484      * <p>
485      *   <strong>Can be dynamically set at runtime.</strong>
486      * </p>
487      * <p>
488      * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
489      *       events to the client too frequently since this is accomplished via an expensive
490      *       interprocess call. One can think of the timeout as a criteria to determine when
491      *       event generation has settled down.
492      */
493     public long notificationTimeout;
494 
495     /**
496      * This field represents a set of flags used for configuring an
497      * {@link AccessibilityService}.
498      * <p>
499      *   <strong>Can be dynamically set at runtime.</strong>
500      * </p>
501      * <p>
502      *   <strong>Note:</strong> Accessibility services with targetSdkVersion greater than
503      *   {@link Build.VERSION_CODES#Q API 29} cannot dynamically set the
504      *   {@link #FLAG_REQUEST_ACCESSIBILITY_BUTTON} at runtime. It must be specified in the
505      *   accessibility service metadata file.
506      * </p>
507      * @see #DEFAULT
508      * @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
509      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
510      * @see #FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY
511      * @see #FLAG_REQUEST_FILTER_KEY_EVENTS
512      * @see #FLAG_REPORT_VIEW_IDS
513      * @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS
514      * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
515      * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
516      * @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
517      * @see #FLAG_INPUT_METHOD_EDITOR
518      */
519     public int flags;
520 
521     /**
522      * Whether or not the service has crashed and is awaiting restart. Only valid from {@link
523      * android.view.accessibility.AccessibilityManager#getInstalledAccessibilityServiceList()},
524      * because that is populated from the internal list of running services.
525      *
526      * @hide
527      */
528     public boolean crashed;
529 
530     /**
531      * A recommended timeout in milliseconds for non-interactive controls.
532      */
533     private int mNonInteractiveUiTimeout;
534 
535     /**
536      * A recommended timeout in milliseconds for interactive controls.
537      */
538     private int mInteractiveUiTimeout;
539 
540     /**
541      * The component name the accessibility service.
542      */
543     @NonNull
544     private ComponentName mComponentName;
545 
546     /**
547      * The Service that implements this accessibility service component.
548      */
549     private ResolveInfo mResolveInfo;
550 
551     /**
552      * The accessibility service setting activity's name, used by the system
553      * settings to launch the setting activity of this accessibility service.
554      */
555     private String mSettingsActivityName;
556 
557     /**
558      * The name of {@link android.service.quicksettings.TileService} is associated with this
559      * accessibility service for one to one mapping. It is used by system settings to remind users
560      * this accessibility service has a {@link android.service.quicksettings.TileService}.
561      */
562     private String mTileServiceName;
563 
564     /**
565      * Bit mask with capabilities of this service.
566      */
567     private int mCapabilities;
568 
569     /**
570      * Resource id of the summary of the accessibility service.
571      */
572     private int mSummaryResId;
573 
574     /**
575      * Non-localized summary of the accessibility service.
576      */
577     private String mNonLocalizedSummary;
578 
579     /**
580      * Resource id of the intro of the accessibility service.
581      */
582     private int mIntroResId;
583 
584     /**
585      * Resource id of the description of the accessibility service.
586      */
587     private int mDescriptionResId;
588 
589     /**
590      * Non localized description of the accessibility service.
591      */
592     private String mNonLocalizedDescription;
593 
594     /**
595      * For accessibility services targeting APIs greater than {@link Build.VERSION_CODES#Q API 29},
596      * {@link #FLAG_REQUEST_ACCESSIBILITY_BUTTON} must be specified in the accessibility service
597      * metadata file. Otherwise, it will be ignored.
598      */
599     @ChangeId
600     @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.Q)
601     private static final long REQUEST_ACCESSIBILITY_BUTTON_CHANGE = 136293963L;
602 
603     /**
604      * Resource id of the animated image of the accessibility service.
605      */
606     private int mAnimatedImageRes;
607 
608     /**
609      * Resource id of the html description of the accessibility service.
610      */
611     private int mHtmlDescriptionRes;
612 
613     /**
614      * Whether the service is for accessibility.
615      *
616      * @hide
617      */
618     private boolean mIsAccessibilityTool = false;
619 
620     /**
621      * {@link InputDevice} sources which may send {@link android.view.MotionEvent}s.
622      * @see #setMotionEventSources(int)
623      * @hide
624      */
625     @IntDef(flag = true, prefix = { "SOURCE_" }, value = {
626             InputDevice.SOURCE_MOUSE,
627             InputDevice.SOURCE_STYLUS,
628             InputDevice.SOURCE_BLUETOOTH_STYLUS,
629             InputDevice.SOURCE_TRACKBALL,
630             InputDevice.SOURCE_MOUSE_RELATIVE,
631             InputDevice.SOURCE_TOUCHPAD,
632             InputDevice.SOURCE_TOUCH_NAVIGATION,
633             InputDevice.SOURCE_ROTARY_ENCODER,
634             InputDevice.SOURCE_JOYSTICK,
635             InputDevice.SOURCE_SENSOR,
636             InputDevice.SOURCE_TOUCHSCREEN
637     })
638     @Retention(RetentionPolicy.SOURCE)
639     public @interface MotionEventSources {}
640 
641     /**
642      * The bit mask of {@link android.view.InputDevice} sources that the accessibility
643      * service wants to listen to for generic {@link android.view.MotionEvent}s.
644      */
645     @MotionEventSources
646     private int mMotionEventSources = 0;
647 
648     private int mObservedMotionEventSources = 0;
649 
650     // Default values for each dynamic property
651     // LINT.IfChange(dynamic_property_defaults)
652     private final DynamicPropertyDefaults mDynamicPropertyDefaults;
653 
654     private static class DynamicPropertyDefaults {
655         private final int mEventTypesDefault;
656         private final List<String> mPackageNamesDefault;
657         private final int mFeedbackTypeDefault;
658         private final long mNotificationTimeoutDefault;
659         private final int mFlagsDefault;
660         private final int mNonInteractiveUiTimeoutDefault;
661         private final int mInteractiveUiTimeoutDefault;
662         private final int mMotionEventSourcesDefault;
663         private final int mObservedMotionEventSourcesDefault;
664 
DynamicPropertyDefaults(AccessibilityServiceInfo info)665         DynamicPropertyDefaults(AccessibilityServiceInfo info) {
666             mEventTypesDefault = info.eventTypes;
667             if (info.packageNames != null) {
668                 mPackageNamesDefault = List.of(info.packageNames);
669             } else {
670                 mPackageNamesDefault = null;
671             }
672             mFeedbackTypeDefault = info.feedbackType;
673             mNotificationTimeoutDefault = info.notificationTimeout;
674             mNonInteractiveUiTimeoutDefault = info.mNonInteractiveUiTimeout;
675             mInteractiveUiTimeoutDefault = info.mInteractiveUiTimeout;
676             mFlagsDefault = info.flags;
677             mMotionEventSourcesDefault = info.mMotionEventSources;
678             mObservedMotionEventSourcesDefault = info.mObservedMotionEventSources;
679         }
680     }
681     // LINT.ThenChange(:dynamic_property_reset)
682 
683     /**
684      * Creates a new instance.
685      */
AccessibilityServiceInfo()686     public AccessibilityServiceInfo() {
687         mDynamicPropertyDefaults = new DynamicPropertyDefaults(this);
688     }
689 
690     /**
691      * Creates a new instance.
692      *
693      * @param resolveInfo The service resolve info.
694      * @param context Context for accessing resources.
695      * @throws XmlPullParserException If a XML parsing error occurs.
696      * @throws IOException If a XML parsing error occurs.
697      *
698      * @hide
699      */
AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context)700     public AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context)
701             throws XmlPullParserException, IOException {
702         ServiceInfo serviceInfo = resolveInfo.serviceInfo;
703         mComponentName = new ComponentName(serviceInfo.packageName, serviceInfo.name);
704         mResolveInfo = resolveInfo;
705 
706         XmlResourceParser parser = null;
707 
708         try {
709             PackageManager packageManager = context.getPackageManager();
710             parser = serviceInfo.loadXmlMetaData(packageManager,
711                     AccessibilityService.SERVICE_META_DATA);
712             if (parser == null) {
713                 return;
714             }
715 
716             int type = 0;
717             while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
718                 type = parser.next();
719             }
720 
721             String nodeName = parser.getName();
722             if (!TAG_ACCESSIBILITY_SERVICE.equals(nodeName)) {
723                 throw new XmlPullParserException( "Meta-data does not start with"
724                         + TAG_ACCESSIBILITY_SERVICE + " tag");
725             }
726 
727             AttributeSet allAttributes = Xml.asAttributeSet(parser);
728             Resources resources = packageManager.getResourcesForApplication(
729                     serviceInfo.applicationInfo);
730             TypedArray asAttributes = resources.obtainAttributes(allAttributes,
731                     com.android.internal.R.styleable.AccessibilityService);
732             eventTypes = asAttributes.getInt(
733                     com.android.internal.R.styleable.AccessibilityService_accessibilityEventTypes,
734                     0);
735             String packageNamez = asAttributes.getString(
736                     com.android.internal.R.styleable.AccessibilityService_packageNames);
737             if (packageNamez != null) {
738                 packageNames = packageNamez.split("(\\s)*,(\\s)*");
739             }
740             feedbackType = asAttributes.getInt(
741                     com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType,
742                     0);
743             notificationTimeout = asAttributes.getInt(
744                     com.android.internal.R.styleable.AccessibilityService_notificationTimeout,
745                     0);
746             mNonInteractiveUiTimeout = asAttributes.getInt(
747                     com.android.internal.R.styleable.AccessibilityService_nonInteractiveUiTimeout,
748                     0);
749             mInteractiveUiTimeout = asAttributes.getInt(
750                     com.android.internal.R.styleable.AccessibilityService_interactiveUiTimeout,
751                     0);
752             flags = asAttributes.getInt(
753                     com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
754             mSettingsActivityName = asAttributes.getString(
755                     com.android.internal.R.styleable.AccessibilityService_settingsActivity);
756             if (asAttributes.getBoolean(com.android.internal.R.styleable
757                     .AccessibilityService_canRetrieveWindowContent, false)) {
758                 mCapabilities |= CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT;
759             }
760             if (asAttributes.getBoolean(com.android.internal.R.styleable
761                     .AccessibilityService_canRequestTouchExplorationMode, false)) {
762                 mCapabilities |= CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION;
763             }
764             if (asAttributes.getBoolean(com.android.internal.R.styleable
765                     .AccessibilityService_canRequestFilterKeyEvents, false)) {
766                 mCapabilities |= CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS;
767             }
768             if (asAttributes.getBoolean(com.android.internal.R.styleable
769                     .AccessibilityService_canControlMagnification, false)) {
770                 mCapabilities |= CAPABILITY_CAN_CONTROL_MAGNIFICATION;
771             }
772             if (asAttributes.getBoolean(com.android.internal.R.styleable
773                     .AccessibilityService_canPerformGestures, false)) {
774                 mCapabilities |= CAPABILITY_CAN_PERFORM_GESTURES;
775             }
776             if (asAttributes.getBoolean(com.android.internal.R.styleable
777                     .AccessibilityService_canRequestFingerprintGestures, false)) {
778                 mCapabilities |= CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES;
779             }
780             if (asAttributes.getBoolean(com.android.internal.R.styleable
781                     .AccessibilityService_canTakeScreenshot, false)) {
782                 mCapabilities |= CAPABILITY_CAN_TAKE_SCREENSHOT;
783             }
784             TypedValue peekedValue = asAttributes.peekValue(
785                     com.android.internal.R.styleable.AccessibilityService_description);
786             if (peekedValue != null) {
787                 mDescriptionResId = peekedValue.resourceId;
788                 CharSequence nonLocalizedDescription = peekedValue.coerceToString();
789                 if (nonLocalizedDescription != null) {
790                     mNonLocalizedDescription = nonLocalizedDescription.toString().trim();
791                 }
792             }
793             peekedValue = asAttributes.peekValue(
794                     com.android.internal.R.styleable.AccessibilityService_summary);
795             if (peekedValue != null) {
796                 mSummaryResId = peekedValue.resourceId;
797                 CharSequence nonLocalizedSummary = peekedValue.coerceToString();
798                 if (nonLocalizedSummary != null) {
799                     mNonLocalizedSummary = nonLocalizedSummary.toString().trim();
800                 }
801             }
802             peekedValue = asAttributes.peekValue(
803                     com.android.internal.R.styleable.AccessibilityService_animatedImageDrawable);
804             if (peekedValue != null) {
805                 mAnimatedImageRes = peekedValue.resourceId;
806             }
807             peekedValue = asAttributes.peekValue(
808                     com.android.internal.R.styleable.AccessibilityService_htmlDescription);
809             if (peekedValue != null) {
810                 mHtmlDescriptionRes = peekedValue.resourceId;
811             }
812             mIsAccessibilityTool = asAttributes.getBoolean(
813                     R.styleable.AccessibilityService_isAccessibilityTool, false);
814             mTileServiceName = asAttributes.getString(
815                     com.android.internal.R.styleable.AccessibilityService_tileService);
816             peekedValue = asAttributes.peekValue(
817                     com.android.internal.R.styleable.AccessibilityService_intro);
818             if (peekedValue != null) {
819                 mIntroResId = peekedValue.resourceId;
820             }
821             asAttributes.recycle();
822         } catch (NameNotFoundException e) {
823             throw new XmlPullParserException( "Unable to create context for: "
824                     + serviceInfo.packageName);
825         } finally {
826             if (parser != null) {
827                 parser.close();
828             }
829 
830             mDynamicPropertyDefaults = new DynamicPropertyDefaults(this);
831         }
832     }
833 
834     /**
835      * Resets all dynamically configurable properties to their default values.
836      *
837      * @hide
838      */
839     // LINT.IfChange(dynamic_property_reset)
resetDynamicallyConfigurableProperties()840     public void resetDynamicallyConfigurableProperties() {
841         eventTypes = mDynamicPropertyDefaults.mEventTypesDefault;
842         if (mDynamicPropertyDefaults.mPackageNamesDefault == null) {
843             packageNames = null;
844         } else {
845             packageNames = mDynamicPropertyDefaults.mPackageNamesDefault.toArray(new String[0]);
846         }
847         feedbackType = mDynamicPropertyDefaults.mFeedbackTypeDefault;
848         notificationTimeout = mDynamicPropertyDefaults.mNotificationTimeoutDefault;
849         mNonInteractiveUiTimeout = mDynamicPropertyDefaults.mNonInteractiveUiTimeoutDefault;
850         mInteractiveUiTimeout = mDynamicPropertyDefaults.mInteractiveUiTimeoutDefault;
851         flags = mDynamicPropertyDefaults.mFlagsDefault;
852         mMotionEventSources = mDynamicPropertyDefaults.mMotionEventSourcesDefault;
853         if (Flags.motionEventObserving()) {
854             mObservedMotionEventSources = mDynamicPropertyDefaults
855                     .mObservedMotionEventSourcesDefault;
856         }
857     }
858     // LINT.ThenChange(:dynamic_property_update)
859 
860     /**
861      * Updates the properties that an AccessibilityService can change dynamically.
862      * <p>
863      * Note: A11y services targeting APIs > Q, it cannot update flagRequestAccessibilityButton
864      * dynamically.
865      * </p>
866      *
867      * @param platformCompat The platform compat service to check the compatibility change.
868      * @param other The info from which to update the properties.
869      *
870      * @hide
871      */
872     // LINT.IfChange(dynamic_property_update)
updateDynamicallyConfigurableProperties(IPlatformCompat platformCompat, AccessibilityServiceInfo other)873     public void updateDynamicallyConfigurableProperties(IPlatformCompat platformCompat,
874             AccessibilityServiceInfo other) {
875         if (isRequestAccessibilityButtonChangeEnabled(platformCompat)) {
876             other.flags &= ~FLAG_REQUEST_ACCESSIBILITY_BUTTON;
877             other.flags |= (flags & FLAG_REQUEST_ACCESSIBILITY_BUTTON);
878         }
879         eventTypes = other.eventTypes;
880         packageNames = other.packageNames;
881         feedbackType = other.feedbackType;
882         notificationTimeout = other.notificationTimeout;
883         mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout;
884         mInteractiveUiTimeout = other.mInteractiveUiTimeout;
885         flags = other.flags;
886         mMotionEventSources = other.mMotionEventSources;
887         if (Flags.motionEventObserving()) {
888             setObservedMotionEventSources(other.mObservedMotionEventSources);
889         }
890         // NOTE: Ensure that only properties that are safe to be modified by the service itself
891         // are included here (regardless of hidden setters, etc.).
892     }
893     // LINT.ThenChange(:dynamic_property_defaults)
894 
isRequestAccessibilityButtonChangeEnabled(IPlatformCompat platformCompat)895     private boolean isRequestAccessibilityButtonChangeEnabled(IPlatformCompat platformCompat) {
896         if (mResolveInfo == null) {
897             return true;
898         }
899         try {
900             if (platformCompat != null) {
901                 return platformCompat.isChangeEnabled(REQUEST_ACCESSIBILITY_BUTTON_CHANGE,
902                         mResolveInfo.serviceInfo.applicationInfo);
903             }
904         } catch (RemoteException ignore) {
905         }
906         return mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.Q;
907     }
908 
909     /**
910      * @hide
911      */
setComponentName(@onNull ComponentName component)912     public void setComponentName(@NonNull ComponentName component) {
913         mComponentName = component;
914     }
915 
916     /**
917      * @hide
918      */
setResolveInfo(@onNull ResolveInfo resolveInfo)919     public void setResolveInfo(@NonNull ResolveInfo resolveInfo) {
920         mResolveInfo = resolveInfo;
921     }
922 
923     /**
924      * @hide
925      */
926     @TestApi
927     @NonNull
getComponentName()928     public ComponentName getComponentName() {
929         return mComponentName;
930     }
931 
932     /**
933      * The accessibility service id.
934      * <p>
935      *   <strong>Generated by the system.</strong>
936      * </p>
937      * @return The id (or {@code null} if the component is not set yet).
938      */
getId()939     public String getId() {
940         return mComponentName == null ? null : mComponentName.flattenToShortString();
941     }
942 
943     /**
944      * The service {@link ResolveInfo}.
945      * <p>
946      *   <strong>Generated by the system.</strong>
947      * </p>
948      * @return The info.
949      */
getResolveInfo()950     public ResolveInfo getResolveInfo() {
951         return mResolveInfo;
952     }
953 
954     /**
955      * The settings activity name.
956      * <p>
957      *    <strong>Statically set from
958      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
959      * </p>
960      * @return The settings activity name.
961      */
getSettingsActivityName()962     public String getSettingsActivityName() {
963         return mSettingsActivityName;
964     }
965 
966     /**
967      * Gets the name of {@link android.service.quicksettings.TileService} is associated with
968      * this accessibility service.
969      *
970      * @return The name of {@link android.service.quicksettings.TileService}.
971      */
972     @Nullable
getTileServiceName()973     public String getTileServiceName() {
974         return mTileServiceName;
975     }
976 
977     /**
978      * Gets the animated image resource id.
979      *
980      * @return The animated image resource id.
981      *
982      * @hide
983      */
getAnimatedImageRes()984     public int getAnimatedImageRes() {
985         return mAnimatedImageRes;
986     }
987 
988     /**
989      * The animated image drawable.
990      * <p>
991      *    Image can not exceed the screen size.
992      *    <strong>Statically set from
993      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
994      * </p>
995      * @return The animated image drawable, or null if the resource is invalid or the image
996      * exceed the screen size.
997      *
998      * @hide
999      */
1000     @Nullable
loadAnimatedImage(@onNull Context context)1001     public Drawable loadAnimatedImage(@NonNull Context context)  {
1002         if (mAnimatedImageRes == /* invalid */ 0) {
1003             return null;
1004         }
1005 
1006         return loadSafeAnimatedImage(context, mResolveInfo.serviceInfo.applicationInfo,
1007                 mAnimatedImageRes);
1008     }
1009 
1010     /**
1011      * Whether this service can retrieve the current window's content.
1012      * <p>
1013      *    <strong>Statically set from
1014      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
1015      * </p>
1016      * @return True if window content can be retrieved.
1017      *
1018      * @deprecated Use {@link #getCapabilities()}.
1019      */
getCanRetrieveWindowContent()1020     public boolean getCanRetrieveWindowContent() {
1021         return (mCapabilities & CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
1022     }
1023 
1024     /**
1025      * Returns the bit mask of capabilities this accessibility service has such as
1026      * being able to retrieve the active window content, etc.
1027      *
1028      * @return The capability bit mask.
1029      *
1030      * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
1031      * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
1032      * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
1033      * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
1034      * @see #CAPABILITY_CAN_PERFORM_GESTURES
1035      * @see #CAPABILITY_CAN_TAKE_SCREENSHOT
1036      */
getCapabilities()1037     public int getCapabilities() {
1038         return mCapabilities;
1039     }
1040 
1041     /**
1042      * Sets the bit mask of capabilities this accessibility service has such as
1043      * being able to retrieve the active window content, etc.
1044      *
1045      * @param capabilities The capability bit mask.
1046      *
1047      * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
1048      * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
1049      * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
1050      * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
1051      * @see #CAPABILITY_CAN_PERFORM_GESTURES
1052      * @see #CAPABILITY_CAN_TAKE_SCREENSHOT
1053      *
1054      * @hide
1055      */
1056     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setCapabilities(int capabilities)1057     public void setCapabilities(int capabilities) {
1058         mCapabilities = capabilities;
1059     }
1060 
1061     /**
1062      * Returns the bit mask of {@link android.view.InputDevice} sources that the accessibility
1063      * service wants to listen to for generic {@link android.view.MotionEvent}s.
1064      */
1065     @MotionEventSources
getMotionEventSources()1066     public int getMotionEventSources() {
1067         return mMotionEventSources;
1068     }
1069 
1070     /**
1071      * Sets the bit mask of {@link android.view.InputDevice} sources that the accessibility
1072      * service wants to listen to for generic {@link android.view.MotionEvent}s.
1073      *
1074      * <p>
1075      * Including an {@link android.view.InputDevice} source that does not send
1076      * {@link android.view.MotionEvent}s is effectively a no-op for that source, since you will
1077      * not receive any events from that source.
1078      * </p>
1079      *
1080      * <p>
1081      * See {@link android.view.InputDevice} for complete source definitions.
1082      * Many input devices send {@link android.view.InputEvent}s from more than one type of source so
1083      * you may need to include multiple {@link android.view.MotionEvent} sources here, in addition
1084      * to using {@link AccessibilityService#onKeyEvent} to listen to {@link android.view.KeyEvent}s.
1085      * </p>
1086      *
1087      * <p>
1088      * <strong>Note:</strong> {@link android.view.InputDevice} sources contain source class bits
1089      * that complicate bitwise flag removal operations. To remove a specific source you should
1090      * rebuild the entire value using bitwise OR operations on the individual source constants.
1091      * </p>
1092      *
1093      * @param motionEventSources A bit mask of {@link android.view.InputDevice} sources.
1094      * @see AccessibilityService#onMotionEvent
1095      */
setMotionEventSources(@otionEventSources int motionEventSources)1096     public void setMotionEventSources(@MotionEventSources int motionEventSources) {
1097         mMotionEventSources = motionEventSources;
1098         mObservedMotionEventSources = 0;
1099     }
1100 
1101     /**
1102      * Sets the bit mask of {@link android.view.InputDevice} sources that the accessibility service
1103      * wants to observe generic {@link android.view.MotionEvent}s from if it has already requested
1104      * to listen to them using {@link #setMotionEventSources(int)}. Events from these sources will
1105      * be sent to the rest of the input pipeline without being consumed by accessibility services.
1106      * This service will still be able to see them.
1107      *
1108      * <p><strong>Note:</strong> you will need to call this function every time you call {@link
1109      * #setMotionEventSources(int)}. Calling {@link #setMotionEventSources(int)} clears the list of
1110      * observed motion event sources for this service.
1111      *
1112      * <p><strong>Note:</strong> {@link android.view.InputDevice} sources contain source class bits
1113      * that complicate bitwise flag removal operations. To remove a specific source you should
1114      * rebuild the entire value using bitwise OR operations on the individual source constants.
1115      *
1116      * <p>Including an {@link android.view.InputDevice} source that does not send {@link
1117      * android.view.MotionEvent}s is effectively a no-op for that source, since you will not receive
1118      * any events from that source.
1119      *
1120      * <p><strong>Note:</strong> Calling this function with a source that has not been listened to
1121      * using {@link #setMotionEventSources(int)} will throw an exception.
1122      *
1123      * @see AccessibilityService#onMotionEvent
1124      * @see #MotionEventSources
1125      * @see #setMotionEventSources(int)
1126      * @hide
1127      */
1128     @FlaggedApi(Flags.FLAG_MOTION_EVENT_OBSERVING)
1129     @TestApi
setObservedMotionEventSources(int observedMotionEventSources)1130     public void setObservedMotionEventSources(int observedMotionEventSources) {
1131         // Confirm that any sources requested here have already been requested for listening.
1132         if ((observedMotionEventSources & ~mMotionEventSources) != 0) {
1133             String message =
1134                     String.format(
1135                             "Requested motion event sources for listening = 0x%x but requested"
1136                                     + " motion event sources for observing = 0x%x.",
1137                             mMotionEventSources, observedMotionEventSources);
1138             throw new IllegalArgumentException(message);
1139         }
1140         mObservedMotionEventSources = observedMotionEventSources;
1141     }
1142 
1143     /**
1144      * Returns the bit mask of {@link android.view.InputDevice} sources that the accessibility
1145      * service wants to observe generic {@link android.view.MotionEvent}s from if it has already
1146      * requested to listen to them using {@link #setMotionEventSources(int)}. Events from these
1147      * sources will be sent to the rest of the input pipeline without being consumed by
1148      * accessibility services. This service will still be able to see them.
1149      *
1150      * @hide
1151      */
1152     @FlaggedApi(Flags.FLAG_MOTION_EVENT_OBSERVING)
1153     @MotionEventSources
1154     @TestApi
getObservedMotionEventSources()1155     public int getObservedMotionEventSources() {
1156         return mObservedMotionEventSources;
1157     }
1158 
1159     /**
1160      * The localized summary of the accessibility service.
1161      *
1162      * <p><strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
1163      * meta-data}.</strong>
1164      *
1165      * @return The localized summary if available, and {@code null} if a summary has not been
1166      *     provided.
1167      */
loadSummary(PackageManager packageManager)1168     public CharSequence loadSummary(PackageManager packageManager) {
1169         if (mSummaryResId == 0) {
1170             return mNonLocalizedSummary;
1171         }
1172         ServiceInfo serviceInfo = mResolveInfo.serviceInfo;
1173         CharSequence summary = packageManager.getText(serviceInfo.packageName,
1174                 mSummaryResId, serviceInfo.applicationInfo);
1175         if (summary != null) {
1176             return summary.toString().trim();
1177         }
1178         return null;
1179     }
1180 
1181     /**
1182      * The localized intro of the accessibility service.
1183      * <p>
1184      *    <strong>Statically set from
1185      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
1186      * </p>
1187      * @return The localized intro if available, and {@code null} if a intro
1188      * has not been provided.
1189      */
1190     @Nullable
loadIntro(@onNull PackageManager packageManager)1191     public CharSequence loadIntro(@NonNull PackageManager packageManager) {
1192         if (mIntroResId == /* invalid */ 0) {
1193             return null;
1194         }
1195         ServiceInfo serviceInfo = mResolveInfo.serviceInfo;
1196         CharSequence intro = packageManager.getText(serviceInfo.packageName,
1197                 mIntroResId, serviceInfo.applicationInfo);
1198         if (intro != null) {
1199             return intro.toString().trim();
1200         }
1201         return null;
1202     }
1203 
1204     /**
1205      * Gets the non-localized description of the accessibility service.
1206      * <p>
1207      *    <strong>Statically set from
1208      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
1209      * </p>
1210      * @return The description.
1211      *
1212      * @deprecated Use {@link #loadDescription(PackageManager)}.
1213      */
getDescription()1214     public String getDescription() {
1215         return mNonLocalizedDescription;
1216     }
1217 
1218     /**
1219      * The localized description of the accessibility service.
1220      * <p>
1221      *    <strong>Statically set from
1222      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
1223      * </p>
1224      * @return The localized description.
1225      */
loadDescription(PackageManager packageManager)1226     public String loadDescription(PackageManager packageManager) {
1227         if (mDescriptionResId == 0) {
1228             return mNonLocalizedDescription;
1229         }
1230         ServiceInfo serviceInfo = mResolveInfo.serviceInfo;
1231         CharSequence description = packageManager.getText(serviceInfo.packageName,
1232                 mDescriptionResId, serviceInfo.applicationInfo);
1233         if (description != null) {
1234             return description.toString().trim();
1235         }
1236         return null;
1237     }
1238 
1239     /**
1240      * The localized and restricted html description of the accessibility service.
1241      * <p>
1242      *    Filters the <img> tag which do not meet the custom specification and the <a> tag.
1243      *    <strong>Statically set from
1244      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
1245      * </p>
1246      * @return The localized and restricted html description.
1247      *
1248      * @hide
1249      */
1250     @Nullable
loadHtmlDescription(@onNull PackageManager packageManager)1251     public String loadHtmlDescription(@NonNull PackageManager packageManager) {
1252         if (mHtmlDescriptionRes == /* invalid */ 0) {
1253             return null;
1254         }
1255 
1256         final ServiceInfo serviceInfo = mResolveInfo.serviceInfo;
1257         final CharSequence htmlDescription = packageManager.getText(serviceInfo.packageName,
1258                 mHtmlDescriptionRes, serviceInfo.applicationInfo);
1259         if (htmlDescription != null) {
1260             return getFilteredHtmlText(htmlDescription.toString().trim());
1261         }
1262         return null;
1263     }
1264 
1265     /**
1266      * Set the recommended time that non-interactive controls need to remain on the screen to
1267      * support the user.
1268      * <p>
1269      *     <strong>This value can be dynamically set at runtime by
1270      *     {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
1271      * </p>
1272      *
1273      * @param timeout The timeout in milliseconds.
1274      *
1275      * @see android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
1276      */
setNonInteractiveUiTimeoutMillis(@ntRangefrom = 0) int timeout)1277     public void setNonInteractiveUiTimeoutMillis(@IntRange(from = 0) int timeout) {
1278         mNonInteractiveUiTimeout = timeout;
1279     }
1280 
1281     /**
1282      * Get the recommended timeout for non-interactive controls.
1283      *
1284      * @return The timeout in milliseconds.
1285      *
1286      * @see #setNonInteractiveUiTimeoutMillis(int)
1287      */
getNonInteractiveUiTimeoutMillis()1288     public int getNonInteractiveUiTimeoutMillis() {
1289         return mNonInteractiveUiTimeout;
1290     }
1291 
1292     /**
1293      * Set the recommended time that interactive controls need to remain on the screen to
1294      * support the user.
1295      * <p>
1296      *     <strong>This value can be dynamically set at runtime by
1297      *     {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
1298      * </p>
1299      *
1300      * @param timeout The timeout in milliseconds.
1301      *
1302      * @see android.R.styleable#AccessibilityService_interactiveUiTimeout
1303      */
setInteractiveUiTimeoutMillis(@ntRangefrom = 0) int timeout)1304     public void setInteractiveUiTimeoutMillis(@IntRange(from = 0) int timeout) {
1305         mInteractiveUiTimeout = timeout;
1306     }
1307 
1308     /**
1309      * Get the recommended timeout for interactive controls.
1310      *
1311      * @return The timeout in milliseconds.
1312      *
1313      * @see #setInteractiveUiTimeoutMillis(int)
1314      */
getInteractiveUiTimeoutMillis()1315     public int getInteractiveUiTimeoutMillis() {
1316         return mInteractiveUiTimeout;
1317     }
1318 
1319     /** {@hide} */
isDirectBootAware()1320     public boolean isDirectBootAware() {
1321         return ((flags & FLAG_FORCE_DIRECT_BOOT_AWARE) != 0)
1322                 || mResolveInfo.serviceInfo.directBootAware;
1323     }
1324 
1325     /**
1326      * Sets whether the service is used to assist users with disabilities.
1327      *
1328      * <p>
1329      * This property is normally provided in the service's {@link #mResolveInfo ResolveInfo}.
1330      * </p>
1331      *
1332      * <p>
1333      * This method is helpful for unit testing. However, this property is not dynamically
1334      * configurable by a standard {@link AccessibilityService} so it's not possible to update the
1335      * copy held by the system with this method.
1336      * </p>
1337      *
1338      * @hide
1339      */
1340     @SystemApi
setAccessibilityTool(boolean isAccessibilityTool)1341     public void setAccessibilityTool(boolean isAccessibilityTool) {
1342         mIsAccessibilityTool = isAccessibilityTool;
1343     }
1344 
1345     /**
1346      * Indicates if the service is used to assist users with disabilities.
1347      *
1348      * @return {@code true} if the property is set to true.
1349      */
isAccessibilityTool()1350     public boolean isAccessibilityTool() {
1351         return mIsAccessibilityTool;
1352     }
1353 
1354     /**
1355      * {@inheritDoc}
1356      */
describeContents()1357     public int describeContents() {
1358         return 0;
1359     }
1360 
1361     /** @hide */
isWithinParcelableSize()1362     public final boolean isWithinParcelableSize() {
1363         final Parcel parcel = Parcel.obtain();
1364         writeToParcel(parcel, 0);
1365         final boolean result = parcel.dataSize() <= IBinder.MAX_IPC_SIZE;
1366         parcel.recycle();
1367         return result;
1368     }
1369 
writeToParcel(Parcel parcel, int flagz)1370     public void writeToParcel(Parcel parcel, int flagz) {
1371         parcel.writeInt(eventTypes);
1372         parcel.writeStringArray(packageNames);
1373         parcel.writeInt(feedbackType);
1374         parcel.writeLong(notificationTimeout);
1375         parcel.writeInt(mNonInteractiveUiTimeout);
1376         parcel.writeInt(mInteractiveUiTimeout);
1377         parcel.writeInt(flags);
1378         parcel.writeInt(crashed ? 1 : 0);
1379         parcel.writeParcelable(mComponentName, flagz);
1380         parcel.writeParcelable(mResolveInfo, 0);
1381         parcel.writeString(mSettingsActivityName);
1382         parcel.writeInt(mCapabilities);
1383         parcel.writeInt(mSummaryResId);
1384         parcel.writeString(mNonLocalizedSummary);
1385         parcel.writeInt(mDescriptionResId);
1386         parcel.writeInt(mAnimatedImageRes);
1387         parcel.writeInt(mHtmlDescriptionRes);
1388         parcel.writeString(mNonLocalizedDescription);
1389         parcel.writeBoolean(mIsAccessibilityTool);
1390         parcel.writeString(mTileServiceName);
1391         parcel.writeInt(mIntroResId);
1392         parcel.writeInt(mMotionEventSources);
1393         parcel.writeInt(mObservedMotionEventSources);
1394     }
1395 
initFromParcel(Parcel parcel)1396     private void initFromParcel(Parcel parcel) {
1397         eventTypes = parcel.readInt();
1398         packageNames = parcel.readStringArray();
1399         feedbackType = parcel.readInt();
1400         notificationTimeout = parcel.readLong();
1401         mNonInteractiveUiTimeout = parcel.readInt();
1402         mInteractiveUiTimeout = parcel.readInt();
1403         flags = parcel.readInt();
1404         crashed = parcel.readInt() != 0;
1405         mComponentName = parcel.readParcelable(this.getClass().getClassLoader(), android.content.ComponentName.class);
1406         mResolveInfo = parcel.readParcelable(null, android.content.pm.ResolveInfo.class);
1407         mSettingsActivityName = parcel.readString();
1408         mCapabilities = parcel.readInt();
1409         mSummaryResId = parcel.readInt();
1410         mNonLocalizedSummary = parcel.readString();
1411         mDescriptionResId = parcel.readInt();
1412         mAnimatedImageRes = parcel.readInt();
1413         mHtmlDescriptionRes = parcel.readInt();
1414         mNonLocalizedDescription = parcel.readString();
1415         mIsAccessibilityTool = parcel.readBoolean();
1416         mTileServiceName = parcel.readString();
1417         mIntroResId = parcel.readInt();
1418         mMotionEventSources = parcel.readInt();
1419         // use the setter here because it throws an exception for invalid values.
1420         setObservedMotionEventSources(parcel.readInt());
1421     }
1422 
1423     @Override
hashCode()1424     public int hashCode() {
1425         return 31 * 1 + ((mComponentName == null) ? 0 : mComponentName.hashCode());
1426     }
1427 
1428     @Override
equals(@ullable Object obj)1429     public boolean equals(@Nullable Object obj) {
1430         if (this == obj) {
1431             return true;
1432         }
1433         if (obj == null) {
1434             return false;
1435         }
1436         if (getClass() != obj.getClass()) {
1437             return false;
1438         }
1439         AccessibilityServiceInfo other = (AccessibilityServiceInfo) obj;
1440         if (mComponentName == null) {
1441             if (other.mComponentName != null) {
1442                 return false;
1443             }
1444         } else if (!mComponentName.equals(other.mComponentName)) {
1445             return false;
1446         }
1447         return true;
1448     }
1449 
1450     @Override
toString()1451     public String toString() {
1452         StringBuilder stringBuilder = new StringBuilder();
1453         appendEventTypes(stringBuilder, eventTypes);
1454         stringBuilder.append(", ");
1455         appendPackageNames(stringBuilder, packageNames);
1456         stringBuilder.append(", ");
1457         appendFeedbackTypes(stringBuilder, feedbackType);
1458         stringBuilder.append(", ");
1459         stringBuilder.append("notificationTimeout: ").append(notificationTimeout);
1460         stringBuilder.append(", ");
1461         stringBuilder.append("nonInteractiveUiTimeout: ").append(mNonInteractiveUiTimeout);
1462         stringBuilder.append(", ");
1463         stringBuilder.append("interactiveUiTimeout: ").append(mInteractiveUiTimeout);
1464         stringBuilder.append(", ");
1465         appendFlags(stringBuilder, flags);
1466         stringBuilder.append(", ");
1467         stringBuilder.append("id: ").append(getId());
1468         stringBuilder.append(", ");
1469         stringBuilder.append("resolveInfo: ").append(mResolveInfo);
1470         stringBuilder.append(", ");
1471         stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName);
1472         stringBuilder.append(", ");
1473         stringBuilder.append("tileServiceName: ").append(mTileServiceName);
1474         stringBuilder.append(", ");
1475         stringBuilder.append("summary: ").append(mNonLocalizedSummary);
1476         stringBuilder.append(", ");
1477         stringBuilder.append("isAccessibilityTool: ").append(mIsAccessibilityTool);
1478         stringBuilder.append(", ");
1479         appendCapabilities(stringBuilder, mCapabilities);
1480         return stringBuilder.toString();
1481     }
1482 
appendFeedbackTypes(StringBuilder stringBuilder, @FeedbackType int feedbackTypes)1483     private static void appendFeedbackTypes(StringBuilder stringBuilder,
1484             @FeedbackType int feedbackTypes) {
1485         stringBuilder.append("feedbackTypes:");
1486         stringBuilder.append("[");
1487         while (feedbackTypes != 0) {
1488             final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackTypes));
1489             stringBuilder.append(feedbackTypeToString(feedbackTypeBit));
1490             feedbackTypes &= ~feedbackTypeBit;
1491             if (feedbackTypes != 0) {
1492                 stringBuilder.append(", ");
1493             }
1494         }
1495         stringBuilder.append("]");
1496     }
1497 
appendPackageNames(StringBuilder stringBuilder, String[] packageNames)1498     private static void appendPackageNames(StringBuilder stringBuilder, String[] packageNames) {
1499         stringBuilder.append("packageNames:");
1500         stringBuilder.append("[");
1501         if (packageNames != null) {
1502             final int packageNameCount = packageNames.length;
1503             for (int i = 0; i < packageNameCount; i++) {
1504                 stringBuilder.append(packageNames[i]);
1505                 if (i < packageNameCount - 1) {
1506                     stringBuilder.append(", ");
1507                 }
1508             }
1509         }
1510         stringBuilder.append("]");
1511     }
1512 
appendEventTypes(StringBuilder stringBuilder, int eventTypes)1513     private static void appendEventTypes(StringBuilder stringBuilder, int eventTypes) {
1514         stringBuilder.append("eventTypes:");
1515         stringBuilder.append("[");
1516         while (eventTypes != 0) {
1517             final int eventTypeBit = (1 << Integer.numberOfTrailingZeros(eventTypes));
1518             stringBuilder.append(AccessibilityEvent.eventTypeToString(eventTypeBit));
1519             eventTypes &= ~eventTypeBit;
1520             if (eventTypes != 0) {
1521                 stringBuilder.append(", ");
1522             }
1523         }
1524         stringBuilder.append("]");
1525     }
1526 
appendFlags(StringBuilder stringBuilder, int flags)1527     private static void appendFlags(StringBuilder stringBuilder, int flags) {
1528         stringBuilder.append("flags:");
1529         stringBuilder.append("[");
1530         while (flags != 0) {
1531             final int flagBit = (1 << Integer.numberOfTrailingZeros(flags));
1532             stringBuilder.append(flagToString(flagBit));
1533             flags &= ~flagBit;
1534             if (flags != 0) {
1535                 stringBuilder.append(", ");
1536             }
1537         }
1538         stringBuilder.append("]");
1539     }
1540 
appendCapabilities(StringBuilder stringBuilder, int capabilities)1541     private static void appendCapabilities(StringBuilder stringBuilder, int capabilities) {
1542         stringBuilder.append("capabilities:");
1543         stringBuilder.append("[");
1544         while (capabilities != 0) {
1545             final int capabilityBit = (1 << Integer.numberOfTrailingZeros(capabilities));
1546             stringBuilder.append(capabilityToString(capabilityBit));
1547             capabilities &= ~capabilityBit;
1548             if (capabilities != 0) {
1549                 stringBuilder.append(", ");
1550             }
1551         }
1552         stringBuilder.append("]");
1553     }
1554 
1555     /**
1556      * Returns the string representation of a feedback type. For example,
1557      * {@link #FEEDBACK_SPOKEN} is represented by the string FEEDBACK_SPOKEN.
1558      *
1559      * @param feedbackType The feedback type.
1560      * @return The string representation.
1561      */
feedbackTypeToString(int feedbackType)1562     public static String feedbackTypeToString(int feedbackType) {
1563         StringBuilder builder = new StringBuilder();
1564         builder.append("[");
1565         while (feedbackType != 0) {
1566             final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType);
1567             feedbackType &= ~feedbackTypeFlag;
1568             switch (feedbackTypeFlag) {
1569                 case FEEDBACK_AUDIBLE:
1570                     if (builder.length() > 1) {
1571                         builder.append(", ");
1572                     }
1573                     builder.append("FEEDBACK_AUDIBLE");
1574                     break;
1575                 case FEEDBACK_HAPTIC:
1576                     if (builder.length() > 1) {
1577                         builder.append(", ");
1578                     }
1579                     builder.append("FEEDBACK_HAPTIC");
1580                     break;
1581                 case FEEDBACK_GENERIC:
1582                     if (builder.length() > 1) {
1583                         builder.append(", ");
1584                     }
1585                     builder.append("FEEDBACK_GENERIC");
1586                     break;
1587                 case FEEDBACK_SPOKEN:
1588                     if (builder.length() > 1) {
1589                         builder.append(", ");
1590                     }
1591                     builder.append("FEEDBACK_SPOKEN");
1592                     break;
1593                 case FEEDBACK_VISUAL:
1594                     if (builder.length() > 1) {
1595                         builder.append(", ");
1596                     }
1597                     builder.append("FEEDBACK_VISUAL");
1598                     break;
1599                 case FEEDBACK_BRAILLE:
1600                     if (builder.length() > 1) {
1601                         builder.append(", ");
1602                     }
1603                     builder.append("FEEDBACK_BRAILLE");
1604                     break;
1605             }
1606         }
1607         builder.append("]");
1608         return builder.toString();
1609     }
1610 
1611     /**
1612      * Returns the string representation of a flag. For example,
1613      * {@link #DEFAULT} is represented by the string DEFAULT.
1614      *
1615      * @param flag The flag.
1616      * @return The string representation.
1617      */
flagToString(int flag)1618     public static String flagToString(int flag) {
1619         switch (flag) {
1620             case DEFAULT:
1621                 return "DEFAULT";
1622             case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS:
1623                 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS";
1624             case FLAG_REQUEST_TOUCH_EXPLORATION_MODE:
1625                 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE";
1626             case FLAG_SERVICE_HANDLES_DOUBLE_TAP:
1627                 return "FLAG_SERVICE_HANDLES_DOUBLE_TAP";
1628             case FLAG_REQUEST_MULTI_FINGER_GESTURES:
1629                 return "FLAG_REQUEST_MULTI_FINGER_GESTURES";
1630             case FLAG_REQUEST_2_FINGER_PASSTHROUGH:
1631                 return "FLAG_REQUEST_2_FINGER_PASSTHROUGH";
1632             case FLAG_SEND_MOTION_EVENTS:
1633                 return "FLAG_SEND_MOTION_EVENTS";
1634             case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
1635                 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
1636             case FLAG_REPORT_VIEW_IDS:
1637                 return "FLAG_REPORT_VIEW_IDS";
1638             case FLAG_REQUEST_FILTER_KEY_EVENTS:
1639                 return "FLAG_REQUEST_FILTER_KEY_EVENTS";
1640             case FLAG_RETRIEVE_INTERACTIVE_WINDOWS:
1641                 return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS";
1642             case FLAG_ENABLE_ACCESSIBILITY_VOLUME:
1643                 return "FLAG_ENABLE_ACCESSIBILITY_VOLUME";
1644             case FLAG_REQUEST_ACCESSIBILITY_BUTTON:
1645                 return "FLAG_REQUEST_ACCESSIBILITY_BUTTON";
1646             case FLAG_REQUEST_FINGERPRINT_GESTURES:
1647                 return "FLAG_REQUEST_FINGERPRINT_GESTURES";
1648             case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
1649                 return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
1650             case FLAG_INPUT_METHOD_EDITOR:
1651                 return "FLAG_INPUT_METHOD_EDITOR";
1652             default:
1653                 return null;
1654         }
1655     }
1656 
1657     /**
1658      * Returns the string representation of a capability. For example,
1659      * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented
1660      * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT.
1661      *
1662      * @param capability The capability.
1663      * @return The string representation.
1664      */
capabilityToString(int capability)1665     public static String capabilityToString(int capability) {
1666         switch (capability) {
1667             case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT:
1668                 return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT";
1669             case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION:
1670                 return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION";
1671             case CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS:
1672                 return "CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS";
1673             case CAPABILITY_CAN_CONTROL_MAGNIFICATION:
1674                 return "CAPABILITY_CAN_CONTROL_MAGNIFICATION";
1675             case CAPABILITY_CAN_PERFORM_GESTURES:
1676                 return "CAPABILITY_CAN_PERFORM_GESTURES";
1677             case CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES:
1678                 return "CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES";
1679             case CAPABILITY_CAN_TAKE_SCREENSHOT:
1680                 return "CAPABILITY_CAN_TAKE_SCREENSHOT";
1681             default:
1682                 return "UNKNOWN";
1683         }
1684     }
1685 
1686     /**
1687      * @hide
1688      * @return The list of {@link CapabilityInfo} objects.
1689      * @deprecated The version that takes a context works better.
1690      */
getCapabilityInfos()1691     public List<CapabilityInfo> getCapabilityInfos() {
1692         return getCapabilityInfos(null);
1693     }
1694 
1695     /**
1696      * @hide
1697      * @param context A valid context
1698      * @return The list of {@link CapabilityInfo} objects.
1699      */
getCapabilityInfos(Context context)1700     public List<CapabilityInfo> getCapabilityInfos(Context context) {
1701         if (mCapabilities == 0) {
1702             return Collections.emptyList();
1703         }
1704         int capabilities = mCapabilities;
1705         List<CapabilityInfo> capabilityInfos = new ArrayList<CapabilityInfo>();
1706         SparseArray<CapabilityInfo> capabilityInfoSparseArray =
1707                 getCapabilityInfoSparseArray(context);
1708         while (capabilities != 0) {
1709             final int capabilityBit = 1 << Integer.numberOfTrailingZeros(capabilities);
1710             capabilities &= ~capabilityBit;
1711             CapabilityInfo capabilityInfo = capabilityInfoSparseArray.get(capabilityBit);
1712             if (capabilityInfo != null) {
1713                 capabilityInfos.add(capabilityInfo);
1714             }
1715         }
1716         return capabilityInfos;
1717     }
1718 
getCapabilityInfoSparseArray(Context context)1719     private static SparseArray<CapabilityInfo> getCapabilityInfoSparseArray(Context context) {
1720         if (sAvailableCapabilityInfos == null) {
1721             sAvailableCapabilityInfos = new SparseArray<CapabilityInfo>();
1722             sAvailableCapabilityInfos.put(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
1723                     new CapabilityInfo(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
1724                             R.string.capability_title_canRetrieveWindowContent,
1725                             R.string.capability_desc_canRetrieveWindowContent));
1726             sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
1727                     new CapabilityInfo(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
1728                             R.string.capability_title_canRequestTouchExploration,
1729                             R.string.capability_desc_canRequestTouchExploration));
1730             sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
1731                     new CapabilityInfo(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
1732                             R.string.capability_title_canRequestFilterKeyEvents,
1733                             R.string.capability_desc_canRequestFilterKeyEvents));
1734             sAvailableCapabilityInfos.put(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
1735                     new CapabilityInfo(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
1736                             R.string.capability_title_canControlMagnification,
1737                             R.string.capability_desc_canControlMagnification));
1738             sAvailableCapabilityInfos.put(CAPABILITY_CAN_PERFORM_GESTURES,
1739                     new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES,
1740                             R.string.capability_title_canPerformGestures,
1741                             R.string.capability_desc_canPerformGestures));
1742             sAvailableCapabilityInfos.put(CAPABILITY_CAN_TAKE_SCREENSHOT,
1743                     new CapabilityInfo(CAPABILITY_CAN_TAKE_SCREENSHOT,
1744                             R.string.capability_title_canTakeScreenshot,
1745                             R.string.capability_desc_canTakeScreenshot));
1746             if ((context == null) || fingerprintAvailable(context)) {
1747                 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES,
1748                         new CapabilityInfo(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES,
1749                                 R.string.capability_title_canCaptureFingerprintGestures,
1750                                 R.string.capability_desc_canCaptureFingerprintGestures));
1751             }
1752         }
1753         return sAvailableCapabilityInfos;
1754     }
1755 
fingerprintAvailable(Context context)1756     private static boolean fingerprintAvailable(Context context) {
1757         return context.getPackageManager().hasSystemFeature(FEATURE_FINGERPRINT)
1758                 && context.getSystemService(FingerprintManager.class).isHardwareDetected();
1759     }
1760     /**
1761      * @hide
1762      */
1763     public static final class CapabilityInfo {
1764         public final int capability;
1765         public final int titleResId;
1766         public final int descResId;
1767 
CapabilityInfo(int capability, int titleResId, int descResId)1768         public CapabilityInfo(int capability, int titleResId, int descResId) {
1769             this.capability = capability;
1770             this.titleResId = titleResId;
1771             this.descResId = descResId;
1772         }
1773     }
1774 
1775     /**
1776      * @see Parcelable.Creator
1777      */
1778     public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityServiceInfo> CREATOR =
1779             new Parcelable.Creator<AccessibilityServiceInfo>() {
1780         public AccessibilityServiceInfo createFromParcel(Parcel parcel) {
1781             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
1782             info.initFromParcel(parcel);
1783             return info;
1784         }
1785 
1786         public AccessibilityServiceInfo[] newArray(int size) {
1787             return new AccessibilityServiceInfo[size];
1788         }
1789     };
1790 }
1791