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