AccessibilityEvent.java revision d116d7c78a9c53f30a73bf273bd7618312cf3847
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.view.accessibility; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21import android.text.TextUtils; 22 23import java.util.ArrayList; 24import java.util.List; 25 26/** 27 * <p> 28 * This class represents accessibility events that are sent by the system when 29 * something notable happens in the user interface. For example, when a 30 * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc. 31 * </p> 32 * <p> 33 * An accessibility event is fired by an individual view which populates the event with 34 * data for its state and requests from its parent to send the event to interested 35 * parties. The parent can optionally add an {@link AccessibilityRecord} for itself before 36 * dispatching a similar request to its parent. A parent can also choose not to respect the 37 * request for sending an event. The accessibility event is sent by the topmost view in the 38 * view tree. Therefore, an {@link android.accessibilityservice.AccessibilityService} can 39 * explore all records in an accessibility event to obtain more information about the 40 * context in which the event was fired. 41 * </p> 42 * <p> 43 * The main purpose of an accessibility event is to expose enough information for an 44 * {@link android.accessibilityservice.AccessibilityService} to provide meaningful feedback 45 * to the user. Sometimes however, an accessibility service may need more contextual 46 * information then the one in the event pay-load. In such cases the service can obtain 47 * the event source which is an {@link AccessibilityNodeInfo} (snapshot of a View state) 48 * which can be used for exploring the window content. Note that the privilege for accessing 49 * an event's source, thus the window content, has to be explicitly requested. For more 50 * details refer to {@link android.accessibilityservice.AccessibilityService}. If an 51 * accessibility service has not requested to retrieve the window content the event will 52 * not contain reference to its source. Also for events of type 53 * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available. 54 * </p> 55 * <p> 56 * This class represents various semantically different accessibility event 57 * types. Each event type has an associated set of related properties. In other 58 * words, each event type is characterized via a subset of the properties exposed 59 * by this class. For each event type there is a corresponding constant defined 60 * in this class. Follows a specification of the event types and their associated properties: 61 * </p> 62 * <p> 63 * <b>VIEW TYPES</b></br> 64 * </p> 65 * <p> 66 * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View} 67 * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.</br> 68 * <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br> 69 * <em>Properties:</em></br> 70 * <ul> 71 * <li>{@link #getEventType()} - The type of the event.</li> 72 * <li>{@link #getSource()} - The source info (for registered clients).</li> 73 * <li>{@link #getClassName()} - The class name of the source.</li> 74 * <li>{@link #getPackageName()} - The package name of the source.</li> 75 * <li>{@link #getEventTime()} - The event time.</li> 76 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 77 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 78 * <li>{@link #isPassword()} - Whether the source is password.</li> 79 * <li>{@link #isChecked()} - Whether the source is checked.</li> 80 * <li>{@link #getContentDescription()} - The content description of the source.</li> 81 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 82 * (without descendants of AdapterView).</li> 83 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 84 * (without descendants of AdapterView).</li> 85 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 86 * inclusive (for descendants of AdapterView).</li> 87 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 88 * inclusive (for descendants of AdapterView).</li> 89 * <li>{@link #getItemCount()} - The total items of the source 90 * (for descendants of AdapterView).</li> 91 * </ul> 92 * </p> 93 * <p> 94 * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View} 95 * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br> 96 * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br> 97 * <em>Properties:</em></br> 98 * <ul> 99 * <li>{@link #getEventType()} - The type of the event.</li> 100 * <li>{@link #getSource()} - The source info (for registered clients).</li> 101 * <li>{@link #getClassName()} - The class name of the source.</li> 102 * <li>{@link #getPackageName()} - The package name of the source.</li> 103 * <li>{@link #getEventTime()} - The event time.</li> 104 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 105 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 106 * <li>{@link #isPassword()} - Whether the source is password.</li> 107 * <li>{@link #isChecked()} - Whether the source is checked.</li> 108 * <li>{@link #getContentDescription()} - The content description of the source.</li> 109 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 110 * (without descendants of AdapterView).</li> 111 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 112 * (without descendants of AdapterView).</li> 113 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 114 * inclusive (for descendants of AdapterView).</li> 115 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 116 * inclusive (for descendants of AdapterView).</li> 117 * <li>{@link #getItemCount()} - The total items of the source 118 * (for descendants of AdapterView).</li> 119 * </ul> 120 * </p> 121 * <p> 122 * <b>View selected</b> - represents the event of selecting an item usually in 123 * the context of an {@link android.widget.AdapterView}.</br> 124 * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br> 125 * <em>Properties:</em></br> 126 * <ul> 127 * <li>{@link #getEventType()} - The type of the event.</li> 128 * <li>{@link #getSource()} - The source info (for registered clients).</li> 129 * <li>{@link #getClassName()} - The class name of the source.</li> 130 * <li>{@link #getPackageName()} - The package name of the source.</li> 131 * <li>{@link #getEventTime()} - The event time.</li> 132 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 133 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 134 * <li>{@link #isPassword()} - Whether the source is password.</li> 135 * <li>{@link #isChecked()} - Whether the source is checked.</li> 136 * <li>{@link #getItemCount()} - The number of selectable items of the source.</li> 137 * <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li> 138 * <li>{@link #getContentDescription()} - The content description of the source.</li> 139 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 140 * (without descendants of AdapterView).</li> 141 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 142 * (without descendants of AdapterView).</li> 143 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 144 * inclusive (for descendants of AdapterView).</li> 145 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 146 * inclusive (for descendants of AdapterView).</li> 147 * <li>{@link #getItemCount()} - The total items of the source 148 * (for descendants of AdapterView).</li> 149 * </ul> 150 * </p> 151 * <p> 152 * <b>View focused</b> - represents the event of focusing a 153 * {@link android.view.View}.</br> 154 * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br> 155 * <em>Properties:</em></br> 156 * <ul> 157 * <li>{@link #getEventType()} - The type of the event.</li> 158 * <li>{@link #getSource()} - The source info (for registered clients).</li> 159 * <li>{@link #getClassName()} - The class name of the source.</li> 160 * <li>{@link #getPackageName()} - The package name of the source.</li> 161 * <li>{@link #getEventTime()} - The event time.</li> 162 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 163 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 164 * <li>{@link #isPassword()} - Whether the source is password.</li> 165 * <li>{@link #isChecked()} - Whether the source is checked.</li> 166 * <li>{@link #getItemCount()} - The number of focusable items on the screen.</li> 167 * <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li> 168 * <li>{@link #getContentDescription()} - The content description of the source.</li> 169 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 170 * (without descendants of AdapterView).</li> 171 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 172 * (without descendants of AdapterView).</li> 173 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 174 * inclusive (for descendants of AdapterView).</li> 175 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 176 * inclusive (for descendants of AdapterView).</li> 177 * <li>{@link #getItemCount()} - The total items of the source 178 * (for descendants of AdapterView).</li> 179 * </ul> 180 * </p> 181 * <p> 182 * <b>View text changed</b> - represents the event of changing the text of an 183 * {@link android.widget.EditText}.</br> 184 * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br> 185 * <em>Properties:</em></br> 186 * <ul> 187 * <li>{@link #getEventType()} - The type of the event.</li> 188 * <li>{@link #getSource()} - The source info (for registered clients).</li> 189 * <li>{@link #getClassName()} - The class name of the source.</li> 190 * <li>{@link #getPackageName()} - The package name of the source.</li> 191 * <li>{@link #getEventTime()} - The event time.</li> 192 * <li>{@link #getText()} - The text of the source.</li> 193 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 194 * <li>{@link #isPassword()} - Whether the source is password.</li> 195 * <li>{@link #isChecked()} - Whether the source is checked.</li> 196 * <li>{@link #getFromIndex()} - The text change start index.</li> 197 * <li>{@link #getAddedCount()} - The number of added characters.</li> 198 * <li>{@link #getRemovedCount()} - The number of removed characters.</li> 199 * <li>{@link #getBeforeText()} - The text of the source before the change.</li> 200 * <li>{@link #getContentDescription()} - The content description of the source.</li> 201 * </ul> 202 * </p> 203 * <p> 204 * <b>View text selection changed</b> - represents the event of changing the text 205 * selection of an {@link android.widget.EditText}.</br> 206 * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br> 207 * <em>Properties:</em></br> 208 * <ul> 209 * <li>{@link #getEventType()} - The type of the event.</li> 210 * <li>{@link #getSource()} - The source info (for registered clients).</li> 211 * <li>{@link #getClassName()} - The class name of the source.</li> 212 * <li>{@link #getPackageName()} - The package name of the source.</li> 213 * <li>{@link #getEventTime()} - The event time.</li> 214 * <li>{@link #getText()} - The text of the source.</li> 215 * <li>{@link #isPassword()} - Whether the source is password.</li> 216 * <li>{@link #getFromIndex()} - The selection start index.</li> 217 * <li>{@link #getToIndex()} - The selection end index.</li> 218 * <li>{@link #getItemCount()} - The length of the source text.</li> 219 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 220 * <li>{@link #getContentDescription()} - The content description of the source.</li> 221 * </ul> 222 * </p> 223 * <p> 224 * <b>View scrolled</b> - represents the event of scrolling a view. If 225 * the source is a descendant of {@link android.widget.AdapterView} the 226 * scroll is reported in terms of visible items - the first visible item, 227 * the last visible item, and the total items - because the the source 228 * is unaware of its pixel size since its adapter is responsible for 229 * creating views. In all other cases the scroll is reported as the current 230 * scroll on the X and Y axis respectively plus the height of the source in 231 * pixels.</br> 232 * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</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 #getText()} - The text of the source's sub-tree.</li> 241 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 242 * <li>{@link #getContentDescription()} - The content description of the source.</li> 243 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 244 * (without descendants of AdapterView).</li> 245 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 246 * (without descendants of AdapterView).</li> 247 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 248 * inclusive (for descendants of AdapterView).</li> 249 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 250 * inclusive (for descendants of AdapterView).</li> 251 * <li>{@link #getItemCount()} - The total items of the source 252 * (for descendants of AdapterView).</li> 253 * </ul> 254 * <em>Note:</em> This event type is not dispatched to descendants though 255 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 256 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 257 * source {@link android.view.View} and the sub-tree rooted at it will not receive 258 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 259 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 260 * text content to such events is by setting the 261 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 262 * view.</br> 263 * </p> 264 * <p> 265 * <b>TRANSITION TYPES</b></br> 266 * </p> 267 * <p> 268 * <b>Window state changed</b> - represents the event of opening a 269 * {@link android.widget.PopupWindow}, {@link android.view.Menu}, 270 * {@link android.app.Dialog}, etc.</br> 271 * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br> 272 * <em>Properties:</em></br> 273 * <ul> 274 * <li>{@link #getEventType()} - The type of the event.</li> 275 * <li>{@link #getSource()} - The source info (for registered clients).</li> 276 * <li>{@link #getClassName()} - The class name of the source.</li> 277 * <li>{@link #getPackageName()} - The package name of the source.</li> 278 * <li>{@link #getEventTime()} - The event time.</li> 279 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 280 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 281 * </ul> 282 * </p> 283 * <p> 284 * <b>Window content changed</b> - represents the event of change in the 285 * content of a window. This change can be adding/removing view, changing 286 * a view size, etc.</br> 287 * </p> 288 * <p> 289 * <strong>Note:</strong> This event is fired only for the window source of the 290 * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED} 291 * and its purpose is to notify clients that the content of the user interaction 292 * window has changed.</br> 293 * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br> 294 * <em>Properties:</em></br> 295 * <ul> 296 * <li>{@link #getEventType()} - The type of the event.</li> 297 * <li>{@link #getSource()} - The source info (for registered clients).</li> 298 * <li>{@link #getClassName()} - The class name of the source.</li> 299 * <li>{@link #getPackageName()} - The package name of the source.</li> 300 * <li>{@link #getEventTime()} - The event time.</li> 301 * </ul> 302 * <em>Note:</em> This event type is not dispatched to descendants though 303 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 304 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 305 * source {@link android.view.View} and the sub-tree rooted at it will not receive 306 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 307 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 308 * text content to such events is by setting the 309 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 310 * view.</br> 311 * </p> 312 * <p> 313 * <b>NOTIFICATION TYPES</b></br> 314 * </p> 315 * <p> 316 * <b>Notification state changed</b> - represents the event showing 317 * {@link android.app.Notification}.</br> 318 * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br> 319 * <em>Properties:</em></br> 320 * <ul> 321 * <li>{@link #getEventType()} - The type of the event.</li> 322 * <li>{@link #getClassName()} - The class name of the source.</li> 323 * <li>{@link #getPackageName()} - The package name of the source.</li> 324 * <li>{@link #getEventTime()} - The event time.</li> 325 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 326 * <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li> 327 * <li>{@link #getText()} - Text for providing more context.</li> 328 * </ul> 329 * <em>Note:</em> This event type is not dispatched to descendants though 330 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 331 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 332 * source {@link android.view.View} and the sub-tree rooted at it will not receive 333 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 334 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 335 * text content to such events is by setting the 336 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 337 * view.</br> 338 * </p> 339 * <p> 340 * <b>EXPLORATION TYPES</b></br> 341 * </p> 342 * <p> 343 * <b>View hover enter</b> - represents the event of beginning to hover 344 * over a {@link android.view.View}. The hover may be generated via 345 * exploring the screen by touch or via a pointing device.</br> 346 * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br> 347 * <em>Properties:</em></br> 348 * <ul> 349 * <li>{@link #getEventType()} - The type of the event.</li> 350 * <li>{@link #getSource()} - The source info (for registered clients).</li> 351 * <li>{@link #getClassName()} - The class name of the source.</li> 352 * <li>{@link #getPackageName()} - The package name of the source.</li> 353 * <li>{@link #getEventTime()} - The event time.</li> 354 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 355 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 356 * <li>{@link #getContentDescription()} - The content description of the source.</li> 357 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 358 * (without descendants of AdapterView).</li> 359 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 360 * (without descendants of AdapterView).</li> 361 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 362 * inclusive (for descendants of AdapterView).</li> 363 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 364 * inclusive (for descendants of AdapterView).</li> 365 * <li>{@link #getItemCount()} - The total items of the source 366 * (for descendants of AdapterView).</li> 367 * </ul> 368 * </p> 369 * <b>View hover exit</b> - represents the event of stopping to hover 370 * over a {@link android.view.View}. The hover may be generated via 371 * exploring the screen by touch or via a pointing device.</br> 372 * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br> 373 * <em>Properties:</em></br> 374 * <ul> 375 * <li>{@link #getEventType()} - The type of the event.</li> 376 * <li>{@link #getSource()} - The source info (for registered clients).</li> 377 * <li>{@link #getClassName()} - The class name of the source.</li> 378 * <li>{@link #getPackageName()} - The package name of the source.</li> 379 * <li>{@link #getEventTime()} - The event time.</li> 380 * <li>{@link #getText()} - The text of the source's sub-tree.</li> 381 * <li>{@link #isEnabled()} - Whether the source is enabled.</li> 382 * <li>{@link #getContentDescription()} - The content description of the source.</li> 383 * <li>{@link #getScrollX()} - The offset of the source left edge in pixels 384 * (without descendants of AdapterView).</li> 385 * <li>{@link #getScrollY()} - The offset of the source top edge in pixels 386 * (without descendants of AdapterView).</li> 387 * <li>{@link #getFromIndex()} - The zero based index of the first visible item of the source, 388 * inclusive (for descendants of AdapterView).</li> 389 * <li>{@link #getToIndex()} - The zero based index of the last visible item of the source, 390 * inclusive (for descendants of AdapterView).</li> 391 * <li>{@link #getItemCount()} - The total items of the source 392 * (for descendants of AdapterView).</li> 393 * </ul> 394 * </p> 395 * <p> 396 * <b>Touch exploration gesture start</b> - represents the event of starting a touch 397 * exploring gesture.</br> 398 * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br> 399 * <em>Properties:</em></br> 400 * <ul> 401 * <li>{@link #getEventType()} - The type of the event.</li> 402 * </ul> 403 * <em>Note:</em> This event type is not dispatched to descendants though 404 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 405 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 406 * source {@link android.view.View} and the sub-tree rooted at it will not receive 407 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 408 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 409 * text content to such events is by setting the 410 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 411 * view.</br> 412 * </p> 413 * <p> 414 * <b>Touch exploration gesture end</b> - represents the event of ending a touch 415 * exploring gesture.</br> 416 * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br> 417 * <em>Properties:</em></br> 418 * <ul> 419 * <li>{@link #getEventType()} - The type of the event.</li> 420 * </ul> 421 * <em>Note:</em> This event type is not dispatched to descendants though 422 * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 423 * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event 424 * source {@link android.view.View} and the sub-tree rooted at it will not receive 425 * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent) 426 * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add 427 * text content to such events is by setting the 428 * {@link android.R.styleable#View_contentDescription contentDescription} of the source 429 * view.</br> 430 * </p> 431 * <p> 432 * <b>Security note</b> 433 * <p> 434 * Since an event contains the text of its source privacy can be compromised by leaking 435 * sensitive information such as passwords. To address this issue any event fired in response 436 * to manipulation of a PASSWORD field does NOT CONTAIN the text of the password. 437 * </p> 438 * 439 * @see android.view.accessibility.AccessibilityManager 440 * @see android.accessibilityservice.AccessibilityService 441 * @see AccessibilityNodeInfo 442 */ 443public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable { 444 private static final boolean DEBUG = false; 445 446 /** 447 * Invalid selection/focus position. 448 * 449 * @see #getCurrentItemIndex() 450 */ 451 public static final int INVALID_POSITION = -1; 452 453 /** 454 * Maximum length of the text fields. 455 * 456 * @see #getBeforeText() 457 * @see #getText() 458 * </br> 459 * Note: This constant is no longer needed since there 460 * is no limit on the length of text that is contained 461 * in an accessibility event anymore. 462 */ 463 @Deprecated 464 public static final int MAX_TEXT_LENGTH = 500; 465 466 /** 467 * Represents the event of clicking on a {@link android.view.View} like 468 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 469 */ 470 public static final int TYPE_VIEW_CLICKED = 0x00000001; 471 472 /** 473 * Represents the event of long clicking on a {@link android.view.View} like 474 * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 475 */ 476 public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002; 477 478 /** 479 * Represents the event of selecting an item usually in the context of an 480 * {@link android.widget.AdapterView}. 481 */ 482 public static final int TYPE_VIEW_SELECTED = 0x00000004; 483 484 /** 485 * Represents the event of focusing a {@link android.view.View}. 486 */ 487 public static final int TYPE_VIEW_FOCUSED = 0x00000008; 488 489 /** 490 * Represents the event of changing the text of an {@link android.widget.EditText}. 491 */ 492 public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010; 493 494 /** 495 * Represents the event of opening a {@link android.widget.PopupWindow}, 496 * {@link android.view.Menu}, {@link android.app.Dialog}, etc. 497 */ 498 public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020; 499 500 /** 501 * Represents the event showing a {@link android.app.Notification}. 502 */ 503 public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040; 504 505 /** 506 * Represents the event of a hover enter over a {@link android.view.View}. 507 */ 508 public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080; 509 510 /** 511 * Represents the event of a hover exit over a {@link android.view.View}. 512 */ 513 public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100; 514 515 /** 516 * Represents the event of starting a touch exploration gesture. 517 */ 518 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200; 519 520 /** 521 * Represents the event of ending a touch exploration gesture. 522 */ 523 public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400; 524 525 /** 526 * Represents the event of changing the content of a window. 527 */ 528 public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800; 529 530 /** 531 * Represents the event of scrolling a view. 532 */ 533 public static final int TYPE_VIEW_SCROLLED = 0x00001000; 534 535 /** 536 * Represents the event of changing the selection in an {@link android.widget.EditText}. 537 */ 538 public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000; 539 540 /** 541 * Mask for {@link AccessibilityEvent} all types. 542 * 543 * @see #TYPE_VIEW_CLICKED 544 * @see #TYPE_VIEW_LONG_CLICKED 545 * @see #TYPE_VIEW_SELECTED 546 * @see #TYPE_VIEW_FOCUSED 547 * @see #TYPE_VIEW_TEXT_CHANGED 548 * @see #TYPE_WINDOW_STATE_CHANGED 549 * @see #TYPE_NOTIFICATION_STATE_CHANGED 550 * @see #TYPE_VIEW_HOVER_ENTER 551 * @see #TYPE_VIEW_HOVER_EXIT 552 * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START 553 * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END 554 * @see #TYPE_WINDOW_CONTENT_CHANGED 555 * @see #TYPE_VIEW_SCROLLED 556 * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED 557 */ 558 public static final int TYPES_ALL_MASK = 0xFFFFFFFF; 559 560 private static final int MAX_POOL_SIZE = 10; 561 private static final Object sPoolLock = new Object(); 562 private static AccessibilityEvent sPool; 563 private static int sPoolSize; 564 private AccessibilityEvent mNext; 565 private boolean mIsInPool; 566 567 private int mEventType; 568 private CharSequence mPackageName; 569 private long mEventTime; 570 571 private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>(); 572 573 /* 574 * Hide constructor from clients. 575 */ 576 private AccessibilityEvent() { 577 } 578 579 /** 580 * Initialize an event from another one. 581 * 582 * @param event The event to initialize from. 583 */ 584 void init(AccessibilityEvent event) { 585 super.init(event); 586 mEventType = event.mEventType; 587 mEventTime = event.mEventTime; 588 mPackageName = event.mPackageName; 589 } 590 591 /** 592 * Sets if this instance is sealed. 593 * 594 * @param sealed Whether is sealed. 595 * 596 * @hide 597 */ 598 @Override 599 public void setSealed(boolean sealed) { 600 super.setSealed(sealed); 601 List<AccessibilityRecord> records = mRecords; 602 final int recordCount = records.size(); 603 for (int i = 0; i < recordCount; i++) { 604 AccessibilityRecord record = records.get(i); 605 record.setSealed(sealed); 606 } 607 } 608 609 /** 610 * Gets the number of records contained in the event. 611 * 612 * @return The number of records. 613 */ 614 public int getRecordCount() { 615 return mRecords.size(); 616 } 617 618 /** 619 * Appends an {@link AccessibilityRecord} to the end of event records. 620 * 621 * @param record The record to append. 622 * 623 * @throws IllegalStateException If called from an AccessibilityService. 624 */ 625 public void appendRecord(AccessibilityRecord record) { 626 enforceNotSealed(); 627 mRecords.add(record); 628 } 629 630 /** 631 * Gets the record at a given index. 632 * 633 * @param index The index. 634 * @return The record at the specified index. 635 */ 636 public AccessibilityRecord getRecord(int index) { 637 return mRecords.get(index); 638 } 639 640 /** 641 * Gets the event type. 642 * 643 * @return The event type. 644 */ 645 public int getEventType() { 646 return mEventType; 647 } 648 649 /** 650 * Sets the event type. 651 * 652 * @param eventType The event type. 653 * 654 * @throws IllegalStateException If called from an AccessibilityService. 655 */ 656 public void setEventType(int eventType) { 657 enforceNotSealed(); 658 mEventType = eventType; 659 } 660 661 /** 662 * Gets the time in which this event was sent. 663 * 664 * @return The event time. 665 */ 666 public long getEventTime() { 667 return mEventTime; 668 } 669 670 /** 671 * Sets the time in which this event was sent. 672 * 673 * @param eventTime The event time. 674 * 675 * @throws IllegalStateException If called from an AccessibilityService. 676 */ 677 public void setEventTime(long eventTime) { 678 enforceNotSealed(); 679 mEventTime = eventTime; 680 } 681 682 /** 683 * Gets the package name of the source. 684 * 685 * @return The package name. 686 */ 687 public CharSequence getPackageName() { 688 return mPackageName; 689 } 690 691 /** 692 * Sets the package name of the source. 693 * 694 * @param packageName The package name. 695 * 696 * @throws IllegalStateException If called from an AccessibilityService. 697 */ 698 public void setPackageName(CharSequence packageName) { 699 enforceNotSealed(); 700 mPackageName = packageName; 701 } 702 703 /** 704 * Returns a cached instance if such is available or a new one is 705 * instantiated with its type property set. 706 * 707 * @param eventType The event type. 708 * @return An instance. 709 */ 710 public static AccessibilityEvent obtain(int eventType) { 711 AccessibilityEvent event = AccessibilityEvent.obtain(); 712 event.setEventType(eventType); 713 return event; 714 } 715 716 /** 717 * Returns a cached instance if such is available or a new one is 718 * created. The returned instance is initialized from the given 719 * <code>event</code>. 720 * 721 * @param event The other event. 722 * @return An instance. 723 */ 724 public static AccessibilityEvent obtain(AccessibilityEvent event) { 725 AccessibilityEvent eventClone = AccessibilityEvent.obtain(); 726 eventClone.init(event); 727 728 final int recordCount = event.mRecords.size(); 729 for (int i = 0; i < recordCount; i++) { 730 AccessibilityRecord record = event.mRecords.get(i); 731 AccessibilityRecord recordClone = AccessibilityRecord.obtain(record); 732 eventClone.mRecords.add(recordClone); 733 } 734 735 return eventClone; 736 } 737 738 /** 739 * Returns a cached instance if such is available or a new one is 740 * instantiated. 741 * 742 * @return An instance. 743 */ 744 public static AccessibilityEvent obtain() { 745 synchronized (sPoolLock) { 746 if (sPool != null) { 747 AccessibilityEvent event = sPool; 748 sPool = sPool.mNext; 749 sPoolSize--; 750 event.mNext = null; 751 event.mIsInPool = false; 752 return event; 753 } 754 return new AccessibilityEvent(); 755 } 756 } 757 758 /** 759 * Recycles an instance back to be reused. 760 * <p> 761 * <b>Note: You must not touch the object after calling this function.</b> 762 * </p> 763 * 764 * @throws IllegalStateException If the event is already recycled. 765 */ 766 @Override 767 public void recycle() { 768 if (mIsInPool) { 769 throw new IllegalStateException("Event already recycled!"); 770 } 771 clear(); 772 synchronized (sPoolLock) { 773 if (sPoolSize <= MAX_POOL_SIZE) { 774 mNext = sPool; 775 sPool = this; 776 mIsInPool = true; 777 sPoolSize++; 778 } 779 } 780 } 781 782 /** 783 * Clears the state of this instance. 784 * 785 * @hide 786 */ 787 @Override 788 protected void clear() { 789 super.clear(); 790 mEventType = 0; 791 mPackageName = null; 792 mEventTime = 0; 793 while (!mRecords.isEmpty()) { 794 AccessibilityRecord record = mRecords.remove(0); 795 record.recycle(); 796 } 797 } 798 799 /** 800 * Creates a new instance from a {@link Parcel}. 801 * 802 * @param parcel A parcel containing the state of a {@link AccessibilityEvent}. 803 */ 804 public void initFromParcel(Parcel parcel) { 805 mSealed = (parcel.readInt() == 1); 806 mEventType = parcel.readInt(); 807 mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 808 mEventTime = parcel.readLong(); 809 mConnectionId = parcel.readInt(); 810 readAccessibilityRecordFromParcel(this, parcel); 811 812 // Read the records. 813 final int recordCount = parcel.readInt(); 814 for (int i = 0; i < recordCount; i++) { 815 AccessibilityRecord record = AccessibilityRecord.obtain(); 816 readAccessibilityRecordFromParcel(record, parcel); 817 record.mConnectionId = mConnectionId; 818 mRecords.add(record); 819 } 820 } 821 822 /** 823 * Reads an {@link AccessibilityRecord} from a parcel. 824 * 825 * @param record The record to initialize. 826 * @param parcel The parcel to read from. 827 */ 828 private void readAccessibilityRecordFromParcel(AccessibilityRecord record, 829 Parcel parcel) { 830 record.mBooleanProperties = parcel.readInt(); 831 record.mCurrentItemIndex = parcel.readInt(); 832 record.mItemCount = parcel.readInt(); 833 record.mFromIndex = parcel.readInt(); 834 record.mToIndex = parcel.readInt(); 835 record.mScrollX = parcel.readInt(); 836 record.mScrollY = parcel.readInt(); 837 record.mMaxScrollX = parcel.readInt(); 838 record.mMaxScrollY = parcel.readInt(); 839 record.mAddedCount = parcel.readInt(); 840 record.mRemovedCount = parcel.readInt(); 841 record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 842 record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 843 record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 844 record.mParcelableData = parcel.readParcelable(null); 845 parcel.readList(record.mText, null); 846 record.mSourceWindowId = parcel.readInt(); 847 record.mSourceViewId = parcel.readInt(); 848 record.mSealed = (parcel.readInt() == 1); 849 } 850 851 /** 852 * {@inheritDoc} 853 */ 854 public void writeToParcel(Parcel parcel, int flags) { 855 parcel.writeInt(isSealed() ? 1 : 0); 856 parcel.writeInt(mEventType); 857 TextUtils.writeToParcel(mPackageName, parcel, 0); 858 parcel.writeLong(mEventTime); 859 parcel.writeInt(mConnectionId); 860 writeAccessibilityRecordToParcel(this, parcel, flags); 861 862 // Write the records. 863 final int recordCount = getRecordCount(); 864 parcel.writeInt(recordCount); 865 for (int i = 0; i < recordCount; i++) { 866 AccessibilityRecord record = mRecords.get(i); 867 writeAccessibilityRecordToParcel(record, parcel, flags); 868 } 869 } 870 871 /** 872 * Writes an {@link AccessibilityRecord} to a parcel. 873 * 874 * @param record The record to write. 875 * @param parcel The parcel to which to write. 876 */ 877 private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel, 878 int flags) { 879 parcel.writeInt(record.mBooleanProperties); 880 parcel.writeInt(record.mCurrentItemIndex); 881 parcel.writeInt(record.mItemCount); 882 parcel.writeInt(record.mFromIndex); 883 parcel.writeInt(record.mToIndex); 884 parcel.writeInt(record.mScrollX); 885 parcel.writeInt(record.mScrollY); 886 parcel.writeInt(record.mMaxScrollX); 887 parcel.writeInt(record.mMaxScrollY); 888 parcel.writeInt(record.mAddedCount); 889 parcel.writeInt(record.mRemovedCount); 890 TextUtils.writeToParcel(record.mClassName, parcel, flags); 891 TextUtils.writeToParcel(record.mContentDescription, parcel, flags); 892 TextUtils.writeToParcel(record.mBeforeText, parcel, flags); 893 parcel.writeParcelable(record.mParcelableData, flags); 894 parcel.writeList(record.mText); 895 parcel.writeInt(record.mSourceWindowId); 896 parcel.writeInt(record.mSourceViewId); 897 parcel.writeInt(record.mSealed ? 1 : 0); 898 } 899 900 /** 901 * {@inheritDoc} 902 */ 903 public int describeContents() { 904 return 0; 905 } 906 907 @Override 908 public String toString() { 909 StringBuilder builder = new StringBuilder(); 910 builder.append("EventType: ").append(eventTypeToString(mEventType)); 911 builder.append("; EventTime: ").append(mEventTime); 912 builder.append("; PackageName: ").append(mPackageName); 913 builder.append(super.toString()); 914 if (DEBUG) { 915 builder.append("\n"); 916 builder.append("; sourceWindowId: ").append(mSourceWindowId); 917 builder.append("; sourceViewId: ").append(mSourceViewId); 918 for (int i = 0; i < mRecords.size(); i++) { 919 AccessibilityRecord record = mRecords.get(i); 920 builder.append(" Record "); 921 builder.append(i); 922 builder.append(":"); 923 builder.append(" [ ClassName: " + record.mClassName); 924 builder.append("; Text: " + record.mText); 925 builder.append("; ContentDescription: " + record.mContentDescription); 926 builder.append("; ItemCount: " + record.mItemCount); 927 builder.append("; CurrentItemIndex: " + record.mCurrentItemIndex); 928 builder.append("; IsEnabled: " + record.isEnabled()); 929 builder.append("; IsPassword: " + record.isPassword()); 930 builder.append("; IsChecked: " + record.isChecked()); 931 builder.append("; IsFullScreen: " + record.isFullScreen()); 932 builder.append("; Scrollable: " + record.isScrollable()); 933 builder.append("; BeforeText: " + record.mBeforeText); 934 builder.append("; FromIndex: " + record.mFromIndex); 935 builder.append("; ToIndex: " + record.mToIndex); 936 builder.append("; ScrollX: " + record.mScrollX); 937 builder.append("; ScrollY: " + record.mScrollY); 938 builder.append("; AddedCount: " + record.mAddedCount); 939 builder.append("; RemovedCount: " + record.mRemovedCount); 940 builder.append("; ParcelableData: " + record.mParcelableData); 941 builder.append(" ]"); 942 builder.append("\n"); 943 } 944 } else { 945 builder.append("; recordCount: ").append(getRecordCount()); 946 } 947 return builder.toString(); 948 } 949 950 /** 951 * Returns the string representation of an event type. For example, 952 * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED. 953 * 954 * @param eventType The event type 955 * @return The string representation. 956 */ 957 public static String eventTypeToString(int eventType) { 958 switch (eventType) { 959 case TYPE_VIEW_CLICKED: 960 return "TYPE_VIEW_CLICKED"; 961 case TYPE_VIEW_LONG_CLICKED: 962 return "TYPE_VIEW_LONG_CLICKED"; 963 case TYPE_VIEW_SELECTED: 964 return "TYPE_VIEW_SELECTED"; 965 case TYPE_VIEW_FOCUSED: 966 return "TYPE_VIEW_FOCUSED"; 967 case TYPE_VIEW_TEXT_CHANGED: 968 return "TYPE_VIEW_TEXT_CHANGED"; 969 case TYPE_WINDOW_STATE_CHANGED: 970 return "TYPE_WINDOW_STATE_CHANGED"; 971 case TYPE_VIEW_HOVER_ENTER: 972 return "TYPE_VIEW_HOVER_ENTER"; 973 case TYPE_VIEW_HOVER_EXIT: 974 return "TYPE_VIEW_HOVER_EXIT"; 975 case TYPE_NOTIFICATION_STATE_CHANGED: 976 return "TYPE_NOTIFICATION_STATE_CHANGED"; 977 case TYPE_TOUCH_EXPLORATION_GESTURE_START: 978 return "TYPE_TOUCH_EXPLORATION_GESTURE_START"; 979 case TYPE_TOUCH_EXPLORATION_GESTURE_END: 980 return "TYPE_TOUCH_EXPLORATION_GESTURE_END"; 981 case TYPE_WINDOW_CONTENT_CHANGED: 982 return "TYPE_WINDOW_CONTENT_CHANGED"; 983 case TYPE_VIEW_TEXT_SELECTION_CHANGED: 984 return "TYPE_VIEW_TEXT_SELECTION_CHANGED"; 985 case TYPE_VIEW_SCROLLED: 986 return "TYPE_VIEW_SCROLLED"; 987 default: 988 return null; 989 } 990 } 991 992 /** 993 * @see Parcelable.Creator 994 */ 995 public static final Parcelable.Creator<AccessibilityEvent> CREATOR = 996 new Parcelable.Creator<AccessibilityEvent>() { 997 public AccessibilityEvent createFromParcel(Parcel parcel) { 998 AccessibilityEvent event = AccessibilityEvent.obtain(); 999 event.initFromParcel(parcel); 1000 return event; 1001 } 1002 1003 public AccessibilityEvent[] newArray(int size) { 1004 return new AccessibilityEvent[size]; 1005 } 1006 }; 1007} 1008