AccessibilityEvent.java revision a20cdc06e599c6fef784a0a479e8329f95e4bd09
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.accessibilityservice.IAccessibilityServiceConnection; 20import android.os.Parcel; 21import android.os.Parcelable; 22import android.text.TextUtils; 23 24import java.util.ArrayList; 25import java.util.List; 26 27/** 28 * This class represents accessibility events that are sent by the system when 29 * something notable happens in the user interface. For example, when a 30 * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc. 31 * <p> 32 * An accessibility event is fired by an individual view which populates the event with 33 * a record for its state and requests from its parent to send the event to interested 34 * parties. The parent can optionally add a record for itself before dispatching a similar 35 * request to its parent. A parent can also choose not to respect the request for sending 36 * an event. The accessibility event is sent by the topmost view in the view tree. 37 * Therefore, an {@link android.accessibilityservice.AccessibilityService} can explore 38 * all records in an accessibility event to obtain more information about the context 39 * in which the event was fired. 40 * <p> 41 * A client can add, remove, and modify records. The getters and setters for individual 42 * properties operate on the current record which can be explicitly set by the client. By 43 * default current is the first record. Thus, querying a record would require setting 44 * it as the current one and interacting with the property getters and setters. 45 * <p> 46 * This class represents various semantically different accessibility event 47 * types. Each event type has associated a set of related properties. In other 48 * words, each event type is characterized via a subset of the properties exposed 49 * by this class. For each event type there is a corresponding constant defined 50 * in this class. Since some event types are semantically close there are mask 51 * constants that group them together. Follows a specification of the event 52 * types and their associated properties: 53 * <p> 54 * <b>VIEW TYPES</b> <br> 55 * <p> 56 * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View} 57 * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br> 58 * Type:{@link #TYPE_VIEW_CLICKED} <br> 59 * Properties:</br> 60 * <ul> 61 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 62 * <li>{@link #getClassName()} - The class name of the source.</li> 63 * <li>{@link #getPackageName()} - The package name of the source.</li> 64 * <li>{@link #getEventTime()} - The event time.</li> 65 * <li>{@link #getText()} - The text of the source.</li> 66 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 67 * <li>{@link #isPassword()} - Whether the source is password.</li> 68 * <li>{@link #isChecked()} - Whether the source is checked.</li> 69 * </ul> 70 * <p> 71 * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View} 72 * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br> 73 * Type:{@link #TYPE_VIEW_LONG_CLICKED} <br> 74 * Properties:</br> 75 * <ul> 76 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 77 * <li>{@link #getClassName()} - The class name of the source.</li> 78 * <li>{@link #getPackageName()} - The package name of the source.</li> 79 * <li>{@link #getEventTime()} - The event time.</li> 80 * <li>{@link #getText()} - The text of the source.</li> 81 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 82 * <li>{@link #isPassword()} - Whether the source is password.</li> 83 * <li>{@link #isChecked()} - Whether the source is checked.</li> 84 * </ul> 85 * <p> 86 * <b>View selected</b> - represents the event of selecting an item usually in 87 * the context of an {@link android.widget.AdapterView}. <br> 88 * Type: {@link #TYPE_VIEW_SELECTED} <br> 89 * Properties:</br> 90 * <ul> 91 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 92 * <li>{@link #getClassName()} - The class name of the source.</li> 93 * <li>{@link #getPackageName()} - The package name of the source.</li> 94 * <li>{@link #getEventTime()} - The event time.</li> 95 * <li>{@link #getText()} - The text of the source.</li> 96 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 97 * <li>{@link #isPassword()} - Whether the source is password.</li> 98 * <li>{@link #isChecked()} - Whether the source is checked.</li> 99 * <li>{@link #getItemCount()} -The number of selectable items of the source.</li> 100 * <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li> 101 * </ul> 102 * <p> 103 * <p> 104 * <b>View focused</b> - represents the event of focusing a 105 * {@link android.view.View}. <br> 106 * Type: {@link #TYPE_VIEW_FOCUSED} <br> 107 * Properties:</br> 108 * <ul> 109 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 110 * <li>{@link #getClassName()} - The class name of the source.</li> 111 * <li>{@link #getPackageName()} - The package name of the source.</li> 112 * <li>{@link #getEventTime()} - The event time.</li> 113 * <li>{@link #getText()} - The text of the source.</li> 114 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 115 * <li>{@link #isPassword()} - Whether the source is password.</li> 116 * <li>{@link #isChecked()} - Whether the source is checked.</li> 117 * <li>{@link #getItemCount()} -The number of focusable items on the screen.</li> 118 * <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li> 119 * </ul> 120 * <p> 121 * <b>View text changed</b> - represents the event of changing the text of an 122 * {@link android.widget.EditText}. <br> 123 * Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br> 124 * Properties:</br> 125 * <ul> 126 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 127 * <li>{@link #getClassName()} - The class name of the source.</li> 128 * <li>{@link #getPackageName()} - The package name of the source.</li> 129 * <li>{@link #getEventTime()} - The event time.</li> 130 * <li>{@link #getText()} - The text of the source.</li> 131 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 132 * <li>{@link #isPassword()} - Whether the source is password.</li> 133 * <li>{@link #isChecked()} - Whether the source is checked.</li> 134 * <li>{@link #getFromIndex()} - The text change start index.</li> 135 * <li>{@link #getAddedCount()} - The number of added characters.</li> 136 * <li>{@link #getRemovedCount()} - The number of removed characters.</li> 137 * <li>{@link #getBeforeText()} - The text of the source before the change.</li> 138 * </ul> 139 * <p> 140 * <b>View text selection changed</b> - represents the event of changing the text 141 * selection of an {@link android.widget.EditText}.<br> 142 * Type: {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} <br> 143 * Properties:</br> 144 * <ul> 145 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 146 * <li>{@link #getClassName()} - The class name of the source.</li> 147 * <li>{@link #getPackageName()} - The package name of the source.</li> 148 * <li>{@link #getEventTime()} - The event time.</li> 149 * <li>{@link #getText()} - The text of the source.</li> 150 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 151 * <li>{@link #isPassword()} - Whether the source is password.</li> 152 * <li>{@link #getFromIndex()} - The selection start index.</li> 153 * <li>{@link #getToIndex()} - The selection end index.</li> 154 * <li>{@link #getItemCount()} - The length of the source text.</li> 155 * <ul> 156 * <p> 157 * <b>View scrolled</b> - represents the event of scrolling a view. If 158 * the source is a descendant of {@link android.widget.AdapterView} the 159 * scroll is reported in terms of visible items - the first visible item, 160 * the last visible item, and the total items - because the the source 161 * is unaware if its pixel size since its adapter is responsible for 162 * creating views. In all other cases the scroll is reported as the current 163 * scroll on the X and Y axis respectively plus the height of the source in 164 * pixels.<br> 165 * Type: {@link #TYPE_VIEW_SCROLLED} <br> 166 * Properties:</br> 167 * <ul> 168 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 169 * <li>{@link #getClassName()} - The class name of the source.</li> 170 * <li>{@link #getPackageName()} - The package name of the source.</li> 171 * <li>{@link #getEventTime()} - The event time.</li> 172 * <li>{@link #getText()} - The text of the source.</li> 173 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 174 * <li>{@link #getScrollX()} - The horizontal offset of the source 175 * (without descendants of AdapterView)).</li> 176 * <li>{@link #getScrollY()} - The vertical offset of the source 177 * (without descendants of AdapterView)).</li> 178 * <li>{@link #getFromIndex()} - The index of the first visible item of the source 179 * (for descendants of AdapterView).</li> 180 * <li>{@link #getToIndex()} - The index of the last visible item of the source 181 * (for descendants of AdapterView).</li> 182 * <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView) 183 * or the height of the source in pixels (all other cases).</li> 184 * <ul> 185 * <p> 186 * <b>TRANSITION TYPES</b> <br> 187 * <p> 188 * <b>Window state changed</b> - represents the event of opening a 189 * {@link android.widget.PopupWindow}, {@link android.view.Menu}, 190 * {@link android.app.Dialog}, etc. <br> 191 * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br> 192 * Properties:</br> 193 * <ul> 194 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 195 * <li>{@link #getClassName()} - The class name of the source.</li> 196 * <li>{@link #getPackageName()} - The package name of the source.</li> 197 * <li>{@link #getEventTime()} - The event time.</li> 198 * <li>{@link #getText()} - The text of the source.</li> 199 * </ul> 200 * <p> 201 * <b>Window content changed</b> - represents the event of change in the 202 * content of a window. This change can be adding/removing view, changing 203 * a view size, etc.<br> 204 * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br> 205 * Properties:</br> 206 * <ul> 207 * <li>{@link #getSource()} - The source info (for registered clients).</li> * 208 * <li>{@link #getClassName()} - The class name of the source.</li> 209 * <li>{@link #getPackageName()} - The package name of the source.</li> 210 * <li>{@link #getEventTime()} - The event time.</li> 211 * <ul> 212 * <p> 213 * <b>NOTIFICATION TYPES</b> <br> 214 * <p> 215 * <b>Notification state changed</b> - represents the event showing/hiding 216 * {@link android.app.Notification}. 217 * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br> 218 * Properties:</br> 219 * <ul> 220 * <li>{@link #getClassName()} - The class name of the source.</li> 221 * <li>{@link #getPackageName()} - The package name of the source.</li> 222 * <li>{@link #getEventTime()} - The event time.</li> 223 * <li>{@link #getText()} - The text of the source.</li> 224 * <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li> 225 * </ul> 226 * <p> 227 * <b>Security note</b> 228 * <p> 229 * Since an event contains the text of its source privacy can be compromised by leaking of 230 * sensitive information such as passwords. To address this issue any event fired in response 231 * to manipulation of a PASSWORD field does NOT CONTAIN the text of the password. 232 * 233 * @see android.view.accessibility.AccessibilityManager 234 * @see android.accessibilityservice.AccessibilityService 235 */ 236public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable { 237 private static final boolean DEBUG = false; 238 239 /** 240 * Invalid selection/focus position. 241 * 242 * @see #getCurrentItemIndex() 243 */ 244 public static final int INVALID_POSITION = -1; 245 246 /** 247 * Maximum length of the text fields. 248 * 249 * @see #getBeforeText() 250 * @see #getText() 251 * </br> 252 * Note: This constant is no longer needed since there 253 * is no limit on the length of text that is contained 254 * in an accessibility event anymore. 255 */ 256 @Deprecated 257 public static final int MAX_TEXT_LENGTH = 500; 258 259 /** 260 * Represents the event of clicking on a {@link android.view.View} like 261 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 262 */ 263 public static final int TYPE_VIEW_CLICKED = 0x00000001; 264 265 /** 266 * Represents the event of long clicking on a {@link android.view.View} like 267 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 268 */ 269 public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002; 270 271 /** 272 * Represents the event of selecting an item usually in the context of an 273 * {@link android.widget.AdapterView}. 274 */ 275 public static final int TYPE_VIEW_SELECTED = 0x00000004; 276 277 /** 278 * Represents the event of focusing a {@link android.view.View}. 279 */ 280 public static final int TYPE_VIEW_FOCUSED = 0x00000008; 281 282 /** 283 * Represents the event of changing the text of an {@link android.widget.EditText}. 284 */ 285 public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010; 286 287 /** 288 * Represents the event of opening/closing a {@link android.widget.PopupWindow}, 289 * {@link android.view.Menu}, {@link android.app.Dialog}, etc. 290 */ 291 public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020; 292 293 /** 294 * Represents the event showing/hiding a {@link android.app.Notification}. 295 */ 296 public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040; 297 298 /** 299 * Represents the event of a hover enter over a {@link android.view.View}. 300 */ 301 public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080; 302 303 /** 304 * Represents the event of a hover exit over a {@link android.view.View}. 305 */ 306 public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100; 307 308 /** 309 * Represents the event of starting a touch exploration gesture. 310 */ 311 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200; 312 313 /** 314 * Represents the event of ending a touch exploration gesture. 315 */ 316 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400; 317 318 /** 319 * Represents the event of changing the content of a window. 320 */ 321 public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800; 322 323 /** 324 * Represents the event of scrolling a view. 325 */ 326 public static final int TYPE_VIEW_SCROLLED = 0x00001000; 327 328 /** 329 * Represents the event of changing the selection in an {@link android.widget.EditText}. 330 */ 331 public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000; 332 333 /** 334 * Mask for {@link AccessibilityEvent} all types. 335 * 336 * @see #TYPE_VIEW_CLICKED 337 * @see #TYPE_VIEW_LONG_CLICKED 338 * @see #TYPE_VIEW_SELECTED 339 * @see #TYPE_VIEW_FOCUSED 340 * @see #TYPE_VIEW_TEXT_CHANGED 341 * @see #TYPE_WINDOW_STATE_CHANGED 342 * @see #TYPE_NOTIFICATION_STATE_CHANGED 343 */ 344 public static final int TYPES_ALL_MASK = 0xFFFFFFFF; 345 346 private static final int MAX_POOL_SIZE = 10; 347 private static final Object sPoolLock = new Object(); 348 private static AccessibilityEvent sPool; 349 private static int sPoolSize; 350 private AccessibilityEvent mNext; 351 private boolean mIsInPool; 352 353 private int mEventType; 354 private CharSequence mPackageName; 355 private long mEventTime; 356 357 private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>(); 358 359 /* 360 * Hide constructor from clients. 361 */ 362 private AccessibilityEvent() { 363 } 364 365 /** 366 * Initialize an event from another one. 367 * 368 * @param event The event to initialize from. 369 */ 370 void init(AccessibilityEvent event) { 371 super.init(event); 372 mEventType = event.mEventType; 373 mEventTime = event.mEventTime; 374 mPackageName = event.mPackageName; 375 } 376 377 /** 378 * Sets the connection for interacting with the AccessibilityManagerService. 379 * 380 * @param connection The connection. 381 * 382 * @hide 383 */ 384 @Override 385 public void setConnection(IAccessibilityServiceConnection connection) { 386 super.setConnection(connection); 387 List<AccessibilityRecord> records = mRecords; 388 final int recordCount = records.size(); 389 for (int i = 0; i < recordCount; i++) { 390 AccessibilityRecord record = records.get(i); 391 record.setConnection(connection); 392 } 393 } 394 395 /** 396 * Sets if this instance is sealed. 397 * 398 * @param sealed Whether is sealed. 399 * 400 * @hide 401 */ 402 @Override 403 public void setSealed(boolean sealed) { 404 super.setSealed(sealed); 405 List<AccessibilityRecord> records = mRecords; 406 final int recordCount = records.size(); 407 for (int i = 0; i < recordCount; i++) { 408 AccessibilityRecord record = records.get(i); 409 record.setSealed(sealed); 410 } 411 } 412 413 /** 414 * Gets the number of records contained in the event. 415 * 416 * @return The number of records. 417 */ 418 public int getRecordCount() { 419 return mRecords.size(); 420 } 421 422 /** 423 * Appends an {@link AccessibilityRecord} to the end of event records. 424 * 425 * @param record The record to append. 426 * 427 * @throws IllegalStateException If called from an AccessibilityService. 428 */ 429 public void appendRecord(AccessibilityRecord record) { 430 enforceNotSealed(); 431 mRecords.add(record); 432 } 433 434 /** 435 * Gets the records at a given index. 436 * 437 * @param index The index. 438 * @return The records at the specified index. 439 */ 440 public AccessibilityRecord getRecord(int index) { 441 return mRecords.get(index); 442 } 443 444 /** 445 * Gets the event type. 446 * 447 * @return The event type. 448 */ 449 public int getEventType() { 450 return mEventType; 451 } 452 453 /** 454 * Sets the event type. 455 * 456 * @param eventType The event type. 457 * 458 * @throws IllegalStateException If called from an AccessibilityService. 459 */ 460 public void setEventType(int eventType) { 461 enforceNotSealed(); 462 mEventType = eventType; 463 } 464 465 /** 466 * Gets the time in which this event was sent. 467 * 468 * @return The event time. 469 */ 470 public long getEventTime() { 471 return mEventTime; 472 } 473 474 /** 475 * Sets the time in which this event was sent. 476 * 477 * @param eventTime The event time. 478 * 479 * @throws IllegalStateException If called from an AccessibilityService. 480 */ 481 public void setEventTime(long eventTime) { 482 enforceNotSealed(); 483 mEventTime = eventTime; 484 } 485 486 /** 487 * Gets the package name of the source. 488 * 489 * @return The package name. 490 */ 491 public CharSequence getPackageName() { 492 return mPackageName; 493 } 494 495 /** 496 * Sets the package name of the source. 497 * 498 * @param packageName The package name. 499 * 500 * @throws IllegalStateException If called from an AccessibilityService. 501 */ 502 public void setPackageName(CharSequence packageName) { 503 enforceNotSealed(); 504 mPackageName = packageName; 505 } 506 507 /** 508 * Returns a cached instance if such is available or a new one is 509 * instantiated with type property set. 510 * 511 * @param eventType The event type. 512 * @return An instance. 513 */ 514 public static AccessibilityEvent obtain(int eventType) { 515 AccessibilityEvent event = AccessibilityEvent.obtain(); 516 event.setEventType(eventType); 517 return event; 518 } 519 520 /** 521 * Returns a cached instance if such is available or a new one is 522 * instantiated with type property set. 523 * 524 * @param event The other event. 525 * @return An instance. 526 */ 527 public static AccessibilityEvent obtain(AccessibilityEvent event) { 528 AccessibilityEvent eventClone = AccessibilityEvent.obtain(); 529 eventClone.init(event); 530 531 final int recordCount = event.mRecords.size(); 532 for (int i = 0; i < recordCount; i++) { 533 AccessibilityRecord record = event.mRecords.get(i); 534 AccessibilityRecord recordClone = AccessibilityRecord.obtain(record); 535 eventClone.mRecords.add(recordClone); 536 } 537 538 return eventClone; 539 } 540 541 /** 542 * Returns a cached instance if such is available or a new one is 543 * instantiated. 544 * 545 * @return An instance. 546 */ 547 public static AccessibilityEvent obtain() { 548 synchronized (sPoolLock) { 549 if (sPool != null) { 550 AccessibilityEvent event = sPool; 551 sPool = sPool.mNext; 552 sPoolSize--; 553 event.mNext = null; 554 event.mIsInPool = false; 555 return event; 556 } 557 return new AccessibilityEvent(); 558 } 559 } 560 561 /** 562 * Return an instance back to be reused. 563 * <p> 564 * <b>Note: You must not touch the object after calling this function.</b> 565 * 566 * @throws IllegalStateException If the event is already recycled. 567 */ 568 @Override 569 public void recycle() { 570 if (mIsInPool) { 571 throw new IllegalStateException("Event already recycled!"); 572 } 573 clear(); 574 synchronized (sPoolLock) { 575 if (sPoolSize <= MAX_POOL_SIZE) { 576 mNext = sPool; 577 sPool = this; 578 mIsInPool = true; 579 sPoolSize++; 580 } 581 } 582 } 583 584 /** 585 * Clears the state of this instance. 586 * 587 * @hide 588 */ 589 @Override 590 protected void clear() { 591 super.clear(); 592 mEventType = 0; 593 mPackageName = null; 594 mEventTime = 0; 595 while (!mRecords.isEmpty()) { 596 AccessibilityRecord record = mRecords.remove(0); 597 record.recycle(); 598 } 599 } 600 601 /** 602 * Creates a new instance from a {@link Parcel}. 603 * 604 * @param parcel A parcel containing the state of a {@link AccessibilityEvent}. 605 */ 606 public void initFromParcel(Parcel parcel) { 607 if (parcel.readInt() == 1) { 608 mConnection = IAccessibilityServiceConnection.Stub.asInterface( 609 parcel.readStrongBinder()); 610 } 611 setSealed(parcel.readInt() == 1); 612 mEventType = parcel.readInt(); 613 mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 614 mEventTime = parcel.readLong(); 615 readAccessibilityRecordFromParcel(this, parcel); 616 617 // Read the records. 618 final int recordCount = parcel.readInt(); 619 for (int i = 0; i < recordCount; i++) { 620 AccessibilityRecord record = AccessibilityRecord.obtain(); 621 // Do this to write the connection only once. 622 record.setConnection(mConnection); 623 readAccessibilityRecordFromParcel(record, parcel); 624 mRecords.add(record); 625 } 626 } 627 628 /** 629 * Reads an {@link AccessibilityRecord} from a parcel. 630 * 631 * @param record The record to initialize. 632 * @param parcel The parcel to read from. 633 */ 634 private void readAccessibilityRecordFromParcel(AccessibilityRecord record, 635 Parcel parcel) { 636 record.mBooleanProperties = parcel.readInt(); 637 record.mCurrentItemIndex = parcel.readInt(); 638 record.mItemCount = parcel.readInt(); 639 record.mFromIndex = parcel.readInt(); 640 record.mToIndex = parcel.readInt(); 641 record.mScrollX = parcel.readInt(); 642 record.mScrollY = parcel.readInt(); 643 record.mAddedCount = parcel.readInt(); 644 record.mRemovedCount = parcel.readInt(); 645 record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 646 record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 647 record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 648 record.mParcelableData = parcel.readParcelable(null); 649 parcel.readList(record.mText, null); 650 record.mSourceWindowId = parcel.readInt(); 651 record.mSourceViewId = parcel.readInt(); 652 record.mSealed = (parcel.readInt() == 1); 653 } 654 655 /** 656 * {@inheritDoc} 657 */ 658 public void writeToParcel(Parcel parcel, int flags) { 659 if (mConnection == null) { 660 parcel.writeInt(0); 661 } else { 662 parcel.writeInt(1); 663 parcel.writeStrongBinder(mConnection.asBinder()); 664 } 665 parcel.writeInt(isSealed() ? 1 : 0); 666 parcel.writeInt(mEventType); 667 TextUtils.writeToParcel(mPackageName, parcel, 0); 668 parcel.writeLong(mEventTime); 669 writeAccessibilityRecordToParcel(this, parcel, flags); 670 671 // Write the records. 672 final int recordCount = getRecordCount(); 673 parcel.writeInt(recordCount); 674 for (int i = 0; i < recordCount; i++) { 675 AccessibilityRecord record = mRecords.get(i); 676 writeAccessibilityRecordToParcel(record, parcel, flags); 677 } 678 } 679 680 /** 681 * Writes an {@link AccessibilityRecord} to a parcel. 682 * 683 * @param record The record to write. 684 * @param parcel The parcel to which to write. 685 */ 686 private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel, 687 int flags) { 688 parcel.writeInt(record.mBooleanProperties); 689 parcel.writeInt(record.mCurrentItemIndex); 690 parcel.writeInt(record.mItemCount); 691 parcel.writeInt(record.mFromIndex); 692 parcel.writeInt(record.mToIndex); 693 parcel.writeInt(record.mScrollX); 694 parcel.writeInt(record.mScrollY); 695 parcel.writeInt(record.mAddedCount); 696 parcel.writeInt(record.mRemovedCount); 697 TextUtils.writeToParcel(record.mClassName, parcel, flags); 698 TextUtils.writeToParcel(record.mContentDescription, parcel, flags); 699 TextUtils.writeToParcel(record.mBeforeText, parcel, flags); 700 parcel.writeParcelable(record.mParcelableData, flags); 701 parcel.writeList(record.mText); 702 parcel.writeInt(record.mSourceWindowId); 703 parcel.writeInt(record.mSourceViewId); 704 parcel.writeInt(record.mSealed ? 1 : 0); 705 } 706 707 /** 708 * {@inheritDoc} 709 */ 710 public int describeContents() { 711 return 0; 712 } 713 714 @Override 715 public String toString() { 716 StringBuilder builder = new StringBuilder(); 717 builder.append("; EventType: ").append(eventTypeToString(mEventType)); 718 builder.append("; EventTime: ").append(mEventTime); 719 builder.append("; PackageName: ").append(mPackageName); 720 builder.append(super.toString()); 721 if (DEBUG) { 722 builder.append("\n"); 723 builder.append("; sourceWindowId: ").append(mSourceWindowId); 724 builder.append("; sourceViewId: ").append(mSourceViewId); 725 for (int i = 0; i < mRecords.size(); i++) { 726 AccessibilityRecord record = mRecords.get(i); 727 builder.append(" Record "); 728 builder.append(i); 729 builder.append(":"); 730 builder.append(" [ ClassName: " + record.mClassName); 731 builder.append("; Text: " + record.mText); 732 builder.append("; ContentDescription: " + record.mContentDescription); 733 builder.append("; ItemCount: " + record.mItemCount); 734 builder.append("; CurrentItemIndex: " + record.mCurrentItemIndex); 735 builder.append("; IsEnabled: " + record.isEnabled()); 736 builder.append("; IsPassword: " + record.isPassword()); 737 builder.append("; IsChecked: " + record.isChecked()); 738 builder.append("; IsFullScreen: " + record.isFullScreen()); 739 builder.append("; Scrollable: " + record.isScrollable()); 740 builder.append("; BeforeText: " + record.mBeforeText); 741 builder.append("; FromIndex: " + record.mFromIndex); 742 builder.append("; ToIndex: " + record.mToIndex); 743 builder.append("; ScrollX: " + record.mScrollX); 744 builder.append("; ScrollY: " + record.mScrollY); 745 builder.append("; AddedCount: " + record.mAddedCount); 746 builder.append("; RemovedCount: " + record.mRemovedCount); 747 builder.append("; ParcelableData: " + record.mParcelableData); 748 builder.append(" ]"); 749 builder.append("\n"); 750 } 751 } else { 752 builder.append("; recordCount: ").append(getAddedCount()); 753 } 754 return builder.toString(); 755 } 756 757 /** 758 * Returns the string representation of an event type. For example, 759 * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED. 760 * 761 * @param feedbackType The event type 762 * @return The string representation. 763 */ 764 public static String eventTypeToString(int feedbackType) { 765 switch (feedbackType) { 766 case TYPE_VIEW_CLICKED: 767 return "TYPE_VIEW_CLICKED"; 768 case TYPE_VIEW_LONG_CLICKED: 769 return "TYPE_VIEW_LONG_CLICKED"; 770 case TYPE_VIEW_SELECTED: 771 return "TYPE_VIEW_SELECTED"; 772 case TYPE_VIEW_FOCUSED: 773 return "TYPE_VIEW_FOCUSED"; 774 case TYPE_VIEW_TEXT_CHANGED: 775 return "TYPE_VIEW_TEXT_CHANGED"; 776 case TYPE_WINDOW_STATE_CHANGED: 777 return "TYPE_WINDOW_STATE_CHANGED"; 778 case TYPE_VIEW_HOVER_ENTER: 779 return "TYPE_VIEW_HOVER_ENTER"; 780 case TYPE_VIEW_HOVER_EXIT: 781 return "TYPE_VIEW_HOVER_EXIT"; 782 case TYPE_NOTIFICATION_STATE_CHANGED: 783 return "TYPE_NOTIFICATION_STATE_CHANGED"; 784 case TYPE_TOUCH_EXPLORATION_GESTURE_START: 785 return "TYPE_TOUCH_EXPLORATION_GESTURE_START"; 786 case TYPE_TOUCH_EXPLORATION_GESTURE_END: 787 return "TYPE_TOUCH_EXPLORATION_GESTURE_END"; 788 case TYPE_WINDOW_CONTENT_CHANGED: 789 return "TYPE_WINDOW_CONTENT_CHANGED"; 790 case TYPE_VIEW_TEXT_SELECTION_CHANGED: 791 return "TYPE_VIEW_TEXT_SELECTION_CHANGED"; 792 case TYPE_VIEW_SCROLLED: 793 return "TYPE_VIEW_SCROLLED"; 794 default: 795 return null; 796 } 797 } 798 799 /** 800 * @see Parcelable.Creator 801 */ 802 public static final Parcelable.Creator<AccessibilityEvent> CREATOR = 803 new Parcelable.Creator<AccessibilityEvent>() { 804 public AccessibilityEvent createFromParcel(Parcel parcel) { 805 AccessibilityEvent event = AccessibilityEvent.obtain(); 806 event.initFromParcel(parcel); 807 return event; 808 } 809 810 public AccessibilityEvent[] newArray(int size) { 811 return new AccessibilityEvent[size]; 812 } 813 }; 814} 815