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.annotation.IntDef;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 import android.text.TextUtils;
     23 import android.util.Pools.SynchronizedPool;
     24 
     25 import com.android.internal.util.BitUtils;
     26 
     27 import java.lang.annotation.Retention;
     28 import java.lang.annotation.RetentionPolicy;
     29 import java.util.ArrayList;
     30 import java.util.List;
     31 
     32 /**
     33  * <p>
     34  * This class represents accessibility events that are sent by the system when
     35  * something notable happens in the user interface. For example, when a
     36  * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
     37  * </p>
     38  * <p>
     39  * An accessibility event is fired by an individual view which populates the event with
     40  * data for its state and requests from its parent to send the event to interested
     41  * parties. The parent can optionally modify or even block the event based on its broader
     42  * understanding of the user interface's context.
     43  * </p>
     44  * <p>
     45  * The main purpose of an accessibility event is to communicate changes in the UI to an
     46  * {@link android.accessibilityservice.AccessibilityService}. The service may then inspect,
     47  * if needed the user interface by examining the View hierarchy, as represented by a tree of
     48  * {@link AccessibilityNodeInfo}s (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  * </ul>
     84  * </p>
     85  * <p>
     86  * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
     87  * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br>
     88  * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br>
     89  * <em>Properties:</em></br>
     90  * <ul>
     91  *   <li>{@link #getEventType()} - The type of the event.</li>
     92  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
     93  *   <li>{@link #getClassName()} - The class name of the source.</li>
     94  *   <li>{@link #getPackageName()} - The package name of the source.</li>
     95  *   <li>{@link #getEventTime()}  - The event time.</li>
     96  * </ul>
     97  * </p>
     98  * <p>
     99  * <b>View selected</b> - represents the event of selecting an item usually in
    100  * the context of an {@link android.widget.AdapterView}.</br>
    101  * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
    102  * <em>Properties:</em></br>
    103  * <ul>
    104  *   <li>{@link #getEventType()} - The type of the event.</li>
    105  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    106  *   <li>{@link #getClassName()} - The class name of the source.</li>
    107  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    108  *   <li>{@link #getEventTime()}  - The event time.</li>
    109  * </ul>
    110  * </p>
    111  * <p>
    112  * <b>View focused</b> - represents the event of focusing a
    113  * {@link android.view.View}.</br>
    114  * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
    115  * <em>Properties:</em></br>
    116  * <ul>
    117  *   <li>{@link #getEventType()} - The type of the event.</li>
    118  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    119  *   <li>{@link #getClassName()} - The class name of the source.</li>
    120  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    121  *   <li>{@link #getEventTime()}  - The event time.</li>
    122  * </ul>
    123  * </p>
    124  * <p>
    125  * <b>View text changed</b> - represents the event of changing the text of an
    126  * {@link android.widget.EditText}.</br>
    127  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
    128  * <em>Properties:</em></br>
    129  * <ul>
    130  *   <li>{@link #getEventType()} - The type of the event.</li>
    131  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    132  *   <li>{@link #getClassName()} - The class name of the source.</li>
    133  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    134  *   <li>{@link #getEventTime()}  - The event time.</li>
    135  *   <li>{@link #getText()} - The new text of the source.</li>
    136  *   <li>{@link #getBeforeText()} - The text of the source before the change.</li>
    137  *   <li>{@link #getFromIndex()} - The text change start index.</li>
    138  *   <li>{@link #getAddedCount()} - The number of added characters.</li>
    139  *   <li>{@link #getRemovedCount()} - The number of removed characters.</li>
    140  * </ul>
    141  * </p>
    142  * <p>
    143  * <b>View text selection changed</b> - represents the event of changing the text
    144  * selection of an {@link android.widget.EditText}.</br>
    145  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
    146  * <em>Properties:</em></br>
    147  * <ul>
    148  *   <li>{@link #getEventType()} - The type of the event.</li>
    149  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    150  *   <li>{@link #getClassName()} - The class name of the source.</li>
    151  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    152  *   <li>{@link #getEventTime()}  - The event time.</li>
    153  * </ul>
    154  * </p>
    155  * <b>View text traversed at movement granularity</b> - represents the event of traversing the
    156  * text of a view at a given granularity. For example, moving to the next word.</br>
    157  * <em>Type:</em> {@link #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY} </br>
    158  * <em>Properties:</em></br>
    159  * <ul>
    160  *   <li>{@link #getEventType()} - The type of the event.</li>
    161  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    162  *   <li>{@link #getClassName()} - The class name of the source.</li>
    163  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    164  *   <li>{@link #getEventTime()}  - The event time.</li>
    165  *   <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text
    166  *       was traversed.</li>
    167  *   <li>{@link #getText()} -  The text of the source's sub-tree.</li>
    168  *   <li>{@link #getFromIndex()} - The start the text that was skipped over in this movement.
    169  *       This is the starting point when moving forward through the text, but not when moving
    170  *       back.</li>
    171  *   <li>{@link #getToIndex()} - The end of the text that was skipped over in this movement.
    172  *       This is the ending point when moving forward through the text, but not when moving
    173  *       back.</li>
    174  *   <li>{@link #getAction()} - Gets traversal action which specifies the direction.</li>
    175  * </ul>
    176  * </p>
    177  * <p>
    178  * <b>View scrolled</b> - represents the event of scrolling a view. </br>
    179  * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
    180  * <em>Properties:</em></br>
    181  * <ul>
    182  *   <li>{@link #getEventType()} - The type of the event.</li>
    183  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    184  *   <li>{@link #getClassName()} - The class name of the source.</li>
    185  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    186  *   <li>{@link #getEventTime()}  - The event time.</li>
    187  *   <li>{@link #getScrollDeltaX()} - The difference in the horizontal position.</li>
    188  *   <li>{@link #getScrollDeltaY()} - The difference in the vertical position.</li>
    189  * </ul>
    190  * </p>
    191  * <p>
    192  * <b>TRANSITION TYPES</b></br>
    193  * </p>
    194  * <p>
    195  * <b>Window state changed</b> - represents the event of a change to a section of
    196  * the user interface that is visually distinct. Should be sent from either the
    197  * root view of a window or from a view that is marked as a pane
    198  * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Not that changes
    199  * to true windows are represented by {@link #TYPE_WINDOWS_CHANGED}.</br>
    200  * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
    201  * <em>Properties:</em></br>
    202  * <ul>
    203  *   <li>{@link #getEventType()} - The type of the event.</li>
    204  *   <li>{@link #getContentChangeTypes()} - The type of state changes.</li>
    205  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    206  *   <li>{@link #getClassName()} - The class name of the source.</li>
    207  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    208  *   <li>{@link #getEventTime()}  - The event time.</li>
    209  *   <li>{@link #getText()} - The text of the source's sub-tree, including the pane titles.</li>
    210  * </ul>
    211  * </p>
    212  * <p>
    213  * <b>Window content changed</b> - represents the event of change in the
    214  * content of a window. This change can be adding/removing view, changing
    215  * a view size, etc.</br>
    216  * </p>
    217  * <p>
    218  * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
    219  * <em>Properties:</em></br>
    220  * <ul>
    221  *   <li>{@link #getEventType()} - The type of the event.</li>
    222  *   <li>{@link #getContentChangeTypes()} - The type of content changes.</li>
    223  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    224  *   <li>{@link #getClassName()} - The class name of the source.</li>
    225  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    226  *   <li>{@link #getEventTime()}  - The event time.</li>
    227  * </ul>
    228  * </p>
    229  * <p>
    230  * <b>Windows changed</b> - represents a change in the windows shown on
    231  * the screen such as a window appeared, a window disappeared, a window size changed,
    232  * a window layer changed, etc. These events should only come from the system, which is responsible
    233  * for managing windows. The list of windows is available from
    234  * {@link android.accessibilityservice.AccessibilityService#getWindows()}.
    235  * For regions of the user interface that are presented as windows but are
    236  * controlled by an app's process, use {@link #TYPE_WINDOW_STATE_CHANGED}.</br>
    237  * <em>Type:</em> {@link #TYPE_WINDOWS_CHANGED}</br>
    238  * <em>Properties:</em></br>
    239  * <ul>
    240  *   <li>{@link #getEventType()} - The type of the event.</li>
    241  *   <li>{@link #getEventTime()} - The event time.</li>
    242  *   <li>{@link #getWindowChanges()}</li> - The specific change to the source window
    243  * </ul>
    244  * <em>Note:</em> You can retrieve the {@link AccessibilityWindowInfo} for the window
    245  * source of the event by looking through the list returned by
    246  * {@link android.accessibilityservice.AccessibilityService#getWindows()} for the window whose ID
    247  * matches {@link #getWindowId()}.
    248  * </p>
    249  * <p>
    250  * <b>NOTIFICATION TYPES</b></br>
    251  * </p>
    252  * <p>
    253  * <b>Notification state changed</b> - represents the event showing a transient piece of information
    254  * to the user. This information may be a {@link android.app.Notification} or
    255  * {@link android.widget.Toast}.</br>
    256  * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
    257  * <em>Properties:</em></br>
    258  * <ul>
    259  *   <li>{@link #getEventType()} - The type of the event.</li>
    260  *   <li>{@link #getClassName()} - The class name of the source.</li>
    261  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    262  *   <li>{@link #getEventTime()}  - The event time.</li>
    263  *   <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}, if
    264  *   applicable.</li>
    265  *   <li>{@link #getText()} - Displayed text of the {@link android.widget.Toast}, if applicable,
    266  *   or may contain text from the {@link android.app.Notification}, although
    267  *   {@link #getParcelableData()} is a richer set of data for {@link android.app.Notification}.</li>
    268  * </ul>
    269  * </p>
    270  * <p>
    271  * <b>EXPLORATION TYPES</b></br>
    272  * </p>
    273  * <p>
    274  * <b>View hover enter</b> - represents the event of beginning to hover
    275  * over a {@link android.view.View}. The hover may be generated via
    276  * exploring the screen by touch or via a pointing device.</br>
    277  * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br>
    278  * <em>Properties:</em></br>
    279  * <ul>
    280  *   <li>{@link #getEventType()} - The type of the event.</li>
    281  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    282  *   <li>{@link #getClassName()} - The class name of the source.</li>
    283  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    284  *   <li>{@link #getEventTime()}  - The event time.</li>
    285  * </ul>
    286  * </p>
    287  * <b>View hover exit</b> - represents the event of stopping to hover
    288  * over a {@link android.view.View}. The hover may be generated via
    289  * exploring the screen by touch or via a pointing device.</br>
    290  * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br>
    291  * <em>Properties:</em></br>
    292  * <ul>
    293  *   <li>{@link #getEventType()} - The type of the event.</li>
    294  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    295  *   <li>{@link #getClassName()} - The class name of the source.</li>
    296  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    297  *   <li>{@link #getEventTime()}  - The event time.</li>
    298  * </ul>
    299  * </p>
    300  * <p>
    301  * <b>Touch interaction start</b> - represents the event of starting a touch
    302  * interaction, which is the user starts touching the screen.</br>
    303  * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_START}</br>
    304  * <em>Properties:</em></br>
    305  * <ul>
    306  *   <li>{@link #getEventType()} - The type of the event.</li>
    307  * </ul>
    308  * <em>Note:</em> This event is fired only by the system and is not passed to the
    309  * view tree to be populated.</br>
    310  * </p>
    311  * <p>
    312  * <b>Touch interaction end</b> - represents the event of ending a touch
    313  * interaction, which is the user stops touching the screen.</br>
    314  * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_END}</br>
    315  * <em>Properties:</em></br>
    316  * <ul>
    317  *   <li>{@link #getEventType()} - The type of the event.</li>
    318  * </ul>
    319  * <em>Note:</em> This event is fired only by the system and is not passed to the
    320  * view tree to be populated.</br>
    321  * </p>
    322  * <p>
    323  * <b>Touch exploration gesture start</b> - represents the event of starting a touch
    324  * exploring gesture.</br>
    325  * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br>
    326  * <em>Properties:</em></br>
    327  * <ul>
    328  *   <li>{@link #getEventType()} - The type of the event.</li>
    329  * </ul>
    330  * <em>Note:</em> This event is fired only by the system and is not passed to the
    331  * view tree to be populated.</br>
    332  * </p>
    333  * <p>
    334  * <b>Touch exploration gesture end</b> - represents the event of ending a touch
    335  * exploring gesture.</br>
    336  * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br>
    337  * <em>Properties:</em></br>
    338  * <ul>
    339  *   <li>{@link #getEventType()} - The type of the event.</li>
    340  * </ul>
    341  * <em>Note:</em> This event is fired only by the system and is not passed to the
    342  * view tree to be populated.</br>
    343  * </p>
    344  * <p>
    345  * <b>Touch gesture detection start</b> - represents the event of starting a user
    346  * gesture detection.</br>
    347  * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_START}</br>
    348  * <em>Properties:</em></br>
    349  * <ul>
    350  *   <li>{@link #getEventType()} - The type of the event.</li>
    351  * </ul>
    352  * <em>Note:</em> This event is fired only by the system and is not passed to the
    353  * view tree to be populated.</br>
    354  * </p>
    355  * <p>
    356  * <b>Touch gesture detection end</b> - represents the event of ending a user
    357  * gesture detection.</br>
    358  * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_END}</br>
    359  * <em>Properties:</em></br>
    360  * <ul>
    361  *   <li>{@link #getEventType()} - The type of the event.</li>
    362  * </ul>
    363  * <em>Note:</em> This event is fired only by the system and is not passed to the
    364  * view tree to be populated.</br>
    365  * </p>
    366  * <p>
    367  * <b>MISCELLANEOUS TYPES</b></br>
    368  * </p>
    369  * <p>
    370  * <b>Announcement</b> - represents the event of an application requesting a screen reader to make
    371  * an announcement. Because the event carries no semantic meaning, this event is appropriate only
    372  * in exceptional situations where additional screen reader output is needed but other types of
    373  * accessibility services do not need to be aware of the change.</br>
    374  * <em>Type:</em> {@link #TYPE_ANNOUNCEMENT}</br>
    375  * <em>Properties:</em></br>
    376  * <ul>
    377  *   <li>{@link #getEventType()} - The type of the event.</li>
    378  *   <li>{@link #getSource()} - The source info (for registered clients).</li>
    379  *   <li>{@link #getClassName()} - The class name of the source.</li>
    380  *   <li>{@link #getPackageName()} - The package name of the source.</li>
    381  *   <li>{@link #getEventTime()}  - The event time.</li>
    382  *   <li>{@link #getText()} - The text of the announcement.</li>
    383  * </ul>
    384  * </p>
    385  *
    386  * @see android.view.accessibility.AccessibilityManager
    387  * @see android.accessibilityservice.AccessibilityService
    388  * @see AccessibilityNodeInfo
    389  */
    390 public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
    391     private static final boolean DEBUG = false;
    392     /** @hide */
    393     public static final boolean DEBUG_ORIGIN = false;
    394 
    395     /**
    396      * Invalid selection/focus position.
    397      *
    398      * @see #getCurrentItemIndex()
    399      */
    400     public static final int INVALID_POSITION = -1;
    401 
    402     /**
    403      * Maximum length of the text fields.
    404      *
    405      * @see #getBeforeText()
    406      * @see #getText()
    407      * </br>
    408      * Note: This constant is no longer needed since there
    409      *       is no limit on the length of text that is contained
    410      *       in an accessibility event anymore.
    411      */
    412     @Deprecated
    413     public static final int MAX_TEXT_LENGTH = 500;
    414 
    415     /**
    416      * Represents the event of clicking on a {@link android.view.View} like
    417      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
    418      */
    419     public static final int TYPE_VIEW_CLICKED = 0x00000001;
    420 
    421     /**
    422      * Represents the event of long clicking on a {@link android.view.View} like
    423      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
    424      */
    425     public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
    426 
    427     /**
    428      * Represents the event of selecting an item usually in the context of an
    429      * {@link android.widget.AdapterView}.
    430      */
    431     public static final int TYPE_VIEW_SELECTED = 0x00000004;
    432 
    433     /**
    434      * Represents the event of setting input focus of a {@link android.view.View}.
    435      */
    436     public static final int TYPE_VIEW_FOCUSED = 0x00000008;
    437 
    438     /**
    439      * Represents the event of changing the text of an {@link android.widget.EditText}.
    440      */
    441     public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
    442 
    443     /**
    444      * Represents the event of a change to a visually distinct section of the user interface.
    445      * These events should only be dispatched from {@link android.view.View}s that have
    446      * accessibility pane titles, and replaces {@link #TYPE_WINDOW_CONTENT_CHANGED} for those
    447      * sources. Details about the change are available from {@link #getContentChangeTypes()}.
    448      */
    449     public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
    450 
    451     /**
    452      * Represents the event showing a {@link android.app.Notification}.
    453      */
    454     public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
    455 
    456     /**
    457      * Represents the event of a hover enter over a {@link android.view.View}.
    458      */
    459     public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
    460 
    461     /**
    462      * Represents the event of a hover exit over a {@link android.view.View}.
    463      */
    464     public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
    465 
    466     /**
    467      * Represents the event of starting a touch exploration gesture.
    468      */
    469     public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
    470 
    471     /**
    472      * Represents the event of ending a touch exploration gesture.
    473      */
    474     public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
    475 
    476     /**
    477      * Represents the event of changing the content of a window and more
    478      * specifically the sub-tree rooted at the event's source.
    479      */
    480     public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
    481 
    482     /**
    483      * Represents the event of scrolling a view. This event type is generally not sent directly.
    484      * @see View#onScrollChanged(int, int, int, int)
    485      */
    486     public static final int TYPE_VIEW_SCROLLED = 0x00001000;
    487 
    488     /**
    489      * Represents the event of changing the selection in an {@link android.widget.EditText}.
    490      */
    491     public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
    492 
    493     /**
    494      * Represents the event of an application making an announcement.
    495      */
    496     public static final int TYPE_ANNOUNCEMENT = 0x00004000;
    497 
    498     /**
    499      * Represents the event of gaining accessibility focus.
    500      */
    501     public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000;
    502 
    503     /**
    504      * Represents the event of clearing accessibility focus.
    505      */
    506     public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
    507 
    508     /**
    509      * Represents the event of traversing the text of a view at a given movement granularity.
    510      */
    511     public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
    512 
    513     /**
    514      * Represents the event of beginning gesture detection.
    515      */
    516     public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
    517 
    518     /**
    519      * Represents the event of ending gesture detection.
    520      */
    521     public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
    522 
    523     /**
    524      * Represents the event of the user starting to touch the screen.
    525      */
    526     public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
    527 
    528     /**
    529      * Represents the event of the user ending to touch the screen.
    530      */
    531     public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
    532 
    533     /**
    534      * Represents the event change in the system windows shown on the screen. This event type should
    535      * only be dispatched by the system.
    536      */
    537     public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
    538 
    539     /**
    540      * Represents the event of a context click on a {@link android.view.View}.
    541      */
    542     public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
    543 
    544     /**
    545      * Represents the event of the assistant currently reading the users screen context.
    546      */
    547     public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000;
    548 
    549     /**
    550      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    551      * The type of change is not defined.
    552      */
    553     public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
    554 
    555     /**
    556      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    557      * One or more content changes occurred in the the subtree rooted at the source node,
    558      * or the subtree's structure changed when a node was added or removed.
    559      */
    560     public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
    561 
    562     /**
    563      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    564      * The node's text changed.
    565      */
    566     public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
    567 
    568     /**
    569      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
    570      * The node's content description changed.
    571      */
    572     public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
    573 
    574     /**
    575      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
    576      * The node's pane title changed.
    577      */
    578     public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 0x00000008;
    579 
    580     /**
    581      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
    582      * The node has a pane title, and either just appeared or just was assigned a title when it
    583      * had none before.
    584      */
    585     public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 0x00000010;
    586 
    587     /**
    588      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
    589      * Can mean one of two slightly different things. The primary meaning is that the node has
    590      * a pane title, and was removed from the node hierarchy. It will also be sent if the pane
    591      * title is set to {@code null} after it contained a title.
    592      * No source will be returned if the node is no longer on the screen. To make the change more
    593      * clear for the user, the first entry in {@link #getText()} will return the value that would
    594      * have been returned by {@code getSource().getPaneTitle()}.
    595      */
    596     public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 0x00000020;
    597 
    598     /**
    599      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    600      * The window was added.
    601      */
    602     public static final int WINDOWS_CHANGE_ADDED = 0x00000001;
    603 
    604     /**
    605      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    606      * A window was removed.
    607      */
    608     public static final int WINDOWS_CHANGE_REMOVED = 0x00000002;
    609 
    610     /**
    611      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    612      * The window's title changed.
    613      */
    614     public static final int WINDOWS_CHANGE_TITLE = 0x00000004;
    615 
    616     /**
    617      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    618      * The window's bounds changed.
    619      */
    620     public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
    621 
    622     /**
    623      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    624      * The window's layer changed.
    625      */
    626     public static final int WINDOWS_CHANGE_LAYER = 0x00000010;
    627 
    628     /**
    629      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    630      * The window's {@link AccessibilityWindowInfo#isActive()} changed.
    631      */
    632     public static final int WINDOWS_CHANGE_ACTIVE = 0x00000020;
    633 
    634     /**
    635      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    636      * The window's {@link AccessibilityWindowInfo#isFocused()} changed.
    637      */
    638     public static final int WINDOWS_CHANGE_FOCUSED = 0x00000040;
    639 
    640     /**
    641      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    642      * The window's {@link AccessibilityWindowInfo#isAccessibilityFocused()} changed.
    643      */
    644     public static final int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 0x00000080;
    645 
    646     /**
    647      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    648      * The window's parent changed.
    649      */
    650     public static final int WINDOWS_CHANGE_PARENT = 0x00000100;
    651 
    652     /**
    653      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    654      * The window's children changed.
    655      */
    656     public static final int WINDOWS_CHANGE_CHILDREN = 0x00000200;
    657 
    658     /**
    659      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
    660      * The window either entered or exited picture-in-picture mode.
    661      */
    662     public static final int WINDOWS_CHANGE_PIP = 0x00000400;
    663 
    664     /** @hide */
    665     @Retention(RetentionPolicy.SOURCE)
    666     @IntDef(flag = true, prefix = { "WINDOWS_CHANGE_" }, value = {
    667             WINDOWS_CHANGE_ADDED,
    668             WINDOWS_CHANGE_REMOVED,
    669             WINDOWS_CHANGE_TITLE,
    670             WINDOWS_CHANGE_BOUNDS,
    671             WINDOWS_CHANGE_LAYER,
    672             WINDOWS_CHANGE_ACTIVE,
    673             WINDOWS_CHANGE_FOCUSED,
    674             WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED,
    675             WINDOWS_CHANGE_PARENT,
    676             WINDOWS_CHANGE_CHILDREN,
    677             WINDOWS_CHANGE_PIP
    678     })
    679     public @interface WindowsChangeTypes {}
    680 
    681     /** @hide */
    682     @Retention(RetentionPolicy.SOURCE)
    683     @IntDef(flag = true, prefix = { "CONTENT_CHANGE_TYPE_" },
    684             value = {
    685                     CONTENT_CHANGE_TYPE_UNDEFINED,
    686                     CONTENT_CHANGE_TYPE_SUBTREE,
    687                     CONTENT_CHANGE_TYPE_TEXT,
    688                     CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION,
    689                     CONTENT_CHANGE_TYPE_PANE_TITLE
    690             })
    691     public @interface ContentChangeTypes {}
    692 
    693     /** @hide */
    694     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
    695             TYPE_VIEW_CLICKED,
    696             TYPE_VIEW_LONG_CLICKED,
    697             TYPE_VIEW_SELECTED,
    698             TYPE_VIEW_FOCUSED,
    699             TYPE_VIEW_TEXT_CHANGED,
    700             TYPE_WINDOW_STATE_CHANGED,
    701             TYPE_NOTIFICATION_STATE_CHANGED,
    702             TYPE_VIEW_HOVER_ENTER,
    703             TYPE_VIEW_HOVER_EXIT,
    704             TYPE_TOUCH_EXPLORATION_GESTURE_START,
    705             TYPE_TOUCH_EXPLORATION_GESTURE_END,
    706             TYPE_WINDOW_CONTENT_CHANGED,
    707             TYPE_VIEW_SCROLLED,
    708             TYPE_VIEW_TEXT_SELECTION_CHANGED,
    709             TYPE_ANNOUNCEMENT,
    710             TYPE_VIEW_ACCESSIBILITY_FOCUSED,
    711             TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED,
    712             TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
    713             TYPE_GESTURE_DETECTION_START,
    714             TYPE_GESTURE_DETECTION_END,
    715             TYPE_TOUCH_INTERACTION_START,
    716             TYPE_TOUCH_INTERACTION_END,
    717             TYPE_WINDOWS_CHANGED,
    718             TYPE_VIEW_CONTEXT_CLICKED,
    719             TYPE_ASSIST_READING_CONTEXT
    720     })
    721     @Retention(RetentionPolicy.SOURCE)
    722     public @interface EventType {}
    723 
    724     /**
    725      * Mask for {@link AccessibilityEvent} all types.
    726      *
    727      * @see #TYPE_VIEW_CLICKED
    728      * @see #TYPE_VIEW_LONG_CLICKED
    729      * @see #TYPE_VIEW_SELECTED
    730      * @see #TYPE_VIEW_FOCUSED
    731      * @see #TYPE_VIEW_TEXT_CHANGED
    732      * @see #TYPE_WINDOW_STATE_CHANGED
    733      * @see #TYPE_NOTIFICATION_STATE_CHANGED
    734      * @see #TYPE_VIEW_HOVER_ENTER
    735      * @see #TYPE_VIEW_HOVER_EXIT
    736      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
    737      * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
    738      * @see #TYPE_WINDOW_CONTENT_CHANGED
    739      * @see #TYPE_VIEW_SCROLLED
    740      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
    741      * @see #TYPE_ANNOUNCEMENT
    742      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
    743      * @see #TYPE_GESTURE_DETECTION_START
    744      * @see #TYPE_GESTURE_DETECTION_END
    745      * @see #TYPE_TOUCH_INTERACTION_START
    746      * @see #TYPE_TOUCH_INTERACTION_END
    747      * @see #TYPE_WINDOWS_CHANGED
    748      * @see #TYPE_VIEW_CONTEXT_CLICKED
    749      */
    750     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
    751 
    752     private static final int MAX_POOL_SIZE = 10;
    753     private static final SynchronizedPool<AccessibilityEvent> sPool =
    754             new SynchronizedPool<>(MAX_POOL_SIZE);
    755 
    756     private @EventType int mEventType;
    757     private CharSequence mPackageName;
    758     private long mEventTime;
    759     int mMovementGranularity;
    760     int mAction;
    761     int mContentChangeTypes;
    762     int mWindowChangeTypes;
    763 
    764     /**
    765      * The stack trace describing where this event originated from on the app side.
    766      * Only populated if {@link #DEBUG_ORIGIN} is enabled
    767      * Can be inspected(e.g. printed) from an
    768      * {@link android.accessibilityservice.AccessibilityService} to trace where particular events
    769      * are being dispatched from.
    770      *
    771      * @hide
    772      */
    773     public StackTraceElement[] originStackTrace = null;
    774 
    775     private ArrayList<AccessibilityRecord> mRecords;
    776 
    777     /*
    778      * Hide constructor from clients.
    779      */
    780     private AccessibilityEvent() {
    781     }
    782 
    783     /**
    784      * Initialize an event from another one.
    785      *
    786      * @param event The event to initialize from.
    787      */
    788     void init(AccessibilityEvent event) {
    789         super.init(event);
    790         mEventType = event.mEventType;
    791         mMovementGranularity = event.mMovementGranularity;
    792         mAction = event.mAction;
    793         mContentChangeTypes = event.mContentChangeTypes;
    794         mWindowChangeTypes = event.mWindowChangeTypes;
    795         mEventTime = event.mEventTime;
    796         mPackageName = event.mPackageName;
    797         if (DEBUG_ORIGIN) originStackTrace = event.originStackTrace;
    798     }
    799 
    800     /**
    801      * Sets if this instance is sealed.
    802      *
    803      * @param sealed Whether is sealed.
    804      *
    805      * @hide
    806      */
    807     @Override
    808     public void setSealed(boolean sealed) {
    809         super.setSealed(sealed);
    810         final List<AccessibilityRecord> records = mRecords;
    811         if (records != null) {
    812             final int recordCount = records.size();
    813             for (int i = 0; i < recordCount; i++) {
    814                 AccessibilityRecord record = records.get(i);
    815                 record.setSealed(sealed);
    816             }
    817         }
    818     }
    819 
    820     /**
    821      * Gets the number of records contained in the event.
    822      *
    823      * @return The number of records.
    824      */
    825     public int getRecordCount() {
    826         return mRecords == null ? 0 : mRecords.size();
    827     }
    828 
    829     /**
    830      * Appends an {@link AccessibilityRecord} to the end of event records.
    831      *
    832      * @param record The record to append.
    833      *
    834      * @throws IllegalStateException If called from an AccessibilityService.
    835      */
    836     public void appendRecord(AccessibilityRecord record) {
    837         enforceNotSealed();
    838         if (mRecords == null) {
    839             mRecords = new ArrayList<AccessibilityRecord>();
    840         }
    841         mRecords.add(record);
    842     }
    843 
    844     /**
    845      * Gets the record at a given index.
    846      *
    847      * @param index The index.
    848      * @return The record at the specified index.
    849      */
    850     public AccessibilityRecord getRecord(int index) {
    851         if (mRecords == null) {
    852             throw new IndexOutOfBoundsException("Invalid index " + index + ", size is 0");
    853         }
    854         return mRecords.get(index);
    855     }
    856 
    857     /**
    858      * Gets the event type.
    859      *
    860      * @return The event type.
    861      */
    862     public @EventType int getEventType() {
    863         return mEventType;
    864     }
    865 
    866     /**
    867      * Gets the bit mask of change types signaled by a
    868      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event or {@link #TYPE_WINDOW_STATE_CHANGED}. A single
    869      * event may represent multiple change types.
    870      *
    871      * @return The bit mask of change types. One or more of:
    872      *         <ul>
    873      *         <li>{@link #CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION}
    874      *         <li>{@link #CONTENT_CHANGE_TYPE_SUBTREE}
    875      *         <li>{@link #CONTENT_CHANGE_TYPE_TEXT}
    876      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_TITLE}
    877      *         <li>{@link #CONTENT_CHANGE_TYPE_UNDEFINED}
    878      *         </ul>
    879      */
    880     @ContentChangeTypes
    881     public int getContentChangeTypes() {
    882         return mContentChangeTypes;
    883     }
    884 
    885     private static String contentChangeTypesToString(int types) {
    886         return BitUtils.flagsToString(types, AccessibilityEvent::singleContentChangeTypeToString);
    887     }
    888 
    889     private static String singleContentChangeTypeToString(int type) {
    890         switch (type) {
    891             case CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION: {
    892                 return "CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION";
    893             }
    894             case CONTENT_CHANGE_TYPE_SUBTREE: return "CONTENT_CHANGE_TYPE_SUBTREE";
    895             case CONTENT_CHANGE_TYPE_TEXT: return "CONTENT_CHANGE_TYPE_TEXT";
    896             case CONTENT_CHANGE_TYPE_PANE_TITLE: return "CONTENT_CHANGE_TYPE_PANE_TITLE";
    897             case CONTENT_CHANGE_TYPE_UNDEFINED: return "CONTENT_CHANGE_TYPE_UNDEFINED";
    898             default: return Integer.toHexString(type);
    899         }
    900     }
    901 
    902     /**
    903      * Sets the bit mask of node tree changes signaled by an
    904      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
    905      *
    906      * @param changeTypes The bit mask of change types.
    907      * @throws IllegalStateException If called from an AccessibilityService.
    908      * @see #getContentChangeTypes()
    909      */
    910     public void setContentChangeTypes(@ContentChangeTypes int changeTypes) {
    911         enforceNotSealed();
    912         mContentChangeTypes = changeTypes;
    913     }
    914 
    915     /**
    916      * Get the bit mask of change types signaled by a {@link #TYPE_WINDOWS_CHANGED} event. A
    917      * single event may represent multiple change types.
    918      *
    919      * @return The bit mask of change types.
    920      */
    921     @WindowsChangeTypes
    922     public int getWindowChanges() {
    923         return mWindowChangeTypes;
    924     }
    925 
    926     /** @hide  */
    927     public void setWindowChanges(@WindowsChangeTypes int changes) {
    928         mWindowChangeTypes = changes;
    929     }
    930 
    931     private static String windowChangeTypesToString(@WindowsChangeTypes int types) {
    932         return BitUtils.flagsToString(types, AccessibilityEvent::singleWindowChangeTypeToString);
    933     }
    934 
    935     private static String singleWindowChangeTypeToString(int type) {
    936         switch (type) {
    937             case WINDOWS_CHANGE_ADDED: return "WINDOWS_CHANGE_ADDED";
    938             case WINDOWS_CHANGE_REMOVED: return "WINDOWS_CHANGE_REMOVED";
    939             case WINDOWS_CHANGE_TITLE: return "WINDOWS_CHANGE_TITLE";
    940             case WINDOWS_CHANGE_BOUNDS: return "WINDOWS_CHANGE_BOUNDS";
    941             case WINDOWS_CHANGE_LAYER: return "WINDOWS_CHANGE_LAYER";
    942             case WINDOWS_CHANGE_ACTIVE: return "WINDOWS_CHANGE_ACTIVE";
    943             case WINDOWS_CHANGE_FOCUSED: return "WINDOWS_CHANGE_FOCUSED";
    944             case WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED:
    945                 return "WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED";
    946             case WINDOWS_CHANGE_PARENT: return "WINDOWS_CHANGE_PARENT";
    947             case WINDOWS_CHANGE_CHILDREN: return "WINDOWS_CHANGE_CHILDREN";
    948             default: return Integer.toHexString(type);
    949         }
    950     }
    951 
    952     /**
    953      * Sets the event type.
    954      *
    955      * @param eventType The event type.
    956      *
    957      * @throws IllegalStateException If called from an AccessibilityService.
    958      */
    959     public void setEventType(@EventType int eventType) {
    960         enforceNotSealed();
    961         mEventType = eventType;
    962     }
    963 
    964     /**
    965      * Gets the time in which this event was sent.
    966      *
    967      * @return The event time.
    968      */
    969     public long getEventTime() {
    970         return mEventTime;
    971     }
    972 
    973     /**
    974      * Sets the time in which this event was sent.
    975      *
    976      * @param eventTime The event time.
    977      *
    978      * @throws IllegalStateException If called from an AccessibilityService.
    979      */
    980     public void setEventTime(long eventTime) {
    981         enforceNotSealed();
    982         mEventTime = eventTime;
    983     }
    984 
    985     /**
    986      * Gets the package name of the source.
    987      *
    988      * @return The package name.
    989      */
    990     public CharSequence getPackageName() {
    991         return mPackageName;
    992     }
    993 
    994     /**
    995      * Sets the package name of the source.
    996      *
    997      * @param packageName The package name.
    998      *
    999      * @throws IllegalStateException If called from an AccessibilityService.
   1000      */
   1001     public void setPackageName(CharSequence packageName) {
   1002         enforceNotSealed();
   1003         mPackageName = packageName;
   1004     }
   1005 
   1006     /**
   1007      * Sets the movement granularity that was traversed.
   1008      *
   1009      * @param granularity The granularity.
   1010      *
   1011      * @throws IllegalStateException If called from an AccessibilityService.
   1012      */
   1013     public void setMovementGranularity(int granularity) {
   1014         enforceNotSealed();
   1015         mMovementGranularity = granularity;
   1016     }
   1017 
   1018     /**
   1019      * Gets the movement granularity that was traversed.
   1020      *
   1021      * @return The granularity.
   1022      */
   1023     public int getMovementGranularity() {
   1024         return mMovementGranularity;
   1025     }
   1026 
   1027     /**
   1028      * Sets the performed action that triggered this event.
   1029      * <p>
   1030      * Valid actions are defined in {@link AccessibilityNodeInfo}:
   1031      * <ul>
   1032      * <li>{@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}
   1033      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
   1034      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS}
   1035      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION}
   1036      * <li>{@link AccessibilityNodeInfo#ACTION_CLICK}
   1037      * <li>etc.
   1038      * </ul>
   1039      *
   1040      * @param action The action.
   1041      * @throws IllegalStateException If called from an AccessibilityService.
   1042      * @see AccessibilityNodeInfo#performAction(int)
   1043      */
   1044     public void setAction(int action) {
   1045         enforceNotSealed();
   1046         mAction = action;
   1047     }
   1048 
   1049     /**
   1050      * Gets the performed action that triggered this event.
   1051      *
   1052      * @return The action.
   1053      */
   1054     public int getAction() {
   1055         return mAction;
   1056     }
   1057 
   1058     /**
   1059      * Convenience method to obtain a {@link #TYPE_WINDOWS_CHANGED} event for a specific window and
   1060      * change set.
   1061      *
   1062      * @param windowId The ID of the window that changed
   1063      * @param windowChangeTypes The changes to populate
   1064      * @return An instance of a TYPE_WINDOWS_CHANGED, populated with the requested fields and with
   1065      *         importantForAccessibility set to {@code true}.
   1066      *
   1067      * @hide
   1068      */
   1069     public static AccessibilityEvent obtainWindowsChangedEvent(
   1070             int windowId, int windowChangeTypes) {
   1071         final AccessibilityEvent event = AccessibilityEvent.obtain(TYPE_WINDOWS_CHANGED);
   1072         event.setWindowId(windowId);
   1073         event.setWindowChanges(windowChangeTypes);
   1074         event.setImportantForAccessibility(true);
   1075         return event;
   1076     }
   1077 
   1078     /**
   1079      * Returns a cached instance if such is available or a new one is
   1080      * instantiated with its type property set.
   1081      *
   1082      * @param eventType The event type.
   1083      * @return An instance.
   1084      */
   1085     public static AccessibilityEvent obtain(int eventType) {
   1086         AccessibilityEvent event = AccessibilityEvent.obtain();
   1087         event.setEventType(eventType);
   1088         return event;
   1089     }
   1090 
   1091     /**
   1092      * Returns a cached instance if such is available or a new one is
   1093      * created. The returned instance is initialized from the given
   1094      * <code>event</code>.
   1095      *
   1096      * @param event The other event.
   1097      * @return An instance.
   1098      */
   1099     public static AccessibilityEvent obtain(AccessibilityEvent event) {
   1100         AccessibilityEvent eventClone = AccessibilityEvent.obtain();
   1101         eventClone.init(event);
   1102 
   1103         if (event.mRecords != null) {
   1104             final int recordCount = event.mRecords.size();
   1105             eventClone.mRecords = new ArrayList<AccessibilityRecord>(recordCount);
   1106             for (int i = 0; i < recordCount; i++) {
   1107                 final AccessibilityRecord record = event.mRecords.get(i);
   1108                 final AccessibilityRecord recordClone = AccessibilityRecord.obtain(record);
   1109                 eventClone.mRecords.add(recordClone);
   1110             }
   1111         }
   1112 
   1113         return eventClone;
   1114     }
   1115 
   1116     /**
   1117      * Returns a cached instance if such is available or a new one is
   1118      * instantiated.
   1119      *
   1120      * @return An instance.
   1121      */
   1122     public static AccessibilityEvent obtain() {
   1123         AccessibilityEvent event = sPool.acquire();
   1124         if (event == null) event = new AccessibilityEvent();
   1125         if (DEBUG_ORIGIN) event.originStackTrace = Thread.currentThread().getStackTrace();
   1126         return event;
   1127     }
   1128 
   1129     /**
   1130      * Recycles an instance back to be reused.
   1131      * <p>
   1132      *   <b>Note: You must not touch the object after calling this function.</b>
   1133      * </p>
   1134      *
   1135      * @throws IllegalStateException If the event is already recycled.
   1136      */
   1137     @Override
   1138     public void recycle() {
   1139         clear();
   1140         sPool.release(this);
   1141     }
   1142 
   1143     /**
   1144      * Clears the state of this instance.
   1145      *
   1146      * @hide
   1147      */
   1148     @Override
   1149     protected void clear() {
   1150         super.clear();
   1151         mEventType = 0;
   1152         mMovementGranularity = 0;
   1153         mAction = 0;
   1154         mContentChangeTypes = 0;
   1155         mWindowChangeTypes = 0;
   1156         mPackageName = null;
   1157         mEventTime = 0;
   1158         if (mRecords != null) {
   1159             while (!mRecords.isEmpty()) {
   1160                 AccessibilityRecord record = mRecords.remove(0);
   1161                 record.recycle();
   1162             }
   1163         }
   1164         if (DEBUG_ORIGIN) originStackTrace = null;
   1165     }
   1166 
   1167     /**
   1168      * Creates a new instance from a {@link Parcel}.
   1169      *
   1170      * @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
   1171      */
   1172     public void initFromParcel(Parcel parcel) {
   1173         mSealed = (parcel.readInt() == 1);
   1174         mEventType = parcel.readInt();
   1175         mMovementGranularity = parcel.readInt();
   1176         mAction = parcel.readInt();
   1177         mContentChangeTypes = parcel.readInt();
   1178         mWindowChangeTypes = parcel.readInt();
   1179         mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1180         mEventTime = parcel.readLong();
   1181         mConnectionId = parcel.readInt();
   1182         readAccessibilityRecordFromParcel(this, parcel);
   1183 
   1184         // Read the records.
   1185         final int recordCount = parcel.readInt();
   1186         if (recordCount > 0) {
   1187             mRecords = new ArrayList<>(recordCount);
   1188             for (int i = 0; i < recordCount; i++) {
   1189                 AccessibilityRecord record = AccessibilityRecord.obtain();
   1190                 readAccessibilityRecordFromParcel(record, parcel);
   1191                 record.mConnectionId = mConnectionId;
   1192                 mRecords.add(record);
   1193             }
   1194         }
   1195 
   1196         if (DEBUG_ORIGIN) {
   1197             originStackTrace = new StackTraceElement[parcel.readInt()];
   1198             for (int i = 0; i < originStackTrace.length; i++) {
   1199                 originStackTrace[i] = new StackTraceElement(
   1200                         parcel.readString(),
   1201                         parcel.readString(),
   1202                         parcel.readString(),
   1203                         parcel.readInt());
   1204             }
   1205         }
   1206     }
   1207 
   1208     /**
   1209      * Reads an {@link AccessibilityRecord} from a parcel.
   1210      *
   1211      * @param record The record to initialize.
   1212      * @param parcel The parcel to read from.
   1213      */
   1214     private void readAccessibilityRecordFromParcel(AccessibilityRecord record,
   1215             Parcel parcel) {
   1216         record.mBooleanProperties = parcel.readInt();
   1217         record.mCurrentItemIndex = parcel.readInt();
   1218         record.mItemCount = parcel.readInt();
   1219         record.mFromIndex = parcel.readInt();
   1220         record.mToIndex = parcel.readInt();
   1221         record.mScrollX = parcel.readInt();
   1222         record.mScrollY =  parcel.readInt();
   1223         record.mScrollDeltaX =  parcel.readInt();
   1224         record.mScrollDeltaY =  parcel.readInt();
   1225         record.mMaxScrollX = parcel.readInt();
   1226         record.mMaxScrollY =  parcel.readInt();
   1227         record.mAddedCount = parcel.readInt();
   1228         record.mRemovedCount = parcel.readInt();
   1229         record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1230         record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1231         record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
   1232         record.mParcelableData = parcel.readParcelable(null);
   1233         parcel.readList(record.mText, null);
   1234         record.mSourceWindowId = parcel.readInt();
   1235         record.mSourceNodeId = parcel.readLong();
   1236         record.mSealed = (parcel.readInt() == 1);
   1237     }
   1238 
   1239     /**
   1240      * {@inheritDoc}
   1241      */
   1242     public void writeToParcel(Parcel parcel, int flags) {
   1243         parcel.writeInt(isSealed() ? 1 : 0);
   1244         parcel.writeInt(mEventType);
   1245         parcel.writeInt(mMovementGranularity);
   1246         parcel.writeInt(mAction);
   1247         parcel.writeInt(mContentChangeTypes);
   1248         parcel.writeInt(mWindowChangeTypes);
   1249         TextUtils.writeToParcel(mPackageName, parcel, 0);
   1250         parcel.writeLong(mEventTime);
   1251         parcel.writeInt(mConnectionId);
   1252         writeAccessibilityRecordToParcel(this, parcel, flags);
   1253 
   1254         // Write the records.
   1255         final int recordCount = getRecordCount();
   1256         parcel.writeInt(recordCount);
   1257         for (int i = 0; i < recordCount; i++) {
   1258             AccessibilityRecord record = mRecords.get(i);
   1259             writeAccessibilityRecordToParcel(record, parcel, flags);
   1260         }
   1261 
   1262         if (DEBUG_ORIGIN) {
   1263             if (originStackTrace == null) originStackTrace = Thread.currentThread().getStackTrace();
   1264             parcel.writeInt(originStackTrace.length);
   1265             for (StackTraceElement element : originStackTrace) {
   1266                 parcel.writeString(element.getClassName());
   1267                 parcel.writeString(element.getMethodName());
   1268                 parcel.writeString(element.getFileName());
   1269                 parcel.writeInt(element.getLineNumber());
   1270             }
   1271         }
   1272     }
   1273 
   1274     /**
   1275      * Writes an {@link AccessibilityRecord} to a parcel.
   1276      *
   1277      * @param record The record to write.
   1278      * @param parcel The parcel to which to write.
   1279      */
   1280     private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel,
   1281             int flags) {
   1282         parcel.writeInt(record.mBooleanProperties);
   1283         parcel.writeInt(record.mCurrentItemIndex);
   1284         parcel.writeInt(record.mItemCount);
   1285         parcel.writeInt(record.mFromIndex);
   1286         parcel.writeInt(record.mToIndex);
   1287         parcel.writeInt(record.mScrollX);
   1288         parcel.writeInt(record.mScrollY);
   1289         parcel.writeInt(record.mScrollDeltaX);
   1290         parcel.writeInt(record.mScrollDeltaY);
   1291         parcel.writeInt(record.mMaxScrollX);
   1292         parcel.writeInt(record.mMaxScrollY);
   1293         parcel.writeInt(record.mAddedCount);
   1294         parcel.writeInt(record.mRemovedCount);
   1295         TextUtils.writeToParcel(record.mClassName, parcel, flags);
   1296         TextUtils.writeToParcel(record.mContentDescription, parcel, flags);
   1297         TextUtils.writeToParcel(record.mBeforeText, parcel, flags);
   1298         parcel.writeParcelable(record.mParcelableData, flags);
   1299         parcel.writeList(record.mText);
   1300         parcel.writeInt(record.mSourceWindowId);
   1301         parcel.writeLong(record.mSourceNodeId);
   1302         parcel.writeInt(record.mSealed ? 1 : 0);
   1303     }
   1304 
   1305     /**
   1306      * {@inheritDoc}
   1307      */
   1308     public int describeContents() {
   1309         return 0;
   1310     }
   1311 
   1312     @Override
   1313     public String toString() {
   1314         StringBuilder builder = new StringBuilder();
   1315         builder.append("EventType: ").append(eventTypeToString(mEventType));
   1316         builder.append("; EventTime: ").append(mEventTime);
   1317         builder.append("; PackageName: ").append(mPackageName);
   1318         if (!DEBUG_CONCISE_TOSTRING || mMovementGranularity != 0) {
   1319             builder.append("; MovementGranularity: ").append(mMovementGranularity);
   1320         }
   1321         if (!DEBUG_CONCISE_TOSTRING || mAction != 0) {
   1322             builder.append("; Action: ").append(mAction);
   1323         }
   1324         if (!DEBUG_CONCISE_TOSTRING || mContentChangeTypes != 0) {
   1325             builder.append("; ContentChangeTypes: ").append(
   1326                     contentChangeTypesToString(mContentChangeTypes));
   1327         }
   1328         if (!DEBUG_CONCISE_TOSTRING || mWindowChangeTypes != 0) {
   1329             builder.append("; WindowChangeTypes: ").append(
   1330                     windowChangeTypesToString(mWindowChangeTypes));
   1331         }
   1332         super.appendTo(builder);
   1333         if (DEBUG || DEBUG_CONCISE_TOSTRING) {
   1334             if (!DEBUG_CONCISE_TOSTRING) {
   1335                 builder.append("\n");
   1336             }
   1337             if (DEBUG) {
   1338                 builder.append("; SourceWindowId: ").append(mSourceWindowId);
   1339                 builder.append("; SourceNodeId: ").append(mSourceNodeId);
   1340             }
   1341             for (int i = 0; i < getRecordCount(); i++) {
   1342                 builder.append("  Record ").append(i).append(":");
   1343                 getRecord(i).appendTo(builder).append("\n");
   1344             }
   1345         } else {
   1346             builder.append("; recordCount: ").append(getRecordCount());
   1347         }
   1348         return builder.toString();
   1349     }
   1350 
   1351     /**
   1352      * Returns the string representation of an event type. For example,
   1353      * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
   1354      *
   1355      * @param eventType The event type
   1356      * @return The string representation.
   1357      */
   1358     public static String eventTypeToString(int eventType) {
   1359         if (eventType == TYPES_ALL_MASK) {
   1360             return "TYPES_ALL_MASK";
   1361         }
   1362         StringBuilder builder = new StringBuilder();
   1363         int eventTypeCount = 0;
   1364         while (eventType != 0) {
   1365             final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType);
   1366             eventType &= ~eventTypeFlag;
   1367 
   1368             if (eventTypeCount > 0) {
   1369                 builder.append(", ");
   1370             }
   1371             builder.append(singleEventTypeToString(eventTypeFlag));
   1372 
   1373             eventTypeCount++;
   1374         }
   1375         if (eventTypeCount > 1) {
   1376             builder.insert(0, '[');
   1377             builder.append(']');
   1378         }
   1379         return builder.toString();
   1380     }
   1381 
   1382     private static String singleEventTypeToString(int eventType) {
   1383         switch (eventType) {
   1384             case TYPE_VIEW_CLICKED: return "TYPE_VIEW_CLICKED";
   1385             case TYPE_VIEW_LONG_CLICKED: return "TYPE_VIEW_LONG_CLICKED";
   1386             case TYPE_VIEW_SELECTED: return "TYPE_VIEW_SELECTED";
   1387             case TYPE_VIEW_FOCUSED: return "TYPE_VIEW_FOCUSED";
   1388             case TYPE_VIEW_TEXT_CHANGED: return "TYPE_VIEW_TEXT_CHANGED";
   1389             case TYPE_WINDOW_STATE_CHANGED: return "TYPE_WINDOW_STATE_CHANGED";
   1390             case TYPE_VIEW_HOVER_ENTER: return "TYPE_VIEW_HOVER_ENTER";
   1391             case TYPE_VIEW_HOVER_EXIT: return "TYPE_VIEW_HOVER_EXIT";
   1392             case TYPE_NOTIFICATION_STATE_CHANGED: return "TYPE_NOTIFICATION_STATE_CHANGED";
   1393             case TYPE_TOUCH_EXPLORATION_GESTURE_START: {
   1394                 return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
   1395             }
   1396             case TYPE_TOUCH_EXPLORATION_GESTURE_END: return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
   1397             case TYPE_WINDOW_CONTENT_CHANGED: return "TYPE_WINDOW_CONTENT_CHANGED";
   1398             case TYPE_VIEW_TEXT_SELECTION_CHANGED: return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
   1399             case TYPE_VIEW_SCROLLED: return "TYPE_VIEW_SCROLLED";
   1400             case TYPE_ANNOUNCEMENT: return "TYPE_ANNOUNCEMENT";
   1401             case TYPE_VIEW_ACCESSIBILITY_FOCUSED: return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
   1402             case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
   1403                 return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
   1404             }
   1405             case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
   1406                 return "TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY";
   1407             }
   1408             case TYPE_GESTURE_DETECTION_START: return "TYPE_GESTURE_DETECTION_START";
   1409             case TYPE_GESTURE_DETECTION_END: return "TYPE_GESTURE_DETECTION_END";
   1410             case TYPE_TOUCH_INTERACTION_START: return "TYPE_TOUCH_INTERACTION_START";
   1411             case TYPE_TOUCH_INTERACTION_END: return "TYPE_TOUCH_INTERACTION_END";
   1412             case TYPE_WINDOWS_CHANGED: return "TYPE_WINDOWS_CHANGED";
   1413             case TYPE_VIEW_CONTEXT_CLICKED: return "TYPE_VIEW_CONTEXT_CLICKED";
   1414             case TYPE_ASSIST_READING_CONTEXT: return "TYPE_ASSIST_READING_CONTEXT";
   1415             default: return Integer.toHexString(eventType);
   1416         }
   1417     }
   1418 
   1419     /**
   1420      * @see Parcelable.Creator
   1421      */
   1422     public static final Parcelable.Creator<AccessibilityEvent> CREATOR =
   1423             new Parcelable.Creator<AccessibilityEvent>() {
   1424         public AccessibilityEvent createFromParcel(Parcel parcel) {
   1425             AccessibilityEvent event = AccessibilityEvent.obtain();
   1426             event.initFromParcel(parcel);
   1427             return event;
   1428         }
   1429 
   1430         public AccessibilityEvent[] newArray(int size) {
   1431             return new AccessibilityEvent[size];
   1432         }
   1433     };
   1434 }
   1435