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