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