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