• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view.accessibility;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.compat.annotation.UnsupportedAppUsage;
22 import android.os.Build;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.text.TextUtils;
26 import android.util.Log;
27 import android.util.Pools.SynchronizedPool;
28 
29 import com.android.internal.util.BitUtils;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /**
37  * <p>
38  * This class represents accessibility events that are sent by the system when
39  * something notable happens in the user interface. For example, when a
40  * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
41  * </p>
42  * <p>
43  * An accessibility event is fired by an individual view which populates the event with
44  * data for its state and requests from its parent to send the event to interested
45  * parties. The parent can optionally modify or even block the event based on its broader
46  * understanding of the user interface's context.
47  * </p>
48  * <p>
49  * The main purpose of an accessibility event is to communicate changes in the UI to an
50  * {@link android.accessibilityservice.AccessibilityService}. The service may then inspect,
51  * if needed the user interface by examining the View hierarchy, as represented by a tree of
52  * {@link AccessibilityNodeInfo}s (snapshot of a View state)
53  * which can be used for exploring the window content. Note that the privilege for accessing
54  * an event's source, thus the window content, has to be explicitly requested. For more
55  * details refer to {@link android.accessibilityservice.AccessibilityService}. If an
56  * accessibility service has not requested to retrieve the window content the event will
57  * not contain reference to its source. Also for events of type
58  * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available.
59  * </p>
60  * <p>
61  * This class represents various semantically different accessibility event
62  * types. Each event type has an associated set of related properties. In other
63  * words, each event type is characterized via a subset of the properties exposed
64  * by this class. For each event type there is a corresponding constant defined
65  * in this class. Follows a specification of the event types and their associated properties:
66  * </p>
67  * <div class="special reference">
68  * <h3>Developer Guides</h3>
69  * <p>For more information about creating and processing AccessibilityEvents, read the
70  * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
71  * developer guide.</p>
72  * </div>
73  * <p>
74  * <b>VIEW TYPES</b></br>
75  * </p>
76  * <p>
77  * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View}
78  * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.</br>
79  * <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br>
80  * <em>Properties:</em></br>
81  * <ul>
82  *   <li>{@link #getEventType()} - The type of the event.</li>
83  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
84  *   <li>{@link #getClassName()} - The class name of the source.</li>
85  *   <li>{@link #getPackageName()} - The package name of the source.</li>
86  *   <li>{@link #getEventTime()}  - The event time.</li>
87  * </ul>
88  * </p>
89  * <p>
90  * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
91  * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br>
92  * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br>
93  * <em>Properties:</em></br>
94  * <ul>
95  *   <li>{@link #getEventType()} - The type of the event.</li>
96  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
97  *   <li>{@link #getClassName()} - The class name of the source.</li>
98  *   <li>{@link #getPackageName()} - The package name of the source.</li>
99  *   <li>{@link #getEventTime()}  - The event time.</li>
100  * </ul>
101  * </p>
102  * <p>
103  * <b>View selected</b> - represents the event of selecting an item usually in
104  * the context of an {@link android.widget.AdapterView}.</br>
105  * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
106  * <em>Properties:</em></br>
107  * <ul>
108  *   <li>{@link #getEventType()} - The type of the event.</li>
109  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
110  *   <li>{@link #getClassName()} - The class name of the source.</li>
111  *   <li>{@link #getPackageName()} - The package name of the source.</li>
112  *   <li>{@link #getEventTime()}  - The event time.</li>
113  * </ul>
114  * </p>
115  * <p>
116  * <b>View focused</b> - represents the event of focusing a
117  * {@link android.view.View}.</br>
118  * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
119  * <em>Properties:</em></br>
120  * <ul>
121  *   <li>{@link #getEventType()} - The type of the event.</li>
122  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
123  *   <li>{@link #getClassName()} - The class name of the source.</li>
124  *   <li>{@link #getPackageName()} - The package name of the source.</li>
125  *   <li>{@link #getEventTime()}  - The event time.</li>
126  * </ul>
127  * </p>
128  * <p>
129  * <b>View text changed</b> - represents the event of changing the text of an
130  * {@link android.widget.EditText}.</br>
131  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
132  * <em>Properties:</em></br>
133  * <ul>
134  *   <li>{@link #getEventType()} - The type of the event.</li>
135  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
136  *   <li>{@link #getClassName()} - The class name of the source.</li>
137  *   <li>{@link #getPackageName()} - The package name of the source.</li>
138  *   <li>{@link #getEventTime()}  - The event time.</li>
139  *   <li>{@link #getText()} - The new text of the source.</li>
140  *   <li>{@link #getBeforeText()} - The text of the source before the change.</li>
141  *   <li>{@link #getFromIndex()} - The text change start index.</li>
142  *   <li>{@link #getAddedCount()} - The number of added characters.</li>
143  *   <li>{@link #getRemovedCount()} - The number of removed characters.</li>
144  * </ul>
145  * </p>
146  * <p>
147  * <b>View text selection changed</b> - represents the event of changing the text
148  * selection of an {@link android.widget.EditText}.</br>
149  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
150  * <em>Properties:</em></br>
151  * <ul>
152  *   <li>{@link #getEventType()} - The type of the event.</li>
153  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
154  *   <li>{@link #getClassName()} - The class name of the source.</li>
155  *   <li>{@link #getPackageName()} - The package name of the source.</li>
156  *   <li>{@link #getEventTime()}  - The event time.</li>
157  * </ul>
158  * </p>
159  * <b>View text traversed at movement granularity</b> - represents the event of traversing the
160  * text of a view at a given granularity. For example, moving to the next word.</br>
161  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY} </br>
162  * <em>Properties:</em></br>
163  * <ul>
164  *   <li>{@link #getEventType()} - The type of the event.</li>
165  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
166  *   <li>{@link #getClassName()} - The class name of the source.</li>
167  *   <li>{@link #getPackageName()} - The package name of the source.</li>
168  *   <li>{@link #getEventTime()}  - The event time.</li>
169  *   <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text
170  *       was traversed.</li>
171  *   <li>{@link #getText()} -  The text of the source's sub-tree.</li>
172  *   <li>{@link #getFromIndex()} - The start the text that was skipped over in this movement.
173  *       This is the starting point when moving forward through the text, but not when moving
174  *       back.</li>
175  *   <li>{@link #getToIndex()} - The end of the text that was skipped over in this movement.
176  *       This is the ending point when moving forward through the text, but not when moving
177  *       back.</li>
178  *   <li>{@link #getAction()} - Gets traversal action which specifies the direction.</li>
179  * </ul>
180  * </p>
181  * <p>
182  * <b>View scrolled</b> - represents the event of scrolling a view. </br>
183  * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
184  * <em>Properties:</em></br>
185  * <ul>
186  *   <li>{@link #getEventType()} - The type of the event.</li>
187  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
188  *   <li>{@link #getClassName()} - The class name of the source.</li>
189  *   <li>{@link #getPackageName()} - The package name of the source.</li>
190  *   <li>{@link #getEventTime()}  - The event time.</li>
191  *   <li>{@link #getScrollDeltaX()} - The difference in the horizontal position.</li>
192  *   <li>{@link #getScrollDeltaY()} - The difference in the vertical position.</li>
193  * </ul>
194  * </p>
195  * <p>
196  * <b>TRANSITION TYPES</b></br>
197  * </p>
198  * <p>
199  * <b>Window state changed</b> - represents the event of a change to a section of
200  * the user interface that is visually distinct. Should be sent from either the
201  * root view of a window or from a view that is marked as a pane
202  * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Note that changes
203  * to true windows are represented by {@link #TYPE_WINDOWS_CHANGED}.</br>
204  * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
205  * <em>Properties:</em></br>
206  * <ul>
207  *   <li>{@link #getEventType()} - The type of the event.</li>
208  *   <li>{@link #getContentChangeTypes()} - The type of state changes.</li>
209  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
210  *   <li>{@link #getClassName()} - The class name of the source.</li>
211  *   <li>{@link #getPackageName()} - The package name of the source.</li>
212  *   <li>{@link #getEventTime()}  - The event time.</li>
213  *   <li>{@link #getText()} - The text of the source's sub-tree, including the pane titles.</li>
214  * </ul>
215  * </p>
216  * <p>
217  * <b>Window content changed</b> - represents the event of change in the
218  * content of a window. This change can be adding/removing view, changing
219  * a view size, etc.</br>
220  * </p>
221  * <p>
222  * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
223  * <em>Properties:</em></br>
224  * <ul>
225  *   <li>{@link #getEventType()} - The type of the event.</li>
226  *   <li>{@link #getContentChangeTypes()} - The type of content changes.</li>
227  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
228  *   <li>{@link #getClassName()} - The class name of the source.</li>
229  *   <li>{@link #getPackageName()} - The package name of the source.</li>
230  *   <li>{@link #getEventTime()}  - The event time.</li>
231  * </ul>
232  * </p>
233  * <p>
234  * <b>Windows changed</b> - represents a change in the windows shown on
235  * the screen such as a window appeared, a window disappeared, a window size changed,
236  * a window layer changed, etc. These events should only come from the system, which is responsible
237  * for managing windows. The list of windows is available from
238  * {@link android.accessibilityservice.AccessibilityService#getWindows()}.
239  * For regions of the user interface that are presented as windows but are
240  * controlled by an app's process, use {@link #TYPE_WINDOW_STATE_CHANGED}.</br>
241  * <em>Type:</em> {@link #TYPE_WINDOWS_CHANGED}</br>
242  * <em>Properties:</em></br>
243  * <ul>
244  *   <li>{@link #getEventType()} - The type of the event.</li>
245  *   <li>{@link #getEventTime()} - The event time.</li>
246  *   <li>{@link #getWindowChanges()}</li> - The specific change to the source window
247  * </ul>
248  * <em>Note:</em> You can retrieve the {@link AccessibilityWindowInfo} for the window
249  * source of the event by looking through the list returned by
250  * {@link android.accessibilityservice.AccessibilityService#getWindows()} for the window whose ID
251  * matches {@link #getWindowId()}.
252  * </p>
253  * <p>
254  * <b>NOTIFICATION TYPES</b></br>
255  * </p>
256  * <p>
257  * <b>Notification state changed</b> - represents the event showing a transient piece of information
258  * to the user. This information may be a {@link android.app.Notification} or
259  * {@link android.widget.Toast}.</br>
260  * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
261  * <em>Properties:</em></br>
262  * <ul>
263  *   <li>{@link #getEventType()} - The type of the event.</li>
264  *   <li>{@link #getClassName()} - The class name of the source.</li>
265  *   <li>{@link #getPackageName()} - The package name of the source.</li>
266  *   <li>{@link #getEventTime()}  - The event time.</li>
267  *   <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}, if
268  *   applicable.</li>
269  *   <li>{@link #getText()} - Displayed text of the {@link android.widget.Toast}, if applicable,
270  *   or may contain text from the {@link android.app.Notification}, although
271  *   {@link #getParcelableData()} is a richer set of data for {@link android.app.Notification}.</li>
272  * </ul>
273  * </p>
274  * <p>
275  * <b>EXPLORATION TYPES</b></br>
276  * </p>
277  * <p>
278  * <b>View hover enter</b> - represents the event of beginning to hover
279  * over a {@link android.view.View}. The hover may be generated via
280  * exploring the screen by touch or via a pointing device.</br>
281  * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br>
282  * <em>Properties:</em></br>
283  * <ul>
284  *   <li>{@link #getEventType()} - The type of the event.</li>
285  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
286  *   <li>{@link #getClassName()} - The class name of the source.</li>
287  *   <li>{@link #getPackageName()} - The package name of the source.</li>
288  *   <li>{@link #getEventTime()}  - The event time.</li>
289  * </ul>
290  * </p>
291  * <b>View hover exit</b> - represents the event of stopping to hover
292  * over a {@link android.view.View}. The hover may be generated via
293  * exploring the screen by touch or via a pointing device.</br>
294  * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br>
295  * <em>Properties:</em></br>
296  * <ul>
297  *   <li>{@link #getEventType()} - The type of the event.</li>
298  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
299  *   <li>{@link #getClassName()} - The class name of the source.</li>
300  *   <li>{@link #getPackageName()} - The package name of the source.</li>
301  *   <li>{@link #getEventTime()}  - The event time.</li>
302  * </ul>
303  * </p>
304  * <p>
305  * <b>Touch interaction start</b> - represents the event of starting a touch
306  * interaction, which is the user starts touching the screen.</br>
307  * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_START}</br>
308  * <em>Properties:</em></br>
309  * <ul>
310  *   <li>{@link #getEventType()} - The type of the event.</li>
311  * </ul>
312  * <em>Note:</em> This event is fired only by the system and is not passed to the
313  * view tree to be populated.</br>
314  * </p>
315  * <p>
316  * <b>Touch interaction end</b> - represents the event of ending a touch
317  * interaction, which is the user stops touching the screen.</br>
318  * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_END}</br>
319  * <em>Properties:</em></br>
320  * <ul>
321  *   <li>{@link #getEventType()} - The type of the event.</li>
322  * </ul>
323  * <em>Note:</em> This event is fired only by the system and is not passed to the
324  * view tree to be populated.</br>
325  * </p>
326  * <p>
327  * <b>Touch exploration gesture start</b> - represents the event of starting a touch
328  * exploring gesture.</br>
329  * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br>
330  * <em>Properties:</em></br>
331  * <ul>
332  *   <li>{@link #getEventType()} - The type of the event.</li>
333  * </ul>
334  * <em>Note:</em> This event is fired only by the system and is not passed to the
335  * view tree to be populated.</br>
336  * </p>
337  * <p>
338  * <b>Touch exploration gesture end</b> - represents the event of ending a touch
339  * exploring gesture.</br>
340  * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br>
341  * <em>Properties:</em></br>
342  * <ul>
343  *   <li>{@link #getEventType()} - The type of the event.</li>
344  * </ul>
345  * <em>Note:</em> This event is fired only by the system and is not passed to the
346  * view tree to be populated.</br>
347  * </p>
348  * <p>
349  * <b>Touch gesture detection start</b> - represents the event of starting a user
350  * gesture detection.</br>
351  * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_START}</br>
352  * <em>Properties:</em></br>
353  * <ul>
354  *   <li>{@link #getEventType()} - The type of the event.</li>
355  * </ul>
356  * <em>Note:</em> This event is fired only by the system and is not passed to the
357  * view tree to be populated.</br>
358  * </p>
359  * <p>
360  * <b>Touch gesture detection end</b> - represents the event of ending a user
361  * gesture detection.</br>
362  * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_END}</br>
363  * <em>Properties:</em></br>
364  * <ul>
365  *   <li>{@link #getEventType()} - The type of the event.</li>
366  * </ul>
367  * <em>Note:</em> This event is fired only by the system and is not passed to the
368  * view tree to be populated.</br>
369  * </p>
370  * <p>
371  * <b>MISCELLANEOUS TYPES</b></br>
372  * </p>
373  * <p>
374  * <b>Announcement</b> - represents the event of an application requesting a screen reader to make
375  * an announcement. Because the event carries no semantic meaning, this event is appropriate only
376  * in exceptional situations where additional screen reader output is needed but other types of
377  * accessibility services do not need to be aware of the change.</br>
378  * <em>Type:</em> {@link #TYPE_ANNOUNCEMENT}</br>
379  * <em>Properties:</em></br>
380  * <ul>
381  *   <li>{@link #getEventType()} - The type of the event.</li>
382  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
383  *   <li>{@link #getClassName()} - The class name of the source.</li>
384  *   <li>{@link #getPackageName()} - The package name of the source.</li>
385  *   <li>{@link #getEventTime()}  - The event time.</li>
386  *   <li>{@link #getText()} - The text of the announcement.</li>
387  * </ul>
388  * </p>
389  *
390  * @see android.view.accessibility.AccessibilityManager
391  * @see android.accessibilityservice.AccessibilityService
392  * @see AccessibilityNodeInfo
393  */
394 public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
395     private static final String LOG_TAG = "AccessibilityEvent";
396 
397     private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG) && Build.IS_DEBUGGABLE;
398 
399     /** @hide */
400     public static final boolean DEBUG_ORIGIN = false;
401 
402     /**
403      * Invalid selection/focus position.
404      *
405      * @see #getCurrentItemIndex()
406      */
407     public static final int INVALID_POSITION = -1;
408 
409     /**
410      * Maximum length of the text fields.
411      *
412      * @see #getBeforeText()
413      * @see #getText()
414      * </br>
415      * Note: This constant is no longer needed since there
416      *       is no limit on the length of text that is contained
417      *       in an accessibility event anymore.
418      */
419     @Deprecated
420     public static final int MAX_TEXT_LENGTH = 500;
421 
422     /**
423      * Represents the event of clicking on a {@link android.view.View} like
424      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
425      */
426     public static final int TYPE_VIEW_CLICKED = 0x00000001;
427 
428     /**
429      * Represents the event of long clicking on a {@link android.view.View} like
430      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
431      */
432     public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
433 
434     /**
435      * Represents the event of selecting an item usually in the context of an
436      * {@link android.widget.AdapterView}.
437      */
438     public static final int TYPE_VIEW_SELECTED = 0x00000004;
439 
440     /**
441      * Represents the event of setting input focus of a {@link android.view.View}.
442      */
443     public static final int TYPE_VIEW_FOCUSED = 0x00000008;
444 
445     /**
446      * Represents the event of changing the text of an {@link android.widget.EditText}.
447      */
448     public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
449 
450     /**
451      * Represents the event of a change to a visually distinct section of the user interface.
452      * These events should only be dispatched from {@link android.view.View}s that have
453      * accessibility pane titles, and replaces {@link #TYPE_WINDOW_CONTENT_CHANGED} for those
454      * sources. Details about the change are available from {@link #getContentChangeTypes()}.
455      */
456     public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
457 
458     /**
459      * Represents the event showing a {@link android.app.Notification}.
460      */
461     public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
462 
463     /**
464      * Represents the event of a hover enter over a {@link android.view.View}.
465      */
466     public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
467 
468     /**
469      * Represents the event of a hover exit over a {@link android.view.View}.
470      */
471     public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
472 
473     /**
474      * Represents the event of starting a touch exploration gesture.
475      */
476     public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
477 
478     /**
479      * Represents the event of ending a touch exploration gesture.
480      */
481     public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
482 
483     /**
484      * Represents the event of changing the content of a window and more
485      * specifically the sub-tree rooted at the event's source.
486      */
487     public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
488 
489     /**
490      * Represents the event of scrolling a view. This event type is generally not sent directly.
491      * @see android.view.View#onScrollChanged(int, int, int, int)
492      */
493     public static final int TYPE_VIEW_SCROLLED = 0x00001000;
494 
495     /**
496      * Represents the event of changing the selection in an {@link android.widget.EditText}.
497      */
498     public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
499 
500     /**
501      * Represents the event of an application making an announcement.
502      */
503     public static final int TYPE_ANNOUNCEMENT = 0x00004000;
504 
505     /**
506      * Represents the event of gaining accessibility focus.
507      */
508     public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000;
509 
510     /**
511      * Represents the event of clearing accessibility focus.
512      */
513     public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
514 
515     /**
516      * Represents the event of traversing the text of a view at a given movement granularity.
517      */
518     public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
519 
520     /**
521      * Represents the event of beginning gesture detection.
522      */
523     public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
524 
525     /**
526      * Represents the event of ending gesture detection.
527      */
528     public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
529 
530     /**
531      * Represents the event of the user starting to touch the screen.
532      */
533     public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
534 
535     /**
536      * Represents the event of the user ending to touch the screen.
537      */
538     public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
539 
540     /**
541      * Represents the event change in the system windows shown on the screen. This event type should
542      * only be dispatched by the system.
543      */
544     public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
545 
546     /**
547      * Represents the event of a context click on a {@link android.view.View}.
548      */
549     public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
550 
551     /**
552      * Represents the event of the assistant currently reading the users screen context.
553      */
554     public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000;
555 
556     /**
557      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
558      * The type of change is not defined.
559      */
560     public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
561 
562     /**
563      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
564      * One or more content changes occurred in the the subtree rooted at the source node,
565      * or the subtree's structure changed when a node was added or removed.
566      */
567     public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
568 
569     /**
570      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
571      * The node's text changed.
572      */
573     public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
574 
575     /**
576      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
577      * The node's content description changed.
578      */
579     public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
580 
581     /**
582      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
583      * The node's pane title changed.
584      */
585     public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 0x00000008;
586 
587     /**
588      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
589      * The node has a pane title, and either just appeared or just was assigned a title when it
590      * had none before.
591      */
592     public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 0x00000010;
593 
594     /**
595      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
596      * Can mean one of two slightly different things. The primary meaning is that the node has
597      * a pane title, and was removed from the node hierarchy. It will also be sent if the pane
598      * title is set to {@code null} after it contained a title.
599      * No source will be returned if the node is no longer on the screen. To make the change more
600      * clear for the user, the first entry in {@link #getText()} will return the value that would
601      * have been returned by {@code getSource().getPaneTitle()}.
602      */
603     public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 0x00000020;
604 
605     /**
606      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
607      * state description of the node as returned by
608      * {@link AccessibilityNodeInfo#getStateDescription} changed. If part of the state description
609      * changes, the changed part can be put into event text. For example, if state description
610      * changed from "on, wifi signal full" to "on, wifi three bars", "wifi three bars" can be put
611      * into the event text.
612      */
613     public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 0x00000040;
614 
615     /**
616      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
617      * The window was added.
618      */
619     public static final int WINDOWS_CHANGE_ADDED = 0x00000001;
620 
621     /**
622      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
623      * A window was removed.
624      */
625     public static final int WINDOWS_CHANGE_REMOVED = 0x00000002;
626 
627     /**
628      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
629      * The window's title changed.
630      */
631     public static final int WINDOWS_CHANGE_TITLE = 0x00000004;
632 
633     /**
634      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
635      * The window's bounds changed.
636      * <p>
637      * Starting in {@link android.os.Build.VERSION_CODES#R R}, this event implies the window's
638      * region changed. It's also possible that region changed but bounds doesn't.
639      * </p>
640      */
641     public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
642 
643     /**
644      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
645      * The window's layer changed.
646      */
647     public static final int WINDOWS_CHANGE_LAYER = 0x00000010;
648 
649     /**
650      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
651      * The window's {@link AccessibilityWindowInfo#isActive()} changed.
652      */
653     public static final int WINDOWS_CHANGE_ACTIVE = 0x00000020;
654 
655     /**
656      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
657      * The window's {@link AccessibilityWindowInfo#isFocused()} changed.
658      */
659     public static final int WINDOWS_CHANGE_FOCUSED = 0x00000040;
660 
661     /**
662      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
663      * The window's {@link AccessibilityWindowInfo#isAccessibilityFocused()} changed.
664      */
665     public static final int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 0x00000080;
666 
667     /**
668      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
669      * The window's parent changed.
670      */
671     public static final int WINDOWS_CHANGE_PARENT = 0x00000100;
672 
673     /**
674      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
675      * The window's children changed.
676      */
677     public static final int WINDOWS_CHANGE_CHILDREN = 0x00000200;
678 
679     /**
680      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
681      * The window either entered or exited picture-in-picture mode.
682      */
683     public static final int WINDOWS_CHANGE_PIP = 0x00000400;
684 
685     /** @hide */
686     @Retention(RetentionPolicy.SOURCE)
687     @IntDef(flag = true, prefix = { "WINDOWS_CHANGE_" }, value = {
688             WINDOWS_CHANGE_ADDED,
689             WINDOWS_CHANGE_REMOVED,
690             WINDOWS_CHANGE_TITLE,
691             WINDOWS_CHANGE_BOUNDS,
692             WINDOWS_CHANGE_LAYER,
693             WINDOWS_CHANGE_ACTIVE,
694             WINDOWS_CHANGE_FOCUSED,
695             WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED,
696             WINDOWS_CHANGE_PARENT,
697             WINDOWS_CHANGE_CHILDREN,
698             WINDOWS_CHANGE_PIP
699     })
700     public @interface WindowsChangeTypes {}
701 
702     /** @hide */
703     @Retention(RetentionPolicy.SOURCE)
704     @IntDef(flag = true, prefix = { "CONTENT_CHANGE_TYPE_" },
705             value = {
706                     CONTENT_CHANGE_TYPE_UNDEFINED,
707                     CONTENT_CHANGE_TYPE_SUBTREE,
708                     CONTENT_CHANGE_TYPE_TEXT,
709                     CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION,
710                     CONTENT_CHANGE_TYPE_STATE_DESCRIPTION,
711                     CONTENT_CHANGE_TYPE_PANE_TITLE,
712                     CONTENT_CHANGE_TYPE_PANE_APPEARED,
713                     CONTENT_CHANGE_TYPE_PANE_DISAPPEARED
714             })
715     public @interface ContentChangeTypes {}
716 
717     /** @hide */
718     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
719             TYPE_VIEW_CLICKED,
720             TYPE_VIEW_LONG_CLICKED,
721             TYPE_VIEW_SELECTED,
722             TYPE_VIEW_FOCUSED,
723             TYPE_VIEW_TEXT_CHANGED,
724             TYPE_WINDOW_STATE_CHANGED,
725             TYPE_NOTIFICATION_STATE_CHANGED,
726             TYPE_VIEW_HOVER_ENTER,
727             TYPE_VIEW_HOVER_EXIT,
728             TYPE_TOUCH_EXPLORATION_GESTURE_START,
729             TYPE_TOUCH_EXPLORATION_GESTURE_END,
730             TYPE_WINDOW_CONTENT_CHANGED,
731             TYPE_VIEW_SCROLLED,
732             TYPE_VIEW_TEXT_SELECTION_CHANGED,
733             TYPE_ANNOUNCEMENT,
734             TYPE_VIEW_ACCESSIBILITY_FOCUSED,
735             TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED,
736             TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
737             TYPE_GESTURE_DETECTION_START,
738             TYPE_GESTURE_DETECTION_END,
739             TYPE_TOUCH_INTERACTION_START,
740             TYPE_TOUCH_INTERACTION_END,
741             TYPE_WINDOWS_CHANGED,
742             TYPE_VIEW_CONTEXT_CLICKED,
743             TYPE_ASSIST_READING_CONTEXT
744     })
745     @Retention(RetentionPolicy.SOURCE)
746     public @interface EventType {}
747 
748     /**
749      * Mask for {@link AccessibilityEvent} all types.
750      *
751      * @see #TYPE_VIEW_CLICKED
752      * @see #TYPE_VIEW_LONG_CLICKED
753      * @see #TYPE_VIEW_SELECTED
754      * @see #TYPE_VIEW_FOCUSED
755      * @see #TYPE_VIEW_TEXT_CHANGED
756      * @see #TYPE_WINDOW_STATE_CHANGED
757      * @see #TYPE_NOTIFICATION_STATE_CHANGED
758      * @see #TYPE_VIEW_HOVER_ENTER
759      * @see #TYPE_VIEW_HOVER_EXIT
760      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
761      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
762      * @see #TYPE_WINDOW_CONTENT_CHANGED
763      * @see #TYPE_VIEW_SCROLLED
764      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
765      * @see #TYPE_ANNOUNCEMENT
766      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
767      * @see #TYPE_GESTURE_DETECTION_START
768      * @see #TYPE_GESTURE_DETECTION_END
769      * @see #TYPE_TOUCH_INTERACTION_START
770      * @see #TYPE_TOUCH_INTERACTION_END
771      * @see #TYPE_WINDOWS_CHANGED
772      * @see #TYPE_VIEW_CONTEXT_CLICKED
773      */
774     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
775 
776     private static final int MAX_POOL_SIZE = 10;
777     private static final SynchronizedPool<AccessibilityEvent> sPool =
778             new SynchronizedPool<>(MAX_POOL_SIZE);
779 
780     @UnsupportedAppUsage
781     private @EventType int mEventType;
782     private CharSequence mPackageName;
783     private long mEventTime;
784     int mMovementGranularity;
785     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
786     int mAction;
787     int mContentChangeTypes;
788     int mWindowChangeTypes;
789 
790     /**
791      * The stack trace describing where this event originated from on the app side.
792      * Only populated if {@link #DEBUG_ORIGIN} is enabled
793      * Can be inspected(e.g. printed) from an
794      * {@link android.accessibilityservice.AccessibilityService} to trace where particular events
795      * are being dispatched from.
796      *
797      * @hide
798      */
799     public StackTraceElement[] originStackTrace = null;
800 
801     private ArrayList<AccessibilityRecord> mRecords;
802 
803     /**
804      * Creates a new {@link AccessibilityEvent}.
805      */
AccessibilityEvent()806     public AccessibilityEvent() {
807         if (DEBUG_ORIGIN) originStackTrace = Thread.currentThread().getStackTrace();
808     }
809 
810 
811     /**
812      * Creates a new {@link AccessibilityEvent} with the given <code>eventType</code>.
813      *
814      * @param eventType The event type.
815      */
AccessibilityEvent(int eventType)816     public AccessibilityEvent(int eventType) {
817         mEventType = eventType;
818         if (DEBUG_ORIGIN) originStackTrace = Thread.currentThread().getStackTrace();
819     }
820 
821     /**
822      * Copy constructor. Creates a new {@link AccessibilityEvent}, and this instance is initialized
823      * from the given <code>event</code>.
824      *
825      * @param event The other event.
826      */
AccessibilityEvent(@onNull AccessibilityEvent event)827     public AccessibilityEvent(@NonNull AccessibilityEvent event) {
828         init(event);
829     }
830 
831     /**
832      * Initialize an event from another one.
833      *
834      * @param event The event to initialize from.
835      */
init(AccessibilityEvent event)836     void init(AccessibilityEvent event) {
837         super.init(event);
838         mEventType = event.mEventType;
839         mMovementGranularity = event.mMovementGranularity;
840         mAction = event.mAction;
841         mContentChangeTypes = event.mContentChangeTypes;
842         mWindowChangeTypes = event.mWindowChangeTypes;
843         mEventTime = event.mEventTime;
844         mPackageName = event.mPackageName;
845         if (event.mRecords != null) {
846             final int recordCount = event.mRecords.size();
847             mRecords = new ArrayList<>(recordCount);
848             for (int i = 0; i < recordCount; i++) {
849                 final AccessibilityRecord record = event.mRecords.get(i);
850                 final AccessibilityRecord recordClone = new AccessibilityRecord(record);
851                 mRecords.add(recordClone);
852             }
853         }
854         if (DEBUG_ORIGIN) originStackTrace = event.originStackTrace;
855     }
856 
857     /**
858      * Sets if this instance is sealed.
859      *
860      * @param sealed Whether is sealed.
861      *
862      * @hide
863      */
864     @Override
setSealed(boolean sealed)865     public void setSealed(boolean sealed) {
866         super.setSealed(sealed);
867         final List<AccessibilityRecord> records = mRecords;
868         if (records != null) {
869             final int recordCount = records.size();
870             for (int i = 0; i < recordCount; i++) {
871                 AccessibilityRecord record = records.get(i);
872                 record.setSealed(sealed);
873             }
874         }
875     }
876 
877     /**
878      * Gets the number of records contained in the event.
879      *
880      * @return The number of records.
881      */
getRecordCount()882     public int getRecordCount() {
883         return mRecords == null ? 0 : mRecords.size();
884     }
885 
886     /**
887      * Appends an {@link AccessibilityRecord} to the end of event records.
888      *
889      * @param record The record to append.
890      *
891      * @throws IllegalStateException If called from an AccessibilityService.
892      */
appendRecord(AccessibilityRecord record)893     public void appendRecord(AccessibilityRecord record) {
894         enforceNotSealed();
895         if (mRecords == null) {
896             mRecords = new ArrayList<AccessibilityRecord>();
897         }
898         mRecords.add(record);
899     }
900 
901     /**
902      * Gets the record at a given index.
903      *
904      * @param index The index.
905      * @return The record at the specified index.
906      */
getRecord(int index)907     public AccessibilityRecord getRecord(int index) {
908         if (mRecords == null) {
909             throw new IndexOutOfBoundsException("Invalid index " + index + ", size is 0");
910         }
911         return mRecords.get(index);
912     }
913 
914     /**
915      * Gets the event type.
916      *
917      * @return The event type.
918      */
getEventType()919     public @EventType int getEventType() {
920         return mEventType;
921     }
922 
923     /**
924      * Gets the bit mask of change types signaled by a
925      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event or {@link #TYPE_WINDOW_STATE_CHANGED}. A single
926      * event may represent multiple change types.
927      *
928      * @return The bit mask of change types. One or more of:
929      *         <ul>
930      *         <li>{@link #CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION}
931      *         <li>{@link #CONTENT_CHANGE_TYPE_STATE_DESCRIPTION}
932      *         <li>{@link #CONTENT_CHANGE_TYPE_SUBTREE}
933      *         <li>{@link #CONTENT_CHANGE_TYPE_TEXT}
934      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_TITLE}
935      *         <li>{@link #CONTENT_CHANGE_TYPE_UNDEFINED}
936      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_APPEARED}
937      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_DISAPPEARED}
938      *         </ul>
939      */
940     @ContentChangeTypes
getContentChangeTypes()941     public int getContentChangeTypes() {
942         return mContentChangeTypes;
943     }
944 
contentChangeTypesToString(int types)945     private static String contentChangeTypesToString(int types) {
946         return BitUtils.flagsToString(types, AccessibilityEvent::singleContentChangeTypeToString);
947     }
948 
singleContentChangeTypeToString(int type)949     private static String singleContentChangeTypeToString(int type) {
950         switch (type) {
951             case CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION:
952                 return "CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION";
953             case CONTENT_CHANGE_TYPE_STATE_DESCRIPTION:
954                 return "CONTENT_CHANGE_TYPE_STATE_DESCRIPTION";
955             case CONTENT_CHANGE_TYPE_SUBTREE: return "CONTENT_CHANGE_TYPE_SUBTREE";
956             case CONTENT_CHANGE_TYPE_TEXT: return "CONTENT_CHANGE_TYPE_TEXT";
957             case CONTENT_CHANGE_TYPE_PANE_TITLE: return "CONTENT_CHANGE_TYPE_PANE_TITLE";
958             case CONTENT_CHANGE_TYPE_UNDEFINED: return "CONTENT_CHANGE_TYPE_UNDEFINED";
959             case CONTENT_CHANGE_TYPE_PANE_APPEARED: return "CONTENT_CHANGE_TYPE_PANE_APPEARED";
960             case CONTENT_CHANGE_TYPE_PANE_DISAPPEARED:
961                 return "CONTENT_CHANGE_TYPE_PANE_DISAPPEARED";
962             default: return Integer.toHexString(type);
963         }
964     }
965 
966     /**
967      * Sets the bit mask of node tree changes signaled by an
968      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
969      *
970      * @param changeTypes The bit mask of change types.
971      * @throws IllegalStateException If called from an AccessibilityService.
972      * @see #getContentChangeTypes()
973      */
setContentChangeTypes(@ontentChangeTypes int changeTypes)974     public void setContentChangeTypes(@ContentChangeTypes int changeTypes) {
975         enforceNotSealed();
976         mContentChangeTypes = changeTypes;
977     }
978 
979     /**
980      * Get the bit mask of change types signaled by a {@link #TYPE_WINDOWS_CHANGED} event. A
981      * single event may represent multiple change types.
982      *
983      * @return The bit mask of change types.
984      */
985     @WindowsChangeTypes
getWindowChanges()986     public int getWindowChanges() {
987         return mWindowChangeTypes;
988     }
989 
990     /** @hide  */
setWindowChanges(@indowsChangeTypes int changes)991     public void setWindowChanges(@WindowsChangeTypes int changes) {
992         mWindowChangeTypes = changes;
993     }
994 
windowChangeTypesToString(@indowsChangeTypes int types)995     private static String windowChangeTypesToString(@WindowsChangeTypes int types) {
996         return BitUtils.flagsToString(types, AccessibilityEvent::singleWindowChangeTypeToString);
997     }
998 
singleWindowChangeTypeToString(int type)999     private static String singleWindowChangeTypeToString(int type) {
1000         switch (type) {
1001             case WINDOWS_CHANGE_ADDED: return "WINDOWS_CHANGE_ADDED";
1002             case WINDOWS_CHANGE_REMOVED: return "WINDOWS_CHANGE_REMOVED";
1003             case WINDOWS_CHANGE_TITLE: return "WINDOWS_CHANGE_TITLE";
1004             case WINDOWS_CHANGE_BOUNDS: return "WINDOWS_CHANGE_BOUNDS";
1005             case WINDOWS_CHANGE_LAYER: return "WINDOWS_CHANGE_LAYER";
1006             case WINDOWS_CHANGE_ACTIVE: return "WINDOWS_CHANGE_ACTIVE";
1007             case WINDOWS_CHANGE_FOCUSED: return "WINDOWS_CHANGE_FOCUSED";
1008             case WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED:
1009                 return "WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED";
1010             case WINDOWS_CHANGE_PARENT: return "WINDOWS_CHANGE_PARENT";
1011             case WINDOWS_CHANGE_CHILDREN: return "WINDOWS_CHANGE_CHILDREN";
1012             case WINDOWS_CHANGE_PIP: return "WINDOWS_CHANGE_PIP";
1013             default: return Integer.toHexString(type);
1014         }
1015     }
1016 
1017     /**
1018      * Sets the event type.
1019      *
1020      * @param eventType The event type.
1021      *
1022      * @throws IllegalStateException If called from an AccessibilityService.
1023      */
setEventType(@ventType int eventType)1024     public void setEventType(@EventType int eventType) {
1025         enforceNotSealed();
1026         mEventType = eventType;
1027     }
1028 
1029     /**
1030      * Gets the time in which this event was sent.
1031      *
1032      * @return The event time.
1033      */
getEventTime()1034     public long getEventTime() {
1035         return mEventTime;
1036     }
1037 
1038     /**
1039      * Sets the time in which this event was sent.
1040      *
1041      * @param eventTime The event time.
1042      *
1043      * @throws IllegalStateException If called from an AccessibilityService.
1044      */
setEventTime(long eventTime)1045     public void setEventTime(long eventTime) {
1046         enforceNotSealed();
1047         mEventTime = eventTime;
1048     }
1049 
1050     /**
1051      * Gets the package name of the source.
1052      *
1053      * @return The package name.
1054      */
getPackageName()1055     public CharSequence getPackageName() {
1056         return mPackageName;
1057     }
1058 
1059     /**
1060      * Sets the package name of the source.
1061      *
1062      * @param packageName The package name.
1063      *
1064      * @throws IllegalStateException If called from an AccessibilityService.
1065      */
setPackageName(CharSequence packageName)1066     public void setPackageName(CharSequence packageName) {
1067         enforceNotSealed();
1068         mPackageName = packageName;
1069     }
1070 
1071     /**
1072      * Sets the movement granularity that was traversed.
1073      *
1074      * @param granularity The granularity.
1075      *
1076      * @throws IllegalStateException If called from an AccessibilityService.
1077      */
setMovementGranularity(int granularity)1078     public void setMovementGranularity(int granularity) {
1079         enforceNotSealed();
1080         mMovementGranularity = granularity;
1081     }
1082 
1083     /**
1084      * Gets the movement granularity that was traversed.
1085      *
1086      * @return The granularity.
1087      */
getMovementGranularity()1088     public int getMovementGranularity() {
1089         return mMovementGranularity;
1090     }
1091 
1092     /**
1093      * Sets the performed action that triggered this event.
1094      * <p>
1095      * Valid actions are defined in {@link AccessibilityNodeInfo}:
1096      * <ul>
1097      * <li>{@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}
1098      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
1099      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS}
1100      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION}
1101      * <li>{@link AccessibilityNodeInfo#ACTION_CLICK}
1102      * <li>etc.
1103      * </ul>
1104      *
1105      * @param action The action.
1106      * @throws IllegalStateException If called from an AccessibilityService.
1107      * @see AccessibilityNodeInfo#performAction(int)
1108      */
setAction(int action)1109     public void setAction(int action) {
1110         enforceNotSealed();
1111         mAction = action;
1112     }
1113 
1114     /**
1115      * Gets the performed action that triggered this event.
1116      *
1117      * @return The action.
1118      */
getAction()1119     public int getAction() {
1120         return mAction;
1121     }
1122 
1123     /**
1124      * Convenience method to obtain a {@link #TYPE_WINDOWS_CHANGED} event for a specific window and
1125      * change set.
1126      *
1127      * @param windowId The ID of the window that changed
1128      * @param windowChangeTypes The changes to populate
1129      * @return An instance of a TYPE_WINDOWS_CHANGED, populated with the requested fields and with
1130      *         importantForAccessibility set to {@code true}.
1131      *
1132      * @hide
1133      */
obtainWindowsChangedEvent( int windowId, int windowChangeTypes)1134     public static AccessibilityEvent obtainWindowsChangedEvent(
1135             int windowId, int windowChangeTypes) {
1136         final AccessibilityEvent event = AccessibilityEvent.obtain(TYPE_WINDOWS_CHANGED);
1137         event.setWindowId(windowId);
1138         event.setWindowChanges(windowChangeTypes);
1139         event.setImportantForAccessibility(true);
1140         return event;
1141     }
1142 
1143     /**
1144      * Returns a cached instance if such is available or a new one is
1145      * instantiated with its type property set.
1146      *
1147      * <p>In most situations object pooling is not beneficial. Create a new instance using the
1148      * constructor {@link #AccessibilityEvent(int)} instead.
1149      *
1150      * @param eventType The event type.
1151      * @return An instance.
1152      */
obtain(int eventType)1153     public static AccessibilityEvent obtain(int eventType) {
1154         AccessibilityEvent event = AccessibilityEvent.obtain();
1155         event.setEventType(eventType);
1156         return event;
1157     }
1158 
1159     /**
1160      * Returns a cached instance if such is available or a new one is
1161      * created. The returned instance is initialized from the given
1162      * <code>event</code>.
1163      *
1164      * <p>In most situations object pooling is not beneficial. Create a new instance using the
1165      * constructor {@link #AccessibilityEvent(AccessibilityEvent)} instead.
1166      *
1167      * @param event The other event.
1168      * @return An instance.
1169      */
obtain(AccessibilityEvent event)1170     public static AccessibilityEvent obtain(AccessibilityEvent event) {
1171         AccessibilityEvent eventClone = AccessibilityEvent.obtain();
1172         eventClone.init(event);
1173         return eventClone;
1174     }
1175 
1176     /**
1177      * Returns a cached instance if such is available or a new one is
1178      * instantiated.
1179      *
1180      * <p>In most situations object pooling is not beneficial. Create a new instance using the
1181      * constructor {@link #AccessibilityEvent()} instead.
1182      *
1183      * @return An instance.
1184      */
obtain()1185     public static AccessibilityEvent obtain() {
1186         AccessibilityEvent event = sPool.acquire();
1187         if (event == null) event = new AccessibilityEvent();
1188         if (DEBUG_ORIGIN) event.originStackTrace = Thread.currentThread().getStackTrace();
1189         return event;
1190     }
1191 
1192     /**
1193      * Recycles an instance back to be reused.
1194      * <p>
1195      *   <b>Note: You must not touch the object after calling this function.</b>
1196      * </p>
1197      *
1198      * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
1199      *
1200      * @throws IllegalStateException If the event is already recycled.
1201      */
1202     @Override
recycle()1203     public void recycle() {
1204         clear();
1205         sPool.release(this);
1206     }
1207 
1208     /**
1209      * Clears the state of this instance.
1210      *
1211      * @hide
1212      */
1213     @Override
clear()1214     protected void clear() {
1215         super.clear();
1216         mEventType = 0;
1217         mMovementGranularity = 0;
1218         mAction = 0;
1219         mContentChangeTypes = 0;
1220         mWindowChangeTypes = 0;
1221         mPackageName = null;
1222         mEventTime = 0;
1223         if (mRecords != null) {
1224             while (!mRecords.isEmpty()) {
1225                 AccessibilityRecord record = mRecords.remove(0);
1226                 record.recycle();
1227             }
1228         }
1229         if (DEBUG_ORIGIN) originStackTrace = null;
1230     }
1231 
1232     /**
1233      * Creates a new instance from a {@link Parcel}.
1234      *
1235      * @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
1236      */
initFromParcel(Parcel parcel)1237     public void initFromParcel(Parcel parcel) {
1238         mSealed = (parcel.readInt() == 1);
1239         mEventType = parcel.readInt();
1240         mMovementGranularity = parcel.readInt();
1241         mAction = parcel.readInt();
1242         mContentChangeTypes = parcel.readInt();
1243         mWindowChangeTypes = parcel.readInt();
1244         mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1245         mEventTime = parcel.readLong();
1246         mConnectionId = parcel.readInt();
1247         readAccessibilityRecordFromParcel(this, parcel);
1248 
1249         // Read the records.
1250         final int recordCount = parcel.readInt();
1251         if (recordCount > 0) {
1252             mRecords = new ArrayList<>(recordCount);
1253             for (int i = 0; i < recordCount; i++) {
1254                 AccessibilityRecord record = AccessibilityRecord.obtain();
1255                 readAccessibilityRecordFromParcel(record, parcel);
1256                 record.mConnectionId = mConnectionId;
1257                 mRecords.add(record);
1258             }
1259         }
1260 
1261         if (DEBUG_ORIGIN) {
1262             originStackTrace = new StackTraceElement[parcel.readInt()];
1263             for (int i = 0; i < originStackTrace.length; i++) {
1264                 originStackTrace[i] = new StackTraceElement(
1265                         parcel.readString(),
1266                         parcel.readString(),
1267                         parcel.readString(),
1268                         parcel.readInt());
1269             }
1270         }
1271     }
1272 
1273     /**
1274      * Reads an {@link AccessibilityRecord} from a parcel.
1275      *
1276      * @param record The record to initialize.
1277      * @param parcel The parcel to read from.
1278      */
readAccessibilityRecordFromParcel(AccessibilityRecord record, Parcel parcel)1279     private void readAccessibilityRecordFromParcel(AccessibilityRecord record,
1280             Parcel parcel) {
1281         record.mBooleanProperties = parcel.readInt();
1282         record.mCurrentItemIndex = parcel.readInt();
1283         record.mItemCount = parcel.readInt();
1284         record.mFromIndex = parcel.readInt();
1285         record.mToIndex = parcel.readInt();
1286         record.mScrollX = parcel.readInt();
1287         record.mScrollY =  parcel.readInt();
1288         record.mScrollDeltaX =  parcel.readInt();
1289         record.mScrollDeltaY =  parcel.readInt();
1290         record.mMaxScrollX = parcel.readInt();
1291         record.mMaxScrollY =  parcel.readInt();
1292         record.mAddedCount = parcel.readInt();
1293         record.mRemovedCount = parcel.readInt();
1294         record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1295         record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1296         record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1297         record.mParcelableData = parcel.readParcelable(null);
1298         parcel.readList(record.mText, null);
1299         record.mSourceWindowId = parcel.readInt();
1300         record.mSourceNodeId = parcel.readLong();
1301         record.mSealed = (parcel.readInt() == 1);
1302     }
1303 
1304     /**
1305      * {@inheritDoc}
1306      */
writeToParcel(Parcel parcel, int flags)1307     public void writeToParcel(Parcel parcel, int flags) {
1308         parcel.writeInt(isSealed() ? 1 : 0);
1309         parcel.writeInt(mEventType);
1310         parcel.writeInt(mMovementGranularity);
1311         parcel.writeInt(mAction);
1312         parcel.writeInt(mContentChangeTypes);
1313         parcel.writeInt(mWindowChangeTypes);
1314         TextUtils.writeToParcel(mPackageName, parcel, 0);
1315         parcel.writeLong(mEventTime);
1316         parcel.writeInt(mConnectionId);
1317         writeAccessibilityRecordToParcel(this, parcel, flags);
1318 
1319         // Write the records.
1320         final int recordCount = getRecordCount();
1321         parcel.writeInt(recordCount);
1322         for (int i = 0; i < recordCount; i++) {
1323             AccessibilityRecord record = mRecords.get(i);
1324             writeAccessibilityRecordToParcel(record, parcel, flags);
1325         }
1326 
1327         if (DEBUG_ORIGIN) {
1328             if (originStackTrace == null) originStackTrace = Thread.currentThread().getStackTrace();
1329             parcel.writeInt(originStackTrace.length);
1330             for (StackTraceElement element : originStackTrace) {
1331                 parcel.writeString(element.getClassName());
1332                 parcel.writeString(element.getMethodName());
1333                 parcel.writeString(element.getFileName());
1334                 parcel.writeInt(element.getLineNumber());
1335             }
1336         }
1337     }
1338 
1339     /**
1340      * Writes an {@link AccessibilityRecord} to a parcel.
1341      *
1342      * @param record The record to write.
1343      * @param parcel The parcel to which to write.
1344      */
writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel, int flags)1345     private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel,
1346             int flags) {
1347         parcel.writeInt(record.mBooleanProperties);
1348         parcel.writeInt(record.mCurrentItemIndex);
1349         parcel.writeInt(record.mItemCount);
1350         parcel.writeInt(record.mFromIndex);
1351         parcel.writeInt(record.mToIndex);
1352         parcel.writeInt(record.mScrollX);
1353         parcel.writeInt(record.mScrollY);
1354         parcel.writeInt(record.mScrollDeltaX);
1355         parcel.writeInt(record.mScrollDeltaY);
1356         parcel.writeInt(record.mMaxScrollX);
1357         parcel.writeInt(record.mMaxScrollY);
1358         parcel.writeInt(record.mAddedCount);
1359         parcel.writeInt(record.mRemovedCount);
1360         TextUtils.writeToParcel(record.mClassName, parcel, flags);
1361         TextUtils.writeToParcel(record.mContentDescription, parcel, flags);
1362         TextUtils.writeToParcel(record.mBeforeText, parcel, flags);
1363         parcel.writeParcelable(record.mParcelableData, flags);
1364         parcel.writeList(record.mText);
1365         parcel.writeInt(record.mSourceWindowId);
1366         parcel.writeLong(record.mSourceNodeId);
1367         parcel.writeInt(record.mSealed ? 1 : 0);
1368     }
1369 
1370     /**
1371      * {@inheritDoc}
1372      */
describeContents()1373     public int describeContents() {
1374         return 0;
1375     }
1376 
1377     @Override
toString()1378     public String toString() {
1379         StringBuilder builder = new StringBuilder();
1380         builder.append("EventType: ").append(eventTypeToString(mEventType));
1381         builder.append("; EventTime: ").append(mEventTime);
1382         builder.append("; PackageName: ").append(mPackageName);
1383         if (!DEBUG_CONCISE_TOSTRING || mMovementGranularity != 0) {
1384             builder.append("; MovementGranularity: ").append(mMovementGranularity);
1385         }
1386         if (!DEBUG_CONCISE_TOSTRING || mAction != 0) {
1387             builder.append("; Action: ").append(mAction);
1388         }
1389         if (!DEBUG_CONCISE_TOSTRING || mContentChangeTypes != 0) {
1390             builder.append("; ContentChangeTypes: ").append(
1391                     contentChangeTypesToString(mContentChangeTypes));
1392         }
1393         if (!DEBUG_CONCISE_TOSTRING || mWindowChangeTypes != 0) {
1394             builder.append("; WindowChangeTypes: ").append(
1395                     windowChangeTypesToString(mWindowChangeTypes));
1396         }
1397         super.appendTo(builder);
1398         if (DEBUG || DEBUG_CONCISE_TOSTRING) {
1399             if (!DEBUG_CONCISE_TOSTRING) {
1400                 builder.append("\n");
1401             }
1402             if (DEBUG) {
1403                 builder.append("; SourceWindowId: 0x").append(Long.toHexString(mSourceWindowId));
1404                 builder.append("; SourceNodeId: 0x").append(Long.toHexString(mSourceNodeId));
1405             }
1406             for (int i = 0; i < getRecordCount(); i++) {
1407                 builder.append("  Record ").append(i).append(":");
1408                 getRecord(i).appendTo(builder).append("\n");
1409             }
1410         } else {
1411             builder.append("; recordCount: ").append(getRecordCount());
1412         }
1413         return builder.toString();
1414     }
1415 
1416     /**
1417      * Returns the string representation of an event type. For example,
1418      * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
1419      *
1420      * @param eventType The event type
1421      * @return The string representation.
1422      */
eventTypeToString(int eventType)1423     public static String eventTypeToString(int eventType) {
1424         if (eventType == TYPES_ALL_MASK) {
1425             return "TYPES_ALL_MASK";
1426         }
1427         StringBuilder builder = new StringBuilder();
1428         int eventTypeCount = 0;
1429         while (eventType != 0) {
1430             final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType);
1431             eventType &= ~eventTypeFlag;
1432 
1433             if (eventTypeCount > 0) {
1434                 builder.append(", ");
1435             }
1436             builder.append(singleEventTypeToString(eventTypeFlag));
1437 
1438             eventTypeCount++;
1439         }
1440         if (eventTypeCount > 1) {
1441             builder.insert(0, '[');
1442             builder.append(']');
1443         }
1444         return builder.toString();
1445     }
1446 
singleEventTypeToString(int eventType)1447     private static String singleEventTypeToString(int eventType) {
1448         switch (eventType) {
1449             case TYPE_VIEW_CLICKED: return "TYPE_VIEW_CLICKED";
1450             case TYPE_VIEW_LONG_CLICKED: return "TYPE_VIEW_LONG_CLICKED";
1451             case TYPE_VIEW_SELECTED: return "TYPE_VIEW_SELECTED";
1452             case TYPE_VIEW_FOCUSED: return "TYPE_VIEW_FOCUSED";
1453             case TYPE_VIEW_TEXT_CHANGED: return "TYPE_VIEW_TEXT_CHANGED";
1454             case TYPE_WINDOW_STATE_CHANGED: return "TYPE_WINDOW_STATE_CHANGED";
1455             case TYPE_VIEW_HOVER_ENTER: return "TYPE_VIEW_HOVER_ENTER";
1456             case TYPE_VIEW_HOVER_EXIT: return "TYPE_VIEW_HOVER_EXIT";
1457             case TYPE_NOTIFICATION_STATE_CHANGED: return "TYPE_NOTIFICATION_STATE_CHANGED";
1458             case TYPE_TOUCH_EXPLORATION_GESTURE_START: {
1459                 return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
1460             }
1461             case TYPE_TOUCH_EXPLORATION_GESTURE_END: return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
1462             case TYPE_WINDOW_CONTENT_CHANGED: return "TYPE_WINDOW_CONTENT_CHANGED";
1463             case TYPE_VIEW_TEXT_SELECTION_CHANGED: return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
1464             case TYPE_VIEW_SCROLLED: return "TYPE_VIEW_SCROLLED";
1465             case TYPE_ANNOUNCEMENT: return "TYPE_ANNOUNCEMENT";
1466             case TYPE_VIEW_ACCESSIBILITY_FOCUSED: return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
1467             case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
1468                 return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
1469             }
1470             case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
1471                 return "TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY";
1472             }
1473             case TYPE_GESTURE_DETECTION_START: return "TYPE_GESTURE_DETECTION_START";
1474             case TYPE_GESTURE_DETECTION_END: return "TYPE_GESTURE_DETECTION_END";
1475             case TYPE_TOUCH_INTERACTION_START: return "TYPE_TOUCH_INTERACTION_START";
1476             case TYPE_TOUCH_INTERACTION_END: return "TYPE_TOUCH_INTERACTION_END";
1477             case TYPE_WINDOWS_CHANGED: return "TYPE_WINDOWS_CHANGED";
1478             case TYPE_VIEW_CONTEXT_CLICKED: return "TYPE_VIEW_CONTEXT_CLICKED";
1479             case TYPE_ASSIST_READING_CONTEXT: return "TYPE_ASSIST_READING_CONTEXT";
1480             default: return Integer.toHexString(eventType);
1481         }
1482     }
1483 
1484     /**
1485      * @see Parcelable.Creator
1486      */
1487     public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityEvent> CREATOR =
1488             new Parcelable.Creator<AccessibilityEvent>() {
1489         public AccessibilityEvent createFromParcel(Parcel parcel) {
1490             AccessibilityEvent event = AccessibilityEvent.obtain();
1491             event.initFromParcel(parcel);
1492             return event;
1493         }
1494 
1495         public AccessibilityEvent[] newArray(int size) {
1496             return new AccessibilityEvent[size];
1497         }
1498     };
1499 }
1500