• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view.accessibility;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 import android.text.TextUtils;
22 import android.util.Pools.SynchronizedPool;
23 
24 import com.android.internal.util.BitUtils;
25 
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * <p>
31  * This class represents accessibility events that are sent by the system when
32  * something notable happens in the user interface. For example, when a
33  * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
34  * </p>
35  * <p>
36  * An accessibility event is fired by an individual view which populates the event with
37  * data for its state and requests from its parent to send the event to interested
38  * parties. The parent can optionally add an {@link AccessibilityRecord} for itself before
39  * dispatching a similar request to its parent. A parent can also choose not to respect the
40  * request for sending an event. The accessibility event is sent by the topmost view in the
41  * view tree. Therefore, an {@link android.accessibilityservice.AccessibilityService} can
42  * explore all records in an accessibility event to obtain more information about the
43  * context in which the event was fired.
44  * </p>
45  * <p>
46  * The main purpose of an accessibility event is to expose enough information for an
47  * {@link android.accessibilityservice.AccessibilityService} to provide meaningful feedback
48  * to the user. Sometimes however, an accessibility service may need more contextual
49  * information then the one in the event pay-load. In such cases the service can obtain
50  * the event source which is an {@link AccessibilityNodeInfo} (snapshot of a View state)
51  * which can be used for exploring the window content. Note that the privilege for accessing
52  * an event's source, thus the window content, has to be explicitly requested. For more
53  * details refer to {@link android.accessibilityservice.AccessibilityService}. If an
54  * accessibility service has not requested to retrieve the window content the event will
55  * not contain reference to its source. Also for events of type
56  * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available.
57  * </p>
58  * <p>
59  * This class represents various semantically different accessibility event
60  * types. Each event type has an associated set of related properties. In other
61  * words, each event type is characterized via a subset of the properties exposed
62  * by this class. For each event type there is a corresponding constant defined
63  * in this class. Follows a specification of the event types and their associated properties:
64  * </p>
65  * <div class="special reference">
66  * <h3>Developer Guides</h3>
67  * <p>For more information about creating and processing AccessibilityEvents, read the
68  * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
69  * developer guide.</p>
70  * </div>
71  * <p>
72  * <b>VIEW TYPES</b></br>
73  * </p>
74  * <p>
75  * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View}
76  * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.</br>
77  * <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br>
78  * <em>Properties:</em></br>
79  * <ul>
80  *   <li>{@link #getEventType()} - The type of the event.</li>
81  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
82  *   <li>{@link #getClassName()} - The class name of the source.</li>
83  *   <li>{@link #getPackageName()} - The package name of the source.</li>
84  *   <li>{@link #getEventTime()}  - The event time.</li>
85  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
86  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
87  *   <li>{@link #isPassword()} - Whether the source is password.</li>
88  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
89  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
90  *   <li>{@link #getScrollX()} - The offset of the source left edge in pixels
91  *       (without descendants of AdapterView).</li>
92  *   <li>{@link #getScrollY()} - The offset of the source top edge in pixels
93  *       (without descendants of AdapterView).</li>
94  *   <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source,
95  *       inclusive (for descendants of AdapterView).</li>
96  *   <li>{@link #getToIndex()} - The zero based index of the last visible item of the source,
97  *       inclusive (for descendants of AdapterView).</li>
98  *   <li>{@link #getItemCount()} - The total items of the source
99  *       (for descendants of AdapterView).</li>
100  * </ul>
101  * </p>
102  * <p>
103  * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
104  * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br>
105  * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</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  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
114  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
115  *   <li>{@link #isPassword()} - Whether the source is password.</li>
116  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
117  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
118  *   <li>{@link #getScrollX()} - The offset of the source left edge in pixels
119  *       (without descendants of AdapterView).</li>
120  *   <li>{@link #getScrollY()} - The offset of the source top edge in pixels
121  *       (without descendants of AdapterView).</li>
122  *   <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source,
123  *       inclusive (for descendants of AdapterView).</li>
124  *   <li>{@link #getToIndex()} - The zero based index of the last visible item of the source,
125  *       inclusive (for descendants of AdapterView).</li>
126  *   <li>{@link #getItemCount()} - The total items of the source
127  *       (for descendants of AdapterView).</li>
128  * </ul>
129  * </p>
130  * <p>
131  * <b>View selected</b> - represents the event of selecting an item usually in
132  * the context of an {@link android.widget.AdapterView}.</br>
133  * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
134  * <em>Properties:</em></br>
135  * <ul>
136  *   <li>{@link #getEventType()} - The type of the event.</li>
137  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
138  *   <li>{@link #getClassName()} - The class name of the source.</li>
139  *   <li>{@link #getPackageName()} - The package name of the source.</li>
140  *   <li>{@link #getEventTime()}  - The event time.</li>
141  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
142  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
143  *   <li>{@link #isPassword()} - Whether the source is password.</li>
144  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
145  *   <li>{@link #getItemCount()} - The number of selectable items of the source.</li>
146  *   <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li>
147  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
148  *   <li>{@link #getScrollX()} - The offset of the source left edge in pixels
149  *       (without descendants of AdapterView).</li>
150  *   <li>{@link #getScrollY()} - The offset of the source top edge in pixels
151  *       (without descendants of AdapterView).</li>
152  *   <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source,
153  *       inclusive (for descendants of AdapterView).</li>
154  *   <li>{@link #getToIndex()} - The zero based index of the last visible item of the source,
155  *       inclusive (for descendants of AdapterView).</li>
156  *   <li>{@link #getItemCount()} - The total items of the source
157  *       (for descendants of AdapterView).</li>
158  * </ul>
159  * </p>
160  * <p>
161  * <b>View focused</b> - represents the event of focusing a
162  * {@link android.view.View}.</br>
163  * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
164  * <em>Properties:</em></br>
165  * <ul>
166  *   <li>{@link #getEventType()} - The type of the event.</li>
167  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
168  *   <li>{@link #getClassName()} - The class name of the source.</li>
169  *   <li>{@link #getPackageName()} - The package name of the source.</li>
170  *   <li>{@link #getEventTime()}  - The event time.</li>
171  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
172  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
173  *   <li>{@link #isPassword()} - Whether the source is password.</li>
174  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
175  *   <li>{@link #getItemCount()} - The number of focusable items on the screen.</li>
176  *   <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li>
177  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
178  *   <li>{@link #getScrollX()} - The offset of the source left edge in pixels
179  *       (without descendants of AdapterView).</li>
180  *   <li>{@link #getScrollY()} - The offset of the source top edge in pixels
181  *       (without descendants of AdapterView).</li>
182  *   <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source,
183  *       inclusive (for descendants of AdapterView).</li>
184  *   <li>{@link #getToIndex()} - The zero based index of the last visible item of the source,
185  *       inclusive (for descendants of AdapterView).</li>
186  *   <li>{@link #getItemCount()} - The total items of the source
187  *       (for descendants of AdapterView).</li>
188  * </ul>
189  * </p>
190  * <p>
191  * <b>View text changed</b> - represents the event of changing the text of an
192  * {@link android.widget.EditText}.</br>
193  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
194  * <em>Properties:</em></br>
195  * <ul>
196  *   <li>{@link #getEventType()} - The type of the event.</li>
197  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
198  *   <li>{@link #getClassName()} - The class name of the source.</li>
199  *   <li>{@link #getPackageName()} - The package name of the source.</li>
200  *   <li>{@link #getEventTime()}  - The event time.</li>
201  *   <li>{@link #getText()} - The text of the source.</li>
202  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
203  *   <li>{@link #isPassword()} - Whether the source is password.</li>
204  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
205  *   <li>{@link #getFromIndex()} - The text change start index.</li>
206  *   <li>{@link #getAddedCount()} - The number of added characters.</li>
207  *   <li>{@link #getRemovedCount()} - The number of removed characters.</li>
208  *   <li>{@link #getBeforeText()} - The text of the source before the change.</li>
209  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
210  * </ul>
211  * </p>
212  * <p>
213  * <b>View text selection changed</b> - represents the event of changing the text
214  * selection of an {@link android.widget.EditText}.</br>
215  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
216  * <em>Properties:</em></br>
217  * <ul>
218  *   <li>{@link #getEventType()} - The type of the event.</li>
219  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
220  *   <li>{@link #getClassName()} - The class name of the source.</li>
221  *   <li>{@link #getPackageName()} - The package name of the source.</li>
222  *   <li>{@link #getEventTime()}  - The event time.</li>
223  *   <li>{@link #getText()} - The text of the source.</li>
224  *   <li>{@link #isPassword()} - Whether the source is password.</li>
225  *   <li>{@link #getFromIndex()} - The selection start index.</li>
226  *   <li>{@link #getToIndex()} - The selection end index.</li>
227  *   <li>{@link #getItemCount()} - The length of the source text.</li>
228  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
229  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
230  * </ul>
231  * </p>
232  * <b>View text traversed at movement granularity</b> - represents the event of traversing the
233  * text of a view at a given granularity. For example, moving to the next word.</br>
234  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY} </br>
235  * <em>Properties:</em></br>
236  * <ul>
237  *   <li>{@link #getEventType()} - The type of the event.</li>
238  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
239  *   <li>{@link #getClassName()} - The class name of the source.</li>
240  *   <li>{@link #getPackageName()} - The package name of the source.</li>
241  *   <li>{@link #getEventTime()}  - The event time.</li>
242  *   <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text
243  *       was traversed.</li>
244  *   <li>{@link #getText()} -  The text of the source's sub-tree.</li>
245  *   <li>{@link #getFromIndex()} - The start the text that was skipped over in this movement.
246  *       This is the starting point when moving forward through the text, but not when moving
247  *       back.</li>
248  *   <li>{@link #getToIndex()} - The end of the text that was skipped over in this movement.
249  *       This is the ending point when moving forward through the text, but not when moving
250  *       back.</li>
251  *   <li>{@link #isPassword()} - Whether the source is password.</li>
252  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
253  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
254  *   <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text
255  *       was traversed.</li>
256  *   <li>{@link #getAction()} - Gets traversal action which specifies the direction.</li>
257  * </ul>
258  * </p>
259  * <p>
260  * <b>View scrolled</b> - represents the event of scrolling a view. If
261  * the source is a descendant of {@link android.widget.AdapterView} the
262  * scroll is reported in terms of visible items - the first visible item,
263  * the last visible item, and the total items - because the the source
264  * is unaware of its pixel size since its adapter is responsible for
265  * creating views. In all other cases the scroll is reported as the current
266  * scroll on the X and Y axis respectively plus the height of the source in
267  * pixels.</br>
268  * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
269  * <em>Properties:</em></br>
270  * <ul>
271  *   <li>{@link #getEventType()} - The type of the event.</li>
272  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
273  *   <li>{@link #getClassName()} - The class name of the source.</li>
274  *   <li>{@link #getPackageName()} - The package name of the source.</li>
275  *   <li>{@link #getEventTime()}  - The event time.</li>
276  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
277  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
278  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
279  *   <li>{@link #getScrollX()} - The offset of the source left edge in pixels
280  *       (without descendants of AdapterView).</li>
281  *   <li>{@link #getScrollY()} - The offset of the source top edge in pixels
282  *       (without descendants of AdapterView).</li>
283  *   <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source,
284  *       inclusive (for descendants of AdapterView).</li>
285  *   <li>{@link #getToIndex()} - The zero based index of the last visible item of the source,
286  *       inclusive (for descendants of AdapterView).</li>
287  *   <li>{@link #getItemCount()} - The total items of the source
288  *       (for descendants of AdapterView).</li>
289  * </ul>
290  * <em>Note:</em> This event type is not dispatched to descendants though
291  * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
292  * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
293  * source {@link android.view.View} and the sub-tree rooted at it will not receive
294  * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
295  * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
296  * text content to such events is by setting the
297  * {@link android.R.styleable#View_contentDescription contentDescription} of the source
298  * view.</br>
299  * </p>
300  * <p>
301  * <b>TRANSITION TYPES</b></br>
302  * </p>
303  * <p>
304  * <b>Window state changed</b> - represents the event of opening a
305  * {@link android.widget.PopupWindow}, {@link android.view.Menu},
306  * {@link android.app.Dialog}, etc.</br>
307  * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
308  * <em>Properties:</em></br>
309  * <ul>
310  *   <li>{@link #getEventType()} - The type of the event.</li>
311  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
312  *   <li>{@link #getClassName()} - The class name of the source.</li>
313  *   <li>{@link #getPackageName()} - The package name of the source.</li>
314  *   <li>{@link #getEventTime()}  - The event time.</li>
315  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
316  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
317  * </ul>
318  * </p>
319  * <p>
320  * <b>Window content changed</b> - represents the event of change in the
321  * content of a window. This change can be adding/removing view, changing
322  * a view size, etc.</br>
323  * </p>
324  * <p>
325  * <strong>Note:</strong> This event is fired only for the window source of the
326  * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED}
327  * and its purpose is to notify clients that the content of the user interaction
328  * window has changed.</br>
329  * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
330  * <em>Properties:</em></br>
331  * <ul>
332  *   <li>{@link #getEventType()} - The type of the event.</li>
333  *   <li>{@link #getContentChangeTypes()} - The type of content changes.</li>
334  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
335  *   <li>{@link #getClassName()} - The class name of the source.</li>
336  *   <li>{@link #getPackageName()} - The package name of the source.</li>
337  *   <li>{@link #getEventTime()}  - The event time.</li>
338  * </ul>
339  * <em>Note:</em> This event type is not dispatched to descendants though
340  * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
341  * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
342  * source {@link android.view.View} and the sub-tree rooted at it will not receive
343  * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
344  * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
345  * text content to such events is by setting the
346  * {@link android.R.styleable#View_contentDescription contentDescription} of the source
347  * view.</br>
348  * </p>
349  * <p>
350  * <b>Windows changed</b> - represents the event of changes in the windows shown on
351  * the screen such as a window appeared, a window disappeared, a window size changed,
352  * a window layer changed, etc.</br>
353  * <em>Type:</em> {@link #TYPE_WINDOWS_CHANGED}</br>
354  * <em>Properties:</em></br>
355  * <ul>
356  *   <li>{@link #getEventType()} - The type of the event.</li>
357  *   <li>{@link #getEventTime()} - The event time.</li>
358  * </ul>
359  * <em>Note:</em> You can retrieve the {@link AccessibilityWindowInfo} for the window
360  * source of the event via {@link AccessibilityEvent#getSource()} to get the source
361  * node on which then call {@link AccessibilityNodeInfo#getWindow()
362  * AccessibilityNodeInfo.getWindow()} to get the window. Also all windows on the screen can
363  * be retrieved by a call to {@link android.accessibilityservice.AccessibilityService#getWindows()
364  * android.accessibilityservice.AccessibilityService.getWindows()}.
365  * </p>
366  * <p>
367  * <b>NOTIFICATION TYPES</b></br>
368  * </p>
369  * <p>
370  * <b>Notification state changed</b> - represents the event showing a transient piece of information
371  * to the user. This information may be a {@link android.app.Notification} or
372  * {@link android.widget.Toast}.</br>
373  * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
374  * <em>Properties:</em></br>
375  * <ul>
376  *   <li>{@link #getEventType()} - The type of the event.</li>
377  *   <li>{@link #getClassName()} - The class name of the source.</li>
378  *   <li>{@link #getPackageName()} - The package name of the source.</li>
379  *   <li>{@link #getEventTime()}  - The event time.</li>
380  *   <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}, if
381  *   applicable.</li>
382  *   <li>{@link #getText()} - Displayed text of the {@link android.widget.Toast}, if applicable,
383  *   or may contain text from the {@link android.app.Notification}, although
384  *   {@link #getParcelableData()} is a richer set of data for {@link android.app.Notification}.</li>
385  * </ul>
386  * </p>
387  * <p>
388  * <b>EXPLORATION TYPES</b></br>
389  * </p>
390  * <p>
391  * <b>View hover enter</b> - represents the event of beginning to hover
392  * over a {@link android.view.View}. The hover may be generated via
393  * exploring the screen by touch or via a pointing device.</br>
394  * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br>
395  * <em>Properties:</em></br>
396  * <ul>
397  *   <li>{@link #getEventType()} - The type of the event.</li>
398  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
399  *   <li>{@link #getClassName()} - The class name of the source.</li>
400  *   <li>{@link #getPackageName()} - The package name of the source.</li>
401  *   <li>{@link #getEventTime()}  - The event time.</li>
402  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
403  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
404  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
405  *   <li>{@link #getScrollX()} - The offset of the source left edge in pixels
406  *       (without descendants of AdapterView).</li>
407  *   <li>{@link #getScrollY()} - The offset of the source top edge in pixels
408  *       (without descendants of AdapterView).</li>
409  *   <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source,
410  *       inclusive (for descendants of AdapterView).</li>
411  *   <li>{@link #getToIndex()} - The zero based index of the last visible item of the source,
412  *       inclusive (for descendants of AdapterView).</li>
413  *   <li>{@link #getItemCount()} - The total items of the source
414  *       (for descendants of AdapterView).</li>
415  * </ul>
416  * </p>
417  * <b>View hover exit</b> - represents the event of stopping to hover
418  * over a {@link android.view.View}. The hover may be generated via
419  * exploring the screen by touch or via a pointing device.</br>
420  * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br>
421  * <em>Properties:</em></br>
422  * <ul>
423  *   <li>{@link #getEventType()} - The type of the event.</li>
424  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
425  *   <li>{@link #getClassName()} - The class name of the source.</li>
426  *   <li>{@link #getPackageName()} - The package name of the source.</li>
427  *   <li>{@link #getEventTime()}  - The event time.</li>
428  *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
429  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
430  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
431  *   <li>{@link #getScrollX()} - The offset of the source left edge in pixels
432  *       (without descendants of AdapterView).</li>
433  *   <li>{@link #getScrollY()} - The offset of the source top edge in pixels
434  *       (without descendants of AdapterView).</li>
435  *   <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source,
436  *       inclusive (for descendants of AdapterView).</li>
437  *   <li>{@link #getToIndex()} - The zero based index of the last visible item of the source,
438  *       inclusive (for descendants of AdapterView).</li>
439  *   <li>{@link #getItemCount()} - The total items of the source
440  *       (for descendants of AdapterView).</li>
441  * </ul>
442  * </p>
443  * <p>
444  * <b>Touch interaction start</b> - represents the event of starting a touch
445  * interaction, which is the user starts touching the screen.</br>
446  * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_START}</br>
447  * <em>Properties:</em></br>
448  * <ul>
449  *   <li>{@link #getEventType()} - The type of the event.</li>
450  * </ul>
451  * <em>Note:</em> This event is fired only by the system and is not passed to the
452  * view tree to be populated.</br>
453  * </p>
454  * <p>
455  * <b>Touch interaction end</b> - represents the event of ending a touch
456  * interaction, which is the user stops touching the screen.</br>
457  * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_END}</br>
458  * <em>Properties:</em></br>
459  * <ul>
460  *   <li>{@link #getEventType()} - The type of the event.</li>
461  * </ul>
462  * <em>Note:</em> This event is fired only by the system and is not passed to the
463  * view tree to be populated.</br>
464  * </p>
465  * <p>
466  * <b>Touch exploration gesture start</b> - represents the event of starting a touch
467  * exploring gesture.</br>
468  * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br>
469  * <em>Properties:</em></br>
470  * <ul>
471  *   <li>{@link #getEventType()} - The type of the event.</li>
472  * </ul>
473  * <em>Note:</em> This event is fired only by the system and is not passed to the
474  * view tree to be populated.</br>
475  * </p>
476  * <p>
477  * <b>Touch exploration gesture end</b> - represents the event of ending a touch
478  * exploring gesture.</br>
479  * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br>
480  * <em>Properties:</em></br>
481  * <ul>
482  *   <li>{@link #getEventType()} - The type of the event.</li>
483  * </ul>
484  * <em>Note:</em> This event is fired only by the system and is not passed to the
485  * view tree to be populated.</br>
486  * </p>
487  * <p>
488  * <b>Touch gesture detection start</b> - represents the event of starting a user
489  * gesture detection.</br>
490  * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_START}</br>
491  * <em>Properties:</em></br>
492  * <ul>
493  *   <li>{@link #getEventType()} - The type of the event.</li>
494  * </ul>
495  * <em>Note:</em> This event is fired only by the system and is not passed to the
496  * view tree to be populated.</br>
497  * </p>
498  * <p>
499  * <b>Touch gesture detection end</b> - represents the event of ending a user
500  * gesture detection.</br>
501  * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_END}</br>
502  * <em>Properties:</em></br>
503  * <ul>
504  *   <li>{@link #getEventType()} - The type of the event.</li>
505  * </ul>
506  * <em>Note:</em> This event is fired only by the system and is not passed to the
507  * view tree to be populated.</br>
508  * </p>
509  * <p>
510  * <b>MISCELLANEOUS TYPES</b></br>
511  * </p>
512  * <p>
513  * <b>Announcement</b> - represents the event of an application making an
514  * announcement. Usually this announcement is related to some sort of a context
515  * change for which none of the events representing UI transitions is a good fit.
516  * For example, announcing a new page in a book.</br>
517  * <em>Type:</em> {@link #TYPE_ANNOUNCEMENT}</br>
518  * <em>Properties:</em></br>
519  * <ul>
520  *   <li>{@link #getEventType()} - The type of the event.</li>
521  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
522  *   <li>{@link #getClassName()} - The class name of the source.</li>
523  *   <li>{@link #getPackageName()} - The package name of the source.</li>
524  *   <li>{@link #getEventTime()}  - The event time.</li>
525  *   <li>{@link #getText()} - The text of the announcement.</li>
526  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
527  * </ul>
528  * </p>
529  *
530  * @see android.view.accessibility.AccessibilityManager
531  * @see android.accessibilityservice.AccessibilityService
532  * @see AccessibilityNodeInfo
533  */
534 public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
535     private static final boolean DEBUG = false;
536 
537     /**
538      * Invalid selection/focus position.
539      *
540      * @see #getCurrentItemIndex()
541      */
542     public static final int INVALID_POSITION = -1;
543 
544     /**
545      * Maximum length of the text fields.
546      *
547      * @see #getBeforeText()
548      * @see #getText()
549      * </br>
550      * Note: This constant is no longer needed since there
551      *       is no limit on the length of text that is contained
552      *       in an accessibility event anymore.
553      */
554     @Deprecated
555     public static final int MAX_TEXT_LENGTH = 500;
556 
557     /**
558      * Represents the event of clicking on a {@link android.view.View} like
559      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
560      */
561     public static final int TYPE_VIEW_CLICKED = 0x00000001;
562 
563     /**
564      * Represents the event of long clicking on a {@link android.view.View} like
565      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
566      */
567     public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
568 
569     /**
570      * Represents the event of selecting an item usually in the context of an
571      * {@link android.widget.AdapterView}.
572      */
573     public static final int TYPE_VIEW_SELECTED = 0x00000004;
574 
575     /**
576      * Represents the event of setting input focus of a {@link android.view.View}.
577      */
578     public static final int TYPE_VIEW_FOCUSED = 0x00000008;
579 
580     /**
581      * Represents the event of changing the text of an {@link android.widget.EditText}.
582      */
583     public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
584 
585     /**
586      * Represents the event of opening a {@link android.widget.PopupWindow},
587      * {@link android.view.Menu}, {@link android.app.Dialog}, etc.
588      */
589     public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
590 
591     /**
592      * Represents the event showing a {@link android.app.Notification}.
593      */
594     public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
595 
596     /**
597      * Represents the event of a hover enter over a {@link android.view.View}.
598      */
599     public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
600 
601     /**
602      * Represents the event of a hover exit over a {@link android.view.View}.
603      */
604     public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
605 
606     /**
607      * Represents the event of starting a touch exploration gesture.
608      */
609     public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
610 
611     /**
612      * Represents the event of ending a touch exploration gesture.
613      */
614     public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
615 
616     /**
617      * Represents the event of changing the content of a window and more
618      * specifically the sub-tree rooted at the event's source.
619      */
620     public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
621 
622     /**
623      * Represents the event of scrolling a view. This event type is generally not sent directly.
624      * @see View#onScrollChanged(int, int, int, int)
625      */
626     public static final int TYPE_VIEW_SCROLLED = 0x00001000;
627 
628     /**
629      * Represents the event of changing the selection in an {@link android.widget.EditText}.
630      */
631     public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
632 
633     /**
634      * Represents the event of an application making an announcement.
635      */
636     public static final int TYPE_ANNOUNCEMENT = 0x00004000;
637 
638     /**
639      * Represents the event of gaining accessibility focus.
640      */
641     public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000;
642 
643     /**
644      * Represents the event of clearing accessibility focus.
645      */
646     public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
647 
648     /**
649      * Represents the event of traversing the text of a view at a given movement granularity.
650      */
651     public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
652 
653     /**
654      * Represents the event of beginning gesture detection.
655      */
656     public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
657 
658     /**
659      * Represents the event of ending gesture detection.
660      */
661     public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
662 
663     /**
664      * Represents the event of the user starting to touch the screen.
665      */
666     public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
667 
668     /**
669      * Represents the event of the user ending to touch the screen.
670      */
671     public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
672 
673     /**
674      * Represents the event change in the windows shown on the screen.
675      */
676     public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
677 
678     /**
679      * Represents the event of a context click on a {@link android.view.View}.
680      */
681     public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
682 
683     /**
684      * Represents the event of the assistant currently reading the users screen context.
685      */
686     public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000;
687 
688     /**
689      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
690      * The type of change is not defined.
691      */
692     public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
693 
694     /**
695      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
696      * A node in the subtree rooted at the source node was added or removed.
697      */
698     public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
699 
700     /**
701      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
702      * The node's text changed.
703      */
704     public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
705 
706     /**
707      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
708      * The node's content description changed.
709      */
710     public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
711 
712     /**
713      * Mask for {@link AccessibilityEvent} all types.
714      *
715      * @see #TYPE_VIEW_CLICKED
716      * @see #TYPE_VIEW_LONG_CLICKED
717      * @see #TYPE_VIEW_SELECTED
718      * @see #TYPE_VIEW_FOCUSED
719      * @see #TYPE_VIEW_TEXT_CHANGED
720      * @see #TYPE_WINDOW_STATE_CHANGED
721      * @see #TYPE_NOTIFICATION_STATE_CHANGED
722      * @see #TYPE_VIEW_HOVER_ENTER
723      * @see #TYPE_VIEW_HOVER_EXIT
724      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
725      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
726      * @see #TYPE_WINDOW_CONTENT_CHANGED
727      * @see #TYPE_VIEW_SCROLLED
728      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
729      * @see #TYPE_ANNOUNCEMENT
730      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
731      * @see #TYPE_GESTURE_DETECTION_START
732      * @see #TYPE_GESTURE_DETECTION_END
733      * @see #TYPE_TOUCH_INTERACTION_START
734      * @see #TYPE_TOUCH_INTERACTION_END
735      * @see #TYPE_WINDOWS_CHANGED
736      * @see #TYPE_VIEW_CONTEXT_CLICKED
737      */
738     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
739 
740     private static final int MAX_POOL_SIZE = 10;
741     private static final SynchronizedPool<AccessibilityEvent> sPool =
742             new SynchronizedPool<AccessibilityEvent>(MAX_POOL_SIZE);
743 
744     private int mEventType;
745     private CharSequence mPackageName;
746     private long mEventTime;
747     int mMovementGranularity;
748     int mAction;
749     int mContentChangeTypes;
750 
751     private ArrayList<AccessibilityRecord> mRecords;
752 
753     /*
754      * Hide constructor from clients.
755      */
AccessibilityEvent()756     private AccessibilityEvent() {
757     }
758 
759     /**
760      * Initialize an event from another one.
761      *
762      * @param event The event to initialize from.
763      */
init(AccessibilityEvent event)764     void init(AccessibilityEvent event) {
765         super.init(event);
766         mEventType = event.mEventType;
767         mMovementGranularity = event.mMovementGranularity;
768         mAction = event.mAction;
769         mContentChangeTypes = event.mContentChangeTypes;
770         mEventTime = event.mEventTime;
771         mPackageName = event.mPackageName;
772     }
773 
774     /**
775      * Sets if this instance is sealed.
776      *
777      * @param sealed Whether is sealed.
778      *
779      * @hide
780      */
781     @Override
setSealed(boolean sealed)782     public void setSealed(boolean sealed) {
783         super.setSealed(sealed);
784         final List<AccessibilityRecord> records = mRecords;
785         if (records != null) {
786             final int recordCount = records.size();
787             for (int i = 0; i < recordCount; i++) {
788                 AccessibilityRecord record = records.get(i);
789                 record.setSealed(sealed);
790             }
791         }
792     }
793 
794     /**
795      * Gets the number of records contained in the event.
796      *
797      * @return The number of records.
798      */
getRecordCount()799     public int getRecordCount() {
800         return mRecords == null ? 0 : mRecords.size();
801     }
802 
803     /**
804      * Appends an {@link AccessibilityRecord} to the end of event records.
805      *
806      * @param record The record to append.
807      *
808      * @throws IllegalStateException If called from an AccessibilityService.
809      */
appendRecord(AccessibilityRecord record)810     public void appendRecord(AccessibilityRecord record) {
811         enforceNotSealed();
812         if (mRecords == null) {
813             mRecords = new ArrayList<AccessibilityRecord>();
814         }
815         mRecords.add(record);
816     }
817 
818     /**
819      * Gets the record at a given index.
820      *
821      * @param index The index.
822      * @return The record at the specified index.
823      */
getRecord(int index)824     public AccessibilityRecord getRecord(int index) {
825         if (mRecords == null) {
826             throw new IndexOutOfBoundsException("Invalid index " + index + ", size is 0");
827         }
828         return mRecords.get(index);
829     }
830 
831     /**
832      * Gets the event type.
833      *
834      * @return The event type.
835      */
getEventType()836     public int getEventType() {
837         return mEventType;
838     }
839 
840     /**
841      * Gets the bit mask of change types signaled by an
842      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event. A single event may represent
843      * multiple change types.
844      *
845      * @return The bit mask of change types. One or more of:
846      *         <ul>
847      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION}
848      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE}
849      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT}
850      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED}
851      *         </ul>
852      */
getContentChangeTypes()853     public int getContentChangeTypes() {
854         return mContentChangeTypes;
855     }
856 
contentChangeTypesToString(int types)857     private static String contentChangeTypesToString(int types) {
858         return BitUtils.flagsToString(types, AccessibilityEvent::singleContentChangeTypeToString);
859     }
860 
singleContentChangeTypeToString(int type)861     private static String singleContentChangeTypeToString(int type) {
862         switch (type) {
863             case CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION: {
864                 return "CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION";
865             }
866             case CONTENT_CHANGE_TYPE_SUBTREE: return "CONTENT_CHANGE_TYPE_SUBTREE";
867             case CONTENT_CHANGE_TYPE_TEXT: return "CONTENT_CHANGE_TYPE_TEXT";
868             case CONTENT_CHANGE_TYPE_UNDEFINED: return "CONTENT_CHANGE_TYPE_UNDEFINED";
869             default: return Integer.toHexString(type);
870         }
871     }
872 
873     /**
874      * Sets the bit mask of node tree changes signaled by an
875      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
876      *
877      * @param changeTypes The bit mask of change types.
878      * @throws IllegalStateException If called from an AccessibilityService.
879      * @see #getContentChangeTypes()
880      */
setContentChangeTypes(int changeTypes)881     public void setContentChangeTypes(int changeTypes) {
882         enforceNotSealed();
883         mContentChangeTypes = changeTypes;
884     }
885 
886     /**
887      * Sets the event type.
888      *
889      * @param eventType The event type.
890      *
891      * @throws IllegalStateException If called from an AccessibilityService.
892      */
setEventType(int eventType)893     public void setEventType(int eventType) {
894         enforceNotSealed();
895         mEventType = eventType;
896     }
897 
898     /**
899      * Gets the time in which this event was sent.
900      *
901      * @return The event time.
902      */
getEventTime()903     public long getEventTime() {
904         return mEventTime;
905     }
906 
907     /**
908      * Sets the time in which this event was sent.
909      *
910      * @param eventTime The event time.
911      *
912      * @throws IllegalStateException If called from an AccessibilityService.
913      */
setEventTime(long eventTime)914     public void setEventTime(long eventTime) {
915         enforceNotSealed();
916         mEventTime = eventTime;
917     }
918 
919     /**
920      * Gets the package name of the source.
921      *
922      * @return The package name.
923      */
getPackageName()924     public CharSequence getPackageName() {
925         return mPackageName;
926     }
927 
928     /**
929      * Sets the package name of the source.
930      *
931      * @param packageName The package name.
932      *
933      * @throws IllegalStateException If called from an AccessibilityService.
934      */
setPackageName(CharSequence packageName)935     public void setPackageName(CharSequence packageName) {
936         enforceNotSealed();
937         mPackageName = packageName;
938     }
939 
940     /**
941      * Sets the movement granularity that was traversed.
942      *
943      * @param granularity The granularity.
944      *
945      * @throws IllegalStateException If called from an AccessibilityService.
946      */
setMovementGranularity(int granularity)947     public void setMovementGranularity(int granularity) {
948         enforceNotSealed();
949         mMovementGranularity = granularity;
950     }
951 
952     /**
953      * Gets the movement granularity that was traversed.
954      *
955      * @return The granularity.
956      */
getMovementGranularity()957     public int getMovementGranularity() {
958         return mMovementGranularity;
959     }
960 
961     /**
962      * Sets the performed action that triggered this event.
963      * <p>
964      * Valid actions are defined in {@link AccessibilityNodeInfo}:
965      * <ul>
966      * <li>{@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}
967      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
968      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS}
969      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION}
970      * <li>{@link AccessibilityNodeInfo#ACTION_CLICK}
971      * <li>etc.
972      * </ul>
973      *
974      * @param action The action.
975      * @throws IllegalStateException If called from an AccessibilityService.
976      * @see AccessibilityNodeInfo#performAction(int)
977      */
setAction(int action)978     public void setAction(int action) {
979         enforceNotSealed();
980         mAction = action;
981     }
982 
983     /**
984      * Gets the performed action that triggered this event.
985      *
986      * @return The action.
987      */
getAction()988     public int getAction() {
989         return mAction;
990     }
991 
992     /**
993      * Returns a cached instance if such is available or a new one is
994      * instantiated with its type property set.
995      *
996      * @param eventType The event type.
997      * @return An instance.
998      */
obtain(int eventType)999     public static AccessibilityEvent obtain(int eventType) {
1000         AccessibilityEvent event = AccessibilityEvent.obtain();
1001         event.setEventType(eventType);
1002         return event;
1003     }
1004 
1005     /**
1006      * Returns a cached instance if such is available or a new one is
1007      * created. The returned instance is initialized from the given
1008      * <code>event</code>.
1009      *
1010      * @param event The other event.
1011      * @return An instance.
1012      */
obtain(AccessibilityEvent event)1013     public static AccessibilityEvent obtain(AccessibilityEvent event) {
1014         AccessibilityEvent eventClone = AccessibilityEvent.obtain();
1015         eventClone.init(event);
1016 
1017         if (event.mRecords != null) {
1018             final int recordCount = event.mRecords.size();
1019             eventClone.mRecords = new ArrayList<AccessibilityRecord>(recordCount);
1020             for (int i = 0; i < recordCount; i++) {
1021                 final AccessibilityRecord record = event.mRecords.get(i);
1022                 final AccessibilityRecord recordClone = AccessibilityRecord.obtain(record);
1023                 eventClone.mRecords.add(recordClone);
1024             }
1025         }
1026 
1027         return eventClone;
1028     }
1029 
1030     /**
1031      * Returns a cached instance if such is available or a new one is
1032      * instantiated.
1033      *
1034      * @return An instance.
1035      */
obtain()1036     public static AccessibilityEvent obtain() {
1037         AccessibilityEvent event = sPool.acquire();
1038         return (event != null) ? event : new AccessibilityEvent();
1039     }
1040 
1041     /**
1042      * Recycles an instance back to be reused.
1043      * <p>
1044      *   <b>Note: You must not touch the object after calling this function.</b>
1045      * </p>
1046      *
1047      * @throws IllegalStateException If the event is already recycled.
1048      */
1049     @Override
recycle()1050     public void recycle() {
1051         clear();
1052         sPool.release(this);
1053     }
1054 
1055     /**
1056      * Clears the state of this instance.
1057      *
1058      * @hide
1059      */
1060     @Override
clear()1061     protected void clear() {
1062         super.clear();
1063         mEventType = 0;
1064         mMovementGranularity = 0;
1065         mAction = 0;
1066         mContentChangeTypes = 0;
1067         mPackageName = null;
1068         mEventTime = 0;
1069         if (mRecords != null) {
1070             while (!mRecords.isEmpty()) {
1071                 AccessibilityRecord record = mRecords.remove(0);
1072                 record.recycle();
1073             }
1074         }
1075     }
1076 
1077     /**
1078      * Creates a new instance from a {@link Parcel}.
1079      *
1080      * @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
1081      */
initFromParcel(Parcel parcel)1082     public void initFromParcel(Parcel parcel) {
1083         mSealed = (parcel.readInt() == 1);
1084         mEventType = parcel.readInt();
1085         mMovementGranularity = parcel.readInt();
1086         mAction = parcel.readInt();
1087         mContentChangeTypes = parcel.readInt();
1088         mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1089         mEventTime = parcel.readLong();
1090         mConnectionId = parcel.readInt();
1091         readAccessibilityRecordFromParcel(this, parcel);
1092 
1093         // Read the records.
1094         final int recordCount = parcel.readInt();
1095         if (recordCount > 0) {
1096             mRecords = new ArrayList<AccessibilityRecord>(recordCount);
1097             for (int i = 0; i < recordCount; i++) {
1098                 AccessibilityRecord record = AccessibilityRecord.obtain();
1099                 readAccessibilityRecordFromParcel(record, parcel);
1100                 record.mConnectionId = mConnectionId;
1101                 mRecords.add(record);
1102             }
1103         }
1104     }
1105 
1106     /**
1107      * Reads an {@link AccessibilityRecord} from a parcel.
1108      *
1109      * @param record The record to initialize.
1110      * @param parcel The parcel to read from.
1111      */
readAccessibilityRecordFromParcel(AccessibilityRecord record, Parcel parcel)1112     private void readAccessibilityRecordFromParcel(AccessibilityRecord record,
1113             Parcel parcel) {
1114         record.mBooleanProperties = parcel.readInt();
1115         record.mCurrentItemIndex = parcel.readInt();
1116         record.mItemCount = parcel.readInt();
1117         record.mFromIndex = parcel.readInt();
1118         record.mToIndex = parcel.readInt();
1119         record.mScrollX = parcel.readInt();
1120         record.mScrollY =  parcel.readInt();
1121         record.mMaxScrollX = parcel.readInt();
1122         record.mMaxScrollY =  parcel.readInt();
1123         record.mAddedCount = parcel.readInt();
1124         record.mRemovedCount = parcel.readInt();
1125         record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1126         record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1127         record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
1128         record.mParcelableData = parcel.readParcelable(null);
1129         parcel.readList(record.mText, null);
1130         record.mSourceWindowId = parcel.readInt();
1131         record.mSourceNodeId = parcel.readLong();
1132         record.mSealed = (parcel.readInt() == 1);
1133     }
1134 
1135     /**
1136      * {@inheritDoc}
1137      */
writeToParcel(Parcel parcel, int flags)1138     public void writeToParcel(Parcel parcel, int flags) {
1139         parcel.writeInt(isSealed() ? 1 : 0);
1140         parcel.writeInt(mEventType);
1141         parcel.writeInt(mMovementGranularity);
1142         parcel.writeInt(mAction);
1143         parcel.writeInt(mContentChangeTypes);
1144         TextUtils.writeToParcel(mPackageName, parcel, 0);
1145         parcel.writeLong(mEventTime);
1146         parcel.writeInt(mConnectionId);
1147         writeAccessibilityRecordToParcel(this, parcel, flags);
1148 
1149         // Write the records.
1150         final int recordCount = getRecordCount();
1151         parcel.writeInt(recordCount);
1152         for (int i = 0; i < recordCount; i++) {
1153             AccessibilityRecord record = mRecords.get(i);
1154             writeAccessibilityRecordToParcel(record, parcel, flags);
1155         }
1156     }
1157 
1158     /**
1159      * Writes an {@link AccessibilityRecord} to a parcel.
1160      *
1161      * @param record The record to write.
1162      * @param parcel The parcel to which to write.
1163      */
writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel, int flags)1164     private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel,
1165             int flags) {
1166         parcel.writeInt(record.mBooleanProperties);
1167         parcel.writeInt(record.mCurrentItemIndex);
1168         parcel.writeInt(record.mItemCount);
1169         parcel.writeInt(record.mFromIndex);
1170         parcel.writeInt(record.mToIndex);
1171         parcel.writeInt(record.mScrollX);
1172         parcel.writeInt(record.mScrollY);
1173         parcel.writeInt(record.mMaxScrollX);
1174         parcel.writeInt(record.mMaxScrollY);
1175         parcel.writeInt(record.mAddedCount);
1176         parcel.writeInt(record.mRemovedCount);
1177         TextUtils.writeToParcel(record.mClassName, parcel, flags);
1178         TextUtils.writeToParcel(record.mContentDescription, parcel, flags);
1179         TextUtils.writeToParcel(record.mBeforeText, parcel, flags);
1180         parcel.writeParcelable(record.mParcelableData, flags);
1181         parcel.writeList(record.mText);
1182         parcel.writeInt(record.mSourceWindowId);
1183         parcel.writeLong(record.mSourceNodeId);
1184         parcel.writeInt(record.mSealed ? 1 : 0);
1185     }
1186 
1187     /**
1188      * {@inheritDoc}
1189      */
describeContents()1190     public int describeContents() {
1191         return 0;
1192     }
1193 
1194     @Override
toString()1195     public String toString() {
1196         StringBuilder builder = new StringBuilder();
1197         builder.append("EventType: ").append(eventTypeToString(mEventType));
1198         builder.append("; EventTime: ").append(mEventTime);
1199         builder.append("; PackageName: ").append(mPackageName);
1200         builder.append("; MovementGranularity: ").append(mMovementGranularity);
1201         builder.append("; Action: ").append(mAction);
1202         builder.append(super.toString());
1203         if (DEBUG) {
1204             builder.append("\n");
1205             builder.append("; ContentChangeTypes: ").append(
1206                     contentChangeTypesToString(mContentChangeTypes));
1207             builder.append("; sourceWindowId: ").append(mSourceWindowId);
1208             builder.append("; mSourceNodeId: ").append(mSourceNodeId);
1209             for (int i = 0; i < getRecordCount(); i++) {
1210                 final AccessibilityRecord record = getRecord(i);
1211                 builder.append("  Record ");
1212                 builder.append(i);
1213                 builder.append(":");
1214                 builder.append(" [ ClassName: " + record.mClassName);
1215                 builder.append("; Text: " + record.mText);
1216                 builder.append("; ContentDescription: " + record.mContentDescription);
1217                 builder.append("; ItemCount: " + record.mItemCount);
1218                 builder.append("; CurrentItemIndex: " + record.mCurrentItemIndex);
1219                 builder.append("; IsEnabled: " + record.isEnabled());
1220                 builder.append("; IsPassword: " + record.isPassword());
1221                 builder.append("; IsChecked: " + record.isChecked());
1222                 builder.append("; IsFullScreen: " + record.isFullScreen());
1223                 builder.append("; Scrollable: " + record.isScrollable());
1224                 builder.append("; BeforeText: " + record.mBeforeText);
1225                 builder.append("; FromIndex: " + record.mFromIndex);
1226                 builder.append("; ToIndex: " + record.mToIndex);
1227                 builder.append("; ScrollX: " + record.mScrollX);
1228                 builder.append("; ScrollY: " + record.mScrollY);
1229                 builder.append("; AddedCount: " + record.mAddedCount);
1230                 builder.append("; RemovedCount: " + record.mRemovedCount);
1231                 builder.append("; ParcelableData: " + record.mParcelableData);
1232                 builder.append(" ]");
1233                 builder.append("\n");
1234             }
1235         } else {
1236             builder.append("; recordCount: ").append(getRecordCount());
1237         }
1238         return builder.toString();
1239     }
1240 
1241     /**
1242      * Returns the string representation of an event type. For example,
1243      * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
1244      *
1245      * @param eventType The event type
1246      * @return The string representation.
1247      */
eventTypeToString(int eventType)1248     public static String eventTypeToString(int eventType) {
1249         if (eventType == TYPES_ALL_MASK) {
1250             return "TYPES_ALL_MASK";
1251         }
1252         StringBuilder builder = new StringBuilder();
1253         int eventTypeCount = 0;
1254         while (eventType != 0) {
1255             final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType);
1256             eventType &= ~eventTypeFlag;
1257 
1258             if (eventTypeCount > 0) {
1259                 builder.append(", ");
1260             }
1261             builder.append(singleEventTypeToString(eventTypeFlag));
1262 
1263             eventTypeCount++;
1264         }
1265         if (eventTypeCount > 1) {
1266             builder.insert(0, '[');
1267             builder.append(']');
1268         }
1269         return builder.toString();
1270     }
1271 
singleEventTypeToString(int eventType)1272     private static String singleEventTypeToString(int eventType) {
1273         switch (eventType) {
1274             case TYPE_VIEW_CLICKED: return "TYPE_VIEW_CLICKED";
1275             case TYPE_VIEW_LONG_CLICKED: return "TYPE_VIEW_LONG_CLICKED";
1276             case TYPE_VIEW_SELECTED: return "TYPE_VIEW_SELECTED";
1277             case TYPE_VIEW_FOCUSED: return "TYPE_VIEW_FOCUSED";
1278             case TYPE_VIEW_TEXT_CHANGED: return "TYPE_VIEW_TEXT_CHANGED";
1279             case TYPE_WINDOW_STATE_CHANGED: return "TYPE_WINDOW_STATE_CHANGED";
1280             case TYPE_VIEW_HOVER_ENTER: return "TYPE_VIEW_HOVER_ENTER";
1281             case TYPE_VIEW_HOVER_EXIT: return "TYPE_VIEW_HOVER_EXIT";
1282             case TYPE_NOTIFICATION_STATE_CHANGED: return "TYPE_NOTIFICATION_STATE_CHANGED";
1283             case TYPE_TOUCH_EXPLORATION_GESTURE_START: {
1284                 return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
1285             }
1286             case TYPE_TOUCH_EXPLORATION_GESTURE_END: return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
1287             case TYPE_WINDOW_CONTENT_CHANGED: return "TYPE_WINDOW_CONTENT_CHANGED";
1288             case TYPE_VIEW_TEXT_SELECTION_CHANGED: return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
1289             case TYPE_VIEW_SCROLLED: return "TYPE_VIEW_SCROLLED";
1290             case TYPE_ANNOUNCEMENT: return "TYPE_ANNOUNCEMENT";
1291             case TYPE_VIEW_ACCESSIBILITY_FOCUSED: return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
1292             case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
1293                 return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
1294             }
1295             case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
1296                 return "TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY";
1297             }
1298             case TYPE_GESTURE_DETECTION_START: return "TYPE_GESTURE_DETECTION_START";
1299             case TYPE_GESTURE_DETECTION_END: return "TYPE_GESTURE_DETECTION_END";
1300             case TYPE_TOUCH_INTERACTION_START: return "TYPE_TOUCH_INTERACTION_START";
1301             case TYPE_TOUCH_INTERACTION_END: return "TYPE_TOUCH_INTERACTION_END";
1302             case TYPE_WINDOWS_CHANGED: return "TYPE_WINDOWS_CHANGED";
1303             case TYPE_VIEW_CONTEXT_CLICKED: return "TYPE_VIEW_CONTEXT_CLICKED";
1304             case TYPE_ASSIST_READING_CONTEXT: return "TYPE_ASSIST_READING_CONTEXT";
1305             default: return Integer.toHexString(eventType);
1306         }
1307     }
1308 
1309     /**
1310      * @see Parcelable.Creator
1311      */
1312     public static final Parcelable.Creator<AccessibilityEvent> CREATOR =
1313             new Parcelable.Creator<AccessibilityEvent>() {
1314         public AccessibilityEvent createFromParcel(Parcel parcel) {
1315             AccessibilityEvent event = AccessibilityEvent.obtain();
1316             event.initFromParcel(parcel);
1317             return event;
1318         }
1319 
1320         public AccessibilityEvent[] newArray(int size) {
1321             return new AccessibilityEvent[size];
1322         }
1323     };
1324 }
1325