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 the text that was skipped over in this movement. 244 * This is the starting point when moving forward through the text, but not when moving 245 * back.</li> 246 * <li>{@link #getToIndex()} - The end of the text that was skipped over in this movement. 247 * This is the ending point when moving forward through the text, but not when moving 248 * back.</li> 249 * <li>{@link #isPassword()} - Whether the source is password.</li> 250 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 251 * <li>{@link #getContentDescription()} - The content description of the source.</li> 252 * <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text 253 * was traversed.</li> 254 * <li>{@link #getAction()} - Gets traversal action which specifies the direction.</li> 255 * </ul> 256 * </p> 257 * <p> 258 * <b>View scrolled</b> - represents the event of scrolling a view. If 259 * the source is a descendant of {@link android.widget.AdapterView} the 260 * scroll is reported in terms of visible items - the first visible item, 261 * the last visible item, and the total items - because the the source 262 * is unaware of its pixel size since its adapter is responsible for 263 * creating views. In all other cases the scroll is reported as the current 264 * scroll on the X and Y axis respectively plus the height of the source in 265 * pixels.</br> 266 * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br> 267 * <em>Properties:</em></br> 268 * <ul> 269 * <li>{@link #getEventType()} - The type of the event.</li> 270 * <li>{@link #getSource()} - The source info (for registered clients).</li> 271 * <li>{@link #getClassName()} - The class name of the source.</li> 272 * <li>{@link #getPackageName()} - The package name of the source.</li> 273 * <li>{@link #getEventTime()} - The event time.</li> 274 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 275 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 276 * <li>{@link #getContentDescription()} - The content description of the source.</li> 277 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 278 * (without descendants of AdapterView).</li> 279 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 280 * (without descendants of AdapterView).</li> 281 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 282 * inclusive (for descendants of AdapterView).</li> 283 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 284 * inclusive (for descendants of AdapterView).</li> 285 * <li>{@link #getItemCount()} - The total items of the source 286 * (for descendants of AdapterView).</li> 287 * </ul> 288 * <em>Note:</em> This event type is not dispatched to descendants though 289 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 290 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 291 * source {@link android.view.View} and the sub-tree rooted at it will not receive 292 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 293 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 294 * text content to such events is by setting the 295 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 296 * view.</br> 297 * </p> 298 * <p> 299 * <b>TRANSITION TYPES</b></br> 300 * </p> 301 * <p> 302 * <b>Window state changed</b> - represents the event of opening a 303 * {@link android.widget.PopupWindow}, {@link android.view.Menu}, 304 * {@link android.app.Dialog}, etc.</br> 305 * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br> 306 * <em>Properties:</em></br> 307 * <ul> 308 * <li>{@link #getEventType()} - The type of the event.</li> 309 * <li>{@link #getSource()} - The source info (for registered clients).</li> 310 * <li>{@link #getClassName()} - The class name of the source.</li> 311 * <li>{@link #getPackageName()} - The package name of the source.</li> 312 * <li>{@link #getEventTime()} - The event time.</li> 313 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 314 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 315 * </ul> 316 * </p> 317 * <p> 318 * <b>Window content changed</b> - represents the event of change in the 319 * content of a window. This change can be adding/removing view, changing 320 * a view size, etc.</br> 321 * </p> 322 * <p> 323 * <strong>Note:</strong> This event is fired only for the window source of the 324 * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED} 325 * and its purpose is to notify clients that the content of the user interaction 326 * window has changed.</br> 327 * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br> 328 * <em>Properties:</em></br> 329 * <ul> 330 * <li>{@link #getEventType()} - The type of the event.</li> 331 * <li>{@link #getContentChangeTypes()} - The type of content changes.</li> 332 * <li>{@link #getSource()} - The source info (for registered clients).</li> 333 * <li>{@link #getClassName()} - The class name of the source.</li> 334 * <li>{@link #getPackageName()} - The package name of the source.</li> 335 * <li>{@link #getEventTime()} - The event time.</li> 336 * </ul> 337 * <em>Note:</em> This event type is not dispatched to descendants though 338 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 339 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 340 * source {@link android.view.View} and the sub-tree rooted at it will not receive 341 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 342 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 343 * text content to such events is by setting the 344 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 345 * view.</br> 346 * </p> 347 * <p> 348 * <b>Windows changed</b> - represents the event of changes in the windows shown on 349 * the screen such as a window appeared, a window disappeared, a window size changed, 350 * a window layer changed, etc.</br> 351 * <em>Type:</em> {@link #TYPE_WINDOWS_CHANGED}</br> 352 * <em>Properties:</em></br> 353 * <ul> 354 * <li>{@link #getEventType()} - The type of the event.</li> 355 * <li>{@link #getEventTime()} - The event time.</li> 356 * </ul> 357 * <em>Note:</em> You can retrieve the {@link AccessibilityWindowInfo} for the window 358 * source of the event via {@link AccessibilityEvent#getSource()} to get the source 359 * node on which then call {@link AccessibilityNodeInfo#getWindow() 360 * AccessibilityNodeInfo.getWindow()} to get the window. Also all windows on the screen can 361 * be retrieved by a call to {@link android.accessibilityservice.AccessibilityService#getWindows() 362 * android.accessibilityservice.AccessibilityService.getWindows()}. 363 * </p> 364 * <p> 365 * <b>NOTIFICATION TYPES</b></br> 366 * </p> 367 * <p> 368 * <b>Notification state changed</b> - represents the event showing a transient piece of information 369 * to the user. This information may be a {@link android.app.Notification} or 370 * {@link android.widget.Toast}.</br> 371 * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br> 372 * <em>Properties:</em></br> 373 * <ul> 374 * <li>{@link #getEventType()} - The type of the event.</li> 375 * <li>{@link #getClassName()} - The class name of the source.</li> 376 * <li>{@link #getPackageName()} - The package name of the source.</li> 377 * <li>{@link #getEventTime()} - The event time.</li> 378 * <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}, if 379 * applicable.</li> 380 * <li>{@link #getText()} - Displayed text of the {@link android.widget.Toast}, if applicable, 381 * or may contain text from the {@link android.app.Notification}, although 382 * {@link #getParcelableData()} is a richer set of data for {@link android.app.Notification}.</li> 383 * </ul> 384 * </p> 385 * <p> 386 * <b>EXPLORATION TYPES</b></br> 387 * </p> 388 * <p> 389 * <b>View hover enter</b> - represents the event of beginning to hover 390 * over a {@link android.view.View}. The hover may be generated via 391 * exploring the screen by touch or via a pointing device.</br> 392 * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br> 393 * <em>Properties:</em></br> 394 * <ul> 395 * <li>{@link #getEventType()} - The type of the event.</li> 396 * <li>{@link #getSource()} - The source info (for registered clients).</li> 397 * <li>{@link #getClassName()} - The class name of the source.</li> 398 * <li>{@link #getPackageName()} - The package name of the source.</li> 399 * <li>{@link #getEventTime()} - The event time.</li> 400 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 401 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 402 * <li>{@link #getContentDescription()} - The content description of the source.</li> 403 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 404 * (without descendants of AdapterView).</li> 405 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 406 * (without descendants of AdapterView).</li> 407 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 408 * inclusive (for descendants of AdapterView).</li> 409 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 410 * inclusive (for descendants of AdapterView).</li> 411 * <li>{@link #getItemCount()} - The total items of the source 412 * (for descendants of AdapterView).</li> 413 * </ul> 414 * </p> 415 * <b>View hover exit</b> - represents the event of stopping to hover 416 * over a {@link android.view.View}. The hover may be generated via 417 * exploring the screen by touch or via a pointing device.</br> 418 * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br> 419 * <em>Properties:</em></br> 420 * <ul> 421 * <li>{@link #getEventType()} - The type of the event.</li> 422 * <li>{@link #getSource()} - The source info (for registered clients).</li> 423 * <li>{@link #getClassName()} - The class name of the source.</li> 424 * <li>{@link #getPackageName()} - The package name of the source.</li> 425 * <li>{@link #getEventTime()} - The event time.</li> 426 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 427 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 428 * <li>{@link #getContentDescription()} - The content description of the source.</li> 429 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 430 * (without descendants of AdapterView).</li> 431 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 432 * (without descendants of AdapterView).</li> 433 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 434 * inclusive (for descendants of AdapterView).</li> 435 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 436 * inclusive (for descendants of AdapterView).</li> 437 * <li>{@link #getItemCount()} - The total items of the source 438 * (for descendants of AdapterView).</li> 439 * </ul> 440 * </p> 441 * <p> 442 * <b>Touch interaction start</b> - represents the event of starting a touch 443 * interaction, which is the user starts touching the screen.</br> 444 * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_START}</br> 445 * <em>Properties:</em></br> 446 * <ul> 447 * <li>{@link #getEventType()} - The type of the event.</li> 448 * </ul> 449 * <em>Note:</em> This event is fired only by the system and is not passed to the 450 * view tree to be populated.</br> 451 * </p> 452 * <p> 453 * <b>Touch interaction end</b> - represents the event of ending a touch 454 * interaction, which is the user stops touching the screen.</br> 455 * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_END}</br> 456 * <em>Properties:</em></br> 457 * <ul> 458 * <li>{@link #getEventType()} - The type of the event.</li> 459 * </ul> 460 * <em>Note:</em> This event is fired only by the system and is not passed to the 461 * view tree to be populated.</br> 462 * </p> 463 * <p> 464 * <b>Touch exploration gesture start</b> - represents the event of starting a touch 465 * exploring gesture.</br> 466 * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br> 467 * <em>Properties:</em></br> 468 * <ul> 469 * <li>{@link #getEventType()} - The type of the event.</li> 470 * </ul> 471 * <em>Note:</em> This event is fired only by the system and is not passed to the 472 * view tree to be populated.</br> 473 * </p> 474 * <p> 475 * <b>Touch exploration gesture end</b> - represents the event of ending a touch 476 * exploring gesture.</br> 477 * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br> 478 * <em>Properties:</em></br> 479 * <ul> 480 * <li>{@link #getEventType()} - The type of the event.</li> 481 * </ul> 482 * <em>Note:</em> This event is fired only by the system and is not passed to the 483 * view tree to be populated.</br> 484 * </p> 485 * <p> 486 * <b>Touch gesture detection start</b> - represents the event of starting a user 487 * gesture detection.</br> 488 * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_START}</br> 489 * <em>Properties:</em></br> 490 * <ul> 491 * <li>{@link #getEventType()} - The type of the event.</li> 492 * </ul> 493 * <em>Note:</em> This event is fired only by the system and is not passed to the 494 * view tree to be populated.</br> 495 * </p> 496 * <p> 497 * <b>Touch gesture detection end</b> - represents the event of ending a user 498 * gesture detection.</br> 499 * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_END}</br> 500 * <em>Properties:</em></br> 501 * <ul> 502 * <li>{@link #getEventType()} - The type of the event.</li> 503 * </ul> 504 * <em>Note:</em> This event is fired only by the system and is not passed to the 505 * view tree to be populated.</br> 506 * </p> 507 * <p> 508 * <b>MISCELLANEOUS TYPES</b></br> 509 * </p> 510 * <p> 511 * <b>Announcement</b> - represents the event of an application making an 512 * announcement. Usually this announcement is related to some sort of a context 513 * change for which none of the events representing UI transitions is a good fit. 514 * For example, announcing a new page in a book.</br> 515 * <em>Type:</em> {@link #TYPE_ANNOUNCEMENT}</br> 516 * <em>Properties:</em></br> 517 * <ul> 518 * <li>{@link #getEventType()} - The type of the event.</li> 519 * <li>{@link #getSource()} - The source info (for registered clients).</li> 520 * <li>{@link #getClassName()} - The class name of the source.</li> 521 * <li>{@link #getPackageName()} - The package name of the source.</li> 522 * <li>{@link #getEventTime()} - The event time.</li> 523 * <li>{@link #getText()} - The text of the announcement.</li> 524 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 525 * </ul> 526 * </p> 527 * 528 * @see android.view.accessibility.AccessibilityManager 529 * @see android.accessibilityservice.AccessibilityService 530 * @see AccessibilityNodeInfo 531 */ 532 public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable { 533 private static final boolean DEBUG = false; 534 535 /** 536 * Invalid selection/focus position. 537 * 538 * @see #getCurrentItemIndex() 539 */ 540 public static final int INVALID_POSITION = -1; 541 542 /** 543 * Maximum length of the text fields. 544 * 545 * @see #getBeforeText() 546 * @see #getText() 547 * </br> 548 * Note: This constant is no longer needed since there 549 * is no limit on the length of text that is contained 550 * in an accessibility event anymore. 551 */ 552 @Deprecated 553 public static final int MAX_TEXT_LENGTH = 500; 554 555 /** 556 * Represents the event of clicking on a {@link android.view.View} like 557 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 558 */ 559 public static final int TYPE_VIEW_CLICKED = 0x00000001; 560 561 /** 562 * Represents the event of long clicking on a {@link android.view.View} like 563 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 564 */ 565 public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002; 566 567 /** 568 * Represents the event of selecting an item usually in the context of an 569 * {@link android.widget.AdapterView}. 570 */ 571 public static final int TYPE_VIEW_SELECTED = 0x00000004; 572 573 /** 574 * Represents the event of setting input focus of a {@link android.view.View}. 575 */ 576 public static final int TYPE_VIEW_FOCUSED = 0x00000008; 577 578 /** 579 * Represents the event of changing the text of an {@link android.widget.EditText}. 580 */ 581 public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010; 582 583 /** 584 * Represents the event of opening a {@link android.widget.PopupWindow}, 585 * {@link android.view.Menu}, {@link android.app.Dialog}, etc. 586 */ 587 public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020; 588 589 /** 590 * Represents the event showing a {@link android.app.Notification}. 591 */ 592 public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040; 593 594 /** 595 * Represents the event of a hover enter over a {@link android.view.View}. 596 */ 597 public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080; 598 599 /** 600 * Represents the event of a hover exit over a {@link android.view.View}. 601 */ 602 public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100; 603 604 /** 605 * Represents the event of starting a touch exploration gesture. 606 */ 607 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200; 608 609 /** 610 * Represents the event of ending a touch exploration gesture. 611 */ 612 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400; 613 614 /** 615 * Represents the event of changing the content of a window and more 616 * specifically the sub-tree rooted at the event's source. 617 */ 618 public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800; 619 620 /** 621 * Represents the event of scrolling a view. 622 */ 623 public static final int TYPE_VIEW_SCROLLED = 0x00001000; 624 625 /** 626 * Represents the event of changing the selection in an {@link android.widget.EditText}. 627 */ 628 public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000; 629 630 /** 631 * Represents the event of an application making an announcement. 632 */ 633 public static final int TYPE_ANNOUNCEMENT = 0x00004000; 634 635 /** 636 * Represents the event of gaining accessibility focus. 637 */ 638 public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000; 639 640 /** 641 * Represents the event of clearing accessibility focus. 642 */ 643 public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000; 644 645 /** 646 * Represents the event of traversing the text of a view at a given movement granularity. 647 */ 648 public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000; 649 650 /** 651 * Represents the event of beginning gesture detection. 652 */ 653 public static final int TYPE_GESTURE_DETECTION_START = 0x00040000; 654 655 /** 656 * Represents the event of ending gesture detection. 657 */ 658 public static final int TYPE_GESTURE_DETECTION_END = 0x00080000; 659 660 /** 661 * Represents the event of the user starting to touch the screen. 662 */ 663 public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000; 664 665 /** 666 * Represents the event of the user ending to touch the screen. 667 */ 668 public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000; 669 670 /** 671 * Represents the event change in the windows shown on the screen. 672 */ 673 public static final int TYPE_WINDOWS_CHANGED = 0x00400000; 674 675 /** 676 * Represents the event of a context click on a {@link android.view.View}. 677 */ 678 public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000; 679 680 /** 681 * Represents the event of the assistant currently reading the users screen context. 682 */ 683 public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000; 684 685 /** 686 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 687 * The type of change is not defined. 688 */ 689 public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000; 690 691 /** 692 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 693 * A node in the subtree rooted at the source node was added or removed. 694 */ 695 public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001; 696 697 /** 698 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 699 * The node's text changed. 700 */ 701 public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002; 702 703 /** 704 * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 705 * The node's content description changed. 706 */ 707 public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004; 708 709 /** 710 * Mask for {@link AccessibilityEvent} all types. 711 * 712 * @see #TYPE_VIEW_CLICKED 713 * @see #TYPE_VIEW_LONG_CLICKED 714 * @see #TYPE_VIEW_SELECTED 715 * @see #TYPE_VIEW_FOCUSED 716 * @see #TYPE_VIEW_TEXT_CHANGED 717 * @see #TYPE_WINDOW_STATE_CHANGED 718 * @see #TYPE_NOTIFICATION_STATE_CHANGED 719 * @see #TYPE_VIEW_HOVER_ENTER 720 * @see #TYPE_VIEW_HOVER_EXIT 721 * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START 722 * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END 723 * @see #TYPE_WINDOW_CONTENT_CHANGED 724 * @see #TYPE_VIEW_SCROLLED 725 * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED 726 * @see #TYPE_ANNOUNCEMENT 727 * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY 728 * @see #TYPE_GESTURE_DETECTION_START 729 * @see #TYPE_GESTURE_DETECTION_END 730 * @see #TYPE_TOUCH_INTERACTION_START 731 * @see #TYPE_TOUCH_INTERACTION_END 732 * @see #TYPE_WINDOWS_CHANGED 733 * @see #TYPE_VIEW_CONTEXT_CLICKED 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.mSourceNode = parcel.readParcelable(null); 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 // create copy of the node here because the node would be recycled just after it is written 1165 // to parcel 1166 parcel.writeParcelable(record.mSourceNode != null ? 1167 AccessibilityNodeInfo.obtain(record.mSourceNode) : null, flags); 1168 parcel.writeInt(record.mSealed ? 1 : 0); 1169 } 1170 1171 /** 1172 * {@inheritDoc} 1173 */ describeContents()1174 public int describeContents() { 1175 return 0; 1176 } 1177 1178 @Override toString()1179 public String toString() { 1180 StringBuilder builder = new StringBuilder(); 1181 builder.append("EventType: ").append(eventTypeToString(mEventType)); 1182 builder.append("; EventTime: ").append(mEventTime); 1183 builder.append("; PackageName: ").append(mPackageName); 1184 builder.append("; MovementGranularity: ").append(mMovementGranularity); 1185 builder.append("; Action: ").append(mAction); 1186 builder.append(super.toString()); 1187 if (DEBUG) { 1188 builder.append("\n"); 1189 builder.append("; ContentChangeTypes: ").append(mContentChangeTypes); 1190 builder.append("; sourceWindowId: ").append(mSourceWindowId); 1191 if (mSourceNode != null) { 1192 builder.append("; mSourceNodeId: ").append(mSourceNode.getSourceNodeId()); 1193 } 1194 for (int i = 0; i < getRecordCount(); i++) { 1195 final AccessibilityRecord record = getRecord(i); 1196 builder.append(" Record "); 1197 builder.append(i); 1198 builder.append(":"); 1199 builder.append(" [ ClassName: " + record.mClassName); 1200 builder.append("; Text: " + record.mText); 1201 builder.append("; ContentDescription: " + record.mContentDescription); 1202 builder.append("; ItemCount: " + record.mItemCount); 1203 builder.append("; CurrentItemIndex: " + record.mCurrentItemIndex); 1204 builder.append("; IsEnabled: " + record.isEnabled()); 1205 builder.append("; IsPassword: " + record.isPassword()); 1206 builder.append("; IsChecked: " + record.isChecked()); 1207 builder.append("; IsFullScreen: " + record.isFullScreen()); 1208 builder.append("; Scrollable: " + record.isScrollable()); 1209 builder.append("; BeforeText: " + record.mBeforeText); 1210 builder.append("; FromIndex: " + record.mFromIndex); 1211 builder.append("; ToIndex: " + record.mToIndex); 1212 builder.append("; ScrollX: " + record.mScrollX); 1213 builder.append("; ScrollY: " + record.mScrollY); 1214 builder.append("; AddedCount: " + record.mAddedCount); 1215 builder.append("; RemovedCount: " + record.mRemovedCount); 1216 builder.append("; ParcelableData: " + record.mParcelableData); 1217 builder.append(" ]"); 1218 builder.append("\n"); 1219 } 1220 } else { 1221 builder.append("; recordCount: ").append(getRecordCount()); 1222 } 1223 return builder.toString(); 1224 } 1225 1226 /** 1227 * Returns the string representation of an event type. For example, 1228 * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED. 1229 * 1230 * @param eventType The event type 1231 * @return The string representation. 1232 */ eventTypeToString(int eventType)1233 public static String eventTypeToString(int eventType) { 1234 if (eventType == TYPES_ALL_MASK) { 1235 return "TYPES_ALL_MASK"; 1236 } 1237 StringBuilder builder = new StringBuilder(); 1238 int eventTypeCount = 0; 1239 while (eventType != 0) { 1240 final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType); 1241 eventType &= ~eventTypeFlag; 1242 switch (eventTypeFlag) { 1243 case TYPE_VIEW_CLICKED: { 1244 if (eventTypeCount > 0) { 1245 builder.append(", "); 1246 } 1247 builder.append("TYPE_VIEW_CLICKED"); 1248 eventTypeCount++; 1249 } break; 1250 case TYPE_VIEW_LONG_CLICKED: { 1251 if (eventTypeCount > 0) { 1252 builder.append(", "); 1253 } 1254 builder.append("TYPE_VIEW_LONG_CLICKED"); 1255 eventTypeCount++; 1256 } break; 1257 case TYPE_VIEW_SELECTED: { 1258 if (eventTypeCount > 0) { 1259 builder.append(", "); 1260 } 1261 builder.append("TYPE_VIEW_SELECTED"); 1262 eventTypeCount++; 1263 } break; 1264 case TYPE_VIEW_FOCUSED: { 1265 if (eventTypeCount > 0) { 1266 builder.append(", "); 1267 } 1268 builder.append("TYPE_VIEW_FOCUSED"); 1269 eventTypeCount++; 1270 } break; 1271 case TYPE_VIEW_TEXT_CHANGED: { 1272 if (eventTypeCount > 0) { 1273 builder.append(", "); 1274 } 1275 builder.append("TYPE_VIEW_TEXT_CHANGED"); 1276 eventTypeCount++; 1277 } break; 1278 case TYPE_WINDOW_STATE_CHANGED: { 1279 if (eventTypeCount > 0) { 1280 builder.append(", "); 1281 } 1282 builder.append("TYPE_WINDOW_STATE_CHANGED"); 1283 eventTypeCount++; 1284 } break; 1285 case TYPE_VIEW_HOVER_ENTER: { 1286 if (eventTypeCount > 0) { 1287 builder.append(", "); 1288 } 1289 builder.append("TYPE_VIEW_HOVER_ENTER"); 1290 eventTypeCount++; 1291 } break; 1292 case TYPE_VIEW_HOVER_EXIT: { 1293 if (eventTypeCount > 0) { 1294 builder.append(", "); 1295 } 1296 builder.append("TYPE_VIEW_HOVER_EXIT"); 1297 eventTypeCount++; 1298 } break; 1299 case TYPE_NOTIFICATION_STATE_CHANGED: { 1300 if (eventTypeCount > 0) { 1301 builder.append(", "); 1302 } 1303 builder.append("TYPE_NOTIFICATION_STATE_CHANGED"); 1304 eventTypeCount++; 1305 } break; 1306 case TYPE_TOUCH_EXPLORATION_GESTURE_START: { 1307 if (eventTypeCount > 0) { 1308 builder.append(", "); 1309 } 1310 builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_START"); 1311 eventTypeCount++; 1312 } break; 1313 case TYPE_TOUCH_EXPLORATION_GESTURE_END: { 1314 if (eventTypeCount > 0) { 1315 builder.append(", "); 1316 } 1317 builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_END"); 1318 eventTypeCount++; 1319 } break; 1320 case TYPE_WINDOW_CONTENT_CHANGED: { 1321 if (eventTypeCount > 0) { 1322 builder.append(", "); 1323 } 1324 builder.append("TYPE_WINDOW_CONTENT_CHANGED"); 1325 eventTypeCount++; 1326 } break; 1327 case TYPE_VIEW_TEXT_SELECTION_CHANGED: { 1328 if (eventTypeCount > 0) { 1329 builder.append(", "); 1330 } 1331 builder.append("TYPE_VIEW_TEXT_SELECTION_CHANGED"); 1332 eventTypeCount++; 1333 } break; 1334 case TYPE_VIEW_SCROLLED: { 1335 if (eventTypeCount > 0) { 1336 builder.append(", "); 1337 } 1338 builder.append("TYPE_VIEW_SCROLLED"); 1339 eventTypeCount++; 1340 } break; 1341 case TYPE_ANNOUNCEMENT: { 1342 if (eventTypeCount > 0) { 1343 builder.append(", "); 1344 } 1345 builder.append("TYPE_ANNOUNCEMENT"); 1346 eventTypeCount++; 1347 } break; 1348 case TYPE_VIEW_ACCESSIBILITY_FOCUSED: { 1349 if (eventTypeCount > 0) { 1350 builder.append(", "); 1351 } 1352 builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUSED"); 1353 eventTypeCount++; 1354 } break; 1355 case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: { 1356 if (eventTypeCount > 0) { 1357 builder.append(", "); 1358 } 1359 builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED"); 1360 eventTypeCount++; 1361 } break; 1362 case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: { 1363 if (eventTypeCount > 0) { 1364 builder.append(", "); 1365 } 1366 builder.append("TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY"); 1367 eventTypeCount++; 1368 } break; 1369 case TYPE_GESTURE_DETECTION_START: { 1370 if (eventTypeCount > 0) { 1371 builder.append(", "); 1372 } 1373 builder.append("TYPE_GESTURE_DETECTION_START"); 1374 eventTypeCount++; 1375 } break; 1376 case TYPE_GESTURE_DETECTION_END: { 1377 if (eventTypeCount > 0) { 1378 builder.append(", "); 1379 } 1380 builder.append("TYPE_GESTURE_DETECTION_END"); 1381 eventTypeCount++; 1382 } break; 1383 case TYPE_TOUCH_INTERACTION_START: { 1384 if (eventTypeCount > 0) { 1385 builder.append(", "); 1386 } 1387 builder.append("TYPE_TOUCH_INTERACTION_START"); 1388 eventTypeCount++; 1389 } break; 1390 case TYPE_TOUCH_INTERACTION_END: { 1391 if (eventTypeCount > 0) { 1392 builder.append(", "); 1393 } 1394 builder.append("TYPE_TOUCH_INTERACTION_END"); 1395 eventTypeCount++; 1396 } break; 1397 case TYPE_WINDOWS_CHANGED: { 1398 if (eventTypeCount > 0) { 1399 builder.append(", "); 1400 } 1401 builder.append("TYPE_WINDOWS_CHANGED"); 1402 eventTypeCount++; 1403 } break; 1404 case TYPE_VIEW_CONTEXT_CLICKED: { 1405 if (eventTypeCount > 0) { 1406 builder.append(", "); 1407 } 1408 builder.append("TYPE_VIEW_CONTEXT_CLICKED"); 1409 eventTypeCount++; 1410 } break; 1411 case TYPE_ASSIST_READING_CONTEXT: { 1412 if (eventTypeCount > 0) { 1413 builder.append(", "); 1414 } 1415 builder.append("TYPE_ASSIST_READING_CONTEXT"); 1416 eventTypeCount++; 1417 } break; 1418 } 1419 } 1420 if (eventTypeCount > 1) { 1421 builder.insert(0, '['); 1422 builder.append(']'); 1423 } 1424 return builder.toString(); 1425 } 1426 1427 /** 1428 * @see Parcelable.Creator 1429 */ 1430 public static final Parcelable.Creator<AccessibilityEvent> CREATOR = 1431 new Parcelable.Creator<AccessibilityEvent>() { 1432 public AccessibilityEvent createFromParcel(Parcel parcel) { 1433 AccessibilityEvent event = AccessibilityEvent.obtain(); 1434 event.initFromParcel(parcel); 1435 return event; 1436 } 1437 1438 public AccessibilityEvent[] newArray(int size) { 1439 return new AccessibilityEvent[size]; 1440 } 1441 }; 1442 } 1443