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