blob: 61c5dac03da69fab195ac1e9d6e5fcb4f2d8e821 [file] [log] [blame]
svetoslavganov75986cf2009-05-14 22:28:01 -07001/*
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
17package android.accessibilityservice;
18
Phil Weaverc09a0212018-03-13 09:50:43 -070019import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
20
Rhed Jao62ea99c2019-09-14 14:25:17 +080021import android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback;
Svetoslav Ganov24c90452017-12-27 15:17:14 -080022import android.annotation.IntDef;
Rhed Jao637c4162018-12-24 16:06:14 +080023import android.annotation.IntRange;
Mathew Inwood62992f12018-08-01 14:28:00 +010024import android.annotation.UnsupportedAppUsage;
Rhed Jaoacde6c92019-11-15 17:54:47 +080025import android.compat.annotation.ChangeId;
26import android.compat.annotation.EnabledAfter;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070027import android.content.ComponentName;
28import android.content.Context;
29import android.content.pm.PackageManager;
30import android.content.pm.PackageManager.NameNotFoundException;
31import android.content.pm.ResolveInfo;
32import android.content.pm.ServiceInfo;
33import android.content.res.Resources;
34import android.content.res.TypedArray;
35import android.content.res.XmlResourceParser;
Phil Weaver27fcd9c2017-01-20 15:57:24 -080036import android.hardware.fingerprint.FingerprintManager;
Rhed Jaoacde6c92019-11-15 17:54:47 +080037import android.os.Build;
svetoslavganov75986cf2009-05-14 22:28:01 -070038import android.os.Parcel;
39import android.os.Parcelable;
Rhed Jaoacde6c92019-11-15 17:54:47 +080040import android.os.RemoteException;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070041import android.util.AttributeSet;
Svetoslav688a6972013-04-16 18:55:38 -070042import android.util.SparseArray;
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -080043import android.util.TypedValue;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070044import android.util.Xml;
Svetoslav Ganov42138042012-03-20 11:51:39 -070045import android.view.View;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070046import android.view.accessibility.AccessibilityEvent;
Svetoslav Ganov80943d82013-01-02 10:25:37 -080047import android.view.accessibility.AccessibilityNodeInfo;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070048
Jeff Sharkeyb5e89c62016-04-01 23:20:31 -060049import com.android.internal.R;
Rhed Jaoacde6c92019-11-15 17:54:47 +080050import com.android.internal.compat.IPlatformCompat;
Jeff Sharkeyb5e89c62016-04-01 23:20:31 -060051
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070052import org.xmlpull.v1.XmlPullParser;
53import org.xmlpull.v1.XmlPullParserException;
54
55import java.io.IOException;
Svetoslav Ganov24c90452017-12-27 15:17:14 -080056import java.lang.annotation.Retention;
57import java.lang.annotation.RetentionPolicy;
Svetoslav688a6972013-04-16 18:55:38 -070058import java.util.ArrayList;
59import java.util.Collections;
60import java.util.List;
svetoslavganov75986cf2009-05-14 22:28:01 -070061
62/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070063 * This class describes an {@link AccessibilityService}. The system notifies an
64 * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s
svetoslavganov75986cf2009-05-14 22:28:01 -070065 * according to the information encapsulated in this class.
66 *
Joe Fernandeze1302ed2012-02-06 14:30:15 -080067 * <div class="special reference">
68 * <h3>Developer Guides</h3>
69 * <p>For more information about creating AccessibilityServices, read the
70 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
71 * developer guide.</p>
72 * </div>
73 *
Scott Main00d17f72013-06-06 18:37:59 -070074 * @attr ref android.R.styleable#AccessibilityService_accessibilityEventTypes
75 * @attr ref android.R.styleable#AccessibilityService_accessibilityFeedbackType
76 * @attr ref android.R.styleable#AccessibilityService_accessibilityFlags
77 * @attr ref android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility
78 * @attr ref android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
79 * @attr ref android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
80 * @attr ref android.R.styleable#AccessibilityService_canRetrieveWindowContent
81 * @attr ref android.R.styleable#AccessibilityService_description
Saige McVea08c41bc2017-01-20 20:22:35 -080082 * @attr ref android.R.styleable#AccessibilityService_summary
Scott Main00d17f72013-06-06 18:37:59 -070083 * @attr ref android.R.styleable#AccessibilityService_notificationTimeout
84 * @attr ref android.R.styleable#AccessibilityService_packageNames
85 * @attr ref android.R.styleable#AccessibilityService_settingsActivity
Rhed Jao41118f32018-10-25 17:03:28 +080086 * @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
87 * @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout
svetoslavganov75986cf2009-05-14 22:28:01 -070088 * @see AccessibilityService
89 * @see android.view.accessibility.AccessibilityEvent
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070090 * @see android.view.accessibility.AccessibilityManager
svetoslavganov75986cf2009-05-14 22:28:01 -070091 */
92public class AccessibilityServiceInfo implements Parcelable {
93
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070094 private static final String TAG_ACCESSIBILITY_SERVICE = "accessibility-service";
95
svetoslavganov75986cf2009-05-14 22:28:01 -070096 /**
Svetoslav688a6972013-04-16 18:55:38 -070097 * Capability: This accessibility service can retrieve the active window content.
Scott Main00d17f72013-06-06 18:37:59 -070098 * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
Svetoslav688a6972013-04-16 18:55:38 -070099 */
100 public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001;
101
102 /**
103 * Capability: This accessibility service can request touch exploration mode in which
104 * touched items are spoken aloud and the UI can be explored via gestures.
Scott Main00d17f72013-06-06 18:37:59 -0700105 * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
Svetoslav688a6972013-04-16 18:55:38 -0700106 */
107 public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002;
108
109 /**
Phil Weaver09d4ff82017-03-31 11:22:17 -0700110 * @deprecated No longer used
Svetoslav688a6972013-04-16 18:55:38 -0700111 */
112 public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004;
113
114 /**
Scott Main00d17f72013-06-06 18:37:59 -0700115 * Capability: This accessibility service can request to filter the key event stream.
116 * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
Svetoslav688a6972013-04-16 18:55:38 -0700117 */
118 public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 0x00000008;
119
Alan Viverette214fb682015-11-17 09:47:11 -0500120 /**
121 * Capability: This accessibility service can control display magnification.
122 * @see android.R.styleable#AccessibilityService_canControlMagnification
123 */
124 public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0x00000010;
125
Phil Weavera6b64f52015-12-04 15:21:35 -0800126 /**
127 * Capability: This accessibility service can perform gestures.
128 * @see android.R.styleable#AccessibilityService_canPerformGestures
129 */
130 public static final int CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020;
131
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800132 /**
133 * Capability: This accessibility service can capture gestures from the fingerprint sensor
Phil Weaverbe2922f2017-04-28 14:58:35 -0700134 * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800135 */
Phil Weaverbe2922f2017-04-28 14:58:35 -0700136 public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 0x00000040;
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800137
138 private static SparseArray<CapabilityInfo> sAvailableCapabilityInfos;
Svetoslav688a6972013-04-16 18:55:38 -0700139
140 /**
svetoslavganov75986cf2009-05-14 22:28:01 -0700141 * Denotes spoken feedback.
142 */
143 public static final int FEEDBACK_SPOKEN = 0x0000001;
144
145 /**
146 * Denotes haptic feedback.
147 */
148 public static final int FEEDBACK_HAPTIC = 0x0000002;
149
150 /**
151 * Denotes audible (not spoken) feedback.
152 */
153 public static final int FEEDBACK_AUDIBLE = 0x0000004;
154
155 /**
156 * Denotes visual feedback.
157 */
158 public static final int FEEDBACK_VISUAL = 0x0000008;
159
160 /**
161 * Denotes generic feedback.
162 */
163 public static final int FEEDBACK_GENERIC = 0x0000010;
164
165 /**
Svetoslav Ganoveb9862f2012-09-06 19:40:29 -0700166 * Denotes braille feedback.
167 */
168 public static final int FEEDBACK_BRAILLE = 0x0000020;
169
170 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700171 * Mask for all feedback types.
172 *
173 * @see #FEEDBACK_SPOKEN
174 * @see #FEEDBACK_HAPTIC
175 * @see #FEEDBACK_AUDIBLE
176 * @see #FEEDBACK_VISUAL
177 * @see #FEEDBACK_GENERIC
Svetoslav Ganoveb9862f2012-09-06 19:40:29 -0700178 * @see #FEEDBACK_BRAILLE
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700179 */
180 public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
181
182 /**
svetoslavganov75986cf2009-05-14 22:28:01 -0700183 * If an {@link AccessibilityService} is the default for a given type.
184 * Default service is invoked only if no package specific one exists. In case of
185 * more than one package specific service only the earlier registered is notified.
186 */
187 public static final int DEFAULT = 0x0000001;
188
189 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700190 * If this flag is set the system will regard views that are not important
191 * for accessibility in addition to the ones that are important for accessibility.
192 * That is, views that are marked as not important for accessibility via
Alan Viverette23be1992013-10-02 17:41:15 -0700193 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or
194 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are
195 * marked as potentially important for accessibility via
Svetoslav Ganov42138042012-03-20 11:51:39 -0700196 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined
Alan Viverette23be1992013-10-02 17:41:15 -0700197 * that are not important for accessibility, are reported while querying the window
198 * content and also the accessibility service will receive accessibility events from
199 * them.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700200 * <p>
Kevin Hufnagle65f42932018-08-14 17:44:53 -0700201 * <strong>Note:</strong> For accessibility services targeting Android 4.1 (API level 16) or
202 * higher, this flag has to be explicitly set for the system to regard views that are not
203 * important for accessibility. For accessibility services targeting Android 4.0.4 (API level
204 * 15) or lower, this flag is ignored and all views are regarded for accessibility purposes.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700205 * </p>
206 * <p>
207 * Usually views not important for accessibility are layout managers that do not
208 * react to user actions, do not draw any content, and do not have any special
209 * semantics in the context of the screen content. For example, a three by three
210 * grid can be implemented as three horizontal linear layouts and one vertical,
211 * or three vertical linear layouts and one horizontal, or one grid layout, etc.
kopriva82c591b2018-10-08 15:57:00 -0700212 * In this context, the actual layout managers used to achieve the grid configuration
213 * are not important; rather it is important that there are nine evenly distributed
Svetoslav Ganov42138042012-03-20 11:51:39 -0700214 * elements.
215 * </p>
216 */
Svetoslav Ganov3ec2e1b2012-05-09 11:02:38 -0700217 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002;
218
219 /**
220 * This flag requests that the system gets into touch exploration mode.
221 * In this mode a single finger moving on the screen behaves as a mouse
222 * pointer hovering over the user interface. The system will also detect
223 * certain gestures performed on the touch screen and notify this service.
224 * The system will enable touch exploration mode if there is at least one
225 * accessibility service that has this flag set. Hence, clearing this
226 * flag does not guarantee that the device will not be in touch exploration
227 * mode since there may be another enabled service that requested it.
Svetoslav0ec04182013-01-31 16:54:40 -0800228 * <p>
Kevin Hufnagle65f42932018-08-14 17:44:53 -0700229 * For accessibility services targeting Android 4.3 (API level 18) or higher
230 * that want to set this flag have to declare this capability in their
231 * meta-data by setting the attribute
232 * {@link android.R.attr#canRequestTouchExplorationMode
233 * canRequestTouchExplorationMode} to true. Otherwise, this flag will
Svetoslav688a6972013-04-16 18:55:38 -0700234 * be ignored. For how to declare the meta-data of a service refer to
235 * {@value AccessibilityService#SERVICE_META_DATA}.
Svetoslav0ec04182013-01-31 16:54:40 -0800236 * </p>
Svetoslav Ganov447d9462013-02-01 19:46:20 +0000237 * <p>
Kevin Hufnagle65f42932018-08-14 17:44:53 -0700238 * Services targeting Android 4.2.2 (API level 17) or lower will work
239 * normally. In other words, the first time they are run, if this flag is
240 * specified, a dialog is shown to the user to confirm enabling explore by
241 * touch.
Svetoslav Ganov447d9462013-02-01 19:46:20 +0000242 * </p>
Scott Main00d17f72013-06-06 18:37:59 -0700243 * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
Svetoslav Ganov3ec2e1b2012-05-09 11:02:38 -0700244 */
Svetoslav0ec04182013-01-31 16:54:40 -0800245 public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700246
247 /**
Phil Weaver09d4ff82017-03-31 11:22:17 -0700248 * @deprecated No longer used
Svetoslav38228962013-01-29 01:04:35 -0800249 */
250 public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008;
251
252 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800253 * This flag requests that the {@link AccessibilityNodeInfo}s obtained
254 * by an {@link AccessibilityService} contain the id of the source view.
255 * The source view id will be a fully qualified resource name of the
256 * form "package:id/name", for example "foo.bar:id/my_list", and it is
257 * useful for UI test automation. This flag is not set by default.
258 */
Svetoslav38228962013-01-29 01:04:35 -0800259 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800260
261 /**
Svetoslav688a6972013-04-16 18:55:38 -0700262 * This flag requests from the system to filter key events. If this flag
263 * is set the accessibility service will receive the key events before
Phil Weavera6b64f52015-12-04 15:21:35 -0800264 * applications allowing it implement global shortcuts.
Svetoslav688a6972013-04-16 18:55:38 -0700265 * <p>
266 * Services that want to set this flag have to declare this capability
267 * in their meta-data by setting the attribute {@link android.R.attr
268 * #canRequestFilterKeyEvents canRequestFilterKeyEvents} to true,
269 * otherwise this flag will be ignored. For how to declare the meta-data
270 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
271 * </p>
Scott Main00d17f72013-06-06 18:37:59 -0700272 * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
Svetoslav688a6972013-04-16 18:55:38 -0700273 */
274 public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020;
275
276 /**
Svetoslav8e3feb12014-02-24 13:46:47 -0800277 * This flag indicates to the system that the accessibility service wants
278 * to access content of all interactive windows. An interactive window is a
Svetoslavf7174e82014-06-12 11:29:35 -0700279 * window that has input focus or can be touched by a sighted user when explore
280 * by touch is not enabled. If this flag is not set your service will not receive
Svetoslav8e3feb12014-02-24 13:46:47 -0800281 * {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED}
282 * events, calling AccessibilityService{@link AccessibilityService#getWindows()
283 * AccessibilityService.getWindows()} will return an empty list, and {@link
284 * AccessibilityNodeInfo#getWindow() AccessibilityNodeInfo.getWindow()} will
285 * return null.
286 * <p>
287 * Services that want to set this flag have to declare the capability
288 * to retrieve window content in their meta-data by setting the attribute
289 * {@link android.R.attr#canRetrieveWindowContent canRetrieveWindowContent} to
290 * true, otherwise this flag will be ignored. For how to declare the meta-data
291 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
292 * </p>
293 * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
294 */
295 public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040;
296
Phil Weaver4acc16d2016-09-14 17:04:49 -0700297 /**
298 * This flag requests that all audio tracks system-wide with
299 * {@link android.media.AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY} be controlled by the
300 * {@link android.media.AudioManager#STREAM_ACCESSIBILITY} volume.
301 */
302 public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080;
303
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800304 /**
305 * This flag indicates to the system that the accessibility service requests that an
306 * accessibility button be shown within the system's navigation area, if available.
Rhed Jaoacde6c92019-11-15 17:54:47 +0800307 * <p>
308 * <strong>Note:</strong> For accessibility services targeting APIs greater than
309 * {@link Build.VERSION_CODES#Q API 29}, this flag must be specified in the
310 * accessibility service metadata file. Otherwise, it will be ignored.
311 * </p>
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800312 */
313 public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100;
314
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800315 /**
316 * This flag requests that all fingerprint gestures be sent to the accessibility service.
Phil Weaver466b71e2018-04-20 14:51:39 -0700317 * <p>
318 * Services that want to set this flag have to declare the capability
319 * to retrieve window content in their meta-data by setting the attribute
320 * {@link android.R.attr#canRequestFingerprintGestures} to
321 * true, otherwise this flag will be ignored. For how to declare the meta-data
322 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
323 * </p>
324 *
325 * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
326 * @see AccessibilityService#getFingerprintGestureController()
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800327 */
Phil Weaverbe2922f2017-04-28 14:58:35 -0700328 public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 0x00000200;
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800329
Rhed Jao6182af72018-08-22 18:48:59 +0800330 /**
331 * This flag requests that accessibility shortcut warning dialog has spoken feedback when
332 * dialog is shown.
333 */
334 public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
335
Rhed Jao62ea99c2019-09-14 14:25:17 +0800336 /**
337 * This flag indicates that the accessibility service will handle the shortcut action itself.
338 * A callback {@link AccessibilityButtonCallback#onClicked(AccessibilityButtonController)} is
339 * called when the user presses the accessibility shortcut. Otherwise, the service is enabled
340 * or disabled by the system instead.
341 */
342 public static final int FLAG_HANDLE_SHORTCUT = 0x00000800;
343
Jeff Sharkeyb5e89c62016-04-01 23:20:31 -0600344 /** {@hide} */
345 public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
346
Svetoslav8e3feb12014-02-24 13:46:47 -0800347 /**
svetoslavganov75986cf2009-05-14 22:28:01 -0700348 * The event types an {@link AccessibilityService} is interested in.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700349 * <p>
350 * <strong>Can be dynamically set at runtime.</strong>
351 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -0700352 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED
Svetoslav Ganov9b317792010-02-17 16:46:42 -0800353 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED
svetoslavganov75986cf2009-05-14 22:28:01 -0700354 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED
355 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED
356 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
svetoslavganov75986cf2009-05-14 22:28:01 -0700357 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
358 * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700359 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START
360 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END
361 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER
362 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT
363 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED
364 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED
365 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
Svetoslav8e3feb12014-02-24 13:46:47 -0800366 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_START
367 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_END
368 * @see android.view.accessibility.AccessibilityEvent#TYPE_ANNOUNCEMENT
369 * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_START
370 * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_END
371 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED
372 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
373 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
374 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED
svetoslavganov75986cf2009-05-14 22:28:01 -0700375 */
376 public int eventTypes;
377
378 /**
379 * The package names an {@link AccessibilityService} is interested in. Setting
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700380 * to <code>null</code> is equivalent to all packages.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700381 * <p>
382 * <strong>Can be dynamically set at runtime.</strong>
383 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -0700384 */
385 public String[] packageNames;
386
Svetoslav Ganov24c90452017-12-27 15:17:14 -0800387
388 /** @hide */
389 @IntDef(flag = true, prefix = { "FEEDBACK_" }, value = {
390 FEEDBACK_AUDIBLE,
391 FEEDBACK_GENERIC,
392 FEEDBACK_HAPTIC,
393 FEEDBACK_SPOKEN,
394 FEEDBACK_VISUAL,
395 FEEDBACK_BRAILLE
396 })
397 @Retention(RetentionPolicy.SOURCE)
398 public @interface FeedbackType {}
399
svetoslavganov75986cf2009-05-14 22:28:01 -0700400 /**
401 * The feedback type an {@link AccessibilityService} provides.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700402 * <p>
403 * <strong>Can be dynamically set at runtime.</strong>
404 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -0700405 * @see #FEEDBACK_AUDIBLE
406 * @see #FEEDBACK_GENERIC
407 * @see #FEEDBACK_HAPTIC
408 * @see #FEEDBACK_SPOKEN
409 * @see #FEEDBACK_VISUAL
Svetoslav Ganoveb9862f2012-09-06 19:40:29 -0700410 * @see #FEEDBACK_BRAILLE
svetoslavganov75986cf2009-05-14 22:28:01 -0700411 */
Svetoslav Ganov24c90452017-12-27 15:17:14 -0800412 @FeedbackType
svetoslavganov75986cf2009-05-14 22:28:01 -0700413 public int feedbackType;
414
415 /**
Kevin Hufnagle65f42932018-08-14 17:44:53 -0700416 * The timeout, in milliseconds, after the most recent event of a given type before an
svetoslavganov75986cf2009-05-14 22:28:01 -0700417 * {@link AccessibilityService} is notified.
418 * <p>
Kevin Hufnagle65f42932018-08-14 17:44:53 -0700419 * <strong>Can be dynamically set at runtime.</strong>
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700420 * </p>
421 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700422 * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
423 * events to the client too frequently since this is accomplished via an expensive
424 * interprocess call. One can think of the timeout as a criteria to determine when
425 * event generation has settled down.
svetoslavganov75986cf2009-05-14 22:28:01 -0700426 */
427 public long notificationTimeout;
428
429 /**
430 * This field represents a set of flags used for configuring an
431 * {@link AccessibilityService}.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700432 * <p>
433 * <strong>Can be dynamically set at runtime.</strong>
434 * </p>
Rhed Jaoacde6c92019-11-15 17:54:47 +0800435 * <p>
436 * <strong>Note:</strong> Accessibility services with targetSdkVersion greater than
437 * {@link Build.VERSION_CODES#Q API 29} cannot dynamically set the
438 * {@link #FLAG_REQUEST_ACCESSIBILITY_BUTTON} at runtime. It must be specified in the
439 * accessibility service metadata file.
440 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -0700441 * @see #DEFAULT
Svetoslav Ganov3ec2e1b2012-05-09 11:02:38 -0700442 * @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
443 * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
Svetoslav688a6972013-04-16 18:55:38 -0700444 * @see #FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY
445 * @see #FLAG_REQUEST_FILTER_KEY_EVENTS
446 * @see #FLAG_REPORT_VIEW_IDS
Svetoslav8e3feb12014-02-24 13:46:47 -0800447 * @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800448 * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
449 * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
Rhed Jao6182af72018-08-22 18:48:59 +0800450 * @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
Rhed Jao62ea99c2019-09-14 14:25:17 +0800451 * @see #FLAG_HANDLE_SHORTCUT
svetoslavganov75986cf2009-05-14 22:28:01 -0700452 */
453 public int flags;
454
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700455 /**
Phil Weaverc09a0212018-03-13 09:50:43 -0700456 * Whether or not the service has crashed and is awaiting restart. Only valid from {@link
Jackal Guofbac8382019-10-03 10:48:26 +0800457 * android.view.accessibility.AccessibilityManager#getInstalledAccessibilityServiceList()},
Phil Weaverc09a0212018-03-13 09:50:43 -0700458 * because that is populated from the internal list of running services.
459 *
460 * @hide
461 */
462 public boolean crashed;
463
464 /**
Rhed Jao41118f32018-10-25 17:03:28 +0800465 * A recommended timeout in milliseconds for non-interactive controls.
Rhed Jaoe9728812018-08-29 12:14:46 +0800466 */
Rhed Jao41118f32018-10-25 17:03:28 +0800467 private int mNonInteractiveUiTimeout;
468
469 /**
470 * A recommended timeout in milliseconds for interactive controls.
471 */
472 private int mInteractiveUiTimeout;
Rhed Jaoe9728812018-08-29 12:14:46 +0800473
474 /**
Phil Weaver106fe732016-11-22 18:18:39 -0800475 * The component name the accessibility service.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700476 */
Phil Weaver106fe732016-11-22 18:18:39 -0800477 private ComponentName mComponentName;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700478
479 /**
480 * The Service that implements this accessibility service component.
481 */
482 private ResolveInfo mResolveInfo;
483
484 /**
485 * The accessibility service setting activity's name, used by the system
486 * settings to launch the setting activity of this accessibility service.
487 */
488 private String mSettingsActivityName;
489
490 /**
Svetoslav688a6972013-04-16 18:55:38 -0700491 * Bit mask with capabilities of this service.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700492 */
Svetoslav688a6972013-04-16 18:55:38 -0700493 private int mCapabilities;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700494
495 /**
Saige McVea08c41bc2017-01-20 20:22:35 -0800496 * Resource id of the summary of the accessibility service.
497 */
498 private int mSummaryResId;
499
500 /**
501 * Non-localized summary of the accessibility service.
502 */
503 private String mNonLocalizedSummary;
504
505 /**
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800506 * Resource id of the description of the accessibility service.
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700507 */
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800508 private int mDescriptionResId;
509
510 /**
511 * Non localized description of the accessibility service.
512 */
513 private String mNonLocalizedDescription;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700514
515 /**
Rhed Jaoacde6c92019-11-15 17:54:47 +0800516 * For accessibility services targeting APIs greater than {@link Build.VERSION_CODES#Q API 29},
517 * {@link #FLAG_REQUEST_ACCESSIBILITY_BUTTON} must be specified in the accessibility service
518 * metadata file. Otherwise, it will be ignored.
519 */
520 @ChangeId
521 @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.Q)
522 private static final long REQUEST_ACCESSIBILITY_BUTTON_CHANGE = 136293963L;
523
524 /**
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700525 * Creates a new instance.
526 */
527 public AccessibilityServiceInfo() {
528 /* do nothing */
529 }
530
531 /**
532 * Creates a new instance.
533 *
534 * @param resolveInfo The service resolve info.
535 * @param context Context for accessing resources.
536 * @throws XmlPullParserException If a XML parsing error occurs.
537 * @throws IOException If a XML parsing error occurs.
538 *
539 * @hide
540 */
541 public AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context)
542 throws XmlPullParserException, IOException {
543 ServiceInfo serviceInfo = resolveInfo.serviceInfo;
Phil Weaver106fe732016-11-22 18:18:39 -0800544 mComponentName = new ComponentName(serviceInfo.packageName, serviceInfo.name);
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700545 mResolveInfo = resolveInfo;
546
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700547 XmlResourceParser parser = null;
548
549 try {
550 PackageManager packageManager = context.getPackageManager();
551 parser = serviceInfo.loadXmlMetaData(packageManager,
552 AccessibilityService.SERVICE_META_DATA);
553 if (parser == null) {
554 return;
555 }
556
557 int type = 0;
558 while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
559 type = parser.next();
560 }
561
562 String nodeName = parser.getName();
563 if (!TAG_ACCESSIBILITY_SERVICE.equals(nodeName)) {
564 throw new XmlPullParserException( "Meta-data does not start with"
565 + TAG_ACCESSIBILITY_SERVICE + " tag");
566 }
567
568 AttributeSet allAttributes = Xml.asAttributeSet(parser);
569 Resources resources = packageManager.getResourcesForApplication(
570 serviceInfo.applicationInfo);
571 TypedArray asAttributes = resources.obtainAttributes(allAttributes,
572 com.android.internal.R.styleable.AccessibilityService);
573 eventTypes = asAttributes.getInt(
574 com.android.internal.R.styleable.AccessibilityService_accessibilityEventTypes,
575 0);
576 String packageNamez = asAttributes.getString(
577 com.android.internal.R.styleable.AccessibilityService_packageNames);
578 if (packageNamez != null) {
579 packageNames = packageNamez.split("(\\s)*,(\\s)*");
580 }
581 feedbackType = asAttributes.getInt(
582 com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType,
583 0);
584 notificationTimeout = asAttributes.getInt(
Svetoslav8e3feb12014-02-24 13:46:47 -0800585 com.android.internal.R.styleable.AccessibilityService_notificationTimeout,
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700586 0);
Rhed Jao41118f32018-10-25 17:03:28 +0800587 mNonInteractiveUiTimeout = asAttributes.getInt(
588 com.android.internal.R.styleable.AccessibilityService_nonInteractiveUiTimeout,
589 0);
590 mInteractiveUiTimeout = asAttributes.getInt(
591 com.android.internal.R.styleable.AccessibilityService_interactiveUiTimeout,
Rhed Jaoe9728812018-08-29 12:14:46 +0800592 0);
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700593 flags = asAttributes.getInt(
594 com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
595 mSettingsActivityName = asAttributes.getString(
596 com.android.internal.R.styleable.AccessibilityService_settingsActivity);
Svetoslav688a6972013-04-16 18:55:38 -0700597 if (asAttributes.getBoolean(com.android.internal.R.styleable
598 .AccessibilityService_canRetrieveWindowContent, false)) {
599 mCapabilities |= CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT;
600 }
601 if (asAttributes.getBoolean(com.android.internal.R.styleable
602 .AccessibilityService_canRequestTouchExplorationMode, false)) {
603 mCapabilities |= CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION;
604 }
605 if (asAttributes.getBoolean(com.android.internal.R.styleable
Svetoslav688a6972013-04-16 18:55:38 -0700606 .AccessibilityService_canRequestFilterKeyEvents, false)) {
607 mCapabilities |= CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS;
608 }
Alan Viverette214fb682015-11-17 09:47:11 -0500609 if (asAttributes.getBoolean(com.android.internal.R.styleable
610 .AccessibilityService_canControlMagnification, false)) {
611 mCapabilities |= CAPABILITY_CAN_CONTROL_MAGNIFICATION;
612 }
Phil Weavera6b64f52015-12-04 15:21:35 -0800613 if (asAttributes.getBoolean(com.android.internal.R.styleable
614 .AccessibilityService_canPerformGestures, false)) {
615 mCapabilities |= CAPABILITY_CAN_PERFORM_GESTURES;
616 }
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800617 if (asAttributes.getBoolean(com.android.internal.R.styleable
Phil Weaverbe2922f2017-04-28 14:58:35 -0700618 .AccessibilityService_canRequestFingerprintGestures, false)) {
619 mCapabilities |= CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES;
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800620 }
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800621 TypedValue peekedValue = asAttributes.peekValue(
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700622 com.android.internal.R.styleable.AccessibilityService_description);
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800623 if (peekedValue != null) {
624 mDescriptionResId = peekedValue.resourceId;
625 CharSequence nonLocalizedDescription = peekedValue.coerceToString();
626 if (nonLocalizedDescription != null) {
627 mNonLocalizedDescription = nonLocalizedDescription.toString().trim();
628 }
629 }
Saige McVea08c41bc2017-01-20 20:22:35 -0800630 peekedValue = asAttributes.peekValue(
631 com.android.internal.R.styleable.AccessibilityService_summary);
632 if (peekedValue != null) {
633 mSummaryResId = peekedValue.resourceId;
634 CharSequence nonLocalizedSummary = peekedValue.coerceToString();
635 if (nonLocalizedSummary != null) {
636 mNonLocalizedSummary = nonLocalizedSummary.toString().trim();
637 }
638 }
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700639 asAttributes.recycle();
640 } catch (NameNotFoundException e) {
641 throw new XmlPullParserException( "Unable to create context for: "
642 + serviceInfo.packageName);
643 } finally {
644 if (parser != null) {
645 parser.close();
646 }
647 }
648 }
649
650 /**
Rhed Jaoacde6c92019-11-15 17:54:47 +0800651 * Updates the properties that an AccessibilityService can change dynamically.
652 * <p>
653 * Note: A11y services targeting APIs > Q, it cannot update flagRequestAccessibilityButton
654 * dynamically.
655 * </p>
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700656 *
Rhed Jaoacde6c92019-11-15 17:54:47 +0800657 * @param platformCompat The platform compat service to check the compatibility change.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700658 * @param other The info from which to update the properties.
659 *
660 * @hide
661 */
Rhed Jaoacde6c92019-11-15 17:54:47 +0800662 public void updateDynamicallyConfigurableProperties(IPlatformCompat platformCompat,
663 AccessibilityServiceInfo other) {
664 if (isRequestAccessibilityButtonChangeEnabled(platformCompat)) {
665 other.flags &= ~FLAG_REQUEST_ACCESSIBILITY_BUTTON;
666 other.flags |= (flags & FLAG_REQUEST_ACCESSIBILITY_BUTTON);
667 }
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700668 eventTypes = other.eventTypes;
669 packageNames = other.packageNames;
670 feedbackType = other.feedbackType;
671 notificationTimeout = other.notificationTimeout;
Rhed Jao41118f32018-10-25 17:03:28 +0800672 mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout;
673 mInteractiveUiTimeout = other.mInteractiveUiTimeout;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700674 flags = other.flags;
675 }
676
Rhed Jaoacde6c92019-11-15 17:54:47 +0800677 private boolean isRequestAccessibilityButtonChangeEnabled(IPlatformCompat platformCompat) {
678 if (mResolveInfo == null) {
679 return true;
680 }
681 try {
682 if (platformCompat != null) {
683 return platformCompat.isChangeEnabledByPackageName(
684 REQUEST_ACCESSIBILITY_BUTTON_CHANGE, mResolveInfo.serviceInfo.packageName,
685 mResolveInfo.serviceInfo.applicationInfo.uid);
686 }
687 } catch (RemoteException ignore) {
688 }
689 return mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.Q;
690 }
691
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700692 /**
Svetoslav57bf8852013-02-07 19:21:42 -0800693 * @hide
694 */
695 public void setComponentName(ComponentName component) {
Phil Weaver106fe732016-11-22 18:18:39 -0800696 mComponentName = component;
697 }
698
699 /**
700 * @hide
701 */
702 public ComponentName getComponentName() {
703 return mComponentName;
Svetoslav57bf8852013-02-07 19:21:42 -0800704 }
705
706 /**
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700707 * The accessibility service id.
708 * <p>
709 * <strong>Generated by the system.</strong>
710 * </p>
711 * @return The id.
712 */
713 public String getId() {
Phil Weaver106fe732016-11-22 18:18:39 -0800714 return mComponentName.flattenToShortString();
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700715 }
716
717 /**
718 * The service {@link ResolveInfo}.
719 * <p>
720 * <strong>Generated by the system.</strong>
721 * </p>
722 * @return The info.
723 */
724 public ResolveInfo getResolveInfo() {
725 return mResolveInfo;
726 }
727
728 /**
729 * The settings activity name.
730 * <p>
731 * <strong>Statically set from
732 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
733 * </p>
734 * @return The settings activity name.
735 */
736 public String getSettingsActivityName() {
737 return mSettingsActivityName;
738 }
739
740 /**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700741 * Whether this service can retrieve the current window's content.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700742 * <p>
743 * <strong>Statically set from
744 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
745 * </p>
Svetoslav Ganovfefd20e2012-04-19 21:44:35 -0700746 * @return True if window content can be retrieved.
Svetoslav688a6972013-04-16 18:55:38 -0700747 *
748 * @deprecated Use {@link #getCapabilities()}.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700749 */
750 public boolean getCanRetrieveWindowContent() {
Svetoslav688a6972013-04-16 18:55:38 -0700751 return (mCapabilities & CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
752 }
753
754 /**
755 * Returns the bit mask of capabilities this accessibility service has such as
756 * being able to retrieve the active window content, etc.
757 *
758 * @return The capability bit mask.
759 *
760 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
761 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800762 * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
Phil Weavera6b64f52015-12-04 15:21:35 -0800763 * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
764 * @see #CAPABILITY_CAN_PERFORM_GESTURES
Svetoslav688a6972013-04-16 18:55:38 -0700765 */
766 public int getCapabilities() {
767 return mCapabilities;
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700768 }
769
770 /**
Svetoslav11adf6d2013-04-24 14:51:29 -0700771 * Sets the bit mask of capabilities this accessibility service has such as
772 * being able to retrieve the active window content, etc.
773 *
774 * @param capabilities The capability bit mask.
775 *
776 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
777 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800778 * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
Phil Weavera6b64f52015-12-04 15:21:35 -0800779 * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
780 * @see #CAPABILITY_CAN_PERFORM_GESTURES
Svetoslav11adf6d2013-04-24 14:51:29 -0700781 *
782 * @hide
783 */
Mathew Inwood62992f12018-08-01 14:28:00 +0100784 @UnsupportedAppUsage
Svetoslav11adf6d2013-04-24 14:51:29 -0700785 public void setCapabilities(int capabilities) {
786 mCapabilities = capabilities;
787 }
788
789 /**
Saige McVea08c41bc2017-01-20 20:22:35 -0800790 * The localized summary of the accessibility service.
791 * <p>
792 * <strong>Statically set from
793 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
794 * </p>
Saige McVeacb75b542017-04-28 20:30:25 -0700795 * @return The localized summary if available, and {@code null} if a summary
796 * has not been provided.
Saige McVea08c41bc2017-01-20 20:22:35 -0800797 */
Saige McVeacb75b542017-04-28 20:30:25 -0700798 public CharSequence loadSummary(PackageManager packageManager) {
Saige McVea08c41bc2017-01-20 20:22:35 -0800799 if (mSummaryResId == 0) {
800 return mNonLocalizedSummary;
801 }
802 ServiceInfo serviceInfo = mResolveInfo.serviceInfo;
803 CharSequence summary = packageManager.getText(serviceInfo.packageName,
804 mSummaryResId, serviceInfo.applicationInfo);
805 if (summary != null) {
806 return summary.toString().trim();
807 }
808 return null;
809 }
810
811 /**
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800812 * Gets the non-localized description of the accessibility service.
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700813 * <p>
814 * <strong>Statically set from
815 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
816 * </p>
817 * @return The description.
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800818 *
819 * @deprecated Use {@link #loadDescription(PackageManager)}.
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700820 */
821 public String getDescription() {
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800822 return mNonLocalizedDescription;
823 }
824
825 /**
826 * The localized description of the accessibility service.
827 * <p>
828 * <strong>Statically set from
829 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
830 * </p>
831 * @return The localized description.
832 */
833 public String loadDescription(PackageManager packageManager) {
834 if (mDescriptionResId == 0) {
835 return mNonLocalizedDescription;
836 }
837 ServiceInfo serviceInfo = mResolveInfo.serviceInfo;
838 CharSequence description = packageManager.getText(serviceInfo.packageName,
839 mDescriptionResId, serviceInfo.applicationInfo);
840 if (description != null) {
841 return description.toString().trim();
842 }
843 return null;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700844 }
845
Rhed Jaoe9728812018-08-29 12:14:46 +0800846 /**
Rhed Jao41118f32018-10-25 17:03:28 +0800847 * Set the recommended time that non-interactive controls need to remain on the screen to
848 * support the user.
Rhed Jaoe9728812018-08-29 12:14:46 +0800849 * <p>
Rhed Jao41118f32018-10-25 17:03:28 +0800850 * <strong>This value can be dynamically set at runtime by
851 * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
Rhed Jaoe9728812018-08-29 12:14:46 +0800852 * </p>
853 *
854 * @param timeout The timeout in milliseconds.
Rhed Jao41118f32018-10-25 17:03:28 +0800855 *
856 * @see android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
Rhed Jaoe9728812018-08-29 12:14:46 +0800857 */
Rhed Jao637c4162018-12-24 16:06:14 +0800858 public void setNonInteractiveUiTimeoutMillis(@IntRange(from = 0) int timeout) {
Rhed Jao41118f32018-10-25 17:03:28 +0800859 mNonInteractiveUiTimeout = timeout;
Rhed Jaoe9728812018-08-29 12:14:46 +0800860 }
861
862 /**
Rhed Jao41118f32018-10-25 17:03:28 +0800863 * Get the recommended timeout for non-interactive controls.
Rhed Jaoe9728812018-08-29 12:14:46 +0800864 *
Rhed Jaoe9728812018-08-29 12:14:46 +0800865 * @return The timeout in milliseconds.
Rhed Jao41118f32018-10-25 17:03:28 +0800866 *
867 * @see #setNonInteractiveUiTimeoutMillis(int)
Rhed Jaoe9728812018-08-29 12:14:46 +0800868 */
Rhed Jao41118f32018-10-25 17:03:28 +0800869 public int getNonInteractiveUiTimeoutMillis() {
870 return mNonInteractiveUiTimeout;
871 }
872
873 /**
874 * Set the recommended time that interactive controls need to remain on the screen to
875 * support the user.
876 * <p>
877 * <strong>This value can be dynamically set at runtime by
878 * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
879 * </p>
880 *
881 * @param timeout The timeout in milliseconds.
882 *
883 * @see android.R.styleable#AccessibilityService_interactiveUiTimeout
884 */
Rhed Jao637c4162018-12-24 16:06:14 +0800885 public void setInteractiveUiTimeoutMillis(@IntRange(from = 0) int timeout) {
Rhed Jao41118f32018-10-25 17:03:28 +0800886 mInteractiveUiTimeout = timeout;
887 }
888
889 /**
890 * Get the recommended timeout for interactive controls.
891 *
892 * @return The timeout in milliseconds.
893 *
894 * @see #setInteractiveUiTimeoutMillis(int)
895 */
896 public int getInteractiveUiTimeoutMillis() {
897 return mInteractiveUiTimeout;
Rhed Jaoe9728812018-08-29 12:14:46 +0800898 }
899
Jeff Sharkeye88e2662016-02-23 17:52:16 -0700900 /** {@hide} */
Jeff Sharkeyb5e89c62016-04-01 23:20:31 -0600901 public boolean isDirectBootAware() {
902 return ((flags & FLAG_FORCE_DIRECT_BOOT_AWARE) != 0)
903 || mResolveInfo.serviceInfo.directBootAware;
Jeff Sharkeye88e2662016-02-23 17:52:16 -0700904 }
905
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700906 /**
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700907 * {@inheritDoc}
908 */
svetoslavganov75986cf2009-05-14 22:28:01 -0700909 public int describeContents() {
910 return 0;
911 }
912
Svetoslav Ganov9b317792010-02-17 16:46:42 -0800913 public void writeToParcel(Parcel parcel, int flagz) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700914 parcel.writeInt(eventTypes);
915 parcel.writeStringArray(packageNames);
916 parcel.writeInt(feedbackType);
917 parcel.writeLong(notificationTimeout);
Rhed Jao41118f32018-10-25 17:03:28 +0800918 parcel.writeInt(mNonInteractiveUiTimeout);
919 parcel.writeInt(mInteractiveUiTimeout);
svetoslavganov75986cf2009-05-14 22:28:01 -0700920 parcel.writeInt(flags);
Phil Weaverc09a0212018-03-13 09:50:43 -0700921 parcel.writeInt(crashed ? 1 : 0);
Phil Weaver106fe732016-11-22 18:18:39 -0800922 parcel.writeParcelable(mComponentName, flagz);
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700923 parcel.writeParcelable(mResolveInfo, 0);
924 parcel.writeString(mSettingsActivityName);
Svetoslav688a6972013-04-16 18:55:38 -0700925 parcel.writeInt(mCapabilities);
Saige McVea08c41bc2017-01-20 20:22:35 -0800926 parcel.writeInt(mSummaryResId);
927 parcel.writeString(mNonLocalizedSummary);
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800928 parcel.writeInt(mDescriptionResId);
929 parcel.writeString(mNonLocalizedDescription);
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700930 }
931
932 private void initFromParcel(Parcel parcel) {
933 eventTypes = parcel.readInt();
934 packageNames = parcel.readStringArray();
935 feedbackType = parcel.readInt();
936 notificationTimeout = parcel.readLong();
Rhed Jao41118f32018-10-25 17:03:28 +0800937 mNonInteractiveUiTimeout = parcel.readInt();
938 mInteractiveUiTimeout = parcel.readInt();
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700939 flags = parcel.readInt();
Phil Weaverc09a0212018-03-13 09:50:43 -0700940 crashed = parcel.readInt() != 0;
Phil Weaver106fe732016-11-22 18:18:39 -0800941 mComponentName = parcel.readParcelable(this.getClass().getClassLoader());
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700942 mResolveInfo = parcel.readParcelable(null);
943 mSettingsActivityName = parcel.readString();
Svetoslav688a6972013-04-16 18:55:38 -0700944 mCapabilities = parcel.readInt();
Saige McVea08c41bc2017-01-20 20:22:35 -0800945 mSummaryResId = parcel.readInt();
946 mNonLocalizedSummary = parcel.readString();
Svetoslav Ganov3d0edd32012-01-03 16:38:46 -0800947 mDescriptionResId = parcel.readInt();
948 mNonLocalizedDescription = parcel.readString();
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700949 }
950
951 @Override
Svetoslav57bf8852013-02-07 19:21:42 -0800952 public int hashCode() {
Phil Weaver106fe732016-11-22 18:18:39 -0800953 return 31 * 1 + ((mComponentName == null) ? 0 : mComponentName.hashCode());
Svetoslav57bf8852013-02-07 19:21:42 -0800954 }
955
956 @Override
957 public boolean equals(Object obj) {
958 if (this == obj) {
959 return true;
960 }
961 if (obj == null) {
962 return false;
963 }
964 if (getClass() != obj.getClass()) {
965 return false;
966 }
967 AccessibilityServiceInfo other = (AccessibilityServiceInfo) obj;
Phil Weaver106fe732016-11-22 18:18:39 -0800968 if (mComponentName == null) {
969 if (other.mComponentName != null) {
Svetoslav57bf8852013-02-07 19:21:42 -0800970 return false;
971 }
Phil Weaver106fe732016-11-22 18:18:39 -0800972 } else if (!mComponentName.equals(other.mComponentName)) {
Svetoslav57bf8852013-02-07 19:21:42 -0800973 return false;
974 }
975 return true;
976 }
977
978 @Override
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700979 public String toString() {
980 StringBuilder stringBuilder = new StringBuilder();
981 appendEventTypes(stringBuilder, eventTypes);
982 stringBuilder.append(", ");
983 appendPackageNames(stringBuilder, packageNames);
984 stringBuilder.append(", ");
985 appendFeedbackTypes(stringBuilder, feedbackType);
986 stringBuilder.append(", ");
987 stringBuilder.append("notificationTimeout: ").append(notificationTimeout);
988 stringBuilder.append(", ");
Rhed Jao41118f32018-10-25 17:03:28 +0800989 stringBuilder.append("nonInteractiveUiTimeout: ").append(mNonInteractiveUiTimeout);
990 stringBuilder.append(", ");
991 stringBuilder.append("interactiveUiTimeout: ").append(mInteractiveUiTimeout);
Rhed Jaoe9728812018-08-29 12:14:46 +0800992 stringBuilder.append(", ");
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700993 appendFlags(stringBuilder, flags);
994 stringBuilder.append(", ");
Phil Weaver106fe732016-11-22 18:18:39 -0800995 stringBuilder.append("id: ").append(getId());
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700996 stringBuilder.append(", ");
997 stringBuilder.append("resolveInfo: ").append(mResolveInfo);
998 stringBuilder.append(", ");
999 stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName);
1000 stringBuilder.append(", ");
Saige McVea08c41bc2017-01-20 20:22:35 -08001001 stringBuilder.append("summary: ").append(mNonLocalizedSummary);
1002 stringBuilder.append(", ");
Svetoslav688a6972013-04-16 18:55:38 -07001003 appendCapabilities(stringBuilder, mCapabilities);
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -07001004 return stringBuilder.toString();
1005 }
1006
Svetoslav Ganov24c90452017-12-27 15:17:14 -08001007 private static void appendFeedbackTypes(StringBuilder stringBuilder,
1008 @FeedbackType int feedbackTypes) {
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -07001009 stringBuilder.append("feedbackTypes:");
1010 stringBuilder.append("[");
1011 while (feedbackTypes != 0) {
1012 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackTypes));
1013 stringBuilder.append(feedbackTypeToString(feedbackTypeBit));
1014 feedbackTypes &= ~feedbackTypeBit;
1015 if (feedbackTypes != 0) {
1016 stringBuilder.append(", ");
1017 }
1018 }
1019 stringBuilder.append("]");
1020 }
1021
1022 private static void appendPackageNames(StringBuilder stringBuilder, String[] packageNames) {
1023 stringBuilder.append("packageNames:");
1024 stringBuilder.append("[");
1025 if (packageNames != null) {
1026 final int packageNameCount = packageNames.length;
1027 for (int i = 0; i < packageNameCount; i++) {
1028 stringBuilder.append(packageNames[i]);
1029 if (i < packageNameCount - 1) {
1030 stringBuilder.append(", ");
1031 }
1032 }
1033 }
1034 stringBuilder.append("]");
1035 }
1036
1037 private static void appendEventTypes(StringBuilder stringBuilder, int eventTypes) {
1038 stringBuilder.append("eventTypes:");
1039 stringBuilder.append("[");
1040 while (eventTypes != 0) {
1041 final int eventTypeBit = (1 << Integer.numberOfTrailingZeros(eventTypes));
1042 stringBuilder.append(AccessibilityEvent.eventTypeToString(eventTypeBit));
1043 eventTypes &= ~eventTypeBit;
1044 if (eventTypes != 0) {
1045 stringBuilder.append(", ");
1046 }
1047 }
1048 stringBuilder.append("]");
1049 }
1050
1051 private static void appendFlags(StringBuilder stringBuilder, int flags) {
1052 stringBuilder.append("flags:");
1053 stringBuilder.append("[");
1054 while (flags != 0) {
1055 final int flagBit = (1 << Integer.numberOfTrailingZeros(flags));
1056 stringBuilder.append(flagToString(flagBit));
1057 flags &= ~flagBit;
1058 if (flags != 0) {
1059 stringBuilder.append(", ");
1060 }
1061 }
1062 stringBuilder.append("]");
1063 }
1064
Svetoslav688a6972013-04-16 18:55:38 -07001065 private static void appendCapabilities(StringBuilder stringBuilder, int capabilities) {
1066 stringBuilder.append("capabilities:");
1067 stringBuilder.append("[");
1068 while (capabilities != 0) {
1069 final int capabilityBit = (1 << Integer.numberOfTrailingZeros(capabilities));
1070 stringBuilder.append(capabilityToString(capabilityBit));
1071 capabilities &= ~capabilityBit;
1072 if (capabilities != 0) {
1073 stringBuilder.append(", ");
1074 }
1075 }
1076 stringBuilder.append("]");
1077 }
1078
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -07001079 /**
1080 * Returns the string representation of a feedback type. For example,
1081 * {@link #FEEDBACK_SPOKEN} is represented by the string FEEDBACK_SPOKEN.
1082 *
1083 * @param feedbackType The feedback type.
1084 * @return The string representation.
1085 */
1086 public static String feedbackTypeToString(int feedbackType) {
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001087 StringBuilder builder = new StringBuilder();
1088 builder.append("[");
Svetoslav Ganovc6c25f92012-03-09 16:01:18 -08001089 while (feedbackType != 0) {
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001090 final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType);
1091 feedbackType &= ~feedbackTypeFlag;
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001092 switch (feedbackTypeFlag) {
1093 case FEEDBACK_AUDIBLE:
Svetoslav Ganovc6c25f92012-03-09 16:01:18 -08001094 if (builder.length() > 1) {
1095 builder.append(", ");
1096 }
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001097 builder.append("FEEDBACK_AUDIBLE");
1098 break;
1099 case FEEDBACK_HAPTIC:
Svetoslav Ganovc6c25f92012-03-09 16:01:18 -08001100 if (builder.length() > 1) {
1101 builder.append(", ");
1102 }
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001103 builder.append("FEEDBACK_HAPTIC");
1104 break;
1105 case FEEDBACK_GENERIC:
Svetoslav Ganovc6c25f92012-03-09 16:01:18 -08001106 if (builder.length() > 1) {
1107 builder.append(", ");
1108 }
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001109 builder.append("FEEDBACK_GENERIC");
1110 break;
1111 case FEEDBACK_SPOKEN:
Svetoslav Ganovc6c25f92012-03-09 16:01:18 -08001112 if (builder.length() > 1) {
1113 builder.append(", ");
1114 }
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001115 builder.append("FEEDBACK_SPOKEN");
1116 break;
1117 case FEEDBACK_VISUAL:
Svetoslav Ganovc6c25f92012-03-09 16:01:18 -08001118 if (builder.length() > 1) {
1119 builder.append(", ");
1120 }
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001121 builder.append("FEEDBACK_VISUAL");
1122 break;
Svetoslav Ganoveb9862f2012-09-06 19:40:29 -07001123 case FEEDBACK_BRAILLE:
1124 if (builder.length() > 1) {
1125 builder.append(", ");
1126 }
1127 builder.append("FEEDBACK_BRAILLE");
1128 break;
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001129 }
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -07001130 }
Svetoslav Ganovbb1b9ea2011-10-19 17:10:14 -07001131 builder.append("]");
1132 return builder.toString();
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -07001133 }
1134
1135 /**
1136 * Returns the string representation of a flag. For example,
1137 * {@link #DEFAULT} is represented by the string DEFAULT.
1138 *
1139 * @param flag The flag.
1140 * @return The string representation.
1141 */
1142 public static String flagToString(int flag) {
1143 switch (flag) {
1144 case DEFAULT:
1145 return "DEFAULT";
Svetoslav Ganov3ec2e1b2012-05-09 11:02:38 -07001146 case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS:
1147 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS";
1148 case FLAG_REQUEST_TOUCH_EXPLORATION_MODE:
1149 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE";
Svetoslav688a6972013-04-16 18:55:38 -07001150 case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
1151 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
1152 case FLAG_REPORT_VIEW_IDS:
1153 return "FLAG_REPORT_VIEW_IDS";
1154 case FLAG_REQUEST_FILTER_KEY_EVENTS:
1155 return "FLAG_REQUEST_FILTER_KEY_EVENTS";
Svetoslav8e3feb12014-02-24 13:46:47 -08001156 case FLAG_RETRIEVE_INTERACTIVE_WINDOWS:
1157 return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS";
Phil Weaver4acc16d2016-09-14 17:04:49 -07001158 case FLAG_ENABLE_ACCESSIBILITY_VOLUME:
1159 return "FLAG_ENABLE_ACCESSIBILITY_VOLUME";
Casey Burkhardt048c2bc2016-12-08 16:09:20 -08001160 case FLAG_REQUEST_ACCESSIBILITY_BUTTON:
1161 return "FLAG_REQUEST_ACCESSIBILITY_BUTTON";
Phil Weaverbe2922f2017-04-28 14:58:35 -07001162 case FLAG_REQUEST_FINGERPRINT_GESTURES:
1163 return "FLAG_REQUEST_FINGERPRINT_GESTURES";
Rhed Jao6182af72018-08-22 18:48:59 +08001164 case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
1165 return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
Rhed Jao62ea99c2019-09-14 14:25:17 +08001166 case FLAG_HANDLE_SHORTCUT:
1167 return "FLAG_HANDLE_SHORTCUT";
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -07001168 default:
1169 return null;
1170 }
svetoslavganov75986cf2009-05-14 22:28:01 -07001171 }
1172
1173 /**
Svetoslav688a6972013-04-16 18:55:38 -07001174 * Returns the string representation of a capability. For example,
1175 * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented
1176 * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT.
1177 *
1178 * @param capability The capability.
1179 * @return The string representation.
1180 */
1181 public static String capabilityToString(int capability) {
1182 switch (capability) {
1183 case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT:
1184 return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT";
1185 case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION:
1186 return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION";
1187 case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
1188 return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
1189 case CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS:
Casey Burkhardt048c2bc2016-12-08 16:09:20 -08001190 return "CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS";
Alan Viverette214fb682015-11-17 09:47:11 -05001191 case CAPABILITY_CAN_CONTROL_MAGNIFICATION:
1192 return "CAPABILITY_CAN_CONTROL_MAGNIFICATION";
Phil Weavera6b64f52015-12-04 15:21:35 -08001193 case CAPABILITY_CAN_PERFORM_GESTURES:
1194 return "CAPABILITY_CAN_PERFORM_GESTURES";
Phil Weaverbe2922f2017-04-28 14:58:35 -07001195 case CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES:
1196 return "CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES";
Svetoslav688a6972013-04-16 18:55:38 -07001197 default:
1198 return "UNKNOWN";
1199 }
1200 }
1201
1202 /**
1203 * @hide
1204 * @return The list of {@link CapabilityInfo} objects.
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001205 * @deprecated The version that takes a context works better.
Svetoslav688a6972013-04-16 18:55:38 -07001206 */
1207 public List<CapabilityInfo> getCapabilityInfos() {
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001208 return getCapabilityInfos(null);
1209 }
1210
1211 /**
1212 * @hide
1213 * @param context A valid context
1214 * @return The list of {@link CapabilityInfo} objects.
1215 */
1216 public List<CapabilityInfo> getCapabilityInfos(Context context) {
Svetoslav688a6972013-04-16 18:55:38 -07001217 if (mCapabilities == 0) {
1218 return Collections.emptyList();
1219 }
1220 int capabilities = mCapabilities;
1221 List<CapabilityInfo> capabilityInfos = new ArrayList<CapabilityInfo>();
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001222 SparseArray<CapabilityInfo> capabilityInfoSparseArray =
1223 getCapabilityInfoSparseArray(context);
Svetoslav688a6972013-04-16 18:55:38 -07001224 while (capabilities != 0) {
1225 final int capabilityBit = 1 << Integer.numberOfTrailingZeros(capabilities);
1226 capabilities &= ~capabilityBit;
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001227 CapabilityInfo capabilityInfo = capabilityInfoSparseArray.get(capabilityBit);
Svetoslav688a6972013-04-16 18:55:38 -07001228 if (capabilityInfo != null) {
1229 capabilityInfos.add(capabilityInfo);
1230 }
1231 }
1232 return capabilityInfos;
1233 }
1234
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001235 private static SparseArray<CapabilityInfo> getCapabilityInfoSparseArray(Context context) {
1236 if (sAvailableCapabilityInfos == null) {
1237 sAvailableCapabilityInfos = new SparseArray<CapabilityInfo>();
1238 sAvailableCapabilityInfos.put(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
1239 new CapabilityInfo(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
1240 R.string.capability_title_canRetrieveWindowContent,
1241 R.string.capability_desc_canRetrieveWindowContent));
1242 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
1243 new CapabilityInfo(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
1244 R.string.capability_title_canRequestTouchExploration,
1245 R.string.capability_desc_canRequestTouchExploration));
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001246 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
1247 new CapabilityInfo(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
1248 R.string.capability_title_canRequestFilterKeyEvents,
1249 R.string.capability_desc_canRequestFilterKeyEvents));
1250 sAvailableCapabilityInfos.put(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
1251 new CapabilityInfo(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
1252 R.string.capability_title_canControlMagnification,
1253 R.string.capability_desc_canControlMagnification));
1254 sAvailableCapabilityInfos.put(CAPABILITY_CAN_PERFORM_GESTURES,
1255 new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES,
1256 R.string.capability_title_canPerformGestures,
1257 R.string.capability_desc_canPerformGestures));
Phil Weaver7917a2f2017-02-16 19:51:14 -08001258 if ((context == null) || fingerprintAvailable(context)) {
Phil Weaverbe2922f2017-04-28 14:58:35 -07001259 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES,
1260 new CapabilityInfo(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES,
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001261 R.string.capability_title_canCaptureFingerprintGestures,
1262 R.string.capability_desc_canCaptureFingerprintGestures));
1263 }
1264 }
1265 return sAvailableCapabilityInfos;
1266 }
1267
Phil Weaver7917a2f2017-02-16 19:51:14 -08001268 private static boolean fingerprintAvailable(Context context) {
1269 return context.getPackageManager().hasSystemFeature(FEATURE_FINGERPRINT)
1270 && context.getSystemService(FingerprintManager.class).isHardwareDetected();
1271 }
Svetoslav688a6972013-04-16 18:55:38 -07001272 /**
1273 * @hide
1274 */
1275 public static final class CapabilityInfo {
1276 public final int capability;
1277 public final int titleResId;
1278 public final int descResId;
1279
1280 public CapabilityInfo(int capability, int titleResId, int descResId) {
1281 this.capability = capability;
1282 this.titleResId = titleResId;
1283 this.descResId = descResId;
1284 }
1285 }
1286
1287 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07001288 * @see Parcelable.Creator
1289 */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001290 public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityServiceInfo> CREATOR =
svetoslavganov75986cf2009-05-14 22:28:01 -07001291 new Parcelable.Creator<AccessibilityServiceInfo>() {
1292 public AccessibilityServiceInfo createFromParcel(Parcel parcel) {
1293 AccessibilityServiceInfo info = new AccessibilityServiceInfo();
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -07001294 info.initFromParcel(parcel);
svetoslavganov75986cf2009-05-14 22:28:01 -07001295 return info;
1296 }
1297
1298 public AccessibilityServiceInfo[] newArray(int size) {
1299 return new AccessibilityServiceInfo[size];
1300 }
1301 };
1302}