Home | History | Annotate | Download | only in accessibility
      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      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    688      * The type of change is not defined.
    689      */
    690     public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
    691 
    692     /**
    693      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    694      * A node in the subtree rooted at the source node was added or removed.
    695      */
    696     public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
    697 
    698     /**
    699      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    700      * The node's text changed.
    701      */
    702     public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
    703 
    704     /**
    705      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    706      * The node's content description changed.
    707      */
    708     public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
    709 
    710     /**
    711      * Mask for {@link AccessibilityEvent} all types.
    712      *
    713      * @see #TYPE_VIEW_CLICKED
    714      * @see #TYPE_VIEW_LONG_CLICKED
    715      * @see #TYPE_VIEW_SELECTED
    716      * @see #TYPE_VIEW_FOCUSED
    717      * @see #TYPE_VIEW_TEXT_CHANGED
    718      * @see #TYPE_WINDOW_STATE_CHANGED
    719      * @see #TYPE_NOTIFICATION_STATE_CHANGED
    720      * @see #TYPE_VIEW_HOVER_ENTER
    721      * @see #TYPE_VIEW_HOVER_EXIT
    722      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
    723      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
    724      * @see #TYPE_WINDOW_CONTENT_CHANGED
    725      * @see #TYPE_VIEW_SCROLLED
    726      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
    727      * @see #TYPE_ANNOUNCEMENT
    728      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
    729      * @see #TYPE_GESTURE_DETECTION_START
    730      * @see #TYPE_GESTURE_DETECTION_END
    731      * @see #TYPE_TOUCH_INTERACTION_START
    732      * @see #TYPE_TOUCH_INTERACTION_END
    733      * @see #TYPE_WINDOWS_CHANGED
    734      */
    735     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
    736 
    737     private static final int MAX_POOL_SIZE = 10;
    738     private static final SynchronizedPool<AccessibilityEvent> sPool =
    739             new SynchronizedPool<AccessibilityEvent>(MAX_POOL_SIZE);
    740 
    741     private int mEventType;
    742     private CharSequence mPackageName;
    743     private long mEventTime;
    744     int mMovementGranularity;
    745     int mAction;
    746     int mContentChangeTypes;
    747 
    748     private ArrayList<AccessibilityRecord> mRecords;
    749 
    750     /*
    751      * Hide constructor from clients.
    752      */
    753     private AccessibilityEvent() {
    754     }
    755 
    756     /**
    757      * Initialize an event from another one.
    758      *
    759      * @param event The event to initialize from.
    760      */
    761     void init(AccessibilityEvent event) {
    762         super.init(event);
    763         mEventType = event.mEventType;
    764         mMovementGranularity = event.mMovementGranularity;
    765         mAction = event.mAction;
    766         mContentChangeTypes = event.mContentChangeTypes;
    767         mEventTime = event.mEventTime;
    768         mPackageName = event.mPackageName;
    769     }
    770 
    771     /**
    772      * Sets if this instance is sealed.
    773      *
    774      * @param sealed Whether is sealed.
    775      *
    776      * @hide
    777      */
    778     @Override
    779     public void setSealed(boolean sealed) {
    780         super.setSealed(sealed);
    781         final List<AccessibilityRecord> records = mRecords;
    782         if (records != null) {
    783             final int recordCount = records.size();
    784             for (int i = 0; i < recordCount; i++) {
    785                 AccessibilityRecord record = records.get(i);
    786                 record.setSealed(sealed);
    787             }
    788         }
    789     }
    790 
    791     /**
    792      * Gets the number of records contained in the event.
    793      *
    794      * @return The number of records.
    795      */
    796     public int getRecordCount() {
    797         return mRecords == null ? 0 : mRecords.size();
    798     }
    799 
    800     /**
    801      * Appends an {@link AccessibilityRecord} to the end of event records.
    802      *
    803      * @param record The record to append.
    804      *
    805      * @throws IllegalStateException If called from an AccessibilityService.
    806      */
    807     public void appendRecord(AccessibilityRecord record) {
    808         enforceNotSealed();
    809         if (mRecords == null) {
    810             mRecords = new ArrayList<AccessibilityRecord>();
    811         }
    812         mRecords.add(record);
    813     }
    814 
    815     /**
    816      * Gets the record at a given index.
    817      *
    818      * @param index The index.
    819      * @return The record at the specified index.
    820      */
    821     public AccessibilityRecord getRecord(int index) {
    822         if (mRecords == null) {
    823             throw new IndexOutOfBoundsException("Invalid index " + index + ", size is 0");
    824         }
    825         return mRecords.get(index);
    826     }
    827 
    828     /**
    829      * Gets the event type.
    830      *
    831      * @return The event type.
    832      */
    833     public int getEventType() {
    834         return mEventType;
    835     }
    836 
    837     /**
    838      * Gets the bit mask of change types signaled by an
    839      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event. A single event may represent
    840      * multiple change types.
    841      *
    842      * @return The bit mask of change types. One or more of:
    843      *         <ul>
    844      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION}
    845      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE}
    846      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT}
    847      *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED}
    848      *         </ul>
    849      */
    850     public int getContentChangeTypes() {
    851         return mContentChangeTypes;
    852     }
    853 
    854     /**
    855      * Sets the bit mask of node tree changes signaled by an
    856      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
    857      *
    858      * @param changeTypes The bit mask of change types.
    859      * @throws IllegalStateException If called from an AccessibilityService.
    860      * @see #getContentChangeTypes()
    861      */
    862     public void setContentChangeTypes(int changeTypes) {
    863         enforceNotSealed();
    864         mContentChangeTypes = changeTypes;
    865     }
    866 
    867     /**
    868      * Sets the event type.
    869      *
    870      * @param eventType The event type.
    871      *
    872      * @throws IllegalStateException If called from an AccessibilityService.
    873      */
    874     public void setEventType(int eventType) {
    875         enforceNotSealed();
    876         mEventType = eventType;
    877     }
    878 
    879     /**
    880      * Gets the time in which this event was sent.
    881      *
    882      * @return The event time.
    883      */
    884     public long getEventTime() {
    885         return mEventTime;
    886     }
    887 
    888     /**
    889      * Sets the time in which this event was sent.
    890      *
    891      * @param eventTime The event time.
    892      *
    893      * @throws IllegalStateException If called from an AccessibilityService.
    894      */
    895     public void setEventTime(long eventTime) {
    896         enforceNotSealed();
    897         mEventTime = eventTime;
    898     }
    899 
    900     /**
    901      * Gets the package name of the source.
    902      *
    903      * @return The package name.
    904      */
    905     public CharSequence getPackageName() {
    906         return mPackageName;
    907     }
    908 
    909     /**
    910      * Sets the package name of the source.
    911      *
    912      * @param packageName The package name.
    913      *
    914      * @throws IllegalStateException If called from an AccessibilityService.
    915      */
    916     public void setPackageName(CharSequence packageName) {
    917         enforceNotSealed();
    918         mPackageName = packageName;
    919     }
    920 
    921     /**
    922      * Sets the movement granularity that was traversed.
    923      *
    924      * @param granularity The granularity.
    925      *
    926      * @throws IllegalStateException If called from an AccessibilityService.
    927      */
    928     public void setMovementGranularity(int granularity) {
    929         enforceNotSealed();
    930         mMovementGranularity = granularity;
    931     }
    932 
    933     /**
    934      * Gets the movement granularity that was traversed.
    935      *
    936      * @return The granularity.
    937      */
    938     public int getMovementGranularity() {
    939         return mMovementGranularity;
    940     }
    941 
    942     /**
    943      * Sets the performed action that triggered this event.
    944      * <p>
    945      * Valid actions are defined in {@link AccessibilityNodeInfo}:
    946      * <ul>
    947      * <li>{@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}
    948      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
    949      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS}
    950      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION}
    951      * <li>{@link AccessibilityNodeInfo#ACTION_CLICK}
    952      * <li>etc.
    953      * </ul>
    954      *
    955      * @param action The action.
    956      * @throws IllegalStateException If called from an AccessibilityService.
    957      * @see AccessibilityNodeInfo#performAction(int)
    958      */
    959     public void setAction(int action) {
    960         enforceNotSealed();
    961         mAction = action;
    962     }
    963 
    964     /**
    965      * Gets the performed action that triggered this event.
    966      *
    967      * @return The action.
    968      */
    969     public int getAction() {
    970         return mAction;
    971     }
    972 
    973     /**
    974      * Returns a cached instance if such is available or a new one is
    975      * instantiated with its type property set.
    976      *
    977      * @param eventType The event type.
    978      * @return An instance.
    979      */
    980     public static AccessibilityEvent obtain(int eventType) {
    981         AccessibilityEvent event = AccessibilityEvent.obtain();
    982         event.setEventType(eventType);
    983         return event;
    984     }
    985 
    986     /**
    987      * Returns a cached instance if such is available or a new one is
    988      * created. The returned instance is initialized from the given
    989      * <code>event</code>.
    990      *
    991      * @param event The other event.
    992      * @return An instance.
    993      */
    994     public static AccessibilityEvent obtain(AccessibilityEvent event) {
    995         AccessibilityEvent eventClone = AccessibilityEvent.obtain();
    996         eventClone.init(event);
    997 
    998         if (event.mRecords != null) {
    999             final int recordCount = event.mRecords.size();
   1000             eventClone.mRecords = new ArrayList<AccessibilityRecord>(recordCount);
   1001             for (int i = 0; i < recordCount; i++) {
   1002                 final AccessibilityRecord record = event.mRecords.get(i);
   1003                 final AccessibilityRecord recordClone = AccessibilityRecord.obtain(record);
   1004                 eventClone.mRecords.add(recordClone);
   1005             }
   1006         }
   1007 
   1008         return eventClone;
   1009     }
   1010 
   1011     /**
   1012      * Returns a cached instance if such is available or a new one is
   1013      * instantiated.
   1014      *
   1015      * @return An instance.
   1016      */
   1017     public static AccessibilityEvent obtain() {
   1018         AccessibilityEvent event = sPool.acquire();
   1019         return (event != null) ? event : new AccessibilityEvent();
   1020     }
   1021 
   1022     /**
   1023      * Recycles an instance back to be reused.
   1024      * <p>
   1025      *   <b>Note: You must not touch the object after calling this function.</b>
   1026      * </p>
   1027      *
   1028      * @throws IllegalStateException If the event is already recycled.
   1029      */
   1030     @Override
   1031     public void recycle() {
   1032         clear();
   1033         sPool.release(this);
   1034     }
   1035 
   1036     /**
   1037      * Clears the state of this instance.
   1038      *
   1039      * @hide
   1040      */
   1041     @Override
   1042     protected void clear() {
   1043         super.clear();
   1044         mEventType = 0;
   1045         mMovementGranularity = 0;
   1046         mAction = 0;
   1047         mContentChangeTypes = 0;
   1048         mPackageName = null;
   1049         mEventTime = 0;
   1050         if (mRecords != null) {
   1051             while (!mRecords.isEmpty()) {
   1052                 AccessibilityRecord record = mRecords.remove(0);
   1053                 record.recycle();
   1054             }
   1055         }
   1056     }
   1057 
   1058     /**
   1059      * Creates a new instance from a {@link Parcel}.
   1060      *
   1061      * @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
   1062      */
   1063     public void initFromParcel(Parcel parcel) {
   1064         mSealed = (parcel.readInt() == 1);
   1065         mEventType = parcel.readInt();
   1066         mMovementGranularity = parcel.readInt();
   1067         mAction = parcel.readInt();
   1068         mContentChangeTypes = parcel.readInt();
   1069         mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1070         mEventTime = parcel.readLong();
   1071         mConnectionId = parcel.readInt();
   1072         readAccessibilityRecordFromParcel(this, parcel);
   1073 
   1074         // Read the records.
   1075         final int recordCount = parcel.readInt();
   1076         if (recordCount > 0) {
   1077             mRecords = new ArrayList<AccessibilityRecord>(recordCount);
   1078             for (int i = 0; i < recordCount; i++) {
   1079                 AccessibilityRecord record = AccessibilityRecord.obtain();
   1080                 readAccessibilityRecordFromParcel(record, parcel);
   1081                 record.mConnectionId = mConnectionId;
   1082                 mRecords.add(record);
   1083             }
   1084         }
   1085     }
   1086 
   1087     /**
   1088      * Reads an {@link AccessibilityRecord} from a parcel.
   1089      *
   1090      * @param record The record to initialize.
   1091      * @param parcel The parcel to read from.
   1092      */
   1093     private void readAccessibilityRecordFromParcel(AccessibilityRecord record,
   1094             Parcel parcel) {
   1095         record.mBooleanProperties = parcel.readInt();
   1096         record.mCurrentItemIndex = parcel.readInt();
   1097         record.mItemCount = parcel.readInt();
   1098         record.mFromIndex = parcel.readInt();
   1099         record.mToIndex = parcel.readInt();
   1100         record.mScrollX = parcel.readInt();
   1101         record.mScrollY =  parcel.readInt();
   1102         record.mMaxScrollX = parcel.readInt();
   1103         record.mMaxScrollY =  parcel.readInt();
   1104         record.mAddedCount = parcel.readInt();
   1105         record.mRemovedCount = parcel.readInt();
   1106         record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1107         record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1108         record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1109         record.mParcelableData = parcel.readParcelable(null);
   1110         parcel.readList(record.mText, null);
   1111         record.mSourceWindowId = parcel.readInt();
   1112         record.mSourceNodeId = parcel.readLong();
   1113         record.mSealed = (parcel.readInt() == 1);
   1114     }
   1115 
   1116     /**
   1117      * {@inheritDoc}
   1118      */
   1119     public void writeToParcel(Parcel parcel, int flags) {
   1120         parcel.writeInt(isSealed() ? 1 : 0);
   1121         parcel.writeInt(mEventType);
   1122         parcel.writeInt(mMovementGranularity);
   1123         parcel.writeInt(mAction);
   1124         parcel.writeInt(mContentChangeTypes);
   1125         TextUtils.writeToParcel(mPackageName, parcel, 0);
   1126         parcel.writeLong(mEventTime);
   1127         parcel.writeInt(mConnectionId);
   1128         writeAccessibilityRecordToParcel(this, parcel, flags);
   1129 
   1130         // Write the records.
   1131         final int recordCount = getRecordCount();
   1132         parcel.writeInt(recordCount);
   1133         for (int i = 0; i < recordCount; i++) {
   1134             AccessibilityRecord record = mRecords.get(i);
   1135             writeAccessibilityRecordToParcel(record, parcel, flags);
   1136         }
   1137     }
   1138 
   1139     /**
   1140      * Writes an {@link AccessibilityRecord} to a parcel.
   1141      *
   1142      * @param record The record to write.
   1143      * @param parcel The parcel to which to write.
   1144      */
   1145     private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel,
   1146             int flags) {
   1147         parcel.writeInt(record.mBooleanProperties);
   1148         parcel.writeInt(record.mCurrentItemIndex);
   1149         parcel.writeInt(record.mItemCount);
   1150         parcel.writeInt(record.mFromIndex);
   1151         parcel.writeInt(record.mToIndex);
   1152         parcel.writeInt(record.mScrollX);
   1153         parcel.writeInt(record.mScrollY);
   1154         parcel.writeInt(record.mMaxScrollX);
   1155         parcel.writeInt(record.mMaxScrollY);
   1156         parcel.writeInt(record.mAddedCount);
   1157         parcel.writeInt(record.mRemovedCount);
   1158         TextUtils.writeToParcel(record.mClassName, parcel, flags);
   1159         TextUtils.writeToParcel(record.mContentDescription, parcel, flags);
   1160         TextUtils.writeToParcel(record.mBeforeText, parcel, flags);
   1161         parcel.writeParcelable(record.mParcelableData, flags);
   1162         parcel.writeList(record.mText);
   1163         parcel.writeInt(record.mSourceWindowId);
   1164         parcel.writeLong(record.mSourceNodeId);
   1165         parcel.writeInt(record.mSealed ? 1 : 0);
   1166     }
   1167 
   1168     /**
   1169      * {@inheritDoc}
   1170      */
   1171     public int describeContents() {
   1172         return 0;
   1173     }
   1174 
   1175     @Override
   1176     public String toString() {
   1177         StringBuilder builder = new StringBuilder();
   1178         builder.append("EventType: ").append(eventTypeToString(mEventType));
   1179         builder.append("; EventTime: ").append(mEventTime);
   1180         builder.append("; PackageName: ").append(mPackageName);
   1181         builder.append("; MovementGranularity: ").append(mMovementGranularity);
   1182         builder.append("; Action: ").append(mAction);
   1183         builder.append(super.toString());
   1184         if (DEBUG) {
   1185             builder.append("\n");
   1186             builder.append("; ContentChangeTypes: ").append(mContentChangeTypes);
   1187             builder.append("; sourceWindowId: ").append(mSourceWindowId);
   1188             builder.append("; mSourceNodeId: ").append(mSourceNodeId);
   1189             for (int i = 0; i < getRecordCount(); i++) {
   1190                 final AccessibilityRecord record = getRecord(i);
   1191                 builder.append("  Record ");
   1192                 builder.append(i);
   1193                 builder.append(":");
   1194                 builder.append(" [ ClassName: " + record.mClassName);
   1195                 builder.append("; Text: " + record.mText);
   1196                 builder.append("; ContentDescription: " + record.mContentDescription);
   1197                 builder.append("; ItemCount: " + record.mItemCount);
   1198                 builder.append("; CurrentItemIndex: " + record.mCurrentItemIndex);
   1199                 builder.append("; IsEnabled: " + record.isEnabled());
   1200                 builder.append("; IsPassword: " + record.isPassword());
   1201                 builder.append("; IsChecked: " + record.isChecked());
   1202                 builder.append("; IsFullScreen: " + record.isFullScreen());
   1203                 builder.append("; Scrollable: " + record.isScrollable());
   1204                 builder.append("; BeforeText: " + record.mBeforeText);
   1205                 builder.append("; FromIndex: " + record.mFromIndex);
   1206                 builder.append("; ToIndex: " + record.mToIndex);
   1207                 builder.append("; ScrollX: " + record.mScrollX);
   1208                 builder.append("; ScrollY: " + record.mScrollY);
   1209                 builder.append("; AddedCount: " + record.mAddedCount);
   1210                 builder.append("; RemovedCount: " + record.mRemovedCount);
   1211                 builder.append("; ParcelableData: " + record.mParcelableData);
   1212                 builder.append(" ]");
   1213                 builder.append("\n");
   1214             }
   1215         } else {
   1216             builder.append("; recordCount: ").append(getRecordCount());
   1217         }
   1218         return builder.toString();
   1219     }
   1220 
   1221     /**
   1222      * Returns the string representation of an event type. For example,
   1223      * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
   1224      *
   1225      * @param eventType The event type
   1226      * @return The string representation.
   1227      */
   1228     public static String eventTypeToString(int eventType) {
   1229         if (eventType == TYPES_ALL_MASK) {
   1230             return "TYPES_ALL_MASK";
   1231         }
   1232         StringBuilder builder = new StringBuilder();
   1233         int eventTypeCount = 0;
   1234         while (eventType != 0) {
   1235             final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType);
   1236             eventType &= ~eventTypeFlag;
   1237             switch (eventTypeFlag) {
   1238                 case TYPE_VIEW_CLICKED: {
   1239                     if (eventTypeCount > 0) {
   1240                         builder.append(", ");
   1241                     }
   1242                     builder.append("TYPE_VIEW_CLICKED");
   1243                     eventTypeCount++;
   1244                 } break;
   1245                 case TYPE_VIEW_LONG_CLICKED: {
   1246                     if (eventTypeCount > 0) {
   1247                         builder.append(", ");
   1248                     }
   1249                     builder.append("TYPE_VIEW_LONG_CLICKED");
   1250                     eventTypeCount++;
   1251                 } break;
   1252                 case TYPE_VIEW_SELECTED: {
   1253                     if (eventTypeCount > 0) {
   1254                         builder.append(", ");
   1255                     }
   1256                     builder.append("TYPE_VIEW_SELECTED");
   1257                     eventTypeCount++;
   1258                 } break;
   1259                 case TYPE_VIEW_FOCUSED: {
   1260                     if (eventTypeCount > 0) {
   1261                         builder.append(", ");
   1262                     }
   1263                     builder.append("TYPE_VIEW_FOCUSED");
   1264                     eventTypeCount++;
   1265                 } break;
   1266                 case TYPE_VIEW_TEXT_CHANGED: {
   1267                     if (eventTypeCount > 0) {
   1268                         builder.append(", ");
   1269                     }
   1270                     builder.append("TYPE_VIEW_TEXT_CHANGED");
   1271                     eventTypeCount++;
   1272                 } break;
   1273                 case TYPE_WINDOW_STATE_CHANGED: {
   1274                     if (eventTypeCount > 0) {
   1275                         builder.append(", ");
   1276                     }
   1277                     builder.append("TYPE_WINDOW_STATE_CHANGED");
   1278                     eventTypeCount++;
   1279                 } break;
   1280                 case TYPE_VIEW_HOVER_ENTER: {
   1281                     if (eventTypeCount > 0) {
   1282                         builder.append(", ");
   1283                     }
   1284                     builder.append("TYPE_VIEW_HOVER_ENTER");
   1285                     eventTypeCount++;
   1286                 } break;
   1287                 case TYPE_VIEW_HOVER_EXIT: {
   1288                     if (eventTypeCount > 0) {
   1289                         builder.append(", ");
   1290                     }
   1291                     builder.append("TYPE_VIEW_HOVER_EXIT");
   1292                     eventTypeCount++;
   1293                 } break;
   1294                 case TYPE_NOTIFICATION_STATE_CHANGED: {
   1295                     if (eventTypeCount > 0) {
   1296                         builder.append(", ");
   1297                     }
   1298                     builder.append("TYPE_NOTIFICATION_STATE_CHANGED");
   1299                     eventTypeCount++;
   1300                 } break;
   1301                 case TYPE_TOUCH_EXPLORATION_GESTURE_START: {
   1302                     if (eventTypeCount > 0) {
   1303                         builder.append(", ");
   1304                     }
   1305                     builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_START");
   1306                     eventTypeCount++;
   1307                 } break;
   1308                 case TYPE_TOUCH_EXPLORATION_GESTURE_END: {
   1309                     if (eventTypeCount > 0) {
   1310                         builder.append(", ");
   1311                     }
   1312                     builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_END");
   1313                     eventTypeCount++;
   1314                 } break;
   1315                 case TYPE_WINDOW_CONTENT_CHANGED: {
   1316                     if (eventTypeCount > 0) {
   1317                         builder.append(", ");
   1318                     }
   1319                     builder.append("TYPE_WINDOW_CONTENT_CHANGED");
   1320                     eventTypeCount++;
   1321                 } break;
   1322                 case TYPE_VIEW_TEXT_SELECTION_CHANGED: {
   1323                     if (eventTypeCount > 0) {
   1324                         builder.append(", ");
   1325                     }
   1326                     builder.append("TYPE_VIEW_TEXT_SELECTION_CHANGED");
   1327                     eventTypeCount++;
   1328                 } break;
   1329                 case TYPE_VIEW_SCROLLED: {
   1330                     if (eventTypeCount > 0) {
   1331                         builder.append(", ");
   1332                     }
   1333                     builder.append("TYPE_VIEW_SCROLLED");
   1334                     eventTypeCount++;
   1335                 } break;
   1336                 case TYPE_ANNOUNCEMENT: {
   1337                     if (eventTypeCount > 0) {
   1338                         builder.append(", ");
   1339                     }
   1340                     builder.append("TYPE_ANNOUNCEMENT");
   1341                     eventTypeCount++;
   1342                 } break;
   1343                 case TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
   1344                     if (eventTypeCount > 0) {
   1345                         builder.append(", ");
   1346                     }
   1347                     builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUSED");
   1348                     eventTypeCount++;
   1349                 } break;
   1350                 case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
   1351                     if (eventTypeCount > 0) {
   1352                         builder.append(", ");
   1353                     }
   1354                     builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED");
   1355                     eventTypeCount++;
   1356                 } break;
   1357                 case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
   1358                     if (eventTypeCount > 0) {
   1359                         builder.append(", ");
   1360                     }
   1361                     builder.append("TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY");
   1362                     eventTypeCount++;
   1363                 } break;
   1364                 case TYPE_GESTURE_DETECTION_START: {
   1365                     if (eventTypeCount > 0) {
   1366                         builder.append(", ");
   1367                     }
   1368                     builder.append("TYPE_GESTURE_DETECTION_START");
   1369                     eventTypeCount++;
   1370                 } break;
   1371                 case TYPE_GESTURE_DETECTION_END: {
   1372                     if (eventTypeCount > 0) {
   1373                         builder.append(", ");
   1374                     }
   1375                     builder.append("TYPE_GESTURE_DETECTION_END");
   1376                     eventTypeCount++;
   1377                 } break;
   1378                 case TYPE_TOUCH_INTERACTION_START: {
   1379                     if (eventTypeCount > 0) {
   1380                         builder.append(", ");
   1381                     }
   1382                     builder.append("TYPE_TOUCH_INTERACTION_START");
   1383                     eventTypeCount++;
   1384                 } break;
   1385                 case TYPE_TOUCH_INTERACTION_END: {
   1386                     if (eventTypeCount > 0) {
   1387                         builder.append(", ");
   1388                     }
   1389                     builder.append("TYPE_TOUCH_INTERACTION_END");
   1390                     eventTypeCount++;
   1391                 } break;
   1392                 case TYPE_WINDOWS_CHANGED: {
   1393                     if (eventTypeCount > 0) {
   1394                         builder.append(", ");
   1395                     }
   1396                     builder.append("TYPE_WINDOWS_CHANGED");
   1397                     eventTypeCount++;
   1398                 } break;
   1399             }
   1400         }
   1401         if (eventTypeCount > 1) {
   1402             builder.insert(0, '[');
   1403             builder.append(']');
   1404         }
   1405         return builder.toString();
   1406     }
   1407 
   1408     /**
   1409      * @see Parcelable.Creator
   1410      */
   1411     public static final Parcelable.Creator<AccessibilityEvent> CREATOR =
   1412             new Parcelable.Creator<AccessibilityEvent>() {
   1413         public AccessibilityEvent createFromParcel(Parcel parcel) {
   1414             AccessibilityEvent event = AccessibilityEvent.obtain();
   1415             event.initFromParcel(parcel);
   1416             return event;
   1417         }
   1418 
   1419         public AccessibilityEvent[] newArray(int size) {
   1420             return new AccessibilityEvent[size];
   1421         }
   1422     };
   1423 }
   1424