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