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)}. Not 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.
609      */
610     public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 0x00000040;
611 
612     /**
613      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
614      * The window was added.
615      */
616     public static final int WINDOWS_CHANGE_ADDED = 0x00000001;
617 
618     /**
619      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
620      * A window was removed.
621      */
622     public static final int WINDOWS_CHANGE_REMOVED = 0x00000002;
623 
624     /**
625      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
626      * The window's title changed.
627      */
628     public static final int WINDOWS_CHANGE_TITLE = 0x00000004;
629 
630     /**
631      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
632      * The window's bounds changed.
633      * <p>
634      * Starting in {@link android.os.Build.VERSION_CODES#R R}, this event implies the window's
635      * region changed. It's also possible that region changed but bounds doesn't.
636      * </p>
637      */
638     public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
639 
640     /**
641      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
642      * The window's layer changed.
643      */
644     public static final int WINDOWS_CHANGE_LAYER = 0x00000010;
645 
646     /**
647      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
648      * The window's {@link AccessibilityWindowInfo#isActive()} changed.
649      */
650     public static final int WINDOWS_CHANGE_ACTIVE = 0x00000020;
651 
652     /**
653      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
654      * The window's {@link AccessibilityWindowInfo#isFocused()} changed.
655      */
656     public static final int WINDOWS_CHANGE_FOCUSED = 0x00000040;
657 
658     /**
659      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
660      * The window's {@link AccessibilityWindowInfo#isAccessibilityFocused()} changed.
661      */
662     public static final int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 0x00000080;
663 
664     /**
665      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
666      * The window's parent changed.
667      */
668     public static final int WINDOWS_CHANGE_PARENT = 0x00000100;
669 
670     /**
671      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
672      * The window's children changed.
673      */
674     public static final int WINDOWS_CHANGE_CHILDREN = 0x00000200;
675 
676     /**
677      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
678      * The window either entered or exited picture-in-picture mode.
679      */
680     public static final int WINDOWS_CHANGE_PIP = 0x00000400;
681 
682     /** @hide */
683     @Retention(RetentionPolicy.SOURCE)
684     @IntDef(flag = true, prefix = { "WINDOWS_CHANGE_" }, value = {
685             WINDOWS_CHANGE_ADDED,
686             WINDOWS_CHANGE_REMOVED,
687             WINDOWS_CHANGE_TITLE,
688             WINDOWS_CHANGE_BOUNDS,
689             WINDOWS_CHANGE_LAYER,
690             WINDOWS_CHANGE_ACTIVE,
691             WINDOWS_CHANGE_FOCUSED,
692             WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED,
693             WINDOWS_CHANGE_PARENT,
694             WINDOWS_CHANGE_CHILDREN,
695             WINDOWS_CHANGE_PIP
696     })
697     public @interface WindowsChangeTypes {}
698 
699     /** @hide */
700     @Retention(RetentionPolicy.SOURCE)
701     @IntDef(flag = true, prefix = { "CONTENT_CHANGE_TYPE_" },
702             value = {
703                     CONTENT_CHANGE_TYPE_UNDEFINED,
704                     CONTENT_CHANGE_TYPE_SUBTREE,
705                     CONTENT_CHANGE_TYPE_TEXT,
706                     CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION,
707                     CONTENT_CHANGE_TYPE_STATE_DESCRIPTION,
708                     CONTENT_CHANGE_TYPE_PANE_TITLE,
709                     CONTENT_CHANGE_TYPE_PANE_APPEARED,
710                     CONTENT_CHANGE_TYPE_PANE_DISAPPEARED
711             })
712     public @interface ContentChangeTypes {}
713 
714     /** @hide */
715     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
716             TYPE_VIEW_CLICKED,
717             TYPE_VIEW_LONG_CLICKED,
718             TYPE_VIEW_SELECTED,
719             TYPE_VIEW_FOCUSED,
720             TYPE_VIEW_TEXT_CHANGED,
721             TYPE_WINDOW_STATE_CHANGED,
722             TYPE_NOTIFICATION_STATE_CHANGED,
723             TYPE_VIEW_HOVER_ENTER,
724             TYPE_VIEW_HOVER_EXIT,
725             TYPE_TOUCH_EXPLORATION_GESTURE_START,
726             TYPE_TOUCH_EXPLORATION_GESTURE_END,
727             TYPE_WINDOW_CONTENT_CHANGED,
728             TYPE_VIEW_SCROLLED,
729             TYPE_VIEW_TEXT_SELECTION_CHANGED,
730             TYPE_ANNOUNCEMENT,
731             TYPE_VIEW_ACCESSIBILITY_FOCUSED,
732             TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED,
733             TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
734             TYPE_GESTURE_DETECTION_START,
735             TYPE_GESTURE_DETECTION_END,
736             TYPE_TOUCH_INTERACTION_START,
737             TYPE_TOUCH_INTERACTION_END,
738             TYPE_WINDOWS_CHANGED,
739             TYPE_VIEW_CONTEXT_CLICKED,
740             TYPE_ASSIST_READING_CONTEXT
741     })
742     @Retention(RetentionPolicy.SOURCE)
743     public @interface EventType {}
744 
745     /**
746      * Mask for {@link AccessibilityEvent} all types.
747      *
748      * @see #TYPE_VIEW_CLICKED
749      * @see #TYPE_VIEW_LONG_CLICKED
750      * @see #TYPE_VIEW_SELECTED
751      * @see #TYPE_VIEW_FOCUSED
752      * @see #TYPE_VIEW_TEXT_CHANGED
753      * @see #TYPE_WINDOW_STATE_CHANGED
754      * @see #TYPE_NOTIFICATION_STATE_CHANGED
755      * @see #TYPE_VIEW_HOVER_ENTER
756      * @see #TYPE_VIEW_HOVER_EXIT
757      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
758      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
759      * @see #TYPE_WINDOW_CONTENT_CHANGED
760      * @see #TYPE_VIEW_SCROLLED
761      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
762      * @see #TYPE_ANNOUNCEMENT
763      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
764      * @see #TYPE_GESTURE_DETECTION_START
765      * @see #TYPE_GESTURE_DETECTION_END
766      * @see #TYPE_TOUCH_INTERACTION_START
767      * @see #TYPE_TOUCH_INTERACTION_END
768      * @see #TYPE_WINDOWS_CHANGED
769      * @see #TYPE_VIEW_CONTEXT_CLICKED
770      */
771     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
772 
773     private static final int MAX_POOL_SIZE = 10;
774     private static final SynchronizedPool<AccessibilityEvent> sPool =
775             new SynchronizedPool<>(MAX_POOL_SIZE);
776 
777     @UnsupportedAppUsage
778     private @EventType int mEventType;
779     private CharSequence mPackageName;
780     private long mEventTime;
781     int mMovementGranularity;
782     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
783     int mAction;
784     int mContentChangeTypes;
785     int mWindowChangeTypes;
786 
787     /**
788      * The stack trace describing where this event originated from on the app side.
789      * Only populated if {@link #DEBUG_ORIGIN} is enabled
790      * Can be inspected(e.g. printed) from an
791      * {@link android.accessibilityservice.AccessibilityService} to trace where particular events
792      * are being dispatched from.
793      *
794      * @hide
795      */
796     public StackTraceElement[] originStackTrace = null;
797 
798     private ArrayList<AccessibilityRecord> mRecords;
799 
800     /**
801      * Creates a new {@link AccessibilityEvent}.
802      */
AccessibilityEvent()803     public AccessibilityEvent() {
804         if (DEBUG_ORIGIN) originStackTrace = Thread.currentThread().getStackTrace();
805     }
806 
807 
808     /**
809      * Creates a new {@link AccessibilityEvent} with the given <code>eventType</code>.
810      *
811      * @param eventType The event type.
812      */
AccessibilityEvent(int eventType)813     public AccessibilityEvent(int eventType) {
814         mEventType = eventType;
815         if (DEBUG_ORIGIN) originStackTrace = Thread.currentThread().getStackTrace();
816     }
817 
818     /**
819      * Copy constructor. Creates a new {@link AccessibilityEvent}, and this instance is initialized
820      * from the given <code>event</code>.
821      *
822      * @param event The other event.
823      */
AccessibilityEvent(@onNull AccessibilityEvent event)824     public AccessibilityEvent(@NonNull AccessibilityEvent event) {
825         init(event);
826     }
827 
828     /**
829      * Initialize an event from another one.
830      *
831      * @param event The event to initialize from.
832      */
init(AccessibilityEvent event)833     void init(AccessibilityEvent event) {
834         super.init(event);
835         mEventType = event.mEventType;
836         mMovementGranularity = event.mMovementGranularity;
837         mAction = event.mAction;
838         mContentChangeTypes = event.mContentChangeTypes;
839         mWindowChangeTypes = event.mWindowChangeTypes;
840         mEventTime = event.mEventTime;
841         mPackageName = event.mPackageName;
842         if (event.mRecords != null) {
843             final int recordCount = event.mRecords.size();
844             mRecords = new ArrayList<>(recordCount);
845             for (int i = 0; i < recordCount; i++) {
846                 final AccessibilityRecord record = event.mRecords.get(i);
847                 final AccessibilityRecord recordClone = new AccessibilityRecord(record);
848                 mRecords.add(recordClone);
849             }
850         }
851         if (DEBUG_ORIGIN) originStackTrace = event.originStackTrace;
852     }
853 
854     /**
855      * Sets if this instance is sealed.
856      *
857      * @param sealed Whether is sealed.
858      *
859      * @hide
860      */
861     @Override
setSealed(boolean sealed)862     public void setSealed(boolean sealed) {
863         super.setSealed(sealed);
864         final List<AccessibilityRecord> records = mRecords;
865         if (records != null) {
866             final int recordCount = records.size();
867             for (int i = 0; i < recordCount; i++) {
868                 AccessibilityRecord record = records.get(i);
869                 record.setSealed(sealed);
870             }
871         }
872     }
873 
874     /**
875      * Gets the number of records contained in the event.
876      *
877      * @return The number of records.
878      */
getRecordCount()879     public int getRecordCount() {
880         return mRecords == null ? 0 : mRecords.size();
881     }
882 
883     /**
884      * Appends an {@link AccessibilityRecord} to the end of event records.
885      *
886      * @param record The record to append.
887      *
888      * @throws IllegalStateException If called from an AccessibilityService.
889      */
appendRecord(AccessibilityRecord record)890     public void appendRecord(AccessibilityRecord record) {
891         enforceNotSealed();
892         if (mRecords == null) {
893             mRecords = new ArrayList<AccessibilityRecord>();
894         }
895         mRecords.add(record);
896     }
897 
898     /**
899      * Gets the record at a given index.
900      *
901      * @param index The index.
902      * @return The record at the specified index.
903      */
getRecord(int index)904     public AccessibilityRecord getRecord(int index) {
905         if (mRecords == null) {
906             throw new IndexOutOfBoundsException("Invalid index " + index + ", size is 0");
907         }
908         return mRecords.get(index);
909     }
910 
911     /**
912      * Gets the event type.
913      *
914      * @return The event type.
915      */
getEventType()916     public @EventType int getEventType() {
917         return mEventType;
918     }
919 
920     /**
921      * Gets the bit mask of change types signaled by a
922      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event or {@link #TYPE_WINDOW_STATE_CHANGED}. A single
923      * event may represent multiple change types.
924      *
925      * @return The bit mask of change types. One or more of:
926      *         <ul>
927      *         <li>{@link #CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION}
928      *         <li>{@link #CONTENT_CHANGE_TYPE_STATE_DESCRIPTION}
929      *         <li>{@link #CONTENT_CHANGE_TYPE_SUBTREE}
930      *         <li>{@link #CONTENT_CHANGE_TYPE_TEXT}
931      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_TITLE}
932      *         <li>{@link #CONTENT_CHANGE_TYPE_UNDEFINED}
933      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_APPEARED}
934      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_DISAPPEARED}
935      *         </ul>
936      */
937     @ContentChangeTypes
getContentChangeTypes()938     public int getContentChangeTypes() {
939         return mContentChangeTypes;
940     }
941 
contentChangeTypesToString(int types)942     private static String contentChangeTypesToString(int types) {
943         return BitUtils.flagsToString(types, AccessibilityEvent::singleContentChangeTypeToString);
944     }
945 
singleContentChangeTypeToString(int type)946     private static String singleContentChangeTypeToString(int type) {
947         switch (type) {
948             case CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION:
949                 return "CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION";
950             case CONTENT_CHANGE_TYPE_STATE_DESCRIPTION:
951                 return "CONTENT_CHANGE_TYPE_STATE_DESCRIPTION";
952             case CONTENT_CHANGE_TYPE_SUBTREE: return "CONTENT_CHANGE_TYPE_SUBTREE";
953             case CONTENT_CHANGE_TYPE_TEXT: return "CONTENT_CHANGE_TYPE_TEXT";
954             case CONTENT_CHANGE_TYPE_PANE_TITLE: return "CONTENT_CHANGE_TYPE_PANE_TITLE";
955             case CONTENT_CHANGE_TYPE_UNDEFINED: return "CONTENT_CHANGE_TYPE_UNDEFINED";
956             case CONTENT_CHANGE_TYPE_PANE_APPEARED: return "CONTENT_CHANGE_TYPE_PANE_APPEARED";
957             case CONTENT_CHANGE_TYPE_PANE_DISAPPEARED:
958                 return "CONTENT_CHANGE_TYPE_PANE_DISAPPEARED";
959             default: return Integer.toHexString(type);
960         }
961     }
962 
963     /**
964      * Sets the bit mask of node tree changes signaled by an
965      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
966      *
967      * @param changeTypes The bit mask of change types.
968      * @throws IllegalStateException If called from an AccessibilityService.
969      * @see #getContentChangeTypes()
970      */
setContentChangeTypes(@ontentChangeTypes int changeTypes)971     public void setContentChangeTypes(@ContentChangeTypes int changeTypes) {
972         enforceNotSealed();
973         mContentChangeTypes = changeTypes;
974     }
975 
976     /**
977      * Get the bit mask of change types signaled by a {@link #TYPE_WINDOWS_CHANGED} event. A
978      * single event may represent multiple change types.
979      *
980      * @return The bit mask of change types.
981      */
982     @WindowsChangeTypes
getWindowChanges()983     public int getWindowChanges() {
984         return mWindowChangeTypes;
985     }
986 
987     /** @hide  */
setWindowChanges(@indowsChangeTypes int changes)988     public void setWindowChanges(@WindowsChangeTypes int changes) {
989         mWindowChangeTypes = changes;
990     }
991 
windowChangeTypesToString(@indowsChangeTypes int types)992     private static String windowChangeTypesToString(@WindowsChangeTypes int types) {
993         return BitUtils.flagsToString(types, AccessibilityEvent::singleWindowChangeTypeToString);
994     }
995 
singleWindowChangeTypeToString(int type)996     private static String singleWindowChangeTypeToString(int type) {
997         switch (type) {
998             case WINDOWS_CHANGE_ADDED: return "WINDOWS_CHANGE_ADDED";
999             case WINDOWS_CHANGE_REMOVED: return "WINDOWS_CHANGE_REMOVED";
1000             case WINDOWS_CHANGE_TITLE: return "WINDOWS_CHANGE_TITLE";
1001             case WINDOWS_CHANGE_BOUNDS: return "WINDOWS_CHANGE_BOUNDS";
1002             case WINDOWS_CHANGE_LAYER: return "WINDOWS_CHANGE_LAYER";
1003             case WINDOWS_CHANGE_ACTIVE: return "WINDOWS_CHANGE_ACTIVE";
1004             case WINDOWS_CHANGE_FOCUSED: return "WINDOWS_CHANGE_FOCUSED";
1005             case WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED:
1006                 return "WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED";
1007             case WINDOWS_CHANGE_PARENT: return "WINDOWS_CHANGE_PARENT";
1008             case WINDOWS_CHANGE_CHILDREN: return "WINDOWS_CHANGE_CHILDREN";
1009             case WINDOWS_CHANGE_PIP: return "WINDOWS_CHANGE_PIP";
1010             default: return Integer.toHexString(type);
1011         }
1012     }
1013 
1014     /**
1015      * Sets the event type.
1016      *
1017      * @param eventType The event type.
1018      *
1019      * @throws IllegalStateException If called from an AccessibilityService.
1020      */
setEventType(@ventType int eventType)1021     public void setEventType(@EventType int eventType) {
1022         enforceNotSealed();
1023         mEventType = eventType;
1024     }
1025 
1026     /**
1027      * Gets the time in which this event was sent.
1028      *
1029      * @return The event time.
1030      */
getEventTime()1031     public long getEventTime() {
1032         return mEventTime;
1033     }
1034 
1035     /**
1036      * Sets the time in which this event was sent.
1037      *
1038      * @param eventTime The event time.
1039      *
1040      * @throws IllegalStateException If called from an AccessibilityService.
1041      */
setEventTime(long eventTime)1042     public void setEventTime(long eventTime) {
1043         enforceNotSealed();
1044         mEventTime = eventTime;
1045     }
1046 
1047     /**
1048      * Gets the package name of the source.
1049      *
1050      * @return The package name.
1051      */
getPackageName()1052     public CharSequence getPackageName() {
1053         return mPackageName;
1054     }
1055 
1056     /**
1057      * Sets the package name of the source.
1058      *
1059      * @param packageName The package name.
1060      *
1061      * @throws IllegalStateException If called from an AccessibilityService.
1062      */
setPackageName(CharSequence packageName)1063     public void setPackageName(CharSequence packageName) {
1064         enforceNotSealed();
1065         mPackageName = packageName;
1066     }
1067 
1068     /**
1069      * Sets the movement granularity that was traversed.
1070      *
1071      * @param granularity The granularity.
1072      *
1073      * @throws IllegalStateException If called from an AccessibilityService.
1074      */
setMovementGranularity(int granularity)1075     public void setMovementGranularity(int granularity) {
1076         enforceNotSealed();
1077         mMovementGranularity = granularity;
1078     }
1079 
1080     /**
1081      * Gets the movement granularity that was traversed.
1082      *
1083      * @return The granularity.
1084      */
getMovementGranularity()1085     public int getMovementGranularity() {
1086         return mMovementGranularity;
1087     }
1088 
1089     /**
1090      * Sets the performed action that triggered this event.
1091      * <p>
1092      * Valid actions are defined in {@link AccessibilityNodeInfo}:
1093      * <ul>
1094      * <li>{@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}
1095      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
1096      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS}
1097      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION}
1098      * <li>{@link AccessibilityNodeInfo#ACTION_CLICK}
1099      * <li>etc.
1100      * </ul>
1101      *
1102      * @param action The action.
1103      * @throws IllegalStateException If called from an AccessibilityService.
1104      * @see AccessibilityNodeInfo#performAction(int)
1105      */
setAction(int action)1106     public void setAction(int action) {
1107         enforceNotSealed();
1108         mAction = action;
1109     }
1110 
1111     /**
1112      * Gets the performed action that triggered this event.
1113      *
1114      * @return The action.
1115      */
getAction()1116     public int getAction() {
1117         return mAction;
1118     }
1119 
1120     /**
1121      * Convenience method to obtain a {@link #TYPE_WINDOWS_CHANGED} event for a specific window and
1122      * change set.
1123      *
1124      * @param windowId The ID of the window that changed
1125      * @param windowChangeTypes The changes to populate
1126      * @return An instance of a TYPE_WINDOWS_CHANGED, populated with the requested fields and with
1127      *         importantForAccessibility set to {@code true}.
1128      *
1129      * @hide
1130      */
obtainWindowsChangedEvent( int windowId, int windowChangeTypes)1131     public static AccessibilityEvent obtainWindowsChangedEvent(
1132             int windowId, int windowChangeTypes) {
1133         final AccessibilityEvent event = AccessibilityEvent.obtain(TYPE_WINDOWS_CHANGED);
1134         event.setWindowId(windowId);
1135         event.setWindowChanges(windowChangeTypes);
1136         event.setImportantForAccessibility(true);
1137         return event;
1138     }
1139 
1140     /**
1141      * Returns a cached instance if such is available or a new one is
1142      * instantiated with its type property set.
1143      *
1144      * <p>In most situations object pooling is not beneficial. Create a new instance using the
1145      * constructor {@link #AccessibilityEvent(int)} instead.
1146      *
1147      * @param eventType The event type.
1148      * @return An instance.
1149      */
obtain(int eventType)1150     public static AccessibilityEvent obtain(int eventType) {
1151         AccessibilityEvent event = AccessibilityEvent.obtain();
1152         event.setEventType(eventType);
1153         return event;
1154     }
1155 
1156     /**
1157      * Returns a cached instance if such is available or a new one is
1158      * created. The returned instance is initialized from the given
1159      * <code>event</code>.
1160      *
1161      * <p>In most situations object pooling is not beneficial. Create a new instance using the
1162      * constructor {@link #AccessibilityEvent(AccessibilityEvent)} instead.
1163      *
1164      * @param event The other event.
1165      * @return An instance.
1166      */
obtain(AccessibilityEvent event)1167     public static AccessibilityEvent obtain(AccessibilityEvent event) {
1168         AccessibilityEvent eventClone = AccessibilityEvent.obtain();
1169         eventClone.init(event);
1170         return eventClone;
1171     }
1172 
1173     /**
1174      * Returns a cached instance if such is available or a new one is
1175      * instantiated.
1176      *
1177      * <p>In most situations object pooling is not beneficial. Create a new instance using the
1178      * constructor {@link #AccessibilityEvent()} instead.
1179      *
1180      * @return An instance.
1181      */
obtain()1182     public static AccessibilityEvent obtain() {
1183         AccessibilityEvent event = sPool.acquire();
1184         if (event == null) event = new AccessibilityEvent();
1185         if (DEBUG_ORIGIN) event.originStackTrace = Thread.currentThread().getStackTrace();
1186         return event;
1187     }
1188 
1189     /**
1190      * Recycles an instance back to be reused.
1191      * <p>
1192      *   <b>Note: You must not touch the object after calling this function.</b>
1193      * </p>
1194      *
1195      * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
1196      *
1197      * @throws IllegalStateException If the event is already recycled.
1198      */
1199     @Override
recycle()1200     public void recycle() {
1201         clear();
1202         sPool.release(this);
1203     }
1204 
1205     /**
1206      * Clears the state of this instance.
1207      *
1208      * @hide
1209      */
1210     @Override
clear()1211     protected void clear() {
1212         super.clear();
1213         mEventType = 0;
1214         mMovementGranularity = 0;
1215         mAction = 0;
1216         mContentChangeTypes = 0;
1217         mWindowChangeTypes = 0;
1218         mPackageName = null;
1219         mEventTime = 0;
1220         if (mRecords != null) {
1221             while (!mRecords.isEmpty()) {
1222                 AccessibilityRecord record = mRecords.remove(0);
1223                 record.recycle();
1224             }
1225         }
1226         if (DEBUG_ORIGIN) originStackTrace = null;
1227     }
1228 
1229     /**
1230      * Creates a new instance from a {@link Parcel}.
1231      *
1232      * @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
1233      */
initFromParcel(Parcel parcel)1234     public void initFromParcel(Parcel parcel) {
1235         mSealed = (parcel.readInt() == 1);
1236         mEventType = parcel.readInt();
1237         mMovementGranularity = parcel.readInt();
1238         mAction = parcel.readInt();
1239         mContentChangeTypes = parcel.readInt();
1240         mWindowChangeTypes = parcel.readInt();
1241         mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1242         mEventTime = parcel.readLong();
1243         mConnectionId = parcel.readInt();
1244         readAccessibilityRecordFromParcel(this, parcel);
1245 
1246         // Read the records.
1247         final int recordCount = parcel.readInt();
1248         if (recordCount > 0) {
1249             mRecords = new ArrayList<>(recordCount);
1250             for (int i = 0; i < recordCount; i++) {
1251                 AccessibilityRecord record = AccessibilityRecord.obtain();
1252                 readAccessibilityRecordFromParcel(record, parcel);
1253                 record.mConnectionId = mConnectionId;
1254                 mRecords.add(record);
1255             }
1256         }
1257 
1258         if (DEBUG_ORIGIN) {
1259             originStackTrace = new StackTraceElement[parcel.readInt()];
1260             for (int i = 0; i < originStackTrace.length; i++) {
1261                 originStackTrace[i] = new StackTraceElement(
1262                         parcel.readString(),
1263                         parcel.readString(),
1264                         parcel.readString(),
1265                         parcel.readInt());
1266             }
1267         }
1268     }
1269 
1270     /**
1271      * Reads an {@link AccessibilityRecord} from a parcel.
1272      *
1273      * @param record The record to initialize.
1274      * @param parcel The parcel to read from.
1275      */
readAccessibilityRecordFromParcel(AccessibilityRecord record, Parcel parcel)1276     private void readAccessibilityRecordFromParcel(AccessibilityRecord record,
1277             Parcel parcel) {
1278         record.mBooleanProperties = parcel.readInt();
1279         record.mCurrentItemIndex = parcel.readInt();
1280         record.mItemCount = parcel.readInt();
1281         record.mFromIndex = parcel.readInt();
1282         record.mToIndex = parcel.readInt();
1283         record.mScrollX = parcel.readInt();
1284         record.mScrollY =  parcel.readInt();
1285         record.mScrollDeltaX =  parcel.readInt();
1286         record.mScrollDeltaY =  parcel.readInt();
1287         record.mMaxScrollX = parcel.readInt();
1288         record.mMaxScrollY =  parcel.readInt();
1289         record.mAddedCount = parcel.readInt();
1290         record.mRemovedCount = parcel.readInt();
1291         record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1292         record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1293         record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1294         record.mParcelableData = parcel.readParcelable(null);
1295         parcel.readList(record.mText, null);
1296         record.mSourceWindowId = parcel.readInt();
1297         record.mSourceNodeId = parcel.readLong();
1298         record.mSealed = (parcel.readInt() == 1);
1299     }
1300 
1301     /**
1302      * {@inheritDoc}
1303      */
writeToParcel(Parcel parcel, int flags)1304     public void writeToParcel(Parcel parcel, int flags) {
1305         parcel.writeInt(isSealed() ? 1 : 0);
1306         parcel.writeInt(mEventType);
1307         parcel.writeInt(mMovementGranularity);
1308         parcel.writeInt(mAction);
1309         parcel.writeInt(mContentChangeTypes);
1310         parcel.writeInt(mWindowChangeTypes);
1311         TextUtils.writeToParcel(mPackageName, parcel, 0);
1312         parcel.writeLong(mEventTime);
1313         parcel.writeInt(mConnectionId);
1314         writeAccessibilityRecordToParcel(this, parcel, flags);
1315 
1316         // Write the records.
1317         final int recordCount = getRecordCount();
1318         parcel.writeInt(recordCount);
1319         for (int i = 0; i < recordCount; i++) {
1320             AccessibilityRecord record = mRecords.get(i);
1321             writeAccessibilityRecordToParcel(record, parcel, flags);
1322         }
1323 
1324         if (DEBUG_ORIGIN) {
1325             if (originStackTrace == null) originStackTrace = Thread.currentThread().getStackTrace();
1326             parcel.writeInt(originStackTrace.length);
1327             for (StackTraceElement element : originStackTrace) {
1328                 parcel.writeString(element.getClassName());
1329                 parcel.writeString(element.getMethodName());
1330                 parcel.writeString(element.getFileName());
1331                 parcel.writeInt(element.getLineNumber());
1332             }
1333         }
1334     }
1335 
1336     /**
1337      * Writes an {@link AccessibilityRecord} to a parcel.
1338      *
1339      * @param record The record to write.
1340      * @param parcel The parcel to which to write.
1341      */
writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel, int flags)1342     private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel,
1343             int flags) {
1344         parcel.writeInt(record.mBooleanProperties);
1345         parcel.writeInt(record.mCurrentItemIndex);
1346         parcel.writeInt(record.mItemCount);
1347         parcel.writeInt(record.mFromIndex);
1348         parcel.writeInt(record.mToIndex);
1349         parcel.writeInt(record.mScrollX);
1350         parcel.writeInt(record.mScrollY);
1351         parcel.writeInt(record.mScrollDeltaX);
1352         parcel.writeInt(record.mScrollDeltaY);
1353         parcel.writeInt(record.mMaxScrollX);
1354         parcel.writeInt(record.mMaxScrollY);
1355         parcel.writeInt(record.mAddedCount);
1356         parcel.writeInt(record.mRemovedCount);
1357         TextUtils.writeToParcel(record.mClassName, parcel, flags);
1358         TextUtils.writeToParcel(record.mContentDescription, parcel, flags);
1359         TextUtils.writeToParcel(record.mBeforeText, parcel, flags);
1360         parcel.writeParcelable(record.mParcelableData, flags);
1361         parcel.writeList(record.mText);
1362         parcel.writeInt(record.mSourceWindowId);
1363         parcel.writeLong(record.mSourceNodeId);
1364         parcel.writeInt(record.mSealed ? 1 : 0);
1365     }
1366 
1367     /**
1368      * {@inheritDoc}
1369      */
describeContents()1370     public int describeContents() {
1371         return 0;
1372     }
1373 
1374     @Override
toString()1375     public String toString() {
1376         StringBuilder builder = new StringBuilder();
1377         builder.append("EventType: ").append(eventTypeToString(mEventType));
1378         builder.append("; EventTime: ").append(mEventTime);
1379         builder.append("; PackageName: ").append(mPackageName);
1380         if (!DEBUG_CONCISE_TOSTRING || mMovementGranularity != 0) {
1381             builder.append("; MovementGranularity: ").append(mMovementGranularity);
1382         }
1383         if (!DEBUG_CONCISE_TOSTRING || mAction != 0) {
1384             builder.append("; Action: ").append(mAction);
1385         }
1386         if (!DEBUG_CONCISE_TOSTRING || mContentChangeTypes != 0) {
1387             builder.append("; ContentChangeTypes: ").append(
1388                     contentChangeTypesToString(mContentChangeTypes));
1389         }
1390         if (!DEBUG_CONCISE_TOSTRING || mWindowChangeTypes != 0) {
1391             builder.append("; WindowChangeTypes: ").append(
1392                     windowChangeTypesToString(mWindowChangeTypes));
1393         }
1394         super.appendTo(builder);
1395         if (DEBUG || DEBUG_CONCISE_TOSTRING) {
1396             if (!DEBUG_CONCISE_TOSTRING) {
1397                 builder.append("\n");
1398             }
1399             if (DEBUG) {
1400                 builder.append("; SourceWindowId: 0x").append(Long.toHexString(mSourceWindowId));
1401                 builder.append("; SourceNodeId: 0x").append(Long.toHexString(mSourceNodeId));
1402             }
1403             for (int i = 0; i < getRecordCount(); i++) {
1404                 builder.append("  Record ").append(i).append(":");
1405                 getRecord(i).appendTo(builder).append("\n");
1406             }
1407         } else {
1408             builder.append("; recordCount: ").append(getRecordCount());
1409         }
1410         return builder.toString();
1411     }
1412 
1413     /**
1414      * Returns the string representation of an event type. For example,
1415      * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
1416      *
1417      * @param eventType The event type
1418      * @return The string representation.
1419      */
eventTypeToString(int eventType)1420     public static String eventTypeToString(int eventType) {
1421         if (eventType == TYPES_ALL_MASK) {
1422             return "TYPES_ALL_MASK";
1423         }
1424         StringBuilder builder = new StringBuilder();
1425         int eventTypeCount = 0;
1426         while (eventType != 0) {
1427             final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType);
1428             eventType &= ~eventTypeFlag;
1429 
1430             if (eventTypeCount > 0) {
1431                 builder.append(", ");
1432             }
1433             builder.append(singleEventTypeToString(eventTypeFlag));
1434 
1435             eventTypeCount++;
1436         }
1437         if (eventTypeCount > 1) {
1438             builder.insert(0, '[');
1439             builder.append(']');
1440         }
1441         return builder.toString();
1442     }
1443 
singleEventTypeToString(int eventType)1444     private static String singleEventTypeToString(int eventType) {
1445         switch (eventType) {
1446             case TYPE_VIEW_CLICKED: return "TYPE_VIEW_CLICKED";
1447             case TYPE_VIEW_LONG_CLICKED: return "TYPE_VIEW_LONG_CLICKED";
1448             case TYPE_VIEW_SELECTED: return "TYPE_VIEW_SELECTED";
1449             case TYPE_VIEW_FOCUSED: return "TYPE_VIEW_FOCUSED";
1450             case TYPE_VIEW_TEXT_CHANGED: return "TYPE_VIEW_TEXT_CHANGED";
1451             case TYPE_WINDOW_STATE_CHANGED: return "TYPE_WINDOW_STATE_CHANGED";
1452             case TYPE_VIEW_HOVER_ENTER: return "TYPE_VIEW_HOVER_ENTER";
1453             case TYPE_VIEW_HOVER_EXIT: return "TYPE_VIEW_HOVER_EXIT";
1454             case TYPE_NOTIFICATION_STATE_CHANGED: return "TYPE_NOTIFICATION_STATE_CHANGED";
1455             case TYPE_TOUCH_EXPLORATION_GESTURE_START: {
1456                 return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
1457             }
1458             case TYPE_TOUCH_EXPLORATION_GESTURE_END: return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
1459             case TYPE_WINDOW_CONTENT_CHANGED: return "TYPE_WINDOW_CONTENT_CHANGED";
1460             case TYPE_VIEW_TEXT_SELECTION_CHANGED: return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
1461             case TYPE_VIEW_SCROLLED: return "TYPE_VIEW_SCROLLED";
1462             case TYPE_ANNOUNCEMENT: return "TYPE_ANNOUNCEMENT";
1463             case TYPE_VIEW_ACCESSIBILITY_FOCUSED: return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
1464             case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
1465                 return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
1466             }
1467             case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
1468                 return "TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY";
1469             }
1470             case TYPE_GESTURE_DETECTION_START: return "TYPE_GESTURE_DETECTION_START";
1471             case TYPE_GESTURE_DETECTION_END: return "TYPE_GESTURE_DETECTION_END";
1472             case TYPE_TOUCH_INTERACTION_START: return "TYPE_TOUCH_INTERACTION_START";
1473             case TYPE_TOUCH_INTERACTION_END: return "TYPE_TOUCH_INTERACTION_END";
1474             case TYPE_WINDOWS_CHANGED: return "TYPE_WINDOWS_CHANGED";
1475             case TYPE_VIEW_CONTEXT_CLICKED: return "TYPE_VIEW_CONTEXT_CLICKED";
1476             case TYPE_ASSIST_READING_CONTEXT: return "TYPE_ASSIST_READING_CONTEXT";
1477             default: return Integer.toHexString(eventType);
1478         }
1479     }
1480 
1481     /**
1482      * @see Parcelable.Creator
1483      */
1484     public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityEvent> CREATOR =
1485             new Parcelable.Creator<AccessibilityEvent>() {
1486         public AccessibilityEvent createFromParcel(Parcel parcel) {
1487             AccessibilityEvent event = AccessibilityEvent.obtain();
1488             event.initFromParcel(parcel);
1489             return event;
1490         }
1491 
1492         public AccessibilityEvent[] newArray(int size) {
1493             return new AccessibilityEvent[size];
1494         }
1495     };
1496 }
1497