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