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>Windows changed</b> - represents the event of changes in the windows shown on 347 * the screen such as a window appeared, a window disappeared, a window size changed, 348 * a window layer changed, etc.</br> 349 * <em>Type:</em> {@link #TYPE_WINDOWS_CHANGED}</br> 350 * <em>Properties:</em></br> 351 * <ul> 352 * <li>{@link #getEventType()} - The type of the event.</li> 353 * <li>{@link #getEventTime()} - The event time.</li> 354 * </ul> 355 * <em>Note:</em> You can retrieve the {@link AccessibilityWindowInfo} for the window 356 * source of the event via {@link AccessibilityEvent#getSource()} to get the source 357 * node on which then call {@link AccessibilityNodeInfo#getWindow() 358 * AccessibilityNodeInfo.getWindow()} to get the window. Also all windows on the screen can 359 * be retrieved by a call to {@link android.accessibilityservice.AccessibilityService#getWindows() 360 * android.accessibilityservice.AccessibilityService.getWindows()}. 361 * </p> 362 * <p> 363 * <b>NOTIFICATION TYPES</b></br> 364 * </p> 365 * <p> 366 * <b>Notification state changed</b> - represents the event showing 367 * {@link android.app.Notification}.</br> 368 * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br> 369 * <em>Properties:</em></br> 370 * <ul> 371 * <li>{@link #getEventType()} - The type of the event.</li> 372 * <li>{@link #getClassName()} - The class name of the source.</li> 373 * <li>{@link #getPackageName()} - The package name of the source.</li> 374 * <li>{@link #getEventTime()} - The event time.</li> 375 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 376 * <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li> 377 * <li>{@link #getText()} - Text for providing more context.</li> 378 * </ul> 379 * <em>Note:</em> This event type is not dispatched to descendants though 380 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 381 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 382 * source {@link android.view.View} and the sub-tree rooted at it will not receive 383 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 384 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 385 * text content to such events is by setting the 386 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 387 * view.</br> 388 * </p> 389 * <p> 390 * <b>EXPLORATION TYPES</b></br> 391 * </p> 392 * <p> 393 * <b>View hover enter</b> - represents the event of beginning to hover 394 * over a {@link android.view.View}. The hover may be generated via 395 * exploring the screen by touch or via a pointing device.</br> 396 * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br> 397 * <em>Properties:</em></br> 398 * <ul> 399 * <li>{@link #getEventType()} - The type of the event.</li> 400 * <li>{@link #getSource()} - The source info (for registered clients).</li> 401 * <li>{@link #getClassName()} - The class name of the source.</li> 402 * <li>{@link #getPackageName()} - The package name of the source.</li> 403 * <li>{@link #getEventTime()} - The event time.</li> 404 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 405 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 406 * <li>{@link #getContentDescription()} - The content description of the source.</li> 407 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 408 * (without descendants of AdapterView).</li> 409 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 410 * (without descendants of AdapterView).</li> 411 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 412 * inclusive (for descendants of AdapterView).</li> 413 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 414 * inclusive (for descendants of AdapterView).</li> 415 * <li>{@link #getItemCount()} - The total items of the source 416 * (for descendants of AdapterView).</li> 417 * </ul> 418 * </p> 419 * <b>View hover exit</b> - represents the event of stopping to hover 420 * over a {@link android.view.View}. The hover may be generated via 421 * exploring the screen by touch or via a pointing device.</br> 422 * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br> 423 * <em>Properties:</em></br> 424 * <ul> 425 * <li>{@link #getEventType()} - The type of the event.</li> 426 * <li>{@link #getSource()} - The source info (for registered clients).</li> 427 * <li>{@link #getClassName()} - The class name of the source.</li> 428 * <li>{@link #getPackageName()} - The package name of the source.</li> 429 * <li>{@link #getEventTime()} - The event time.</li> 430 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 431 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 432 * <li>{@link #getContentDescription()} - The content description of the source.</li> 433 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 434 * (without descendants of AdapterView).</li> 435 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 436 * (without descendants of AdapterView).</li> 437 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 438 * inclusive (for descendants of AdapterView).</li> 439 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 440 * inclusive (for descendants of AdapterView).</li> 441 * <li>{@link #getItemCount()} - The total items of the source 442 * (for descendants of AdapterView).</li> 443 * </ul> 444 * </p> 445 * <p> 446 * <b>Touch interaction start</b> - represents the event of starting a touch 447 * interaction, which is the user starts touching the screen.</br> 448 * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_START}</br> 449 * <em>Properties:</em></br> 450 * <ul> 451 * <li>{@link #getEventType()} - The type of the event.</li> 452 * </ul> 453 * <em>Note:</em> This event is fired only by the system and is not passed to the 454 * view tree to be populated.</br> 455 * </p> 456 * <p> 457 * <b>Touch interaction end</b> - represents the event of ending a touch 458 * interaction, which is the user stops touching the screen.</br> 459 * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_END}</br> 460 * <em>Properties:</em></br> 461 * <ul> 462 * <li>{@link #getEventType()} - The type of the event.</li> 463 * </ul> 464 * <em>Note:</em> This event is fired only by the system and is not passed to the 465 * view tree to be populated.</br> 466 * </p> 467 * <p> 468 * <b>Touch exploration gesture start</b> - represents the event of starting a touch 469 * exploring gesture.</br> 470 * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br> 471 * <em>Properties:</em></br> 472 * <ul> 473 * <li>{@link #getEventType()} - The type of the event.</li> 474 * </ul> 475 * <em>Note:</em> This event is fired only by the system and is not passed to the 476 * view tree to be populated.</br> 477 * </p> 478 * <p> 479 * <b>Touch exploration gesture end</b> - represents the event of ending a touch 480 * exploring gesture.</br> 481 * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br> 482 * <em>Properties:</em></br> 483 * <ul> 484 * <li>{@link #getEventType()} - The type of the event.</li> 485 * </ul> 486 * <em>Note:</em> This event is fired only by the system and is not passed to the 487 * view tree to be populated.</br> 488 * </p> 489 * <p> 490 * <b>Touch gesture detection start</b> - represents the event of starting a user 491 * gesture detection.</br> 492 * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_START}</br> 493 * <em>Properties:</em></br> 494 * <ul> 495 * <li>{@link #getEventType()} - The type of the event.</li> 496 * </ul> 497 * <em>Note:</em> This event is fired only by the system and is not passed to the 498 * view tree to be populated.</br> 499 * </p> 500 * <p> 501 * <b>Touch gesture detection end</b> - represents the event of ending a user 502 * gesture detection.</br> 503 * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_END}</br> 504 * <em>Properties:</em></br> 505 * <ul> 506 * <li>{@link #getEventType()} - The type of the event.</li> 507 * </ul> 508 * <em>Note:</em> This event is fired only by the system and is not passed to the 509 * view tree to be populated.</br> 510 * </p> 511 * <p> 512 * <b>MISCELLANEOUS TYPES</b></br> 513 * </p> 514 * <p> 515 * <b>Announcement</b> - represents the event of an application making an 516 * announcement. Usually this announcement is related to some sort of a context 517 * change for which none of the events representing UI transitions is a good fit. 518 * For example, announcing a new page in a book.</br> 519 * <em>Type:</em> {@link #TYPE_ANNOUNCEMENT}</br> 520 * <em>Properties:</em></br> 521 * <ul> 522 * <li>{@link #getEventType()} - The type of the event.</li> 523 * <li>{@link #getSource()} - The source info (for registered clients).</li> 524 * <li>{@link #getClassName()} - The class name of the source.</li> 525 * <li>{@link #getPackageName()} - The package name of the source.</li> 526 * <li>{@link #getEventTime()} - The event time.</li> 527 * <li>{@link #getText()} - The text of the announcement.</li> 528 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 529 * </ul> 530 * </p> 531 * <p> 532 * <b>Security note</b> 533 * <p> 534 * Since an event contains the text of its source privacy can be compromised by leaking 535 * sensitive information such as passwords. To address this issue any event fired in response 536 * to manipulation of a PASSWORD field does NOT CONTAIN the text of the password. 537 * </p> 538 * 539 * @see android.view.accessibility.AccessibilityManager 540 * @see android.accessibilityservice.AccessibilityService 541 * @see AccessibilityNodeInfo 542 */ 543 public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable { 544 private static final boolean DEBUG = false; 545 546 /** 547 * Invalid selection/focus position. 548 * 549 * @see #getCurrentItemIndex() 550 */ 551 public static final int INVALID_POSITION = -1; 552 553 /** 554 * Maximum length of the text fields. 555 * 556 * @see #getBeforeText() 557 * @see #getText() 558 * </br> 559 * Note: This constant is no longer needed since there 560 * is no limit on the length of text that is contained 561 * in an accessibility event anymore. 562 */ 563 @Deprecated 564 public static final int MAX_TEXT_LENGTH = 500; 565 566 /** 567 * Represents the event of clicking on a {@link android.view.View} like 568 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 569 */ 570 public static final int TYPE_VIEW_CLICKED = 0x00000001; 571 572 /** 573 * Represents the event of long clicking on a {@link android.view.View} like 574 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 575 */ 576 public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002; 577 578 /** 579 * Represents the event of selecting an item usually in the context of an 580 * {@link android.widget.AdapterView}. 581 */ 582 public static final int TYPE_VIEW_SELECTED = 0x00000004; 583 584 /** 585 * Represents the event of setting input focus of a {@link android.view.View}. 586 */ 587 public static final int TYPE_VIEW_FOCUSED = 0x00000008; 588 589 /** 590 * Represents the event of changing the text of an {@link android.widget.EditText}. 591 */ 592 public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010; 593 594 /** 595 * Represents the event of opening a {@link android.widget.PopupWindow}, 596 * {@link android.view.Menu}, {@link android.app.Dialog}, etc. 597 */ 598 public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020; 599 600 /** 601 * Represents the event showing a {@link android.app.Notification}. 602 */ 603 public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040; 604 605 /** 606 * Represents the event of a hover enter over a {@link android.view.View}. 607 */ 608 public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080; 609 610 /** 611 * Represents the event of a hover exit over a {@link android.view.View}. 612 */ 613 public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100; 614 615 /** 616 * Represents the event of starting a touch exploration gesture. 617 */ 618 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200; 619 620 /** 621 * Represents the event of ending a touch exploration gesture. 622 */ 623 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400; 624 625 /** 626 * Represents the event of changing the content of a window and more 627 * specifically the sub-tree rooted at the event's source. 628 */ 629 public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800; 630 631 /** 632 * Represents the event of scrolling a view. 633 */ 634 public static final int TYPE_VIEW_SCROLLED = 0x00001000; 635 636 /** 637 * Represents the event of changing the selection in an {@link android.widget.EditText}. 638 */ 639 public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000; 640 641 /** 642 * Represents the event of an application making an announcement. 643 */ 644 public static final int TYPE_ANNOUNCEMENT = 0x00004000; 645 646 /** 647 * Represents the event of gaining accessibility focus. 648 */ 649 public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000; 650 651 /** 652 * Represents the event of clearing accessibility focus. 653 */ 654 public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000; 655 656 /** 657 * Represents the event of traversing the text of a view at a given movement granularity. 658 */ 659 public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000; 660 661 /** 662 * Represents the event of beginning gesture detection. 663 */ 664 public static final int TYPE_GESTURE_DETECTION_START = 0x00040000; 665 666 /** 667 * Represents the event of ending gesture detection. 668 */ 669 public static final int TYPE_GESTURE_DETECTION_END = 0x00080000; 670 671 /** 672 * Represents the event of the user starting to touch the screen. 673 */ 674 public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000; 675 676 /** 677 * Represents the event of the user ending to touch the screen. 678 */ 679 public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000; 680 681 /** 682 * Represents the event change in the windows shown on the screen. 683 */ 684 public static final int TYPE_WINDOWS_CHANGED = 0x00400000; 685 686 /** 687 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 688 * The type of change is not defined. 689 */ 690 public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000; 691 692 /** 693 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 694 * A node in the subtree rooted at the source node was added or removed. 695 */ 696 public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001; 697 698 /** 699 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 700 * The node's text changed. 701 */ 702 public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002; 703 704 /** 705 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 706 * The node's content description changed. 707 */ 708 public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004; 709 710 /** 711 * Mask for {@link AccessibilityEvent} all types. 712 * 713 * @see #TYPE_VIEW_CLICKED 714 * @see #TYPE_VIEW_LONG_CLICKED 715 * @see #TYPE_VIEW_SELECTED 716 * @see #TYPE_VIEW_FOCUSED 717 * @see #TYPE_VIEW_TEXT_CHANGED 718 * @see #TYPE_WINDOW_STATE_CHANGED 719 * @see #TYPE_NOTIFICATION_STATE_CHANGED 720 * @see #TYPE_VIEW_HOVER_ENTER 721 * @see #TYPE_VIEW_HOVER_EXIT 722 * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START 723 * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END 724 * @see #TYPE_WINDOW_CONTENT_CHANGED 725 * @see #TYPE_VIEW_SCROLLED 726 * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED 727 * @see #TYPE_ANNOUNCEMENT 728 * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY 729 * @see #TYPE_GESTURE_DETECTION_START 730 * @see #TYPE_GESTURE_DETECTION_END 731 * @see #TYPE_TOUCH_INTERACTION_START 732 * @see #TYPE_TOUCH_INTERACTION_END 733 * @see #TYPE_WINDOWS_CHANGED 734 */ 735 public static final int TYPES_ALL_MASK = 0xFFFFFFFF; 736 737 private static final int MAX_POOL_SIZE = 10; 738 private static final SynchronizedPool<AccessibilityEvent> sPool = 739 new SynchronizedPool<AccessibilityEvent>(MAX_POOL_SIZE); 740 741 private int mEventType; 742 private CharSequence mPackageName; 743 private long mEventTime; 744 int mMovementGranularity; 745 int mAction; 746 int mContentChangeTypes; 747 748 private ArrayList<AccessibilityRecord> mRecords; 749 750 /* 751 * Hide constructor from clients. 752 */ AccessibilityEvent()753 private AccessibilityEvent() { 754 } 755 756 /** 757 * Initialize an event from another one. 758 * 759 * @param event The event to initialize from. 760 */ init(AccessibilityEvent event)761 void init(AccessibilityEvent event) { 762 super.init(event); 763 mEventType = event.mEventType; 764 mMovementGranularity = event.mMovementGranularity; 765 mAction = event.mAction; 766 mContentChangeTypes = event.mContentChangeTypes; 767 mEventTime = event.mEventTime; 768 mPackageName = event.mPackageName; 769 } 770 771 /** 772 * Sets if this instance is sealed. 773 * 774 * @param sealed Whether is sealed. 775 * 776 * @hide 777 */ 778 @Override setSealed(boolean sealed)779 public void setSealed(boolean sealed) { 780 super.setSealed(sealed); 781 final List<AccessibilityRecord> records = mRecords; 782 if (records != null) { 783 final int recordCount = records.size(); 784 for (int i = 0; i < recordCount; i++) { 785 AccessibilityRecord record = records.get(i); 786 record.setSealed(sealed); 787 } 788 } 789 } 790 791 /** 792 * Gets the number of records contained in the event. 793 * 794 * @return The number of records. 795 */ getRecordCount()796 public int getRecordCount() { 797 return mRecords == null ? 0 : mRecords.size(); 798 } 799 800 /** 801 * Appends an {@link AccessibilityRecord} to the end of event records. 802 * 803 * @param record The record to append. 804 * 805 * @throws IllegalStateException If called from an AccessibilityService. 806 */ appendRecord(AccessibilityRecord record)807 public void appendRecord(AccessibilityRecord record) { 808 enforceNotSealed(); 809 if (mRecords == null) { 810 mRecords = new ArrayList<AccessibilityRecord>(); 811 } 812 mRecords.add(record); 813 } 814 815 /** 816 * Gets the record at a given index. 817 * 818 * @param index The index. 819 * @return The record at the specified index. 820 */ getRecord(int index)821 public AccessibilityRecord getRecord(int index) { 822 if (mRecords == null) { 823 throw new IndexOutOfBoundsException("Invalid index " + index + ", size is 0"); 824 } 825 return mRecords.get(index); 826 } 827 828 /** 829 * Gets the event type. 830 * 831 * @return The event type. 832 */ getEventType()833 public int getEventType() { 834 return mEventType; 835 } 836 837 /** 838 * Gets the bit mask of change types signaled by an 839 * {@link #TYPE_WINDOW_CONTENT_CHANGED} event. A single event may represent 840 * multiple change types. 841 * 842 * @return The bit mask of change types. One or more of: 843 * <ul> 844 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION} 845 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE} 846 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT} 847 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED} 848 * </ul> 849 */ getContentChangeTypes()850 public int getContentChangeTypes() { 851 return mContentChangeTypes; 852 } 853 854 /** 855 * Sets the bit mask of node tree changes signaled by an 856 * {@link #TYPE_WINDOW_CONTENT_CHANGED} event. 857 * 858 * @param changeTypes The bit mask of change types. 859 * @throws IllegalStateException If called from an AccessibilityService. 860 * @see #getContentChangeTypes() 861 */ setContentChangeTypes(int changeTypes)862 public void setContentChangeTypes(int changeTypes) { 863 enforceNotSealed(); 864 mContentChangeTypes = changeTypes; 865 } 866 867 /** 868 * Sets the event type. 869 * 870 * @param eventType The event type. 871 * 872 * @throws IllegalStateException If called from an AccessibilityService. 873 */ setEventType(int eventType)874 public void setEventType(int eventType) { 875 enforceNotSealed(); 876 mEventType = eventType; 877 } 878 879 /** 880 * Gets the time in which this event was sent. 881 * 882 * @return The event time. 883 */ getEventTime()884 public long getEventTime() { 885 return mEventTime; 886 } 887 888 /** 889 * Sets the time in which this event was sent. 890 * 891 * @param eventTime The event time. 892 * 893 * @throws IllegalStateException If called from an AccessibilityService. 894 */ setEventTime(long eventTime)895 public void setEventTime(long eventTime) { 896 enforceNotSealed(); 897 mEventTime = eventTime; 898 } 899 900 /** 901 * Gets the package name of the source. 902 * 903 * @return The package name. 904 */ getPackageName()905 public CharSequence getPackageName() { 906 return mPackageName; 907 } 908 909 /** 910 * Sets the package name of the source. 911 * 912 * @param packageName The package name. 913 * 914 * @throws IllegalStateException If called from an AccessibilityService. 915 */ setPackageName(CharSequence packageName)916 public void setPackageName(CharSequence packageName) { 917 enforceNotSealed(); 918 mPackageName = packageName; 919 } 920 921 /** 922 * Sets the movement granularity that was traversed. 923 * 924 * @param granularity The granularity. 925 * 926 * @throws IllegalStateException If called from an AccessibilityService. 927 */ setMovementGranularity(int granularity)928 public void setMovementGranularity(int granularity) { 929 enforceNotSealed(); 930 mMovementGranularity = granularity; 931 } 932 933 /** 934 * Gets the movement granularity that was traversed. 935 * 936 * @return The granularity. 937 */ getMovementGranularity()938 public int getMovementGranularity() { 939 return mMovementGranularity; 940 } 941 942 /** 943 * Sets the performed action that triggered this event. 944 * <p> 945 * Valid actions are defined in {@link AccessibilityNodeInfo}: 946 * <ul> 947 * <li>{@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS} 948 * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS} 949 * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS} 950 * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION} 951 * <li>{@link AccessibilityNodeInfo#ACTION_CLICK} 952 * <li>etc. 953 * </ul> 954 * 955 * @param action The action. 956 * @throws IllegalStateException If called from an AccessibilityService. 957 * @see AccessibilityNodeInfo#performAction(int) 958 */ setAction(int action)959 public void setAction(int action) { 960 enforceNotSealed(); 961 mAction = action; 962 } 963 964 /** 965 * Gets the performed action that triggered this event. 966 * 967 * @return The action. 968 */ getAction()969 public int getAction() { 970 return mAction; 971 } 972 973 /** 974 * Returns a cached instance if such is available or a new one is 975 * instantiated with its type property set. 976 * 977 * @param eventType The event type. 978 * @return An instance. 979 */ obtain(int eventType)980 public static AccessibilityEvent obtain(int eventType) { 981 AccessibilityEvent event = AccessibilityEvent.obtain(); 982 event.setEventType(eventType); 983 return event; 984 } 985 986 /** 987 * Returns a cached instance if such is available or a new one is 988 * created. The returned instance is initialized from the given 989 * <code>event</code>. 990 * 991 * @param event The other event. 992 * @return An instance. 993 */ obtain(AccessibilityEvent event)994 public static AccessibilityEvent obtain(AccessibilityEvent event) { 995 AccessibilityEvent eventClone = AccessibilityEvent.obtain(); 996 eventClone.init(event); 997 998 if (event.mRecords != null) { 999 final int recordCount = event.mRecords.size(); 1000 eventClone.mRecords = new ArrayList<AccessibilityRecord>(recordCount); 1001 for (int i = 0; i < recordCount; i++) { 1002 final AccessibilityRecord record = event.mRecords.get(i); 1003 final AccessibilityRecord recordClone = AccessibilityRecord.obtain(record); 1004 eventClone.mRecords.add(recordClone); 1005 } 1006 } 1007 1008 return eventClone; 1009 } 1010 1011 /** 1012 * Returns a cached instance if such is available or a new one is 1013 * instantiated. 1014 * 1015 * @return An instance. 1016 */ obtain()1017 public static AccessibilityEvent obtain() { 1018 AccessibilityEvent event = sPool.acquire(); 1019 return (event != null) ? event : new AccessibilityEvent(); 1020 } 1021 1022 /** 1023 * Recycles an instance back to be reused. 1024 * <p> 1025 * <b>Note: You must not touch the object after calling this function.</b> 1026 * </p> 1027 * 1028 * @throws IllegalStateException If the event is already recycled. 1029 */ 1030 @Override recycle()1031 public void recycle() { 1032 clear(); 1033 sPool.release(this); 1034 } 1035 1036 /** 1037 * Clears the state of this instance. 1038 * 1039 * @hide 1040 */ 1041 @Override clear()1042 protected void clear() { 1043 super.clear(); 1044 mEventType = 0; 1045 mMovementGranularity = 0; 1046 mAction = 0; 1047 mContentChangeTypes = 0; 1048 mPackageName = null; 1049 mEventTime = 0; 1050 if (mRecords != null) { 1051 while (!mRecords.isEmpty()) { 1052 AccessibilityRecord record = mRecords.remove(0); 1053 record.recycle(); 1054 } 1055 } 1056 } 1057 1058 /** 1059 * Creates a new instance from a {@link Parcel}. 1060 * 1061 * @param parcel A parcel containing the state of a {@link AccessibilityEvent}. 1062 */ initFromParcel(Parcel parcel)1063 public void initFromParcel(Parcel parcel) { 1064 mSealed = (parcel.readInt() == 1); 1065 mEventType = parcel.readInt(); 1066 mMovementGranularity = parcel.readInt(); 1067 mAction = parcel.readInt(); 1068 mContentChangeTypes = parcel.readInt(); 1069 mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 1070 mEventTime = parcel.readLong(); 1071 mConnectionId = parcel.readInt(); 1072 readAccessibilityRecordFromParcel(this, parcel); 1073 1074 // Read the records. 1075 final int recordCount = parcel.readInt(); 1076 if (recordCount > 0) { 1077 mRecords = new ArrayList<AccessibilityRecord>(recordCount); 1078 for (int i = 0; i < recordCount; i++) { 1079 AccessibilityRecord record = AccessibilityRecord.obtain(); 1080 readAccessibilityRecordFromParcel(record, parcel); 1081 record.mConnectionId = mConnectionId; 1082 mRecords.add(record); 1083 } 1084 } 1085 } 1086 1087 /** 1088 * Reads an {@link AccessibilityRecord} from a parcel. 1089 * 1090 * @param record The record to initialize. 1091 * @param parcel The parcel to read from. 1092 */ readAccessibilityRecordFromParcel(AccessibilityRecord record, Parcel parcel)1093 private void readAccessibilityRecordFromParcel(AccessibilityRecord record, 1094 Parcel parcel) { 1095 record.mBooleanProperties = parcel.readInt(); 1096 record.mCurrentItemIndex = parcel.readInt(); 1097 record.mItemCount = parcel.readInt(); 1098 record.mFromIndex = parcel.readInt(); 1099 record.mToIndex = parcel.readInt(); 1100 record.mScrollX = parcel.readInt(); 1101 record.mScrollY = parcel.readInt(); 1102 record.mMaxScrollX = parcel.readInt(); 1103 record.mMaxScrollY = parcel.readInt(); 1104 record.mAddedCount = parcel.readInt(); 1105 record.mRemovedCount = parcel.readInt(); 1106 record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 1107 record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 1108 record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 1109 record.mParcelableData = parcel.readParcelable(null); 1110 parcel.readList(record.mText, null); 1111 record.mSourceWindowId = parcel.readInt(); 1112 record.mSourceNodeId = parcel.readLong(); 1113 record.mSealed = (parcel.readInt() == 1); 1114 } 1115 1116 /** 1117 * {@inheritDoc} 1118 */ writeToParcel(Parcel parcel, int flags)1119 public void writeToParcel(Parcel parcel, int flags) { 1120 parcel.writeInt(isSealed() ? 1 : 0); 1121 parcel.writeInt(mEventType); 1122 parcel.writeInt(mMovementGranularity); 1123 parcel.writeInt(mAction); 1124 parcel.writeInt(mContentChangeTypes); 1125 TextUtils.writeToParcel(mPackageName, parcel, 0); 1126 parcel.writeLong(mEventTime); 1127 parcel.writeInt(mConnectionId); 1128 writeAccessibilityRecordToParcel(this, parcel, flags); 1129 1130 // Write the records. 1131 final int recordCount = getRecordCount(); 1132 parcel.writeInt(recordCount); 1133 for (int i = 0; i < recordCount; i++) { 1134 AccessibilityRecord record = mRecords.get(i); 1135 writeAccessibilityRecordToParcel(record, parcel, flags); 1136 } 1137 } 1138 1139 /** 1140 * Writes an {@link AccessibilityRecord} to a parcel. 1141 * 1142 * @param record The record to write. 1143 * @param parcel The parcel to which to write. 1144 */ writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel, int flags)1145 private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel, 1146 int flags) { 1147 parcel.writeInt(record.mBooleanProperties); 1148 parcel.writeInt(record.mCurrentItemIndex); 1149 parcel.writeInt(record.mItemCount); 1150 parcel.writeInt(record.mFromIndex); 1151 parcel.writeInt(record.mToIndex); 1152 parcel.writeInt(record.mScrollX); 1153 parcel.writeInt(record.mScrollY); 1154 parcel.writeInt(record.mMaxScrollX); 1155 parcel.writeInt(record.mMaxScrollY); 1156 parcel.writeInt(record.mAddedCount); 1157 parcel.writeInt(record.mRemovedCount); 1158 TextUtils.writeToParcel(record.mClassName, parcel, flags); 1159 TextUtils.writeToParcel(record.mContentDescription, parcel, flags); 1160 TextUtils.writeToParcel(record.mBeforeText, parcel, flags); 1161 parcel.writeParcelable(record.mParcelableData, flags); 1162 parcel.writeList(record.mText); 1163 parcel.writeInt(record.mSourceWindowId); 1164 parcel.writeLong(record.mSourceNodeId); 1165 parcel.writeInt(record.mSealed ? 1 : 0); 1166 } 1167 1168 /** 1169 * {@inheritDoc} 1170 */ describeContents()1171 public int describeContents() { 1172 return 0; 1173 } 1174 1175 @Override toString()1176 public String toString() { 1177 StringBuilder builder = new StringBuilder(); 1178 builder.append("EventType: ").append(eventTypeToString(mEventType)); 1179 builder.append("; EventTime: ").append(mEventTime); 1180 builder.append("; PackageName: ").append(mPackageName); 1181 builder.append("; MovementGranularity: ").append(mMovementGranularity); 1182 builder.append("; Action: ").append(mAction); 1183 builder.append(super.toString()); 1184 if (DEBUG) { 1185 builder.append("\n"); 1186 builder.append("; ContentChangeTypes: ").append(mContentChangeTypes); 1187 builder.append("; sourceWindowId: ").append(mSourceWindowId); 1188 builder.append("; mSourceNodeId: ").append(mSourceNodeId); 1189 for (int i = 0; i < getRecordCount(); i++) { 1190 final AccessibilityRecord record = getRecord(i); 1191 builder.append(" Record "); 1192 builder.append(i); 1193 builder.append(":"); 1194 builder.append(" [ ClassName: " + record.mClassName); 1195 builder.append("; Text: " + record.mText); 1196 builder.append("; ContentDescription: " + record.mContentDescription); 1197 builder.append("; ItemCount: " + record.mItemCount); 1198 builder.append("; CurrentItemIndex: " + record.mCurrentItemIndex); 1199 builder.append("; IsEnabled: " + record.isEnabled()); 1200 builder.append("; IsPassword: " + record.isPassword()); 1201 builder.append("; IsChecked: " + record.isChecked()); 1202 builder.append("; IsFullScreen: " + record.isFullScreen()); 1203 builder.append("; Scrollable: " + record.isScrollable()); 1204 builder.append("; BeforeText: " + record.mBeforeText); 1205 builder.append("; FromIndex: " + record.mFromIndex); 1206 builder.append("; ToIndex: " + record.mToIndex); 1207 builder.append("; ScrollX: " + record.mScrollX); 1208 builder.append("; ScrollY: " + record.mScrollY); 1209 builder.append("; AddedCount: " + record.mAddedCount); 1210 builder.append("; RemovedCount: " + record.mRemovedCount); 1211 builder.append("; ParcelableData: " + record.mParcelableData); 1212 builder.append(" ]"); 1213 builder.append("\n"); 1214 } 1215 } else { 1216 builder.append("; recordCount: ").append(getRecordCount()); 1217 } 1218 return builder.toString(); 1219 } 1220 1221 /** 1222 * Returns the string representation of an event type. For example, 1223 * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED. 1224 * 1225 * @param eventType The event type 1226 * @return The string representation. 1227 */ eventTypeToString(int eventType)1228 public static String eventTypeToString(int eventType) { 1229 if (eventType == TYPES_ALL_MASK) { 1230 return "TYPES_ALL_MASK"; 1231 } 1232 StringBuilder builder = new StringBuilder(); 1233 int eventTypeCount = 0; 1234 while (eventType != 0) { 1235 final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType); 1236 eventType &= ~eventTypeFlag; 1237 switch (eventTypeFlag) { 1238 case TYPE_VIEW_CLICKED: { 1239 if (eventTypeCount > 0) { 1240 builder.append(", "); 1241 } 1242 builder.append("TYPE_VIEW_CLICKED"); 1243 eventTypeCount++; 1244 } break; 1245 case TYPE_VIEW_LONG_CLICKED: { 1246 if (eventTypeCount > 0) { 1247 builder.append(", "); 1248 } 1249 builder.append("TYPE_VIEW_LONG_CLICKED"); 1250 eventTypeCount++; 1251 } break; 1252 case TYPE_VIEW_SELECTED: { 1253 if (eventTypeCount > 0) { 1254 builder.append(", "); 1255 } 1256 builder.append("TYPE_VIEW_SELECTED"); 1257 eventTypeCount++; 1258 } break; 1259 case TYPE_VIEW_FOCUSED: { 1260 if (eventTypeCount > 0) { 1261 builder.append(", "); 1262 } 1263 builder.append("TYPE_VIEW_FOCUSED"); 1264 eventTypeCount++; 1265 } break; 1266 case TYPE_VIEW_TEXT_CHANGED: { 1267 if (eventTypeCount > 0) { 1268 builder.append(", "); 1269 } 1270 builder.append("TYPE_VIEW_TEXT_CHANGED"); 1271 eventTypeCount++; 1272 } break; 1273 case TYPE_WINDOW_STATE_CHANGED: { 1274 if (eventTypeCount > 0) { 1275 builder.append(", "); 1276 } 1277 builder.append("TYPE_WINDOW_STATE_CHANGED"); 1278 eventTypeCount++; 1279 } break; 1280 case TYPE_VIEW_HOVER_ENTER: { 1281 if (eventTypeCount > 0) { 1282 builder.append(", "); 1283 } 1284 builder.append("TYPE_VIEW_HOVER_ENTER"); 1285 eventTypeCount++; 1286 } break; 1287 case TYPE_VIEW_HOVER_EXIT: { 1288 if (eventTypeCount > 0) { 1289 builder.append(", "); 1290 } 1291 builder.append("TYPE_VIEW_HOVER_EXIT"); 1292 eventTypeCount++; 1293 } break; 1294 case TYPE_NOTIFICATION_STATE_CHANGED: { 1295 if (eventTypeCount > 0) { 1296 builder.append(", "); 1297 } 1298 builder.append("TYPE_NOTIFICATION_STATE_CHANGED"); 1299 eventTypeCount++; 1300 } break; 1301 case TYPE_TOUCH_EXPLORATION_GESTURE_START: { 1302 if (eventTypeCount > 0) { 1303 builder.append(", "); 1304 } 1305 builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_START"); 1306 eventTypeCount++; 1307 } break; 1308 case TYPE_TOUCH_EXPLORATION_GESTURE_END: { 1309 if (eventTypeCount > 0) { 1310 builder.append(", "); 1311 } 1312 builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_END"); 1313 eventTypeCount++; 1314 } break; 1315 case TYPE_WINDOW_CONTENT_CHANGED: { 1316 if (eventTypeCount > 0) { 1317 builder.append(", "); 1318 } 1319 builder.append("TYPE_WINDOW_CONTENT_CHANGED"); 1320 eventTypeCount++; 1321 } break; 1322 case TYPE_VIEW_TEXT_SELECTION_CHANGED: { 1323 if (eventTypeCount > 0) { 1324 builder.append(", "); 1325 } 1326 builder.append("TYPE_VIEW_TEXT_SELECTION_CHANGED"); 1327 eventTypeCount++; 1328 } break; 1329 case TYPE_VIEW_SCROLLED: { 1330 if (eventTypeCount > 0) { 1331 builder.append(", "); 1332 } 1333 builder.append("TYPE_VIEW_SCROLLED"); 1334 eventTypeCount++; 1335 } break; 1336 case TYPE_ANNOUNCEMENT: { 1337 if (eventTypeCount > 0) { 1338 builder.append(", "); 1339 } 1340 builder.append("TYPE_ANNOUNCEMENT"); 1341 eventTypeCount++; 1342 } break; 1343 case TYPE_VIEW_ACCESSIBILITY_FOCUSED: { 1344 if (eventTypeCount > 0) { 1345 builder.append(", "); 1346 } 1347 builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUSED"); 1348 eventTypeCount++; 1349 } break; 1350 case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: { 1351 if (eventTypeCount > 0) { 1352 builder.append(", "); 1353 } 1354 builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED"); 1355 eventTypeCount++; 1356 } break; 1357 case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: { 1358 if (eventTypeCount > 0) { 1359 builder.append(", "); 1360 } 1361 builder.append("TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY"); 1362 eventTypeCount++; 1363 } break; 1364 case TYPE_GESTURE_DETECTION_START: { 1365 if (eventTypeCount > 0) { 1366 builder.append(", "); 1367 } 1368 builder.append("TYPE_GESTURE_DETECTION_START"); 1369 eventTypeCount++; 1370 } break; 1371 case TYPE_GESTURE_DETECTION_END: { 1372 if (eventTypeCount > 0) { 1373 builder.append(", "); 1374 } 1375 builder.append("TYPE_GESTURE_DETECTION_END"); 1376 eventTypeCount++; 1377 } break; 1378 case TYPE_TOUCH_INTERACTION_START: { 1379 if (eventTypeCount > 0) { 1380 builder.append(", "); 1381 } 1382 builder.append("TYPE_TOUCH_INTERACTION_START"); 1383 eventTypeCount++; 1384 } break; 1385 case TYPE_TOUCH_INTERACTION_END: { 1386 if (eventTypeCount > 0) { 1387 builder.append(", "); 1388 } 1389 builder.append("TYPE_TOUCH_INTERACTION_END"); 1390 eventTypeCount++; 1391 } break; 1392 case TYPE_WINDOWS_CHANGED: { 1393 if (eventTypeCount > 0) { 1394 builder.append(", "); 1395 } 1396 builder.append("TYPE_WINDOWS_CHANGED"); 1397 eventTypeCount++; 1398 } break; 1399 } 1400 } 1401 if (eventTypeCount > 1) { 1402 builder.insert(0, '['); 1403 builder.append(']'); 1404 } 1405 return builder.toString(); 1406 } 1407 1408 /** 1409 * @see Parcelable.Creator 1410 */ 1411 public static final Parcelable.Creator<AccessibilityEvent> CREATOR = 1412 new Parcelable.Creator<AccessibilityEvent>() { 1413 public AccessibilityEvent createFromParcel(Parcel parcel) { 1414 AccessibilityEvent event = AccessibilityEvent.obtain(); 1415 event.initFromParcel(parcel); 1416 return event; 1417 } 1418 1419 public AccessibilityEvent[] newArray(int size) { 1420 return new AccessibilityEvent[size]; 1421 } 1422 }; 1423 } 1424