1 /* 2 * Copyright (C) 2011 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 static com.android.internal.util.BitUtils.bitAt; 20 import static com.android.internal.util.BitUtils.isBitSet; 21 22 import static java.util.Collections.EMPTY_LIST; 23 24 import android.accessibilityservice.AccessibilityService; 25 import android.accessibilityservice.AccessibilityServiceInfo; 26 import android.annotation.FlaggedApi; 27 import android.annotation.IntDef; 28 import android.annotation.NonNull; 29 import android.annotation.Nullable; 30 import android.annotation.SuppressLint; 31 import android.annotation.TestApi; 32 import android.compat.annotation.UnsupportedAppUsage; 33 import android.content.ClipData; 34 import android.graphics.Rect; 35 import android.graphics.Region; 36 import android.os.Build; 37 import android.os.Bundle; 38 import android.os.IBinder; 39 import android.os.Parcel; 40 import android.os.Parcelable; 41 import android.text.InputType; 42 import android.text.Spannable; 43 import android.text.SpannableStringBuilder; 44 import android.text.Spanned; 45 import android.text.TextUtils; 46 import android.text.style.AccessibilityClickableSpan; 47 import android.text.style.AccessibilityReplacementSpan; 48 import android.text.style.AccessibilityURLSpan; 49 import android.text.style.ClickableSpan; 50 import android.text.style.ReplacementSpan; 51 import android.text.style.URLSpan; 52 import android.util.ArrayMap; 53 import android.util.ArraySet; 54 import android.util.Log; 55 import android.util.LongArray; 56 import android.util.Size; 57 import android.util.TypedValue; 58 import android.view.SurfaceView; 59 import android.view.TouchDelegate; 60 import android.view.View; 61 import android.view.ViewGroup; 62 import android.view.ViewRootImpl; 63 import android.widget.TextView; 64 65 import com.android.internal.R; 66 import com.android.internal.util.CollectionUtils; 67 import com.android.internal.util.Preconditions; 68 69 import java.lang.annotation.Retention; 70 import java.lang.annotation.RetentionPolicy; 71 import java.time.Duration; 72 import java.util.ArrayList; 73 import java.util.Collections; 74 import java.util.List; 75 import java.util.Map; 76 import java.util.Objects; 77 78 /** 79 * This class represents a node of the window content as well as actions that 80 * can be requested from its source. From the point of view of an 81 * {@link android.accessibilityservice.AccessibilityService} a window's content is 82 * presented as a tree of accessibility node infos, which may or may not map one-to-one 83 * to the view hierarchy. In other words, a custom view is free to report itself as 84 * a tree of accessibility node info. 85 * </p> 86 * <p> 87 * Once an accessibility node info is delivered to an accessibility service it is 88 * made immutable and calling a state mutation method generates an error. See 89 * {@link #setQueryFromAppProcessEnabled} if you would like to inspect the 90 * node tree from the app process for testing or debugging tools. 91 * </p> 92 * <p> 93 * Please refer to {@link android.accessibilityservice.AccessibilityService} for 94 * details about how to obtain a handle to window content as a tree of accessibility 95 * node info as well as details about the security model. 96 * </p> 97 * <div class="special reference"> 98 * <h3>Developer Guides</h3> 99 * <p>For more information about making applications accessible, read the 100 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 101 * developer guide.</p> 102 * </div> 103 * <aside class="note"> 104 * <b>Note:</b> Use a {@link androidx.core.view.accessibility.AccessibilityNodeInfoCompat} 105 * wrapper instead of this class for backwards-compatibility. </aside> 106 * 107 * @see android.accessibilityservice.AccessibilityService 108 * @see AccessibilityEvent 109 * @see AccessibilityManager 110 */ 111 public class AccessibilityNodeInfo implements Parcelable { 112 113 private static final String TAG = "AccessibilityNodeInfo"; 114 115 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG) && Build.IS_DEBUGGABLE; 116 117 /** @hide */ 118 public static final int UNDEFINED_CONNECTION_ID = -1; 119 120 /** @hide */ 121 public static final int UNDEFINED_SELECTION_INDEX = -1; 122 123 /** @hide */ 124 public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE; 125 126 /** @hide */ 127 public static final int ROOT_ITEM_ID = Integer.MAX_VALUE - 1; 128 129 /** @hide */ 130 public static final int LEASHED_ITEM_ID = Integer.MAX_VALUE - 2; 131 132 /** @hide */ 133 public static final long UNDEFINED_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID); 134 135 /** @hide */ 136 public static final long ROOT_NODE_ID = makeNodeId(ROOT_ITEM_ID, 137 AccessibilityNodeProvider.HOST_VIEW_ID); 138 139 /** @hide */ 140 public static final long LEASHED_NODE_ID = makeNodeId(LEASHED_ITEM_ID, 141 AccessibilityNodeProvider.HOST_VIEW_ID); 142 143 // Prefetch flags. 144 145 /** 146 * Prefetching strategy that prefetches the ancestors of the requested node. 147 * <p> Ancestors will be prefetched before siblings and descendants. 148 * 149 * @see #getChild(int, int) 150 * @see #getParent(int) 151 * @see AccessibilityWindowInfo#getRoot(int) 152 * @see AccessibilityService#getRootInActiveWindow(int) 153 * @see AccessibilityEvent#getSource(int) 154 */ 155 public static final int FLAG_PREFETCH_ANCESTORS = 1 /* << 0 */; 156 157 /** 158 * Prefetching strategy that prefetches the siblings of the requested node. 159 * <p> To avoid disconnected trees, this flag will also prefetch the parent. Siblings will be 160 * prefetched before descendants. 161 * 162 * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used. 163 */ 164 public static final int FLAG_PREFETCH_SIBLINGS = 1 << 1; 165 166 /** 167 * Prefetching strategy that prefetches the descendants in a hybrid depth first and breadth 168 * first approach. 169 * <p> The children of the root node is prefetched before recursing on the children. This 170 * must not be combined with {@link #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST} or 171 * {@link #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST} or this will trigger an 172 * IllegalArgumentException. 173 * 174 * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used. 175 */ 176 public static final int FLAG_PREFETCH_DESCENDANTS_HYBRID = 1 << 2; 177 178 /** 179 * Prefetching strategy that prefetches the descendants of the requested node depth-first. 180 * <p> This must not be combined with {@link #FLAG_PREFETCH_DESCENDANTS_HYBRID} or 181 * {@link #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST} or this will trigger an 182 * IllegalArgumentException. 183 * 184 * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used. 185 */ 186 public static final int FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST = 1 << 3; 187 188 /** 189 * Prefetching strategy that prefetches the descendants of the requested node breadth-first. 190 * <p> This must not be combined with {@link #FLAG_PREFETCH_DESCENDANTS_HYBRID} or 191 * {@link #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST} or this will trigger an 192 * IllegalArgumentException. 193 * 194 * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used. 195 */ 196 public static final int FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST = 1 << 4; 197 198 /** 199 * Prefetching flag that specifies prefetching should not be interrupted by a request to 200 * retrieve a node or perform an action on a node. 201 * 202 * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used. 203 */ 204 public static final int FLAG_PREFETCH_UNINTERRUPTIBLE = 1 << 5; 205 206 /** 207 * Mask for {@link PrefetchingStrategy} all types. 208 * 209 * @see #FLAG_PREFETCH_ANCESTORS 210 * @see #FLAG_PREFETCH_SIBLINGS 211 * @see #FLAG_PREFETCH_DESCENDANTS_HYBRID 212 * @see #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST 213 * @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST 214 * @see #FLAG_PREFETCH_UNINTERRUPTIBLE 215 * 216 * @hide 217 */ 218 public static final int FLAG_PREFETCH_MASK = 0x0000003F; 219 220 /** 221 * Mask for {@link PrefetchingStrategy} that includes only descendants-related strategies. 222 * 223 * @see #FLAG_PREFETCH_DESCENDANTS_HYBRID 224 * @see #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST 225 * @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST 226 * 227 * @hide 228 */ 229 public static final int FLAG_PREFETCH_DESCENDANTS_MASK = 0x0000001C; 230 231 /** 232 * Maximum batch size of prefetched nodes for a request. 233 */ 234 @SuppressLint("MinMaxConstant") 235 public static final int MAX_NUMBER_OF_PREFETCHED_NODES = 50; 236 237 /** @hide */ 238 @Retention(RetentionPolicy.SOURCE) 239 @IntDef(flag = true, prefix = { "FLAG_PREFETCH" }, value = { 240 FLAG_PREFETCH_ANCESTORS, 241 FLAG_PREFETCH_SIBLINGS, 242 FLAG_PREFETCH_DESCENDANTS_HYBRID, 243 FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST, 244 FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST, 245 FLAG_PREFETCH_UNINTERRUPTIBLE 246 }) 247 public @interface PrefetchingStrategy {} 248 249 // Service flags. 250 251 /** 252 * @see AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 253 * @hide 254 */ 255 public static final int FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS = 1 << 7; 256 257 /** 258 * @see AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS 259 * @hide 260 */ 261 public static final int FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS = 1 << 8; 262 263 /** 264 * @see AccessibilityServiceInfo#isAccessibilityTool() 265 * @hide 266 */ 267 public static final int FLAG_SERVICE_IS_ACCESSIBILITY_TOOL = 1 << 9; 268 269 /** 270 * Mask for all types of additional view data exposed to services. 271 * 272 * @hide 273 */ 274 public static final int FLAG_REPORT_MASK = 275 FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS 276 | FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS 277 | FLAG_SERVICE_IS_ACCESSIBILITY_TOOL; 278 279 // Actions. 280 281 /** 282 * Action that gives input focus to the node. 283 * See {@link AccessibilityAction#ACTION_FOCUS} 284 */ 285 public static final int ACTION_FOCUS = 1 /* << 0 */; 286 287 /** 288 * Action that clears input focus of the node. 289 * See {@link AccessibilityAction#ACTION_CLEAR_FOCUS} 290 */ 291 public static final int ACTION_CLEAR_FOCUS = 1 << 1; 292 293 /** 294 * Action that selects the node. 295 * @see AccessibilityAction#ACTION_SELECT 296 */ 297 public static final int ACTION_SELECT = 1 << 2; 298 299 /** 300 * Action that deselects the node. 301 */ 302 public static final int ACTION_CLEAR_SELECTION = 1 << 3; 303 304 /** 305 * Action that clicks on the node info. 306 * 307 * @see AccessibilityAction#ACTION_CLICK 308 */ 309 public static final int ACTION_CLICK = 1 << 4; 310 311 /** 312 * Action that long clicks on the node. 313 * 314 * <p>It does not support coordinate information for anchoring.</p> 315 * @see AccessibilityAction#ACTION_LONG_CLICK 316 */ 317 public static final int ACTION_LONG_CLICK = 1 << 5; 318 319 /** 320 * Action that gives accessibility focus to the node. 321 * See {@link AccessibilityAction#ACTION_ACCESSIBILITY_FOCUS} 322 */ 323 public static final int ACTION_ACCESSIBILITY_FOCUS = 1 << 6; 324 325 /** 326 * Action that clears accessibility focus of the node. 327 * See {@link AccessibilityAction#ACTION_CLEAR_ACCESSIBILITY_FOCUS} 328 */ 329 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 1 << 7; 330 331 /** 332 * Action that requests to go to the next entity in this node's text 333 * at a given movement granularity. For example, move to the next character, 334 * word, etc. 335 * <p> 336 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, 337 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 338 * <strong>Example:</strong> Move to the previous character and do not extend selection. 339 * <code><pre><p> 340 * Bundle arguments = new Bundle(); 341 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 342 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); 343 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, 344 * false); 345 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments); 346 * </code></pre></p> 347 * </p> 348 * 349 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 350 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 351 * 352 * @see #setMovementGranularities(int) 353 * @see #getMovementGranularities() 354 * 355 * @see #MOVEMENT_GRANULARITY_CHARACTER 356 * @see #MOVEMENT_GRANULARITY_WORD 357 * @see #MOVEMENT_GRANULARITY_LINE 358 * @see #MOVEMENT_GRANULARITY_PARAGRAPH 359 * @see #MOVEMENT_GRANULARITY_PAGE 360 */ 361 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 1 << 8; 362 363 /** 364 * Action that requests to go to the previous entity in this node's text 365 * at a given movement granularity. For example, move to the next character, 366 * word, etc. 367 * <p> 368 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, 369 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 370 * <strong>Example:</strong> Move to the next character and do not extend selection. 371 * <code><pre><p> 372 * Bundle arguments = new Bundle(); 373 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 374 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); 375 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, 376 * false); 377 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, 378 * arguments); 379 * </code></pre></p> 380 * </p> 381 * 382 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 383 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 384 * 385 * @see #setMovementGranularities(int) 386 * @see #getMovementGranularities() 387 * 388 * @see #MOVEMENT_GRANULARITY_CHARACTER 389 * @see #MOVEMENT_GRANULARITY_WORD 390 * @see #MOVEMENT_GRANULARITY_LINE 391 * @see #MOVEMENT_GRANULARITY_PARAGRAPH 392 * @see #MOVEMENT_GRANULARITY_PAGE 393 */ 394 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 1 << 9; 395 396 /** 397 * Action to move to the next HTML element of a given type. For example, move 398 * to the BUTTON, INPUT, TABLE, etc. 399 * <p> 400 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 401 * <strong>Example:</strong> 402 * <code><pre><p> 403 * Bundle arguments = new Bundle(); 404 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 405 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments); 406 * </code></pre></p> 407 * </p> 408 */ 409 public static final int ACTION_NEXT_HTML_ELEMENT = 1 << 10; 410 411 /** 412 * Action to move to the previous HTML element of a given type. For example, move 413 * to the BUTTON, INPUT, TABLE, etc. 414 * <p> 415 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 416 * <strong>Example:</strong> 417 * <code><pre><p> 418 * Bundle arguments = new Bundle(); 419 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 420 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments); 421 * </code></pre></p> 422 * </p> 423 */ 424 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 1 << 11; 425 426 /** 427 * Action to scroll the node content forward. 428 * @see AccessibilityAction#ACTION_SCROLL_FORWARD 429 */ 430 public static final int ACTION_SCROLL_FORWARD = 1 << 12; 431 432 /** 433 * Action to scroll the node content backward. 434 * @see AccessibilityAction#ACTION_SCROLL_BACKWARD 435 */ 436 public static final int ACTION_SCROLL_BACKWARD = 1 << 13; 437 438 /** 439 * Action to copy the current selection to the clipboard. 440 */ 441 public static final int ACTION_COPY = 1 << 14; 442 443 /** 444 * Action to paste the current clipboard content. 445 */ 446 public static final int ACTION_PASTE = 1 << 15; 447 448 /** 449 * Action to cut the current selection and place it to the clipboard. 450 */ 451 public static final int ACTION_CUT = 1 << 16; 452 453 /** 454 * Action to set the selection. Performing this action with no arguments 455 * clears the selection. 456 * 457 * @see AccessibilityAction#ACTION_SET_SELECTION 458 * @see #ACTION_ARGUMENT_SELECTION_START_INT 459 * @see #ACTION_ARGUMENT_SELECTION_END_INT 460 */ 461 public static final int ACTION_SET_SELECTION = 1 << 17; 462 463 /** 464 * Action to expand an expandable node. 465 */ 466 public static final int ACTION_EXPAND = 1 << 18; 467 468 /** 469 * Action to collapse an expandable node. 470 */ 471 public static final int ACTION_COLLAPSE = 1 << 19; 472 473 /** 474 * Action to dismiss a dismissable node. 475 */ 476 public static final int ACTION_DISMISS = 1 << 20; 477 478 /** 479 * Action that sets the text of the node. Performing the action without argument, using <code> 480 * null</code> or empty {@link CharSequence} will clear the text. This action will also put the 481 * cursor at the end of text. 482 * @see AccessibilityAction#ACTION_SET_TEXT 483 */ 484 public static final int ACTION_SET_TEXT = 1 << 21; 485 486 /** @hide */ 487 public static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT; 488 489 /** 490 * Mask to verify if a given value is a combination of the existing ACTION_ constants. 491 * 492 * The smallest possible action is 1, and the largest is 1 << 21, or {@link ACTION_SET_TEXT}. A 493 * node can have any combination of actions present, so a node's max action int is: 494 * 495 * 0000 0000 0011 1111 1111 1111 1111 1111 496 * 497 * Therefore, if an action has any of the following bits flipped, it will be invalid: 498 * 499 * 1111 1111 11-- ---- ---- ---- ---- ---- 500 * 501 * This can be represented in hexadecimal as 0xFFC00000. 502 * 503 * @see AccessibilityNodeInfo#addAction(int) 504 */ 505 private static final int INVALID_ACTIONS_MASK = 0xFFC00000; 506 507 // Action arguments. 508 509 /** 510 * Argument for which movement granularity to be used when traversing the node text. 511 * <p> 512 * <strong>Type:</strong> int<br> 513 * <strong>Actions:</strong> 514 * <ul> 515 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li> 516 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li> 517 * </ul> 518 * </p> 519 * 520 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY 521 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 522 */ 523 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = 524 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT"; 525 526 /** 527 * Argument for which HTML element to get moving to the next/previous HTML element. 528 * <p> 529 * <strong>Type:</strong> String<br> 530 * <strong>Actions:</strong> 531 * <ul> 532 * <li>{@link AccessibilityAction#ACTION_NEXT_HTML_ELEMENT}</li> 533 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT}</li> 534 * </ul> 535 * </p> 536 * 537 * @see AccessibilityAction#ACTION_NEXT_HTML_ELEMENT 538 * @see AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT 539 */ 540 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = 541 "ACTION_ARGUMENT_HTML_ELEMENT_STRING"; 542 543 /** 544 * Argument for specifying the extended selection. 545 * 546 * <p><strong>Type:</strong> {@link AccessibilityNodeInfo.Selection}<br> 547 * <strong>Actions:</strong> 548 * 549 * <ul> 550 * <li>{@link AccessibilityAction#ACTION_SET_EXTENDED_SELECTION} 551 * </ul> 552 * 553 * @see AccessibilityAction#ACTION_SET_EXTENDED_SELECTION 554 */ 555 @FlaggedApi(Flags.FLAG_A11Y_SELECTION_API) 556 public static final String ACTION_ARGUMENT_SELECTION_PARCELABLE = 557 "android.view.accessibility.action.ARGUMENT_SELECTION_PARCELABLE"; 558 559 /** 560 * Argument for whether when moving at granularity to extend the selection 561 * or to move it otherwise. 562 * <p> 563 * <strong>Type:</strong> boolean<br> 564 * <strong>Actions:</strong> 565 * <ul> 566 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li> 567 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li> 568 * </ul> 569 * 570 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY 571 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 572 */ 573 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = 574 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN"; 575 576 /** 577 * Argument for specifying the selection start. 578 * <p> 579 * <strong>Type:</strong> int<br> 580 * <strong>Actions:</strong> 581 * <ul> 582 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li> 583 * </ul> 584 * 585 * @see AccessibilityAction#ACTION_SET_SELECTION 586 */ 587 public static final String ACTION_ARGUMENT_SELECTION_START_INT = 588 "ACTION_ARGUMENT_SELECTION_START_INT"; 589 590 /** 591 * Argument for specifying the selection end. 592 * <p> 593 * <strong>Type:</strong> int<br> 594 * <strong>Actions:</strong> 595 * <ul> 596 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li> 597 * </ul> 598 * 599 * @see AccessibilityAction#ACTION_SET_SELECTION 600 */ 601 public static final String ACTION_ARGUMENT_SELECTION_END_INT = 602 "ACTION_ARGUMENT_SELECTION_END_INT"; 603 604 /** 605 * Argument for specifying the text content to set. 606 * <p> 607 * <strong>Type:</strong> CharSequence<br> 608 * <strong>Actions:</strong> 609 * <ul> 610 * <li>{@link AccessibilityAction#ACTION_SET_TEXT}</li> 611 * </ul> 612 * 613 * @see AccessibilityAction#ACTION_SET_TEXT 614 */ 615 public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = 616 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE"; 617 618 /** 619 * Argument for specifying the collection row to make visible on screen. 620 * <p> 621 * <strong>Type:</strong> int<br> 622 * <strong>Actions:</strong> 623 * <ul> 624 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li> 625 * </ul> 626 * 627 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION 628 */ 629 public static final String ACTION_ARGUMENT_ROW_INT = 630 "android.view.accessibility.action.ARGUMENT_ROW_INT"; 631 632 /** 633 * Argument for specifying the collection column to make visible on screen. 634 * <p> 635 * <strong>Type:</strong> int<br> 636 * <strong>Actions:</strong> 637 * <ul> 638 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li> 639 * </ul> 640 * 641 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION 642 */ 643 public static final String ACTION_ARGUMENT_COLUMN_INT = 644 "android.view.accessibility.action.ARGUMENT_COLUMN_INT"; 645 646 /** 647 * Argument for specifying the progress value to set. 648 * <p> 649 * <strong>Type:</strong> float<br> 650 * <strong>Actions:</strong> 651 * <ul> 652 * <li>{@link AccessibilityAction#ACTION_SET_PROGRESS}</li> 653 * </ul> 654 * 655 * @see AccessibilityAction#ACTION_SET_PROGRESS 656 */ 657 public static final String ACTION_ARGUMENT_PROGRESS_VALUE = 658 "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE"; 659 660 /** 661 * Argument for specifying the x coordinate to which to move a window. 662 * <p> 663 * <strong>Type:</strong> int<br> 664 * <strong>Actions:</strong> 665 * <ul> 666 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li> 667 * </ul> 668 * 669 * @see AccessibilityAction#ACTION_MOVE_WINDOW 670 */ 671 public static final String ACTION_ARGUMENT_MOVE_WINDOW_X = 672 "ACTION_ARGUMENT_MOVE_WINDOW_X"; 673 674 /** 675 * Argument for specifying the y coordinate to which to move a window. 676 * <p> 677 * <strong>Type:</strong> int<br> 678 * <strong>Actions:</strong> 679 * <ul> 680 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li> 681 * </ul> 682 * 683 * @see AccessibilityAction#ACTION_MOVE_WINDOW 684 */ 685 public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y = 686 "ACTION_ARGUMENT_MOVE_WINDOW_Y"; 687 688 /** 689 * Argument to pass the {@link AccessibilityClickableSpan}. 690 * For use with R.id.accessibilityActionClickOnClickableSpan 691 * @hide 692 */ 693 public static final String ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN = 694 "android.view.accessibility.action.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN"; 695 696 /** 697 * Argument to represent the duration in milliseconds to press and hold a node. 698 * <p> 699 * <strong>Type:</strong> int<br> 700 * <strong>Actions:</strong> 701 * <ul> 702 * <li>{@link AccessibilityAction#ACTION_PRESS_AND_HOLD}</li> 703 * </ul> 704 * 705 * @see AccessibilityAction#ACTION_PRESS_AND_HOLD 706 */ 707 public static final String ACTION_ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT = 708 "android.view.accessibility.action.ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT"; 709 710 /** 711 * <p>Argument to represent the direction when using 712 * {@link AccessibilityAction#ACTION_SCROLL_IN_DIRECTION}.</p> 713 * 714 * <p> 715 * The value of this argument can be one of: 716 * <ul> 717 * <li>{@link View#FOCUS_DOWN}</li> 718 * <li>{@link View#FOCUS_UP}</li> 719 * <li>{@link View#FOCUS_LEFT}</li> 720 * <li>{@link View#FOCUS_RIGHT}</li> 721 * <li>{@link View#FOCUS_FORWARD}</li> 722 * <li>{@link View#FOCUS_BACKWARD}</li> 723 * </ul> 724 * </p> 725 */ 726 public static final String ACTION_ARGUMENT_DIRECTION_INT = 727 "android.view.accessibility.action.ARGUMENT_DIRECTION_INT"; 728 729 /** 730 * <p>Argument to represent the scroll amount as a percent of the visible area of a node, with 731 * 1.0F as the default. Values smaller than 1.0F represent a partial scroll of the node, and 732 * values larger than 1.0F represent a scroll that extends beyond the currently visible node 733 * Rect. Setting this to {@link Float#POSITIVE_INFINITY} or to another "too large" value should 734 * scroll to the end of the node. Negative values should not be used with this argument. 735 * </p> 736 * 737 * <p> 738 * This argument should be used with the following scroll actions: 739 * <ul> 740 * <li>{@link AccessibilityAction#ACTION_SCROLL_FORWARD}</li> 741 * <li>{@link AccessibilityAction#ACTION_SCROLL_BACKWARD}</li> 742 * <li>{@link AccessibilityAction#ACTION_SCROLL_UP}</li> 743 * <li>{@link AccessibilityAction#ACTION_SCROLL_DOWN}</li> 744 * <li>{@link AccessibilityAction#ACTION_SCROLL_LEFT}</li> 745 * <li>{@link AccessibilityAction#ACTION_SCROLL_RIGHT}</li> 746 * </ul> 747 * </p> 748 * <p> 749 * Example: if a view representing a list of items implements 750 * {@link AccessibilityAction#ACTION_SCROLL_FORWARD} to scroll forward by an entire screen 751 * (one "page"), then passing a value of .25F via this argument should scroll that view 752 * only by 1/4th of a screen. Passing a value of 1.50F via this argument should scroll the 753 * view by 1 1/2 screens or to end of the node if the node doesn't extend to 1 1/2 screens. 754 * </p> 755 * 756 * <p> 757 * This argument should not be used with the following scroll actions, which don't cleanly 758 * conform to granular scroll semantics: 759 * <ul> 760 * <li>{@link AccessibilityAction#ACTION_SCROLL_IN_DIRECTION}</li> 761 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li> 762 * </ul> 763 * </p> 764 * 765 * <p> 766 * Views that support this argument should set 767 * {@link #setGranularScrollingSupported(boolean)} to true. Clients should use 768 * {@link #isGranularScrollingSupported()} to check if granular scrolling is supported. 769 * </p> 770 */ 771 @FlaggedApi(Flags.FLAG_GRANULAR_SCROLLING) 772 public static final String ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT = 773 "android.view.accessibility.action.ARGUMENT_SCROLL_AMOUNT_FLOAT"; 774 775 // Expanded state types. 776 777 /** 778 * Expanded state for a non-expandable element 779 * 780 * @see #getExpandedState() 781 * @see #setExpandedState(int) 782 */ 783 @FlaggedApi(Flags.FLAG_A11Y_EXPANSION_STATE_API) 784 public static final int EXPANDED_STATE_UNDEFINED = 0; 785 786 /** 787 * Expanded state for a collapsed expandable element. 788 * 789 * @see #getExpandedState() 790 * @see #setExpandedState(int) 791 */ 792 @FlaggedApi(Flags.FLAG_A11Y_EXPANSION_STATE_API) 793 public static final int EXPANDED_STATE_COLLAPSED = 1; 794 795 /** 796 * Expanded state for an expanded expandable element that can still be expanded further. 797 * 798 * @see #getExpandedState() 799 * @see #setExpandedState(int) 800 */ 801 @FlaggedApi(Flags.FLAG_A11Y_EXPANSION_STATE_API) 802 public static final int EXPANDED_STATE_PARTIAL = 2; 803 804 /** 805 * Expanded state for a expanded expandable element that cannot be expanded further. 806 * 807 * @see #getExpandedState() 808 * @see #setExpandedState(int) 809 */ 810 @FlaggedApi(Flags.FLAG_A11Y_EXPANSION_STATE_API) 811 public static final int EXPANDED_STATE_FULL = 3; 812 813 /** @hide */ 814 @Retention(RetentionPolicy.SOURCE) 815 @IntDef( 816 prefix = "EXPANDED_STATE_", 817 value = { 818 EXPANDED_STATE_UNDEFINED, 819 EXPANDED_STATE_COLLAPSED, 820 EXPANDED_STATE_PARTIAL, 821 EXPANDED_STATE_FULL, 822 }) 823 public @interface ExpandedState {} 824 825 // Focus types. 826 827 /** 828 * The input focus. 829 */ 830 public static final int FOCUS_INPUT = 1; 831 832 /** 833 * The accessibility focus. 834 */ 835 public static final int FOCUS_ACCESSIBILITY = 2; 836 837 // Movement granularities. 838 839 /** 840 * Movement granularity bit for traversing the text of a node by character. 841 */ 842 public static final int MOVEMENT_GRANULARITY_CHARACTER = 1 /* << 0 */; 843 844 /** 845 * Movement granularity bit for traversing the text of a node by word. 846 */ 847 public static final int MOVEMENT_GRANULARITY_WORD = 1 << 1; 848 849 /** 850 * Movement granularity bit for traversing the text of a node by line. 851 */ 852 public static final int MOVEMENT_GRANULARITY_LINE = 1 << 2; 853 854 /** 855 * Movement granularity bit for traversing the text of a node by paragraph. 856 */ 857 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 1 << 3; 858 859 /** 860 * Movement granularity bit for traversing the text of a node by page. 861 */ 862 public static final int MOVEMENT_GRANULARITY_PAGE = 1 << 4; 863 864 // Extra data arguments. 865 866 /** 867 * Key used to request and locate extra data for text character location. This key requests that 868 * an array of {@link android.graphics.RectF}s be added to the extras. This request is made with 869 * {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by this request are two 870 * integers: {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and 871 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index must be valid 872 * inside the CharSequence returned by {@link #getText()}, and the length must be positive. 873 * <p> 874 * The data can be retrieved from the {@code Bundle} returned by {@link #getExtras()} using this 875 * string as a key for {@link Bundle#getParcelableArray(String, Class)}. The 876 * {@link android.graphics.RectF} will be {@code null} for characters that either do not exist 877 * or are off the screen. 878 * <p> 879 * Note that character locations returned are modified by changes in display magnification. 880 * 881 * {@see #refreshWithExtraData(String, Bundle)} 882 */ 883 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = 884 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"; 885 886 /** 887 * Key used to request and locate extra data for text character location in 888 * window coordinates. This key requests that an array of 889 * {@link android.graphics.RectF}s be added to the extras. This request is made 890 * with {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by 891 * this request are two integers: 892 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and 893 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index 894 * must be valid inside the CharSequence returned by {@link #getText()}, and 895 * the length must be positive. 896 * <p> 897 * Providers may advertise that they support text characters in window coordinates using 898 * {@link #setAvailableExtraData(List)}. Services may check if an implementation supports text 899 * characters in window coordinates with {@link #getAvailableExtraData()}. 900 * <p> 901 * The data can be retrieved from the {@code Bundle} returned by 902 * {@link #getExtras()} using this string as a key for 903 * {@link Bundle#getParcelableArray(String, Class)}. The 904 * {@link android.graphics.RectF} will be {@code null} for characters that either do 905 * not exist or are outside of the window bounds. 906 * <p> 907 * Note that character locations in window bounds are not modified by 908 * changes in display magnification. 909 * 910 * {@see #refreshWithExtraData(String, Bundle)} 911 */ 912 @FlaggedApi(Flags.FLAG_A11Y_CHARACTER_IN_WINDOW_API) 913 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY = 914 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY"; 915 916 /** 917 * Integer argument specifying the start index of the requested text location data. Must be 918 * valid inside the CharSequence returned by {@link #getText()}. 919 * 920 * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY 921 */ 922 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = 923 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX"; 924 925 /** 926 * Integer argument specifying the end index of the requested text location data. Must be 927 * positive and no larger than {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH}. 928 * 929 * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY 930 */ 931 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = 932 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH"; 933 934 /** 935 * The maximum allowed length of the requested text location data. 936 */ 937 public static final int EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH = 20000; 938 939 /** 940 * Key used to request extra data for the rendering information. 941 * The key requests that a {@link AccessibilityNodeInfo.ExtraRenderingInfo} be added to this 942 * info. This request is made with {@link #refreshWithExtraData(String, Bundle)} without 943 * argument. 944 * <p> 945 * The data can be retrieved from the {@link ExtraRenderingInfo} returned by 946 * {@link #getExtraRenderingInfo()} using {@link ExtraRenderingInfo#getLayoutSize}, 947 * {@link ExtraRenderingInfo#getTextSizeInPx()} and 948 * {@link ExtraRenderingInfo#getTextSizeUnit()}. For layout params, it is supported by both 949 * {@link TextView} and {@link ViewGroup}. For text size and unit, it is only supported by 950 * {@link TextView}. 951 * 952 * @see #refreshWithExtraData(String, Bundle) 953 */ 954 public static final String EXTRA_DATA_RENDERING_INFO_KEY = 955 "android.view.accessibility.extra.DATA_RENDERING_INFO_KEY"; 956 957 /** @hide */ 958 public static final String EXTRA_DATA_REQUESTED_KEY = 959 "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested"; 960 961 // Tri-state checked states. 962 963 /** @hide */ 964 @Retention(RetentionPolicy.SOURCE) 965 @IntDef(prefix = { "CHECKED_STATE" }, value = { 966 CHECKED_STATE_FALSE, 967 CHECKED_STATE_TRUE, 968 CHECKED_STATE_PARTIAL 969 }) 970 public @interface CheckedState {} 971 972 /** 973 * This node is not checked. 974 */ 975 @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED) 976 public static final int CHECKED_STATE_FALSE = 0; 977 978 /** 979 * This node is checked. 980 */ 981 @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED) 982 public static final int CHECKED_STATE_TRUE = 1; 983 984 /** 985 * This node is partially checked. For example, 986 * when a checkbox owns a number of sub-options and they have 987 * different states, then the main checkbox is in a partially-checked state. 988 */ 989 @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED) 990 public static final int CHECKED_STATE_PARTIAL = 2; 991 992 // Boolean attributes. 993 994 private static final int BOOLEAN_PROPERTY_CHECKABLE = 1 /* << 0 */; 995 996 private static final int BOOLEAN_PROPERTY_CHECKED = 1 << 1; 997 998 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 1 << 2; 999 1000 private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 3; 1001 1002 private static final int BOOLEAN_PROPERTY_SELECTED = 1 << 4; 1003 1004 private static final int BOOLEAN_PROPERTY_CLICKABLE = 1 << 5; 1005 1006 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 1 << 6; 1007 1008 private static final int BOOLEAN_PROPERTY_ENABLED = 1 << 7; 1009 1010 private static final int BOOLEAN_PROPERTY_PASSWORD = 1 << 8; 1011 1012 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 1 << 9; 1013 1014 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 1 << 10; 1015 1016 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 1 << 11; 1017 1018 private static final int BOOLEAN_PROPERTY_EDITABLE = 1 << 12; 1019 1020 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 1 << 13; 1021 1022 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 1 << 14; 1023 1024 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 1 << 15; 1025 1026 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 1 << 16; 1027 1028 private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 1 << 17; 1029 1030 private static final int BOOLEAN_PROPERTY_IMPORTANCE = 1 << 18; 1031 1032 private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 1 << 19; 1033 1034 private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 1 << 20; 1035 1036 private static final int BOOLEAN_PROPERTY_IS_HEADING = 1 << 21; 1037 1038 private static final int BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY = 1 << 22; 1039 1040 private static final int BOOLEAN_PROPERTY_IS_TEXT_SELECTABLE = 1 << 23; 1041 1042 private static final int BOOLEAN_PROPERTY_REQUEST_INITIAL_ACCESSIBILITY_FOCUS = 1 << 24; 1043 1044 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 1 << 25; 1045 1046 private static final int BOOLEAN_PROPERTY_SUPPORTS_GRANULAR_SCROLLING = 1 << 26; 1047 1048 private static final int BOOLEAN_PROPERTY_FIELD_REQUIRED = 1 << 27; 1049 1050 /** 1051 * Bits that provide the id of a virtual descendant of a view. 1052 */ 1053 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L; 1054 /** 1055 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a 1056 * virtual descendant of a view. Such a descendant does not exist in the view 1057 * hierarchy and is only reported via the accessibility APIs. 1058 */ 1059 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32; 1060 1061 /** 1062 * Gets the accessibility view id which identifies a View in the view three. 1063 * 1064 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}. 1065 * @return The accessibility view id part of the node id. 1066 * 1067 * @hide 1068 */ 1069 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getAccessibilityViewId(long accessibilityNodeId)1070 public static int getAccessibilityViewId(long accessibilityNodeId) { 1071 return (int) accessibilityNodeId; 1072 } 1073 1074 /** 1075 * Gets the virtual descendant id which identifies an imaginary view in a 1076 * containing View. 1077 * 1078 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}. 1079 * @return The virtual view id part of the node id. 1080 * 1081 * @hide 1082 */ 1083 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getVirtualDescendantId(long accessibilityNodeId)1084 public static int getVirtualDescendantId(long accessibilityNodeId) { 1085 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK) 1086 >> VIRTUAL_DESCENDANT_ID_SHIFT); 1087 } 1088 1089 /** 1090 * Makes a node id by shifting the <code>virtualDescendantId</code> 1091 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking 1092 * the bitwise or with the <code>accessibilityViewId</code>. 1093 * 1094 * @param accessibilityViewId A View accessibility id. 1095 * @param virtualDescendantId A virtual descendant id. 1096 * @return The node id. 1097 * 1098 * @hide 1099 */ makeNodeId(int accessibilityViewId, int virtualDescendantId)1100 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) { 1101 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId; 1102 } 1103 1104 private static final AccessibilityNodeInfo DEFAULT = new AccessibilityNodeInfo(); 1105 1106 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1107 private boolean mSealed; 1108 1109 // Data. 1110 private int mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; 1111 @UnsupportedAppUsage 1112 private long mSourceNodeId = UNDEFINED_NODE_ID; 1113 private long mParentNodeId = UNDEFINED_NODE_ID; 1114 private long mLabelForId = UNDEFINED_NODE_ID; 1115 private long mLabeledById = UNDEFINED_NODE_ID; 1116 private LongArray mLabeledByIds; 1117 private long mTraversalBefore = UNDEFINED_NODE_ID; 1118 private long mTraversalAfter = UNDEFINED_NODE_ID; 1119 1120 private long mMinDurationBetweenContentChanges = 0; 1121 1122 private int mBooleanProperties; 1123 private final Rect mBoundsInParent = new Rect(); 1124 private final Rect mBoundsInScreen = new Rect(); 1125 private final Rect mBoundsInWindow = new Rect(); 1126 private int mDrawingOrderInParent; 1127 1128 private CharSequence mPackageName; 1129 private CharSequence mClassName; 1130 // Hidden, unparceled value used to hold the original value passed to setText 1131 private CharSequence mOriginalText; 1132 private CharSequence mText; 1133 private CharSequence mHintText; 1134 private CharSequence mError; 1135 private CharSequence mPaneTitle; 1136 private CharSequence mStateDescription; 1137 private CharSequence mContentDescription; 1138 private CharSequence mSupplementalDescription; 1139 private CharSequence mTooltipText; 1140 private String mViewIdResourceName; 1141 private String mUniqueId; 1142 private CharSequence mContainerTitle; 1143 private ArrayList<String> mExtraDataKeys; 1144 1145 @UnsupportedAppUsage 1146 private LongArray mChildNodeIds; 1147 private ArrayList<AccessibilityAction> mActions; 1148 1149 private int mMaxTextLength = -1; 1150 private int mMovementGranularities; 1151 1152 // TODO(b/362782158) Initialize mExpandedState explicitly with 1153 // the EXPANDED_STATE_UNDEFINED state when flagging is removed. 1154 private int mExpandedState; 1155 1156 private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX; 1157 private int mTextSelectionEnd = UNDEFINED_SELECTION_INDEX; 1158 private int mInputType = InputType.TYPE_NULL; 1159 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE; 1160 1161 private Bundle mExtras; 1162 1163 private int mConnectionId = UNDEFINED_CONNECTION_ID; 1164 1165 private Selection mSelection; 1166 1167 private RangeInfo mRangeInfo; 1168 private CollectionInfo mCollectionInfo; 1169 private CollectionItemInfo mCollectionItemInfo; 1170 1171 private TouchDelegateInfo mTouchDelegateInfo; 1172 1173 private ExtraRenderingInfo mExtraRenderingInfo; 1174 1175 private IBinder mLeashedChild; 1176 private IBinder mLeashedParent; 1177 private long mLeashedParentNodeId = UNDEFINED_NODE_ID; 1178 1179 // TODO(b/369951517) Initialize mChecked explicitly with 1180 // the CHECKED_FALSE state when flagging is removed. 1181 private int mChecked; 1182 1183 /** 1184 * Creates a new {@link AccessibilityNodeInfo}. 1185 */ AccessibilityNodeInfo()1186 public AccessibilityNodeInfo() { 1187 } 1188 1189 /** 1190 * Creates a new {@link AccessibilityNodeInfo} with the given <code>source</code>. 1191 * 1192 * @param source The source view. 1193 */ AccessibilityNodeInfo(@onNull View source)1194 public AccessibilityNodeInfo(@NonNull View source) { 1195 setSource(source); 1196 } 1197 1198 /** 1199 * Creates a new {@link AccessibilityNodeInfo} with the given <code>source</code>. 1200 * 1201 * @param root The root of the virtual subtree. 1202 * @param virtualDescendantId The id of the virtual descendant. 1203 */ AccessibilityNodeInfo(@onNull View root, int virtualDescendantId)1204 public AccessibilityNodeInfo(@NonNull View root, int virtualDescendantId) { 1205 setSource(root, virtualDescendantId); 1206 } 1207 1208 /** 1209 * Copy constructor. Creates a new {@link AccessibilityNodeInfo}, and this new instance is 1210 * initialized from the given <code>info</code>. 1211 * 1212 * @param info The other info. 1213 */ AccessibilityNodeInfo(@onNull AccessibilityNodeInfo info)1214 public AccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info) { 1215 init(info); 1216 } 1217 1218 /** 1219 * Sets the source. 1220 * <p> 1221 * <strong>Note:</strong> Cannot be called from an 1222 * {@link android.accessibilityservice.AccessibilityService}. 1223 * This class is made immutable before being delivered to an AccessibilityService. 1224 * </p> 1225 * 1226 * @param source The info source. 1227 */ setSource(View source)1228 public void setSource(View source) { 1229 setSource(source, AccessibilityNodeProvider.HOST_VIEW_ID); 1230 } 1231 1232 /** 1233 * Sets the source to be a virtual descendant of the given <code>root</code>. 1234 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root 1235 * is set as the source. 1236 * <p> 1237 * A virtual descendant is an imaginary View that is reported as a part of the view 1238 * hierarchy for accessibility purposes. This enables custom views that draw complex 1239 * content to report themselves as a tree of virtual views, thus conveying their 1240 * logical structure. 1241 * </p> 1242 * <p> 1243 * <strong>Note:</strong> Cannot be called from an 1244 * {@link android.accessibilityservice.AccessibilityService}. 1245 * This class is made immutable before being delivered to an AccessibilityService. 1246 * </p> 1247 * 1248 * @param root The root of the virtual subtree. 1249 * @param virtualDescendantId The id of the virtual descendant. 1250 */ setSource(View root, int virtualDescendantId)1251 public void setSource(View root, int virtualDescendantId) { 1252 enforceNotSealed(); 1253 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID; 1254 final int rootAccessibilityViewId = 1255 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 1256 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 1257 } 1258 1259 /** 1260 * Find the view that has the specified focus type. The search starts from 1261 * the view represented by this node info. 1262 * 1263 * <p> 1264 * <strong>Note:</strong> If this view hierarchy has a {@link SurfaceView} embedding another 1265 * view hierarchy via {@link SurfaceView#setChildSurfacePackage}, there is a limitation that 1266 * this API won't be able to find the node for the view on the embedded view hierarchy. It's 1267 * because views don't know about the embedded hierarchies. Instead, you could traverse all 1268 * the children to find the node. Or, use {@link AccessibilityService#findFocus(int)} for 1269 * {@link #FOCUS_ACCESSIBILITY} only since it has no such limitation. 1270 * </p> 1271 * 1272 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or 1273 * {@link #FOCUS_ACCESSIBILITY}. 1274 * @return The node info of the focused view or null. 1275 * 1276 * @see #FOCUS_INPUT 1277 * @see #FOCUS_ACCESSIBILITY 1278 */ findFocus(int focus)1279 public AccessibilityNodeInfo findFocus(int focus) { 1280 enforceSealed(); 1281 enforceValidFocusType(focus); 1282 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 1283 return null; 1284 } 1285 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId, 1286 mSourceNodeId, focus); 1287 } 1288 1289 /** 1290 * Searches for the nearest view in the specified direction that can take 1291 * the input focus. 1292 * 1293 * <p> 1294 * <strong>Note:</strong> If this view hierarchy has a {@link SurfaceView} embedding another 1295 * view hierarchy via {@link SurfaceView#setChildSurfacePackage}, there is a limitation that 1296 * this API won't be able to find the node for the view in the specified direction on the 1297 * embedded view hierarchy. It's because views don't know about the embedded hierarchies. 1298 * Instead, you could traverse all the children to find the node. 1299 * </p> 1300 * 1301 * @param direction The direction. Can be one of: 1302 * {@link View#FOCUS_DOWN}, 1303 * {@link View#FOCUS_UP}, 1304 * {@link View#FOCUS_LEFT}, 1305 * {@link View#FOCUS_RIGHT}, 1306 * {@link View#FOCUS_FORWARD}, 1307 * {@link View#FOCUS_BACKWARD}. 1308 * 1309 * @return The node info for the view that can take accessibility focus. 1310 */ focusSearch(int direction)1311 public AccessibilityNodeInfo focusSearch(int direction) { 1312 enforceSealed(); 1313 enforceValidFocusDirection(direction); 1314 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 1315 return null; 1316 } 1317 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId, 1318 mSourceNodeId, direction); 1319 } 1320 1321 /** 1322 * Gets the id of the window from which the info comes from. 1323 * 1324 * @return The window id. 1325 */ getWindowId()1326 public int getWindowId() { 1327 return mWindowId; 1328 } 1329 1330 /** 1331 * Refreshes this info with the latest state of the view it represents. 1332 * 1333 * @param bypassCache Whether to bypass the cache. 1334 * @return Whether the refresh succeeded. 1335 * 1336 * @hide 1337 */ 1338 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) refresh(Bundle arguments, boolean bypassCache)1339 public boolean refresh(Bundle arguments, boolean bypassCache) { 1340 enforceSealed(); 1341 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 1342 return false; 1343 } 1344 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 1345 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId( 1346 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0, arguments); 1347 if (refreshedInfo == null) { 1348 return false; 1349 } 1350 init(refreshedInfo); 1351 return true; 1352 } 1353 1354 /** 1355 * Refreshes this info with the latest state of the view it represents. 1356 * 1357 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented 1358 * by this node is no longer in the view tree (and thus this node is obsolete). 1359 */ refresh()1360 public boolean refresh() { 1361 return refresh(null, true); 1362 } 1363 1364 /** 1365 * Refreshes this info with the latest state of the view it represents, and request new 1366 * data be added by the View. 1367 * 1368 * @param extraDataKey The extra data requested. Data that must be requested 1369 * with this mechanism is generally expensive to retrieve, so should only be 1370 * requested when needed. See 1371 * {@link #EXTRA_DATA_RENDERING_INFO_KEY}, 1372 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}, 1373 * {@link #getAvailableExtraData()} and {@link #getExtraRenderingInfo()}. 1374 * @param args A bundle of arguments for the request. These depend on the particular request. 1375 * 1376 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented 1377 * by this node is no longer in the view tree (and thus this node is obsolete). 1378 */ refreshWithExtraData(String extraDataKey, Bundle args)1379 public boolean refreshWithExtraData(String extraDataKey, Bundle args) { 1380 // limits the text location length to make sure the rectangle array allocation avoids 1381 // the binder transaction failure and OOM crash. 1382 if (args.getInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH, -1) 1383 > EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH) { 1384 args.putInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH, 1385 EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH); 1386 } 1387 1388 args.putString(EXTRA_DATA_REQUESTED_KEY, extraDataKey); 1389 return refresh(args, true); 1390 } 1391 1392 /** 1393 * Returns the array containing the IDs of this node's children. 1394 * 1395 * @hide 1396 */ getChildNodeIds()1397 public LongArray getChildNodeIds() { 1398 return mChildNodeIds; 1399 } 1400 1401 /** 1402 * Returns the id of the child at the specified index. 1403 * 1404 * @throws IndexOutOfBoundsException when index < 0 || index >= 1405 * getChildCount() 1406 * @hide 1407 */ getChildId(int index)1408 public long getChildId(int index) { 1409 if (mChildNodeIds == null) { 1410 throw new IndexOutOfBoundsException(); 1411 } 1412 return mChildNodeIds.get(index); 1413 } 1414 1415 /** 1416 * Gets the number of children. 1417 * 1418 * @return The child count. 1419 */ getChildCount()1420 public int getChildCount() { 1421 return mChildNodeIds == null ? 0 : mChildNodeIds.size(); 1422 } 1423 1424 /** 1425 * Get the child at given index. 1426 * 1427 * @param index The child index. 1428 * @return The child node. 1429 * 1430 * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before 1431 * calling {@link #setQueryFromAppProcessEnabled}. 1432 */ getChild(int index)1433 public AccessibilityNodeInfo getChild(int index) { 1434 return getChild(index, FLAG_PREFETCH_DESCENDANTS_HYBRID); 1435 } 1436 1437 1438 /** 1439 * Get the child at given index. 1440 * 1441 * <p> 1442 * See {@link #getParent(int)} for a description of prefetching. 1443 * @param index The child index. 1444 * @param prefetchingStrategy the prefetching strategy. 1445 * @return The child node. 1446 * 1447 * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before 1448 * calling {@link #setQueryFromAppProcessEnabled}. 1449 * 1450 */ 1451 @Nullable getChild(int index, @PrefetchingStrategy int prefetchingStrategy)1452 public AccessibilityNodeInfo getChild(int index, @PrefetchingStrategy int prefetchingStrategy) { 1453 enforceSealed(); 1454 if (mChildNodeIds == null) { 1455 return null; 1456 } 1457 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 1458 return null; 1459 } 1460 final long childId = mChildNodeIds.get(index); 1461 final AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 1462 if (mLeashedChild != null && childId == LEASHED_NODE_ID) { 1463 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mLeashedChild, 1464 ROOT_NODE_ID, false, prefetchingStrategy, null); 1465 } 1466 1467 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId, 1468 childId, false, prefetchingStrategy, null); 1469 } 1470 1471 /** 1472 * Adds a child. 1473 * <p> 1474 * <strong>Note:</strong> Cannot be called from an 1475 * {@link android.accessibilityservice.AccessibilityService}. 1476 * This class is made immutable before being delivered to an AccessibilityService. 1477 * Note that a view cannot be made its own child. 1478 * </p> 1479 * 1480 * @param child The child. 1481 * 1482 * @throws IllegalStateException If called from an AccessibilityService. 1483 */ addChild(View child)1484 public void addChild(View child) { 1485 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, true); 1486 } 1487 1488 /** 1489 * Adds a view root from leashed content as a child. This method is used to embedded another 1490 * view hierarchy. 1491 * <p> 1492 * <strong>Note:</strong> Only one leashed child is permitted. 1493 * </p> 1494 * <p> 1495 * <strong>Note:</strong> Cannot be called from an 1496 * {@link android.accessibilityservice.AccessibilityService}. 1497 * This class is made immutable before being delivered to an AccessibilityService. 1498 * Note that a view cannot be made its own child. 1499 * </p> 1500 * 1501 * @param token The token to which a view root is added. 1502 * 1503 * @throws IllegalStateException If called from an AccessibilityService. 1504 * @hide 1505 */ 1506 @TestApi addChild(@onNull IBinder token)1507 public void addChild(@NonNull IBinder token) { 1508 enforceNotSealed(); 1509 if (token == null) { 1510 return; 1511 } 1512 if (mChildNodeIds == null) { 1513 mChildNodeIds = new LongArray(); 1514 } 1515 1516 mLeashedChild = token; 1517 // Checking uniqueness. 1518 // Since only one leashed child is permitted, skip adding ID if the ID already exists. 1519 if (mChildNodeIds.indexOf(LEASHED_NODE_ID) >= 0) { 1520 return; 1521 } 1522 mChildNodeIds.add(LEASHED_NODE_ID); 1523 } 1524 1525 /** 1526 * Unchecked version of {@link #addChild(View)} that does not verify 1527 * uniqueness. For framework use only. 1528 * 1529 * @hide 1530 */ addChildUnchecked(View child)1531 public void addChildUnchecked(View child) { 1532 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, false); 1533 } 1534 1535 /** 1536 * Removes a child. If the child was not previously added to the node, 1537 * calling this method has no effect. 1538 * <p> 1539 * <strong>Note:</strong> Cannot be called from an 1540 * {@link android.accessibilityservice.AccessibilityService}. 1541 * This class is made immutable before being delivered to an AccessibilityService. 1542 * </p> 1543 * 1544 * @param child The child. 1545 * @return true if the child was present 1546 * 1547 * @throws IllegalStateException If called from an AccessibilityService. 1548 */ removeChild(View child)1549 public boolean removeChild(View child) { 1550 return removeChild(child, AccessibilityNodeProvider.HOST_VIEW_ID); 1551 } 1552 1553 /** 1554 * Removes a leashed child. If the child was not previously added to the node, 1555 * calling this method has no effect. 1556 * <p> 1557 * <strong>Note:</strong> Cannot be called from an 1558 * {@link android.accessibilityservice.AccessibilityService}. 1559 * This class is made immutable before being delivered to an AccessibilityService. 1560 * </p> 1561 * 1562 * @param token The token of the leashed child 1563 * @return true if the child was present 1564 * 1565 * @throws IllegalStateException If called from an AccessibilityService. 1566 * @hide 1567 */ removeChild(IBinder token)1568 public boolean removeChild(IBinder token) { 1569 enforceNotSealed(); 1570 if (mChildNodeIds == null || mLeashedChild == null) { 1571 return false; 1572 } 1573 if (!mLeashedChild.equals(token)) { 1574 return false; 1575 } 1576 final int index = mChildNodeIds.indexOf(LEASHED_NODE_ID); 1577 mLeashedChild = null; 1578 if (index < 0) { 1579 return false; 1580 } 1581 mChildNodeIds.remove(index); 1582 return true; 1583 } 1584 1585 /** 1586 * Adds a virtual child which is a descendant of the given <code>root</code>. 1587 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root 1588 * is added as a child. 1589 * <p> 1590 * A virtual descendant is an imaginary View that is reported as a part of the view 1591 * hierarchy for accessibility purposes. This enables custom views that draw complex 1592 * content to report them selves as a tree of virtual views, thus conveying their 1593 * logical structure. 1594 * Note that a view cannot be made its own child. 1595 * </p> 1596 * 1597 * @param root The root of the virtual subtree. 1598 * @param virtualDescendantId The id of the virtual child. 1599 */ addChild(View root, int virtualDescendantId)1600 public void addChild(View root, int virtualDescendantId) { 1601 addChildInternal(root, virtualDescendantId, true); 1602 } 1603 addChildInternal(View root, int virtualDescendantId, boolean checked)1604 private void addChildInternal(View root, int virtualDescendantId, boolean checked) { 1605 enforceNotSealed(); 1606 if (mChildNodeIds == null) { 1607 mChildNodeIds = new LongArray(); 1608 } 1609 final int rootAccessibilityViewId = 1610 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 1611 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 1612 if (childNodeId == mSourceNodeId) { 1613 Log.e(TAG, "Rejecting attempt to make a View its own child"); 1614 return; 1615 } 1616 1617 // If we're checking uniqueness and the ID already exists, abort. 1618 if (checked && mChildNodeIds.indexOf(childNodeId) >= 0) { 1619 return; 1620 } 1621 mChildNodeIds.add(childNodeId); 1622 } 1623 1624 /** 1625 * Removes a virtual child which is a descendant of the given 1626 * <code>root</code>. If the child was not previously added to the node, 1627 * calling this method has no effect. 1628 * 1629 * @param root The root of the virtual subtree. 1630 * @param virtualDescendantId The id of the virtual child. 1631 * @return true if the child was present 1632 * @see #addChild(View, int) 1633 */ removeChild(View root, int virtualDescendantId)1634 public boolean removeChild(View root, int virtualDescendantId) { 1635 enforceNotSealed(); 1636 final LongArray childIds = mChildNodeIds; 1637 if (childIds == null) { 1638 return false; 1639 } 1640 final int rootAccessibilityViewId = 1641 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 1642 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 1643 final int index = childIds.indexOf(childNodeId); 1644 if (index < 0) { 1645 return false; 1646 } 1647 childIds.remove(index); 1648 return true; 1649 } 1650 1651 /** 1652 * Gets the actions that can be performed on the node. 1653 */ getActionList()1654 public List<AccessibilityAction> getActionList() { 1655 return CollectionUtils.emptyIfNull(mActions); 1656 } 1657 1658 /** 1659 * Gets the actions that can be performed on the node. 1660 * 1661 * @return The bit mask of with actions. 1662 * 1663 * @see AccessibilityNodeInfo#ACTION_FOCUS 1664 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS 1665 * @see AccessibilityNodeInfo#ACTION_SELECT 1666 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION 1667 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS 1668 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS 1669 * @see AccessibilityNodeInfo#ACTION_CLICK 1670 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK 1671 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY 1672 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 1673 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT 1674 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT 1675 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD 1676 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD 1677 * 1678 * @deprecated Use {@link #getActionList()}. 1679 */ 1680 @Deprecated getActions()1681 public int getActions() { 1682 int returnValue = 0; 1683 1684 if (mActions == null) { 1685 return returnValue; 1686 } 1687 1688 final int actionSize = mActions.size(); 1689 for (int i = 0; i < actionSize; i++) { 1690 int actionId = mActions.get(i).getId(); 1691 if (actionId <= LAST_LEGACY_STANDARD_ACTION) { 1692 returnValue |= actionId; 1693 } 1694 } 1695 1696 return returnValue; 1697 } 1698 1699 /** 1700 * Adds an action that can be performed on the node. 1701 * <p> 1702 * To add a standard action use the static constants on {@link AccessibilityAction}. 1703 * To add a custom action create a new {@link AccessibilityAction} by passing in a 1704 * resource id from your application as the action id and an optional label that 1705 * describes the action. To override one of the standard actions use as the action 1706 * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that 1707 * describes the action. 1708 * </p> 1709 * <p> 1710 * Use {@link androidx.core.view.ViewCompat#addAccessibilityAction(View, CharSequence, 1711 * AccessibilityViewCommand)} to register an action directly on the view. 1712 * <p> 1713 * <strong>Note:</strong> Cannot be called from an 1714 * {@link android.accessibilityservice.AccessibilityService}. 1715 * This class is made immutable before being delivered to an AccessibilityService. 1716 * </p> 1717 * 1718 * @param action The action. 1719 * 1720 * @throws IllegalStateException If called from an AccessibilityService. 1721 */ addAction(AccessibilityAction action)1722 public void addAction(AccessibilityAction action) { 1723 enforceNotSealed(); 1724 1725 addActionUnchecked(action); 1726 } 1727 addActionUnchecked(AccessibilityAction action)1728 private void addActionUnchecked(AccessibilityAction action) { 1729 if (action == null) { 1730 return; 1731 } 1732 1733 if (mActions == null) { 1734 mActions = new ArrayList<>(); 1735 } 1736 1737 mActions.remove(action); 1738 mActions.add(action); 1739 } 1740 1741 /** 1742 * Adds an action that can be performed on the node. 1743 * <p> 1744 * <strong>Note:</strong> Cannot be called from an 1745 * {@link android.accessibilityservice.AccessibilityService}. 1746 * This class is made immutable before being delivered to an AccessibilityService. 1747 * </p> 1748 * 1749 * @param action The action. 1750 * 1751 * @throws IllegalStateException If called from an AccessibilityService. 1752 * @throws IllegalArgumentException If the argument is not one of the standard actions. 1753 * 1754 * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)} 1755 */ 1756 @Deprecated addAction(int action)1757 public void addAction(int action) { 1758 enforceNotSealed(); 1759 1760 if ((action & INVALID_ACTIONS_MASK) != 0) { 1761 throw new IllegalArgumentException("Action is not a combination of the standard " + 1762 "actions: " + action); 1763 } 1764 1765 addStandardActions(action); 1766 } 1767 1768 /** 1769 * Removes an action that can be performed on the node. If the action was 1770 * not already added to the node, calling this method has no effect. 1771 * <p> 1772 * <strong>Note:</strong> Cannot be called from an 1773 * {@link android.accessibilityservice.AccessibilityService}. 1774 * This class is made immutable before being delivered to an AccessibilityService. 1775 * </p> 1776 * 1777 * @param action The action to be removed. 1778 * 1779 * @throws IllegalStateException If called from an AccessibilityService. 1780 * @deprecated Use {@link #removeAction(AccessibilityAction)} 1781 */ 1782 @Deprecated removeAction(int action)1783 public void removeAction(int action) { 1784 enforceNotSealed(); 1785 1786 removeAction(getActionSingleton(action)); 1787 } 1788 1789 /** 1790 * Removes an action that can be performed on the node. If the action was 1791 * not already added to the node, calling this method has no effect. 1792 * <p> 1793 * <strong>Note:</strong> Cannot be called from an 1794 * {@link android.accessibilityservice.AccessibilityService}. 1795 * This class is made immutable before being delivered to an AccessibilityService. 1796 * </p> 1797 * 1798 * @param action The action to be removed. 1799 * @return The action removed from the list of actions. 1800 * 1801 * @throws IllegalStateException If called from an AccessibilityService. 1802 */ removeAction(AccessibilityAction action)1803 public boolean removeAction(AccessibilityAction action) { 1804 enforceNotSealed(); 1805 1806 if (mActions == null || action == null) { 1807 return false; 1808 } 1809 1810 return mActions.remove(action); 1811 } 1812 1813 /** 1814 * Removes all actions. 1815 * 1816 * @hide 1817 */ removeAllActions()1818 public void removeAllActions() { 1819 if (mActions != null) { 1820 mActions.clear(); 1821 } 1822 } 1823 1824 /** 1825 * Gets the node before which this one is visited during traversal. A screen-reader 1826 * must visit the content of this node before the content of the one it precedes. 1827 * 1828 * @return The succeeding node if such or <code>null</code>. 1829 * 1830 * @see #setTraversalBefore(android.view.View) 1831 * @see #setTraversalBefore(android.view.View, int) 1832 */ getTraversalBefore()1833 public AccessibilityNodeInfo getTraversalBefore() { 1834 enforceSealed(); 1835 return getNodeForAccessibilityId(mConnectionId, mWindowId, mTraversalBefore); 1836 } 1837 1838 /** 1839 * Sets the view before whose node this one should be visited during traversal. A 1840 * screen-reader must visit the content of this node before the content of the one 1841 * it precedes. 1842 * <p> 1843 * <strong>Note:</strong> Cannot be called from an 1844 * {@link android.accessibilityservice.AccessibilityService}. 1845 * This class is made immutable before being delivered to an AccessibilityService. 1846 * </p> 1847 * 1848 * @param view The view providing the preceding node. 1849 * 1850 * @see #getTraversalBefore() 1851 */ setTraversalBefore(View view)1852 public void setTraversalBefore(View view) { 1853 setTraversalBefore(view, AccessibilityNodeProvider.HOST_VIEW_ID); 1854 } 1855 1856 /** 1857 * Sets the node before which this one is visited during traversal. A screen-reader 1858 * must visit the content of this node before the content of the one it precedes. 1859 * The successor is a virtual descendant of the given <code>root</code>. If 1860 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set 1861 * as the successor. 1862 * <p> 1863 * A virtual descendant is an imaginary View that is reported as a part of the view 1864 * hierarchy for accessibility purposes. This enables custom views that draw complex 1865 * content to report them selves as a tree of virtual views, thus conveying their 1866 * logical structure. 1867 * </p> 1868 * <p> 1869 * <strong>Note:</strong> Cannot be called from an 1870 * {@link android.accessibilityservice.AccessibilityService}. 1871 * This class is made immutable before being delivered to an AccessibilityService. 1872 * </p> 1873 * 1874 * @param root The root of the virtual subtree. 1875 * @param virtualDescendantId The id of the virtual descendant. 1876 */ setTraversalBefore(View root, int virtualDescendantId)1877 public void setTraversalBefore(View root, int virtualDescendantId) { 1878 enforceNotSealed(); 1879 final int rootAccessibilityViewId = (root != null) 1880 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 1881 mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 1882 } 1883 1884 /** 1885 * Gets the node after which this one is visited in accessibility traversal. 1886 * A screen-reader must visit the content of the other node before the content 1887 * of this one. 1888 * 1889 * @return The succeeding node if such or <code>null</code>. 1890 * 1891 * @see #setTraversalAfter(android.view.View) 1892 * @see #setTraversalAfter(android.view.View, int) 1893 */ getTraversalAfter()1894 public AccessibilityNodeInfo getTraversalAfter() { 1895 enforceSealed(); 1896 return getNodeForAccessibilityId(mConnectionId, mWindowId, mTraversalAfter); 1897 } 1898 1899 /** 1900 * Sets the view whose node is visited after this one in accessibility traversal. 1901 * A screen-reader must visit the content of the other node before the content 1902 * of this one. 1903 * <p> 1904 * <strong>Note:</strong> Cannot be called from an 1905 * {@link android.accessibilityservice.AccessibilityService}. 1906 * This class is made immutable before being delivered to an AccessibilityService. 1907 * </p> 1908 * 1909 * @param view The previous view. 1910 * 1911 * @see #getTraversalAfter() 1912 */ setTraversalAfter(View view)1913 public void setTraversalAfter(View view) { 1914 setTraversalAfter(view, AccessibilityNodeProvider.HOST_VIEW_ID); 1915 } 1916 1917 /** 1918 * Sets the node after which this one is visited in accessibility traversal. 1919 * A screen-reader must visit the content of the other node before the content 1920 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID} 1921 * the root is set as the predecessor. 1922 * <p> 1923 * A virtual descendant is an imaginary View that is reported as a part of the view 1924 * hierarchy for accessibility purposes. This enables custom views that draw complex 1925 * content to report them selves as a tree of virtual views, thus conveying their 1926 * logical structure. 1927 * </p> 1928 * <p> 1929 * <strong>Note:</strong> Cannot be called from an 1930 * {@link android.accessibilityservice.AccessibilityService}. 1931 * This class is made immutable before being delivered to an AccessibilityService. 1932 * </p> 1933 * 1934 * @param root The root of the virtual subtree. 1935 * @param virtualDescendantId The id of the virtual descendant. 1936 */ setTraversalAfter(View root, int virtualDescendantId)1937 public void setTraversalAfter(View root, int virtualDescendantId) { 1938 enforceNotSealed(); 1939 final int rootAccessibilityViewId = (root != null) 1940 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 1941 mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 1942 } 1943 1944 /** 1945 * Get the extra data available for this node. 1946 * <p> 1947 * Some data that is useful for some accessibility services is expensive to compute, and would 1948 * place undue overhead on apps to compute all the time. That data can be requested with 1949 * {@link #refreshWithExtraData(String, Bundle)}. 1950 * 1951 * @return An unmodifiable list of keys corresponding to extra data that can be requested. 1952 * @see #EXTRA_DATA_RENDERING_INFO_KEY 1953 * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY 1954 */ getAvailableExtraData()1955 public List<String> getAvailableExtraData() { 1956 if (mExtraDataKeys != null) { 1957 return Collections.unmodifiableList(mExtraDataKeys); 1958 } else { 1959 return EMPTY_LIST; 1960 } 1961 } 1962 1963 /** 1964 * Set the extra data available for this node. 1965 * <p> 1966 * <strong>Note:</strong> When a {@code View} passes in a non-empty list, it promises that 1967 * it will populate the node's extras with corresponding pieces of information in 1968 * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)}. 1969 * <p> 1970 * <strong>Note:</strong> Cannot be called from an 1971 * {@link android.accessibilityservice.AccessibilityService}. 1972 * This class is made immutable before being delivered to an AccessibilityService. 1973 * 1974 * @param extraDataKeys A list of types of extra data that are available. 1975 * @see #getAvailableExtraData() 1976 * 1977 * @throws IllegalStateException If called from an AccessibilityService. 1978 */ setAvailableExtraData(List<String> extraDataKeys)1979 public void setAvailableExtraData(List<String> extraDataKeys) { 1980 enforceNotSealed(); 1981 mExtraDataKeys = new ArrayList<>(extraDataKeys); 1982 } 1983 1984 /** 1985 * Sets the maximum text length, or -1 for no limit. 1986 * <p> 1987 * Typically used to indicate that an editable text field has a limit on 1988 * the number of characters entered. 1989 * <p> 1990 * <strong>Note:</strong> Cannot be called from an 1991 * {@link android.accessibilityservice.AccessibilityService}. 1992 * This class is made immutable before being delivered to an AccessibilityService. 1993 * 1994 * @param max The maximum text length. 1995 * @see #getMaxTextLength() 1996 * 1997 * @throws IllegalStateException If called from an AccessibilityService. 1998 */ setMaxTextLength(int max)1999 public void setMaxTextLength(int max) { 2000 enforceNotSealed(); 2001 mMaxTextLength = max; 2002 } 2003 2004 /** 2005 * Returns the maximum text length for this node. 2006 * 2007 * @return The maximum text length, or -1 for no limit. 2008 * @see #setMaxTextLength(int) 2009 */ getMaxTextLength()2010 public int getMaxTextLength() { 2011 return mMaxTextLength; 2012 } 2013 2014 /** 2015 * Sets the movement granularities for traversing the text of this node. 2016 * <p> 2017 * <strong>Note:</strong> Cannot be called from an 2018 * {@link android.accessibilityservice.AccessibilityService}. 2019 * This class is made immutable before being delivered to an AccessibilityService. 2020 * </p> 2021 * 2022 * @param granularities The bit mask with granularities. 2023 * 2024 * @throws IllegalStateException If called from an AccessibilityService. 2025 */ setMovementGranularities(int granularities)2026 public void setMovementGranularities(int granularities) { 2027 enforceNotSealed(); 2028 mMovementGranularities = granularities; 2029 } 2030 2031 /** 2032 * Gets the movement granularities for traversing the text of this node. 2033 * 2034 * @return The bit mask with granularities. 2035 */ getMovementGranularities()2036 public int getMovementGranularities() { 2037 return mMovementGranularities; 2038 } 2039 2040 /** 2041 * Sets the expanded state of the node. 2042 * 2043 * <p><strong>Note:</strong> Cannot be called from an {@link 2044 * android.accessibilityservice.AccessibilityService}. This class is made immutable before being 2045 * delivered to an {@link android.accessibilityservice.AccessibilityService}. 2046 * 2047 * @param state new expanded state of this node. 2048 * @throws IllegalArgumentException If state is not one of: 2049 * <ul> 2050 * <li>{@link #EXPANDED_STATE_UNDEFINED} 2051 * <li>{@link #EXPANDED_STATE_COLLAPSED} 2052 * <li>{@link #EXPANDED_STATE_PARTIAL} 2053 * <li>{@link #EXPANDED_STATE_FULL} 2054 * </ul> 2055 * 2056 * @throws IllegalStateException If called from an AccessibilityService 2057 */ 2058 @FlaggedApi(Flags.FLAG_A11Y_EXPANSION_STATE_API) setExpandedState(@xpandedState int state)2059 public void setExpandedState(@ExpandedState int state) { 2060 enforceValidExpandedState(state); 2061 enforceNotSealed(); 2062 mExpandedState = state; 2063 } 2064 2065 /** 2066 * Gets the expanded state for this node. 2067 * 2068 * @return The expanded state, one of: 2069 * <ul> 2070 * <li>{@link #EXPANDED_STATE_UNDEFINED} 2071 * <li>{@link #EXPANDED_STATE_COLLAPSED} 2072 * <li>{@link #EXPANDED_STATE_FULL} 2073 * <li>{@link #EXPANDED_STATE_PARTIAL} 2074 * </ul> 2075 */ 2076 @FlaggedApi(Flags.FLAG_A11Y_EXPANSION_STATE_API) getExpandedState()2077 public @ExpandedState int getExpandedState() { 2078 return mExpandedState; 2079 } 2080 2081 /** 2082 * Sets the minimum time duration between two content change events, which is used in throttling 2083 * content change events in accessibility services. 2084 * 2085 * <p> 2086 * Example: An app can set MinMillisBetweenContentChanges as 1 min for a view which sends 2087 * content change events to accessibility services one event per second. 2088 * Accessibility service will throttle those content change events and only handle one event 2089 * per minute for that view. 2090 * </p> 2091 * <p> 2092 * Example UI elements that frequently update and may benefit from a duration are progress bars, 2093 * timers, and stopwatches. 2094 * </p> 2095 * 2096 * @see AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED 2097 * @see AccessibilityEvent#getContentChangeTypes 2098 * @param duration the minimum duration between content change events. 2099 * Negative duration would be treated as zero. 2100 */ setMinDurationBetweenContentChanges(@onNull Duration duration)2101 public void setMinDurationBetweenContentChanges(@NonNull Duration duration) { 2102 enforceNotSealed(); 2103 mMinDurationBetweenContentChanges = duration.toMillis(); 2104 } 2105 2106 /** 2107 * Gets the minimum time duration between two content change events. 2108 */ 2109 @NonNull getMinDurationBetweenContentChanges()2110 public Duration getMinDurationBetweenContentChanges() { 2111 return Duration.ofMillis(mMinDurationBetweenContentChanges); 2112 } 2113 2114 /** 2115 * Performs an action on the node. 2116 * <p> 2117 * <strong>Note:</strong> An action can be performed only if the request is made 2118 * from an {@link android.accessibilityservice.AccessibilityService}. 2119 * </p> 2120 * 2121 * @param action The action to perform. 2122 * @return True if the action was performed. 2123 * 2124 * @throws IllegalStateException If called outside of an AccessibilityService. 2125 */ performAction(int action)2126 public boolean performAction(int action) { 2127 enforceSealed(); 2128 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 2129 return false; 2130 } 2131 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 2132 Bundle arguments = null; 2133 if (mExtras != null) { 2134 arguments = mExtras; 2135 } 2136 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId, 2137 action, arguments); 2138 } 2139 2140 /** 2141 * Performs an action on the node. 2142 * <p> 2143 * <strong>Note:</strong> An action can be performed only if the request is made 2144 * from an {@link android.accessibilityservice.AccessibilityService}. 2145 * </p> 2146 * 2147 * @param action The action to perform. 2148 * @param arguments A bundle with additional arguments. 2149 * @return True if the action was performed. 2150 * 2151 * @throws IllegalStateException If called outside of an AccessibilityService. 2152 */ performAction(int action, Bundle arguments)2153 public boolean performAction(int action, Bundle arguments) { 2154 enforceSealed(); 2155 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 2156 return false; 2157 } 2158 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 2159 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId, 2160 action, arguments); 2161 } 2162 2163 /** 2164 * Finds {@link AccessibilityNodeInfo}s by text. The match is case 2165 * insensitive containment. The search is relative to this info i.e. 2166 * this info is the root of the traversed tree. 2167 * 2168 * <p> 2169 * <strong>Note:</strong> If this view hierarchy has a {@link SurfaceView} embedding another 2170 * view hierarchy via {@link SurfaceView#setChildSurfacePackage}, there is a limitation that 2171 * this API won't be able to find the node for the view on the embedded view hierarchy. It's 2172 * because views don't know about the embedded hierarchies. Instead, you could traverse all 2173 * the children to find the node. 2174 * </p> 2175 * 2176 * @param text The searched text. 2177 * @return A list of node info. 2178 */ findAccessibilityNodeInfosByText(String text)2179 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) { 2180 enforceSealed(); 2181 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 2182 return Collections.emptyList(); 2183 } 2184 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 2185 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId, 2186 text); 2187 } 2188 2189 /** 2190 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource 2191 * name where a fully qualified id is of the from "package:id/id_resource_name". 2192 * For example, if the target application's package is "foo.bar" and the id 2193 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz". 2194 * 2195 * <p> 2196 * <strong>Note:</strong> The primary usage of this API is for UI test automation 2197 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo} 2198 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS} 2199 * flag when configuring the {@link android.accessibilityservice.AccessibilityService}. 2200 * </p> 2201 * <p> 2202 * <strong>Note:</strong> If this view hierarchy has a {@link SurfaceView} embedding another 2203 * view hierarchy via {@link SurfaceView#setChildSurfacePackage}, there is a limitation that 2204 * this API won't be able to find the node for the view on the embedded view hierarchy. It's 2205 * because views don't know about the embedded hierarchies. Instead, you could traverse all 2206 * the children to find the node. 2207 * </p> 2208 * 2209 * @param viewId The fully qualified resource name of the view id to find. 2210 * @return A list of node info. 2211 */ findAccessibilityNodeInfosByViewId(@onNull String viewId)2212 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(@NonNull String viewId) { 2213 enforceSealed(); 2214 if (viewId == null) { 2215 Log.e(TAG, "returns empty list due to null viewId."); 2216 return Collections.emptyList(); 2217 } 2218 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 2219 return Collections.emptyList(); 2220 } 2221 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 2222 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId, 2223 viewId); 2224 } 2225 2226 /** 2227 * Gets the window to which this node belongs. 2228 * 2229 * @return The window. 2230 * 2231 * @see android.accessibilityservice.AccessibilityService#getWindows() 2232 */ getWindow()2233 public AccessibilityWindowInfo getWindow() { 2234 enforceSealed(); 2235 if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) { 2236 return null; 2237 } 2238 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 2239 return client.getWindow(mConnectionId, mWindowId); 2240 } 2241 2242 /** 2243 * Gets the parent. 2244 * 2245 * @return The parent. 2246 * 2247 * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before 2248 * calling {@link #setQueryFromAppProcessEnabled}. 2249 */ getParent()2250 public AccessibilityNodeInfo getParent() { 2251 enforceSealed(); 2252 if (mLeashedParent != null && mLeashedParentNodeId != UNDEFINED_NODE_ID) { 2253 return getNodeForAccessibilityId(mConnectionId, mLeashedParent, mLeashedParentNodeId, 2254 FLAG_PREFETCH_ANCESTORS | FLAG_PREFETCH_SIBLINGS); 2255 } 2256 return getNodeForAccessibilityId(mConnectionId, mWindowId, mParentNodeId); 2257 } 2258 2259 /** 2260 * Gets the parent. 2261 * 2262 * <p> 2263 * Use {@code prefetchingStrategy} to determine the types of 2264 * nodes prefetched from the app if the requested node is not in the cache and must be retrieved 2265 * by the app. The default strategy for {@link #getParent()} is a combination of ancestor and 2266 * sibling strategies. The app will prefetch until all nodes fulfilling the strategies are 2267 * fetched, another node request is sent, or the maximum prefetch batch size of 2268 * {@link #MAX_NUMBER_OF_PREFETCHED_NODES} nodes is reached. To prevent interruption by another 2269 * request and to force prefetching of the max batch size, use 2270 * {@link AccessibilityNodeInfo#FLAG_PREFETCH_UNINTERRUPTIBLE}. 2271 * </p> 2272 * 2273 * @param prefetchingStrategy the prefetching strategy. 2274 * @return The parent. 2275 * 2276 * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before 2277 * calling {@link #setQueryFromAppProcessEnabled}. 2278 * 2279 * @see #FLAG_PREFETCH_ANCESTORS 2280 * @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST 2281 * @see #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST 2282 * @see #FLAG_PREFETCH_DESCENDANTS_HYBRID 2283 * @see #FLAG_PREFETCH_SIBLINGS 2284 * @see #FLAG_PREFETCH_UNINTERRUPTIBLE 2285 */ 2286 @Nullable getParent(@refetchingStrategy int prefetchingStrategy)2287 public AccessibilityNodeInfo getParent(@PrefetchingStrategy int prefetchingStrategy) { 2288 enforceSealed(); 2289 if (mLeashedParent != null && mLeashedParentNodeId != UNDEFINED_NODE_ID) { 2290 return getNodeForAccessibilityId(mConnectionId, mLeashedParent, mLeashedParentNodeId, 2291 prefetchingStrategy); 2292 } 2293 return getNodeForAccessibilityId(mConnectionId, mWindowId, mParentNodeId, 2294 prefetchingStrategy); 2295 } 2296 2297 /** 2298 * @return The parent node id. 2299 * 2300 * @hide 2301 */ getParentNodeId()2302 public long getParentNodeId() { 2303 return mParentNodeId; 2304 } 2305 2306 /** 2307 * Sets the parent. 2308 * <p> 2309 * <strong>Note:</strong> Cannot be called from an 2310 * {@link android.accessibilityservice.AccessibilityService}. 2311 * This class is made immutable before being delivered to an AccessibilityService. 2312 * </p> 2313 * 2314 * @param parent The parent. 2315 * 2316 * @throws IllegalStateException If called from an AccessibilityService. 2317 */ setParent(View parent)2318 public void setParent(View parent) { 2319 setParent(parent, AccessibilityNodeProvider.HOST_VIEW_ID); 2320 } 2321 2322 /** 2323 * Sets the parent to be a virtual descendant of the given <code>root</code>. 2324 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root 2325 * is set as the parent. 2326 * <p> 2327 * A virtual descendant is an imaginary View that is reported as a part of the view 2328 * hierarchy for accessibility purposes. This enables custom views that draw complex 2329 * content to report them selves as a tree of virtual views, thus conveying their 2330 * logical structure. 2331 * </p> 2332 * <p> 2333 * <strong>Note:</strong> Cannot be called from an 2334 * {@link android.accessibilityservice.AccessibilityService}. 2335 * This class is made immutable before being delivered to an AccessibilityService. 2336 * </p> 2337 * 2338 * @param root The root of the virtual subtree. 2339 * @param virtualDescendantId The id of the virtual descendant. 2340 */ setParent(View root, int virtualDescendantId)2341 public void setParent(View root, int virtualDescendantId) { 2342 enforceNotSealed(); 2343 final int rootAccessibilityViewId = 2344 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 2345 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 2346 } 2347 2348 /** 2349 * Gets the node bounds in the viewParent's coordinates. 2350 * {@link #getParent()} does not represent the source's viewParent. 2351 * Instead it represents the result of {@link View#getParentForAccessibility()}, 2352 * which returns the closest ancestor where {@link View#isImportantForAccessibility()} is true. 2353 * So this method is not reliable. 2354 * <p> 2355 * When magnification is enabled, the bounds in parent are also scaled up by magnification 2356 * scale. For example, it returns Rect(20, 20, 200, 200) for original bounds 2357 * Rect(10, 10, 100, 100), when the magnification scale is 2. 2358 * <p/> 2359 * 2360 * @param outBounds The output node bounds. 2361 * @deprecated Use {@link #getBoundsInScreen(Rect)} instead. 2362 * 2363 */ 2364 @Deprecated getBoundsInParent(Rect outBounds)2365 public void getBoundsInParent(Rect outBounds) { 2366 outBounds.set(mBoundsInParent.left, mBoundsInParent.top, 2367 mBoundsInParent.right, mBoundsInParent.bottom); 2368 } 2369 2370 /** 2371 * Sets the node bounds in the viewParent's coordinates. 2372 * {@link #getParent()} does not represent the source's viewParent. 2373 * Instead it represents the result of {@link View#getParentForAccessibility()}, 2374 * which returns the closest ancestor where {@link View#isImportantForAccessibility()} is true. 2375 * So this method is not reliable. 2376 * 2377 * <p> 2378 * <strong>Note:</strong> Cannot be called from an 2379 * {@link android.accessibilityservice.AccessibilityService}. 2380 * This class is made immutable before being delivered to an AccessibilityService. 2381 * </p> 2382 * 2383 * @param bounds The node bounds. 2384 * 2385 * @throws IllegalStateException If called from an AccessibilityService. 2386 * @deprecated Accessibility services should not care about these bounds. 2387 */ 2388 @Deprecated setBoundsInParent(Rect bounds)2389 public void setBoundsInParent(Rect bounds) { 2390 enforceNotSealed(); 2391 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom); 2392 } 2393 2394 /** 2395 * Gets the node bounds in screen coordinates. 2396 * <p> 2397 * When magnification is enabled, the bounds in screen are scaled up by magnification scale 2398 * and the positions are also adjusted according to the offset of magnification viewport. 2399 * For example, it returns Rect(-180, -180, 0, 0) for original bounds Rect(10, 10, 100, 100), 2400 * when the magnification scale is 2 and offsets for X and Y are both 200. 2401 * <p/> 2402 * 2403 * @param outBounds The output node bounds. 2404 */ getBoundsInScreen(Rect outBounds)2405 public void getBoundsInScreen(Rect outBounds) { 2406 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top, 2407 mBoundsInScreen.right, mBoundsInScreen.bottom); 2408 } 2409 2410 /** 2411 * Returns the actual rect containing the node bounds in screen coordinates. 2412 * 2413 * @hide Not safe to expose outside the framework. 2414 */ getBoundsInScreen()2415 public Rect getBoundsInScreen() { 2416 return mBoundsInScreen; 2417 } 2418 2419 /** 2420 * Sets the node bounds in screen coordinates. 2421 * <p> 2422 * <strong>Note:</strong> Cannot be called from an 2423 * {@link android.accessibilityservice.AccessibilityService}. 2424 * This class is made immutable before being delivered to an AccessibilityService. 2425 * </p> 2426 * 2427 * @param bounds The node bounds. 2428 * 2429 * @throws IllegalStateException If called from an AccessibilityService. 2430 */ setBoundsInScreen(Rect bounds)2431 public void setBoundsInScreen(Rect bounds) { 2432 enforceNotSealed(); 2433 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom); 2434 } 2435 2436 /** 2437 * Gets the node bounds in window coordinates. 2438 * <p> 2439 * The node bounds returned are not scaled by magnification. 2440 * <p/> 2441 * 2442 * @param outBounds The output node bounds. 2443 */ getBoundsInWindow(@onNull Rect outBounds)2444 public void getBoundsInWindow(@NonNull Rect outBounds) { 2445 outBounds.set(mBoundsInWindow.left, mBoundsInWindow.top, 2446 mBoundsInWindow.right, mBoundsInWindow.bottom); 2447 } 2448 2449 /** 2450 * Returns the actual rect containing the node bounds in window coordinates. 2451 * 2452 * @hide Not safe to expose outside the framework. 2453 */ 2454 @NonNull getBoundsInWindow()2455 public Rect getBoundsInWindow() { 2456 return mBoundsInWindow; 2457 } 2458 2459 /** 2460 * Sets the node bounds in window coordinates. 2461 * <p> 2462 * <strong>Note:</strong> Cannot be called from an 2463 * {@link android.accessibilityservice.AccessibilityService}. 2464 * This class is made immutable before being delivered to an AccessibilityService. 2465 * </p> 2466 * 2467 * @param bounds The node bounds. 2468 * 2469 * @throws IllegalStateException If called from an AccessibilityService. 2470 */ setBoundsInWindow(@onNull Rect bounds)2471 public void setBoundsInWindow(@NonNull Rect bounds) { 2472 enforceNotSealed(); 2473 mBoundsInWindow.set(bounds); 2474 } 2475 2476 /** 2477 * Gets whether this node is checkable. 2478 * 2479 * @return True if the node is checkable. 2480 */ isCheckable()2481 public boolean isCheckable() { 2482 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE); 2483 } 2484 2485 /** 2486 * Sets whether this node is checkable. 2487 * <p> 2488 * <strong>Note:</strong> Cannot be called from an 2489 * {@link android.accessibilityservice.AccessibilityService}. 2490 * This class is made immutable before being delivered to an AccessibilityService. 2491 * </p> 2492 * 2493 * @param checkable True if the node is checkable. 2494 * 2495 * @throws IllegalStateException If called from an AccessibilityService. 2496 */ setCheckable(boolean checkable)2497 public void setCheckable(boolean checkable) { 2498 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable); 2499 } 2500 2501 /** 2502 * Gets whether this node is checked. This is only meaningful 2503 * when {@link #isCheckable()} returns {@code true}. 2504 * 2505 * @deprecated Use {@link #getChecked()} instead. 2506 * 2507 * @return True if the node is checked. 2508 */ 2509 @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED) 2510 @Deprecated isChecked()2511 public boolean isChecked() { 2512 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED); 2513 } 2514 2515 /** 2516 * Sets whether this node is checked. This is only meaningful 2517 * when {@link #isCheckable()} returns {@code true}. 2518 * <p> 2519 * <strong>Note:</strong> Cannot be called from an 2520 * {@link android.accessibilityservice.AccessibilityService}. 2521 * This class is made immutable before being delivered to an AccessibilityService. 2522 * </p> 2523 * 2524 * @deprecated Use {@link #setChecked(int)} instead. 2525 * 2526 * @param checked True if the node is checked. 2527 * 2528 * @throws IllegalStateException If called from an AccessibilityService. 2529 */ 2530 @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED) 2531 @Deprecated setChecked(boolean checked)2532 public void setChecked(boolean checked) { 2533 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked); 2534 if (Flags.triStateChecked()) { 2535 mChecked = checked ? CHECKED_STATE_TRUE : CHECKED_STATE_FALSE; 2536 } 2537 } 2538 2539 /** 2540 * Gets the checked state of this node. This is only meaningful 2541 * when {@link #isCheckable()} returns {@code true}. 2542 * 2543 * @see #setCheckable(boolean) 2544 * @see #isCheckable() 2545 * @see #setChecked(int) 2546 * 2547 * @return The checked state, one of: 2548 * <ul> 2549 * <li>{@link #CHECKED_STATE_FALSE} 2550 * <li>{@link #CHECKED_STATE_TRUE} 2551 * <li>{@link #CHECKED_STATE_PARTIAL} 2552 * </ul> 2553 */ 2554 @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED) getChecked()2555 public @CheckedState int getChecked() { 2556 return mChecked; 2557 } 2558 2559 /** 2560 * Sets the checked state of this node. This is only meaningful 2561 * when {@link #isCheckable()} returns {@code true}. 2562 * <p> 2563 * <strong>Note:</strong> Cannot be called from an 2564 * {@link android.accessibilityservice.AccessibilityService}. 2565 * This class is made immutable before being delivered to an AccessibilityService. 2566 * </p> 2567 * 2568 * @see #setCheckable(boolean) 2569 * @see #isCheckable() 2570 * @see #getChecked() 2571 * 2572 * @param checked The checked state. One of 2573 * <ul> 2574 * <li>{@link #CHECKED_STATE_FALSE} 2575 * <li>{@link #CHECKED_STATE_TRUE} 2576 * <li>{@link #CHECKED_STATE_PARTIAL} 2577 * </ul> 2578 * 2579 * @throws IllegalStateException If called from an AccessibilityService. 2580 * @throws IllegalArgumentException if checked is not one of {@link #CHECKED_STATE_FALSE}, 2581 * {@link #CHECKED_STATE_TRUE}, or {@link #CHECKED_STATE_PARTIAL}. 2582 */ 2583 @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED) setChecked(@heckedState int checked)2584 public void setChecked(@CheckedState int checked) { 2585 enforceNotSealed(); 2586 switch (checked) { 2587 case CHECKED_STATE_FALSE: 2588 case CHECKED_STATE_TRUE: 2589 case CHECKED_STATE_PARTIAL: 2590 mChecked = checked; 2591 break; 2592 default: 2593 throw new IllegalArgumentException("Unknown checked argument: " + checked); 2594 } 2595 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked == CHECKED_STATE_TRUE); 2596 } 2597 2598 /** 2599 * Gets whether a node representing a form field requires input or selection. 2600 * 2601 * @return {@code true} if {@code this} node represents a form field that requires input or 2602 * selection, {@code false} otherwise. 2603 */ 2604 @FlaggedApi(Flags.FLAG_A11Y_IS_REQUIRED_API) isFieldRequired()2605 public boolean isFieldRequired() { 2606 return getBooleanProperty(BOOLEAN_PROPERTY_FIELD_REQUIRED); 2607 } 2608 2609 /** 2610 * Sets whether {@code this} node represents a form field that requires input or selection. 2611 * 2612 * <p><strong>Note:</strong> Cannot be called from an AccessibilityService. This class is made 2613 * immutable before being delivered to an AccessibilityService. 2614 * 2615 * @param required {@code true} if input or selection of this node should be required, {@code 2616 * false} otherwise. 2617 * @throws IllegalStateException If called from an AccessibilityService 2618 */ 2619 @FlaggedApi(Flags.FLAG_A11Y_IS_REQUIRED_API) setFieldRequired(boolean required)2620 public void setFieldRequired(boolean required) { 2621 setBooleanProperty(BOOLEAN_PROPERTY_FIELD_REQUIRED, required); 2622 } 2623 2624 /** 2625 * Gets whether this node is focusable. 2626 * 2627 * <p>In the View system, this typically maps to {@link View#isFocusable()}. 2628 * @return True if the node is focusable. 2629 */ isFocusable()2630 public boolean isFocusable() { 2631 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE); 2632 } 2633 2634 /** 2635 * Sets whether this node is focusable. 2636 * <p> 2637 * <strong>Note:</strong> Cannot be called from an 2638 * {@link android.accessibilityservice.AccessibilityService}. 2639 * This class is made immutable before being delivered to an AccessibilityService. 2640 * </p> 2641 * <p>To mark a node as explicitly focusable for a screen reader, consider using 2642 * {@link #setScreenReaderFocusable(boolean)} instead. 2643 * 2644 * @param focusable True if the node is focusable. 2645 * 2646 * @throws IllegalStateException If called from an AccessibilityService. 2647 */ setFocusable(boolean focusable)2648 public void setFocusable(boolean focusable) { 2649 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable); 2650 } 2651 2652 /** 2653 * Gets whether this node is focused. 2654 * 2655 * <p>This is distinct from {@link #isAccessibilityFocused()}, which is used by screen readers. 2656 * See {@link AccessibilityAction#ACTION_ACCESSIBILITY_FOCUS} for details. 2657 * 2658 * @return True if the node is focused. 2659 */ isFocused()2660 public boolean isFocused() { 2661 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED); 2662 } 2663 2664 /** 2665 * Sets whether this node is focused. 2666 * <p> 2667 * <strong>Note:</strong> Cannot be called from an 2668 * {@link android.accessibilityservice.AccessibilityService}. 2669 * This class is made immutable before being delivered to an AccessibilityService. 2670 * </p> 2671 * 2672 * @param focused True if the node is focused. 2673 * 2674 * @throws IllegalStateException If called from an AccessibilityService. 2675 */ setFocused(boolean focused)2676 public void setFocused(boolean focused) { 2677 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused); 2678 } 2679 2680 /** 2681 * Sets the extended selection, which is a representation of selection that spans multiple nodes 2682 * that exist within the subtree of the node defining selection. 2683 * 2684 * <p><b>Note:</b> The start and end {@link SelectionPosition} of the provided {@link Selection} 2685 * should be constructed with {@code this} node or a descendant of it. 2686 * 2687 * <p><b>Note:</b> {@link AccessibilityNodeInfo#setFocusable} and 2688 * {@link AccessibilityNodeInfo#setFocused} should both be called with {@code true} 2689 * before setting the selection in order to make {@code this} node a candidate to 2690 * contain a selection. 2691 * 2692 * <p><b>Note:</b> Cannot be called from an AccessibilityService. This class is made immutable 2693 * before being delivered to an AccessibilityService. 2694 * 2695 * @param selection The extended selection within the node's subtree, or {@code null} if no 2696 * selection exists. 2697 * @see AccessibilityNodeInfo.AccessibilityAction#ACTION_SET_EXTENDED_SELECTION 2698 * @throws IllegalStateException If called from an AccessibilityService 2699 */ 2700 @FlaggedApi(Flags.FLAG_A11Y_SELECTION_API) setSelection(@ullable Selection selection)2701 public void setSelection(@Nullable Selection selection) { 2702 enforceNotSealed(); 2703 mSelection = selection; 2704 } 2705 2706 /** 2707 * Gets the extended selection, which is a representation of selection that spans multiple nodes 2708 * that exist within the subtree of the node defining selection. 2709 * 2710 * <p><b>Note:</b> Nodes that are candidates to contain a selection should return 2711 * {@code true} from {@link #isFocusable()} and {@link #isFocused()}. 2712 * The start and end {@link SelectionPosition}s of this {@link Selection} 2713 * should exist within {@code this} node or its descendants. 2714 * 2715 * @return The extended selection within the node's subtree, or {@code null} if no selection 2716 * exists. 2717 */ 2718 @FlaggedApi(Flags.FLAG_A11Y_SELECTION_API) getSelection()2719 public @Nullable Selection getSelection() { 2720 if (mSelection != null) { 2721 mSelection.getStart().setWindowId(mWindowId); 2722 mSelection.getStart().setConnectionId(mConnectionId); 2723 mSelection.getEnd().setWindowId(mWindowId); 2724 mSelection.getEnd().setConnectionId(mConnectionId); 2725 } 2726 return mSelection; 2727 } 2728 2729 /** 2730 * Gets whether this node is visible to the user. 2731 * <p> 2732 * Between {@link Build.VERSION_CODES#JELLY_BEAN API 16} and 2733 * {@link Build.VERSION_CODES#Q API 29}, this method may incorrectly return false when 2734 * magnification is enabled. On other versions, a node is considered visible even if it is not 2735 * on the screen because magnification is active. 2736 * </p> 2737 * 2738 * @return Whether the node is visible to the user. 2739 */ isVisibleToUser()2740 public boolean isVisibleToUser() { 2741 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER); 2742 } 2743 2744 /** 2745 * Sets whether this node is visible to the user. 2746 * <p> 2747 * <strong>Note:</strong> Cannot be called from an 2748 * {@link android.accessibilityservice.AccessibilityService}. 2749 * This class is made immutable before being delivered to an AccessibilityService. 2750 * </p> 2751 * 2752 * @param visibleToUser Whether the node is visible to the user. 2753 * 2754 * @throws IllegalStateException If called from an AccessibilityService. 2755 */ setVisibleToUser(boolean visibleToUser)2756 public void setVisibleToUser(boolean visibleToUser) { 2757 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser); 2758 } 2759 2760 /** 2761 * Gets whether this node is accessibility focused. 2762 * 2763 * <p>This is distinct from {@link #isFocused()}, which is used to track system focus. 2764 * See {@link #ACTION_ACCESSIBILITY_FOCUS} for details. 2765 * @return True if the node is accessibility focused. 2766 */ isAccessibilityFocused()2767 public boolean isAccessibilityFocused() { 2768 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED); 2769 } 2770 2771 /** 2772 * Sets whether this node is accessibility focused. 2773 * <p> 2774 * <strong>Note:</strong> Cannot be called from an 2775 * {@link android.accessibilityservice.AccessibilityService}. 2776 * This class is made immutable before being delivered to an AccessibilityService. 2777 * </p> 2778 * <p>The UI element updating this property should send an event of 2779 * {@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED} 2780 * or {@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED} if its 2781 * accessibility-focused state changes. 2782 * @param focused True if the node is accessibility focused. 2783 * 2784 * @throws IllegalStateException If called from an AccessibilityService. 2785 */ setAccessibilityFocused(boolean focused)2786 public void setAccessibilityFocused(boolean focused) { 2787 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused); 2788 } 2789 2790 /** 2791 * Gets whether this node is selected. 2792 * 2793 * @return True if the node is selected. 2794 */ isSelected()2795 public boolean isSelected() { 2796 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED); 2797 } 2798 2799 /** 2800 * Sets whether this node is selected. 2801 * <p> 2802 * <strong>Note:</strong> Cannot be called from an 2803 * {@link android.accessibilityservice.AccessibilityService}. 2804 * This class is made immutable before being delivered to an AccessibilityService. 2805 * </p> 2806 * 2807 * @param selected True if the node is selected. 2808 * 2809 * @throws IllegalStateException If called from an AccessibilityService. 2810 */ setSelected(boolean selected)2811 public void setSelected(boolean selected) { 2812 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected); 2813 } 2814 2815 /** 2816 * Gets whether this node is clickable. 2817 * 2818 * @return True if the node is clickable. 2819 */ isClickable()2820 public boolean isClickable() { 2821 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE); 2822 } 2823 2824 /** 2825 * Sets whether this node is clickable. 2826 * <p> 2827 * <strong>Note:</strong> Cannot be called from an 2828 * {@link android.accessibilityservice.AccessibilityService}. 2829 * This class is made immutable before being delivered to an AccessibilityService. 2830 * </p> 2831 * 2832 * @param clickable True if the node is clickable. 2833 * 2834 * @throws IllegalStateException If called from an AccessibilityService. 2835 */ setClickable(boolean clickable)2836 public void setClickable(boolean clickable) { 2837 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable); 2838 } 2839 2840 /** 2841 * Gets whether this node is long clickable. 2842 * 2843 * @return True if the node is long clickable. 2844 */ isLongClickable()2845 public boolean isLongClickable() { 2846 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE); 2847 } 2848 2849 /** 2850 * Sets whether this node is long clickable. 2851 * <p> 2852 * <strong>Note:</strong> Cannot be called from an 2853 * {@link android.accessibilityservice.AccessibilityService}. 2854 * This class is made immutable before being delivered to an AccessibilityService. 2855 * </p> 2856 * 2857 * @param longClickable True if the node is long clickable. 2858 * 2859 * @throws IllegalStateException If called from an AccessibilityService. 2860 */ setLongClickable(boolean longClickable)2861 public void setLongClickable(boolean longClickable) { 2862 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable); 2863 } 2864 2865 /** 2866 * Gets whether this node is enabled. 2867 * 2868 * @return True if the node is enabled. 2869 */ isEnabled()2870 public boolean isEnabled() { 2871 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED); 2872 } 2873 2874 /** 2875 * Sets whether this node is enabled. 2876 * <p> 2877 * <strong>Note:</strong> Cannot be called from an 2878 * {@link android.accessibilityservice.AccessibilityService}. 2879 * This class is made immutable before being delivered to an AccessibilityService. 2880 * </p> 2881 * 2882 * @param enabled True if the node is enabled. 2883 * 2884 * @throws IllegalStateException If called from an AccessibilityService. 2885 */ setEnabled(boolean enabled)2886 public void setEnabled(boolean enabled) { 2887 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled); 2888 } 2889 2890 /** 2891 * Gets whether this node is a password. 2892 * 2893 * @return True if the node is a password. 2894 */ isPassword()2895 public boolean isPassword() { 2896 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD); 2897 } 2898 2899 /** 2900 * Sets whether this node is a password. 2901 * <p> 2902 * <strong>Note:</strong> Cannot be called from an 2903 * {@link android.accessibilityservice.AccessibilityService}. 2904 * This class is made immutable before being delivered to an AccessibilityService. 2905 * </p> 2906 * 2907 * @param password True if the node is a password. 2908 * 2909 * @throws IllegalStateException If called from an AccessibilityService. 2910 */ setPassword(boolean password)2911 public void setPassword(boolean password) { 2912 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password); 2913 } 2914 2915 /** 2916 * Gets if the node is scrollable. 2917 * 2918 * @return True if the node is scrollable, false otherwise. 2919 */ isScrollable()2920 public boolean isScrollable() { 2921 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE); 2922 } 2923 2924 /** 2925 * Sets if the node is scrollable. 2926 * <p> 2927 * <strong>Note:</strong> Cannot be called from an 2928 * {@link android.accessibilityservice.AccessibilityService}. 2929 * This class is made immutable before being delivered to an AccessibilityService. 2930 * </p> 2931 * 2932 * @param scrollable True if the node is scrollable, false otherwise. 2933 * 2934 * @throws IllegalStateException If called from an AccessibilityService. 2935 */ setScrollable(boolean scrollable)2936 public void setScrollable(boolean scrollable) { 2937 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable); 2938 } 2939 2940 /** 2941 * Gets if the node supports granular scrolling. 2942 * 2943 * @return True if all scroll actions that could support 2944 * {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT} have done so, false otherwise. 2945 */ 2946 @FlaggedApi(Flags.FLAG_GRANULAR_SCROLLING) isGranularScrollingSupported()2947 public boolean isGranularScrollingSupported() { 2948 return getBooleanProperty(BOOLEAN_PROPERTY_SUPPORTS_GRANULAR_SCROLLING); 2949 } 2950 2951 /** 2952 * Sets if the node supports granular scrolling. This should be set to true if all scroll 2953 * actions which could support {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT} have done so. 2954 * <p> 2955 * <strong>Note:</strong> Cannot be called from an 2956 * {@link android.accessibilityservice.AccessibilityService}. 2957 * This class is made immutable before being delivered to an AccessibilityService. 2958 * </p> 2959 * 2960 * @param granularScrollingSupported True if the node supports granular scrolling, false 2961 * otherwise. 2962 * 2963 * @throws IllegalStateException If called from an AccessibilityService. 2964 */ 2965 @FlaggedApi(Flags.FLAG_GRANULAR_SCROLLING) setGranularScrollingSupported(boolean granularScrollingSupported)2966 public void setGranularScrollingSupported(boolean granularScrollingSupported) { 2967 setBooleanProperty(BOOLEAN_PROPERTY_SUPPORTS_GRANULAR_SCROLLING, 2968 granularScrollingSupported); 2969 } 2970 2971 /** 2972 * Gets if the node has selectable text. 2973 * 2974 * <p> 2975 * Services should use {@link #ACTION_SET_SELECTION} for selection. Editable text nodes must 2976 * also be selectable. But not all UIs will populate this field, so services should consider 2977 * 'isTextSelectable | isEditable' to ensure they don't miss nodes with selectable text. 2978 * </p> 2979 * 2980 * @see #isEditable 2981 * @return True if the node has selectable text. 2982 */ isTextSelectable()2983 public boolean isTextSelectable() { 2984 return getBooleanProperty(BOOLEAN_PROPERTY_IS_TEXT_SELECTABLE); 2985 } 2986 2987 /** 2988 * Sets if the node has selectable text. 2989 * <p> 2990 * <strong>Note:</strong> Cannot be called from an 2991 * {@link android.accessibilityservice.AccessibilityService}. 2992 * This class is made immutable before being delivered to an AccessibilityService. 2993 * </p> 2994 * 2995 * @param selectableText True if the node has selectable text, false otherwise. 2996 * 2997 * @throws IllegalStateException If called from an AccessibilityService. 2998 */ setTextSelectable(boolean selectableText)2999 public void setTextSelectable(boolean selectableText) { 3000 setBooleanProperty(BOOLEAN_PROPERTY_IS_TEXT_SELECTABLE, selectableText); 3001 } 3002 3003 /** 3004 * Gets whether the node has {@link #setRequestInitialAccessibilityFocus}. 3005 * 3006 * @return True if the node has requested initial accessibility focus. 3007 */ hasRequestInitialAccessibilityFocus()3008 public boolean hasRequestInitialAccessibilityFocus() { 3009 return getBooleanProperty(BOOLEAN_PROPERTY_REQUEST_INITIAL_ACCESSIBILITY_FOCUS); 3010 } 3011 3012 /** 3013 * Sets whether the node has requested initial accessibility focus. 3014 * 3015 * <p> 3016 * If the node {@link #hasRequestInitialAccessibilityFocus}, this node would be one of 3017 * candidates to be accessibility focused when the window appears. 3018 * </p> 3019 * 3020 * <p> 3021 * <strong>Note:</strong> Cannot be called from an 3022 * {@link android.accessibilityservice.AccessibilityService}. 3023 * This class is made immutable before being delivered to an AccessibilityService. 3024 * </p> 3025 * 3026 * @param requestInitialAccessibilityFocus True if the node requests to receive initial 3027 * accessibility focus. 3028 * @throws IllegalStateException If called from an AccessibilityService. 3029 */ setRequestInitialAccessibilityFocus(boolean requestInitialAccessibilityFocus)3030 public void setRequestInitialAccessibilityFocus(boolean requestInitialAccessibilityFocus) { 3031 setBooleanProperty(BOOLEAN_PROPERTY_REQUEST_INITIAL_ACCESSIBILITY_FOCUS, 3032 requestInitialAccessibilityFocus); 3033 } 3034 3035 /** 3036 * Gets if the node is editable. 3037 * 3038 * @return True if the node is editable, false otherwise. 3039 */ isEditable()3040 public boolean isEditable() { 3041 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE); 3042 } 3043 3044 /** 3045 * Sets whether this node is editable. 3046 * <p> 3047 * <strong>Note:</strong> Cannot be called from an 3048 * {@link android.accessibilityservice.AccessibilityService}. 3049 * This class is made immutable before being delivered to an AccessibilityService. 3050 * </p> 3051 * 3052 * @param editable True if the node is editable. 3053 * 3054 * @throws IllegalStateException If called from an AccessibilityService. 3055 */ setEditable(boolean editable)3056 public void setEditable(boolean editable) { 3057 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable); 3058 } 3059 3060 /** 3061 * Gets if the node's accessibility data is considered sensitive. 3062 * 3063 * @return True if the node's data is considered sensitive, false otherwise. 3064 * @see View#isAccessibilityDataSensitive() 3065 */ isAccessibilityDataSensitive()3066 public boolean isAccessibilityDataSensitive() { 3067 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE); 3068 } 3069 3070 /** 3071 * Sets whether this node's accessibility data is considered sensitive. 3072 * 3073 * <p> 3074 * <strong>Note:</strong> Cannot be called from an {@link AccessibilityService}. 3075 * This class is made immutable before being delivered to an AccessibilityService. 3076 * </p> 3077 * 3078 * @param accessibilityDataSensitive True if the node's accessibility data is considered 3079 * sensitive. 3080 * @throws IllegalStateException If called from an AccessibilityService. 3081 * @see View#setAccessibilityDataSensitive 3082 */ setAccessibilityDataSensitive(boolean accessibilityDataSensitive)3083 public void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) { 3084 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE, 3085 accessibilityDataSensitive); 3086 } 3087 3088 /** 3089 * If this node represents a visually distinct region of the screen that may update separately 3090 * from the rest of the window, it is considered a pane. Set the pane title to indicate that 3091 * the node is a pane, and to provide a title for it. 3092 * <p> 3093 * <strong>Note:</strong> Cannot be called from an 3094 * {@link android.accessibilityservice.AccessibilityService}. 3095 * This class is made immutable before being delivered to an AccessibilityService. 3096 * </p> 3097 * @param paneTitle The title of the pane represented by this node. 3098 */ setPaneTitle(@ullable CharSequence paneTitle)3099 public void setPaneTitle(@Nullable CharSequence paneTitle) { 3100 enforceNotSealed(); 3101 mPaneTitle = (paneTitle == null) 3102 ? null : paneTitle.subSequence(0, paneTitle.length()); 3103 } 3104 3105 /** 3106 * Get the title of the pane represented by this node. 3107 * 3108 * @return The title of the pane represented by this node, or {@code null} if this node does 3109 * not represent a pane. 3110 */ getPaneTitle()3111 public @Nullable CharSequence getPaneTitle() { 3112 return mPaneTitle; 3113 } 3114 3115 /** 3116 * Get the drawing order of the view corresponding it this node. 3117 * <p> 3118 * Drawing order is determined only within the node's parent, so this index is only relative 3119 * to its siblings. 3120 * <p> 3121 * In some cases, the drawing order is essentially simultaneous, so it is possible for two 3122 * siblings to return the same value. It is also possible that values will be skipped. 3123 * 3124 * @return The drawing position of the view corresponding to this node relative to its siblings. 3125 */ getDrawingOrder()3126 public int getDrawingOrder() { 3127 return mDrawingOrderInParent; 3128 } 3129 3130 /** 3131 * Set the drawing order of the view corresponding it this node. 3132 * 3133 * <p> 3134 * <strong>Note:</strong> Cannot be called from an 3135 * {@link android.accessibilityservice.AccessibilityService}. 3136 * This class is made immutable before being delivered to an AccessibilityService. 3137 * </p> 3138 * @param drawingOrderInParent 3139 * @throws IllegalStateException If called from an AccessibilityService. 3140 */ setDrawingOrder(int drawingOrderInParent)3141 public void setDrawingOrder(int drawingOrderInParent) { 3142 enforceNotSealed(); 3143 mDrawingOrderInParent = drawingOrderInParent; 3144 } 3145 3146 /** 3147 * Gets the collection info if the node is a collection. A collection 3148 * child is always a collection item. 3149 * 3150 * @return The collection info. 3151 */ getCollectionInfo()3152 public CollectionInfo getCollectionInfo() { 3153 return mCollectionInfo; 3154 } 3155 3156 /** 3157 * Sets the collection info if the node is a collection. A collection 3158 * child is always a collection item. 3159 * <p> 3160 * <strong>Note:</strong> Cannot be called from an 3161 * {@link android.accessibilityservice.AccessibilityService}. 3162 * This class is made immutable before being delivered to an AccessibilityService. 3163 * </p> 3164 * 3165 * @param collectionInfo The collection info. 3166 */ setCollectionInfo(CollectionInfo collectionInfo)3167 public void setCollectionInfo(CollectionInfo collectionInfo) { 3168 enforceNotSealed(); 3169 mCollectionInfo = collectionInfo; 3170 } 3171 3172 /** 3173 * Gets the collection item info if the node is a collection item. A collection 3174 * item is always a child of a collection. 3175 * 3176 * @return The collection item info. 3177 */ getCollectionItemInfo()3178 public CollectionItemInfo getCollectionItemInfo() { 3179 return mCollectionItemInfo; 3180 } 3181 3182 /** 3183 * Sets the collection item info if the node is a collection item. A collection 3184 * item is always a child of a collection. 3185 * <p> 3186 * <strong>Note:</strong> Cannot be called from an 3187 * {@link android.accessibilityservice.AccessibilityService}. 3188 * This class is made immutable before being delivered to an AccessibilityService. 3189 * </p> 3190 */ setCollectionItemInfo(CollectionItemInfo collectionItemInfo)3191 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) { 3192 enforceNotSealed(); 3193 mCollectionItemInfo = collectionItemInfo; 3194 } 3195 3196 /** 3197 * Gets the range info if this node is a range. 3198 * 3199 * @return The range. 3200 */ getRangeInfo()3201 public RangeInfo getRangeInfo() { 3202 return mRangeInfo; 3203 } 3204 3205 /** 3206 * Sets the range info if this node is a range. 3207 * <p> 3208 * <strong>Note:</strong> Cannot be called from an 3209 * {@link android.accessibilityservice.AccessibilityService}. 3210 * This class is made immutable before being delivered to an AccessibilityService. 3211 * </p> 3212 * 3213 * @param rangeInfo The range info. 3214 */ setRangeInfo(RangeInfo rangeInfo)3215 public void setRangeInfo(RangeInfo rangeInfo) { 3216 enforceNotSealed(); 3217 mRangeInfo = rangeInfo; 3218 } 3219 3220 /** 3221 * Gets the {@link ExtraRenderingInfo extra rendering info} if the node is meant to be 3222 * refreshed with extra data to examine rendering related accessibility issues. 3223 * 3224 * @return The {@link ExtraRenderingInfo extra rendering info}. 3225 * 3226 * @see #EXTRA_DATA_RENDERING_INFO_KEY 3227 * @see #refreshWithExtraData(String, Bundle) 3228 */ 3229 @Nullable getExtraRenderingInfo()3230 public ExtraRenderingInfo getExtraRenderingInfo() { 3231 return mExtraRenderingInfo; 3232 } 3233 3234 /** 3235 * Sets the extra rendering info, <code>extraRenderingInfo<code/>, if the node is meant to be 3236 * refreshed with extra data. 3237 * <p> 3238 * <strong>Note:</strong> Cannot be called from an 3239 * {@link android.accessibilityservice.AccessibilityService}. 3240 * This class is made immutable before being delivered to an AccessibilityService. 3241 * </p> 3242 * 3243 * @param extraRenderingInfo The {@link ExtraRenderingInfo extra rendering info}. 3244 * @hide 3245 */ setExtraRenderingInfo(@onNull ExtraRenderingInfo extraRenderingInfo)3246 public void setExtraRenderingInfo(@NonNull ExtraRenderingInfo extraRenderingInfo) { 3247 enforceNotSealed(); 3248 mExtraRenderingInfo = extraRenderingInfo; 3249 } 3250 3251 /** 3252 * Gets if the content of this node is invalid. For example, 3253 * a date is not well-formed. 3254 * 3255 * @return If the node content is invalid. 3256 */ isContentInvalid()3257 public boolean isContentInvalid() { 3258 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID); 3259 } 3260 3261 /** 3262 * Sets if the content of this node is invalid. For example, 3263 * a date is not well-formed. 3264 * <p> 3265 * <strong>Note:</strong> Cannot be called from an 3266 * {@link android.accessibilityservice.AccessibilityService}. 3267 * This class is made immutable before being delivered to an AccessibilityService. 3268 * </p> 3269 * 3270 * @param contentInvalid If the node content is invalid. 3271 */ setContentInvalid(boolean contentInvalid)3272 public void setContentInvalid(boolean contentInvalid) { 3273 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid); 3274 } 3275 3276 /** 3277 * Gets whether this node is context clickable. 3278 * 3279 * @return True if the node is context clickable. 3280 */ isContextClickable()3281 public boolean isContextClickable() { 3282 return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE); 3283 } 3284 3285 /** 3286 * Sets whether this node is context clickable. 3287 * <p> 3288 * <strong>Note:</strong> Cannot be called from an 3289 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable 3290 * before being delivered to an AccessibilityService. 3291 * </p> 3292 * 3293 * @param contextClickable True if the node is context clickable. 3294 * @throws IllegalStateException If called from an AccessibilityService. 3295 */ setContextClickable(boolean contextClickable)3296 public void setContextClickable(boolean contextClickable) { 3297 setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable); 3298 } 3299 3300 /** 3301 * Gets the node's live region mode. 3302 * <p> 3303 * A live region is a node that contains information that is important for 3304 * the user and when it changes the user should be notified. For example, 3305 * a Snackbar that displays a confirmation notification should be marked 3306 * as a live region with mode 3307 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}. 3308 * <p> 3309 * It is the responsibility of the accessibility service to monitor 3310 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating 3311 * changes to live region nodes and their children. 3312 * 3313 * @return The live region mode, or 3314 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a 3315 * live region. 3316 * @see android.view.View#getAccessibilityLiveRegion() 3317 */ getLiveRegion()3318 public int getLiveRegion() { 3319 return mLiveRegion; 3320 } 3321 3322 /** 3323 * Sets the node's live region mode. 3324 * <p> 3325 * <strong>Note:</strong> Cannot be called from an 3326 * {@link android.accessibilityservice.AccessibilityService}. This class is 3327 * made immutable before being delivered to an AccessibilityService. 3328 * 3329 * @param mode The live region mode, or 3330 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a 3331 * live region. 3332 * @see android.view.View#setAccessibilityLiveRegion(int) 3333 */ setLiveRegion(int mode)3334 public void setLiveRegion(int mode) { 3335 enforceNotSealed(); 3336 mLiveRegion = mode; 3337 } 3338 3339 /** 3340 * Gets if the node is a multi line editable text. 3341 * 3342 * @return True if the node is multi line. 3343 */ isMultiLine()3344 public boolean isMultiLine() { 3345 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE); 3346 } 3347 3348 /** 3349 * Sets if the node is a multi line editable text. 3350 * <p> 3351 * <strong>Note:</strong> Cannot be called from an 3352 * {@link android.accessibilityservice.AccessibilityService}. 3353 * This class is made immutable before being delivered to an AccessibilityService. 3354 * </p> 3355 * 3356 * @param multiLine True if the node is multi line. 3357 */ setMultiLine(boolean multiLine)3358 public void setMultiLine(boolean multiLine) { 3359 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine); 3360 } 3361 3362 /** 3363 * Gets if this node opens a popup or a dialog. 3364 * 3365 * @return If the the node opens a popup. 3366 */ canOpenPopup()3367 public boolean canOpenPopup() { 3368 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP); 3369 } 3370 3371 /** 3372 * Sets if this node opens a popup or a dialog. 3373 * <p> 3374 * <strong>Note:</strong> Cannot be called from an 3375 * {@link android.accessibilityservice.AccessibilityService}. 3376 * This class is made immutable before being delivered to an AccessibilityService. 3377 * </p> 3378 * 3379 * @param opensPopup If the the node opens a popup. 3380 */ setCanOpenPopup(boolean opensPopup)3381 public void setCanOpenPopup(boolean opensPopup) { 3382 enforceNotSealed(); 3383 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup); 3384 } 3385 3386 /** 3387 * Gets if the node can be dismissed. 3388 * 3389 * @return If the node can be dismissed. 3390 */ isDismissable()3391 public boolean isDismissable() { 3392 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE); 3393 } 3394 3395 /** 3396 * Sets if the node can be dismissed. 3397 * <p> 3398 * <strong>Note:</strong> Cannot be called from an 3399 * {@link android.accessibilityservice.AccessibilityService}. 3400 * This class is made immutable before being delivered to an AccessibilityService. 3401 * </p> 3402 * 3403 * @param dismissable If the node can be dismissed. 3404 */ setDismissable(boolean dismissable)3405 public void setDismissable(boolean dismissable) { 3406 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable); 3407 } 3408 3409 /** 3410 * Returns whether the node originates from a view considered important for accessibility. 3411 * 3412 * @return {@code true} if the node originates from a view considered important for 3413 * accessibility, {@code false} otherwise 3414 * 3415 * @see View#isImportantForAccessibility() 3416 */ isImportantForAccessibility()3417 public boolean isImportantForAccessibility() { 3418 return getBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE); 3419 } 3420 3421 /** 3422 * Sets whether the node is considered important for accessibility. 3423 * <p> 3424 * <strong>Note:</strong> Cannot be called from an 3425 * {@link android.accessibilityservice.AccessibilityService}. 3426 * This class is made immutable before being delivered to an AccessibilityService. 3427 * </p> 3428 * 3429 * @param important {@code true} if the node is considered important for accessibility, 3430 * {@code false} otherwise 3431 */ setImportantForAccessibility(boolean important)3432 public void setImportantForAccessibility(boolean important) { 3433 setBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE, important); 3434 } 3435 3436 /** 3437 * Returns whether the node is explicitly marked as a focusable unit by a screen reader. Note 3438 * that {@code false} indicates that it is not explicitly marked, not that the node is not 3439 * a focusable unit. Screen readers should generally use other signals, such as 3440 * {@link #isFocusable()}, or the presence of text in a node, to determine what should receive 3441 * focus. 3442 * 3443 * @return {@code true} if the node is specifically marked as a focusable unit for screen 3444 * readers, {@code false} otherwise. 3445 * 3446 * @see View#isScreenReaderFocusable() 3447 */ isScreenReaderFocusable()3448 public boolean isScreenReaderFocusable() { 3449 return getBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE); 3450 } 3451 3452 /** 3453 * Sets whether the node should be considered a focusable unit by a screen reader. 3454 * <p> 3455 * <strong>Note:</strong> Cannot be called from an 3456 * {@link android.accessibilityservice.AccessibilityService}. 3457 * This class is made immutable before being delivered to an AccessibilityService. 3458 * </p> 3459 * <p>This can be used to 3460 * <a href="{@docRoot}guide/topics/ui/accessibility/principles#content-groups">group related 3461 * content.</a> 3462 * </p> 3463 * 3464 * @param screenReaderFocusable {@code true} if the node is a focusable unit for screen readers, 3465 * {@code false} otherwise. 3466 */ setScreenReaderFocusable(boolean screenReaderFocusable)3467 public void setScreenReaderFocusable(boolean screenReaderFocusable) { 3468 setBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE, screenReaderFocusable); 3469 } 3470 3471 /** 3472 * Returns whether the node's text represents a hint for the user to enter text. It should only 3473 * be {@code true} if the node has editable text. 3474 * 3475 * @return {@code true} if the text in the node represents a hint to the user, {@code false} 3476 * otherwise. 3477 */ isShowingHintText()3478 public boolean isShowingHintText() { 3479 return getBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT); 3480 } 3481 3482 /** 3483 * Sets whether the node's text represents a hint for the user to enter text. It should only 3484 * be {@code true} if the node has editable text. 3485 * <p> 3486 * <strong>Note:</strong> Cannot be called from an 3487 * {@link android.accessibilityservice.AccessibilityService}. 3488 * This class is made immutable before being delivered to an AccessibilityService. 3489 * </p> 3490 * 3491 * @param showingHintText {@code true} if the text in the node represents a hint to the user, 3492 * {@code false} otherwise. 3493 */ setShowingHintText(boolean showingHintText)3494 public void setShowingHintText(boolean showingHintText) { 3495 setBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT, showingHintText); 3496 } 3497 3498 /** 3499 * Returns whether node represents a heading. 3500 * <p><strong>Note:</strong> Returns {@code true} if either {@link #setHeading(boolean)} 3501 * marks this node as a heading or if the node has a {@link CollectionItemInfo} that marks 3502 * it as such, to accomodate apps that use the now-deprecated API.</p> 3503 * 3504 * @return {@code true} if the node is a heading, {@code false} otherwise. 3505 */ isHeading()3506 public boolean isHeading() { 3507 if (getBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING)) return true; 3508 CollectionItemInfo itemInfo = getCollectionItemInfo(); 3509 return ((itemInfo != null) && itemInfo.mHeading); 3510 } 3511 3512 /** 3513 * Sets whether the node represents a heading. 3514 * 3515 * <p> 3516 * <strong>Note:</strong> Cannot be called from an 3517 * {@link android.accessibilityservice.AccessibilityService}. 3518 * This class is made immutable before being delivered to an AccessibilityService. 3519 * </p> 3520 * 3521 * @param isHeading {@code true} if the node is a heading, {@code false} otherwise. 3522 */ setHeading(boolean isHeading)3523 public void setHeading(boolean isHeading) { 3524 setBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING, isHeading); 3525 } 3526 3527 /** 3528 * Returns whether node represents a text entry key that is part of a keyboard or keypad. 3529 * 3530 * @return {@code true} if the node is a text entry key., {@code false} otherwise. 3531 */ isTextEntryKey()3532 public boolean isTextEntryKey() { 3533 return getBooleanProperty(BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY); 3534 } 3535 3536 /** 3537 * Sets whether the node represents a text entry key that is part of a keyboard or keypad. 3538 * 3539 * <p> 3540 * <strong>Note:</strong> Cannot be called from an 3541 * {@link android.accessibilityservice.AccessibilityService}. 3542 * This class is made immutable before being delivered to an AccessibilityService. 3543 * </p> 3544 * 3545 * @param isTextEntryKey {@code true} if the node is a text entry key, {@code false} otherwise. 3546 */ setTextEntryKey(boolean isTextEntryKey)3547 public void setTextEntryKey(boolean isTextEntryKey) { 3548 setBooleanProperty(BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY, isTextEntryKey); 3549 } 3550 3551 /** 3552 * Gets the package this node comes from. 3553 * 3554 * @return The package name. 3555 */ getPackageName()3556 public CharSequence getPackageName() { 3557 return mPackageName; 3558 } 3559 3560 /** 3561 * Sets the package this node comes from. 3562 * <p> 3563 * <strong>Note:</strong> Cannot be called from an 3564 * {@link android.accessibilityservice.AccessibilityService}. 3565 * This class is made immutable before being delivered to an AccessibilityService. 3566 * </p> 3567 * 3568 * @param packageName The package name. 3569 * 3570 * @throws IllegalStateException If called from an AccessibilityService. 3571 */ setPackageName(CharSequence packageName)3572 public void setPackageName(CharSequence packageName) { 3573 enforceNotSealed(); 3574 mPackageName = packageName; 3575 } 3576 3577 /** 3578 * Gets the class this node comes from. 3579 * 3580 * @return The class name. 3581 */ getClassName()3582 public CharSequence getClassName() { 3583 return mClassName; 3584 } 3585 3586 /** 3587 * Sets the class this node comes from. 3588 * <p> 3589 * <strong>Note:</strong> Cannot be called from an 3590 * {@link android.accessibilityservice.AccessibilityService}. 3591 * This class is made immutable before being delivered to an AccessibilityService. 3592 * </p> 3593 * 3594 * @param className The class name. 3595 * 3596 * @throws IllegalStateException If called from an AccessibilityService. 3597 */ setClassName(CharSequence className)3598 public void setClassName(CharSequence className) { 3599 enforceNotSealed(); 3600 mClassName = className; 3601 } 3602 3603 /** 3604 * Gets the text of this node. 3605 * <p> 3606 * <strong>Note:</strong> If the text contains {@link ClickableSpan}s or {@link URLSpan}s, 3607 * these spans will have been replaced with ones whose {@link ClickableSpan#onClick(View)} 3608 * can be called from an {@link AccessibilityService}. When called from a service, the 3609 * {@link View} argument is ignored and the corresponding span will be found on the view that 3610 * this {@code AccessibilityNodeInfo} represents and called with that view as its argument. 3611 * <p> 3612 * This treatment of {@link ClickableSpan}s means that the text returned from this method may 3613 * different slightly one passed to {@link #setText(CharSequence)}, although they will be 3614 * equivalent according to {@link TextUtils#equals(CharSequence, CharSequence)}. The 3615 * {@link ClickableSpan#onClick(View)} of any spans, however, will generally not work outside 3616 * of an accessibility service. 3617 * </p> 3618 * 3619 * @return The text. 3620 */ getText()3621 public CharSequence getText() { 3622 // Attach this node to any spans that need it 3623 if (mText instanceof Spanned) { 3624 Spanned spanned = (Spanned) mText; 3625 AccessibilityClickableSpan[] clickableSpans = 3626 spanned.getSpans(0, mText.length(), AccessibilityClickableSpan.class); 3627 for (int i = 0; i < clickableSpans.length; i++) { 3628 clickableSpans[i].copyConnectionDataFrom(this); 3629 } 3630 AccessibilityURLSpan[] urlSpans = 3631 spanned.getSpans(0, mText.length(), AccessibilityURLSpan.class); 3632 for (int i = 0; i < urlSpans.length; i++) { 3633 urlSpans[i].copyConnectionDataFrom(this); 3634 } 3635 } 3636 return mText; 3637 } 3638 3639 /** 3640 * Get the text passed to setText before any changes to the spans. 3641 * @hide 3642 */ getOriginalText()3643 public CharSequence getOriginalText() { 3644 return mOriginalText; 3645 } 3646 3647 /** 3648 * Sets the text of this node. 3649 * <p> 3650 * <strong>Note:</strong> Cannot be called from an 3651 * {@link android.accessibilityservice.AccessibilityService}. 3652 * This class is made immutable before being delivered to an AccessibilityService. 3653 * </p> 3654 * 3655 * @param text The text. 3656 * 3657 * @throws IllegalStateException If called from an AccessibilityService. 3658 */ setText(CharSequence text)3659 public void setText(CharSequence text) { 3660 enforceNotSealed(); 3661 mOriginalText = text; 3662 if (text instanceof Spanned) { 3663 CharSequence tmpText = text; 3664 tmpText = replaceClickableSpan(tmpText); 3665 tmpText = replaceReplacementSpan(tmpText); 3666 mText = tmpText; 3667 return; 3668 } 3669 mText = (text == null) ? null : text.subSequence(0, text.length()); 3670 } 3671 3672 /** 3673 * Replaces any ClickableSpan in the given {@code text} with placeholders. 3674 * 3675 * @param text The text. 3676 * 3677 * @return The spannable with ClickableSpan replacement. 3678 */ replaceClickableSpan(CharSequence text)3679 private CharSequence replaceClickableSpan(CharSequence text) { 3680 ClickableSpan[] clickableSpans = 3681 ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class); 3682 Spannable spannable = new SpannableStringBuilder(text); 3683 if (clickableSpans.length == 0) { 3684 return text; 3685 } 3686 for (int i = 0; i < clickableSpans.length; i++) { 3687 ClickableSpan span = clickableSpans[i]; 3688 if ((span instanceof AccessibilityClickableSpan) 3689 || (span instanceof AccessibilityURLSpan)) { 3690 // We've already done enough 3691 break; 3692 } 3693 int spanToReplaceStart = spannable.getSpanStart(span); 3694 int spanToReplaceEnd = spannable.getSpanEnd(span); 3695 int spanToReplaceFlags = spannable.getSpanFlags(span); 3696 if (spanToReplaceStart < 0) { 3697 continue; 3698 } 3699 spannable.removeSpan(span); 3700 ClickableSpan replacementSpan = (span instanceof URLSpan) 3701 ? new AccessibilityURLSpan((URLSpan) span) 3702 : new AccessibilityClickableSpan(span.getId()); 3703 spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd, 3704 spanToReplaceFlags); 3705 } 3706 return spannable; 3707 } 3708 3709 /** 3710 * Replaces any ReplacementSpan in the given {@code text} if the object has content description. 3711 * 3712 * @param text The text. 3713 * 3714 * @return The spannable with ReplacementSpan replacement. 3715 */ replaceReplacementSpan(CharSequence text)3716 private CharSequence replaceReplacementSpan(CharSequence text) { 3717 ReplacementSpan[] replacementSpans = 3718 ((Spanned) text).getSpans(0, text.length(), ReplacementSpan.class); 3719 SpannableStringBuilder spannable = new SpannableStringBuilder(text); 3720 if (replacementSpans.length == 0) { 3721 return text; 3722 } 3723 for (int i = 0; i < replacementSpans.length; i++) { 3724 ReplacementSpan span = replacementSpans[i]; 3725 CharSequence replacementText = span.getContentDescription(); 3726 if (span instanceof AccessibilityReplacementSpan) { 3727 // We've already done enough 3728 break; 3729 } 3730 if (replacementText == null) { 3731 continue; 3732 } 3733 int spanToReplaceStart = spannable.getSpanStart(span); 3734 int spanToReplaceEnd = spannable.getSpanEnd(span); 3735 int spanToReplaceFlags = spannable.getSpanFlags(span); 3736 if (spanToReplaceStart < 0) { 3737 continue; 3738 } 3739 spannable.removeSpan(span); 3740 ReplacementSpan replacementSpan = new AccessibilityReplacementSpan(replacementText); 3741 spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd, 3742 spanToReplaceFlags); 3743 } 3744 return spannable; 3745 } 3746 3747 /** 3748 * Gets the hint text of this node. Only applies to nodes where text can be entered. 3749 * 3750 * @return The hint text. 3751 */ getHintText()3752 public CharSequence getHintText() { 3753 return mHintText; 3754 } 3755 3756 /** 3757 * Sets the hint text of this node. Only applies to nodes where text can be entered. 3758 * <p> 3759 * <strong>Note:</strong> Cannot be called from an 3760 * {@link android.accessibilityservice.AccessibilityService}. 3761 * This class is made immutable before being delivered to an AccessibilityService. 3762 * </p> 3763 * 3764 * @param hintText The hint text for this mode. 3765 * 3766 * @throws IllegalStateException If called from an AccessibilityService. 3767 */ setHintText(CharSequence hintText)3768 public void setHintText(CharSequence hintText) { 3769 enforceNotSealed(); 3770 mHintText = (hintText == null) ? null : hintText.subSequence(0, hintText.length()); 3771 } 3772 3773 /** 3774 * Sets the error text of this node. 3775 * <p> 3776 * <strong>Note:</strong> Cannot be called from an 3777 * {@link android.accessibilityservice.AccessibilityService}. 3778 * This class is made immutable before being delivered to an AccessibilityService. 3779 * </p> 3780 * 3781 * @param error The error text. 3782 * 3783 * @throws IllegalStateException If called from an AccessibilityService. 3784 */ setError(CharSequence error)3785 public void setError(CharSequence error) { 3786 enforceNotSealed(); 3787 mError = (error == null) ? null : error.subSequence(0, error.length()); 3788 } 3789 3790 /** 3791 * Gets the error text of this node. 3792 * 3793 * @return The error text. 3794 */ getError()3795 public CharSequence getError() { 3796 return mError; 3797 } 3798 3799 /** 3800 * Get the state description of this node. 3801 * 3802 * @return the state description 3803 */ getStateDescription()3804 public @Nullable CharSequence getStateDescription() { 3805 return mStateDescription; 3806 } 3807 3808 /** 3809 * Gets the content description of this node. 3810 * 3811 * @return The content description. 3812 */ getContentDescription()3813 public CharSequence getContentDescription() { 3814 return mContentDescription; 3815 } 3816 3817 /** 3818 * Gets the supplemental description of this node. A supplemental description provides 3819 * brief supplemental information for this node, such as the purpose of the node when 3820 * that purpose is not conveyed within its textual representation. For example, if a 3821 * dropdown select has a purpose of setting font family, the supplemental description 3822 * could be "font family". If this node has children, its supplemental description serves 3823 * as additional information and is not intended to replace any existing information 3824 * in the subtree. This is different from the {@link #getContentDescription()} in that 3825 * this description is purely supplemental while a content description may be used 3826 * to replace a description for a node or its subtree that an assistive technology 3827 * would otherwise compute based on other properties of the node and its descendants. 3828 * 3829 * @return The supplemental description. 3830 * @see #setSupplementalDescription(CharSequence) 3831 * @see #getContentDescription() 3832 */ 3833 @FlaggedApi(Flags.FLAG_SUPPLEMENTAL_DESCRIPTION) 3834 @Nullable getSupplementalDescription()3835 public CharSequence getSupplementalDescription() { 3836 return mSupplementalDescription; 3837 } 3838 3839 /** 3840 * Sets the state description of this node. 3841 * <p> 3842 * <strong>Note:</strong> Cannot be called from an 3843 * {@link android.accessibilityservice.AccessibilityService}. 3844 * This class is made immutable before being delivered to an AccessibilityService. 3845 * </p> 3846 * 3847 * @param stateDescription the state description of this node. 3848 * 3849 * @throws IllegalStateException If called from an AccessibilityService. 3850 */ setStateDescription(@ullable CharSequence stateDescription)3851 public void setStateDescription(@Nullable CharSequence stateDescription) { 3852 enforceNotSealed(); 3853 mStateDescription = (stateDescription == null) ? null 3854 : stateDescription.subSequence(0, stateDescription.length()); 3855 } 3856 3857 /** 3858 * Sets the content description of this node. 3859 * <p> 3860 * <strong>Note:</strong> Cannot be called from an 3861 * {@link android.accessibilityservice.AccessibilityService}. 3862 * This class is made immutable before being delivered to an AccessibilityService. 3863 * </p> 3864 * 3865 * @param contentDescription The content description. 3866 * 3867 * @throws IllegalStateException If called from an AccessibilityService. 3868 */ setContentDescription(CharSequence contentDescription)3869 public void setContentDescription(CharSequence contentDescription) { 3870 enforceNotSealed(); 3871 mContentDescription = (contentDescription == null) ? null 3872 : contentDescription.subSequence(0, contentDescription.length()); 3873 } 3874 3875 /** 3876 * Sets the supplemental description of this node. A supplemental description provides 3877 * brief supplemental information for this node, such as the purpose of the node when 3878 * that purpose is not conveyed within its textual representation. For example, if a 3879 * dropdown select has a purpose of setting font family, the supplemental description 3880 * could be "font family". If this node has children, its supplemental description serves 3881 * as additional information and is not intended to replace any existing information 3882 * in the subtree. This is different from the {@link #setContentDescription(CharSequence)} 3883 * in that this description is purely supplemental while a content description may be used 3884 * to replace a description for a node or its subtree that an assistive technology 3885 * would otherwise compute based on other properties of the node and its descendants. 3886 * <p> 3887 * <strong>Note:</strong> Cannot be called from an 3888 * {@link android.accessibilityservice.AccessibilityService}. 3889 * This class is made immutable before being delivered to an AccessibilityService. 3890 * 3891 * @param supplementalDescription The supplemental description. 3892 * 3893 * @throws IllegalStateException If called from an AccessibilityService. 3894 * @see #getSupplementalDescription() 3895 * @see #setContentDescription(CharSequence) 3896 */ 3897 @FlaggedApi(Flags.FLAG_SUPPLEMENTAL_DESCRIPTION) setSupplementalDescription(@ullable CharSequence supplementalDescription)3898 public void setSupplementalDescription(@Nullable CharSequence supplementalDescription) { 3899 enforceNotSealed(); 3900 mSupplementalDescription = (supplementalDescription == null) ? null 3901 : supplementalDescription.subSequence(0, supplementalDescription.length()); 3902 } 3903 3904 /** 3905 * Gets the tooltip text of this node. 3906 * 3907 * @return The tooltip text. 3908 */ 3909 @Nullable getTooltipText()3910 public CharSequence getTooltipText() { 3911 return mTooltipText; 3912 } 3913 3914 /** 3915 * Sets the tooltip text of this node. 3916 * <p> 3917 * <strong>Note:</strong> Cannot be called from an 3918 * {@link android.accessibilityservice.AccessibilityService}. 3919 * This class is made immutable before being delivered to an AccessibilityService. 3920 * </p> 3921 * 3922 * @param tooltipText The tooltip text. 3923 * 3924 * @throws IllegalStateException If called from an AccessibilityService. 3925 */ setTooltipText(@ullable CharSequence tooltipText)3926 public void setTooltipText(@Nullable CharSequence tooltipText) { 3927 enforceNotSealed(); 3928 mTooltipText = (tooltipText == null) ? null 3929 : tooltipText.subSequence(0, tooltipText.length()); 3930 } 3931 3932 /** 3933 * Sets the view for which the view represented by this info serves as a 3934 * label for accessibility purposes. 3935 * 3936 * @deprecated Use {@link #addLabeledBy(View)} on the labeled node instead, 3937 * since {@link #getLabeledByList()} and {@link #getLabeledBy()} on the 3938 * labeled node are not automatically populated when this method is used. 3939 * 3940 * @param labeled The view for which this info serves as a label. 3941 */ 3942 @FlaggedApi(Flags.FLAG_DEPRECATE_ANI_LABEL_FOR_APIS) 3943 @Deprecated setLabelFor(View labeled)3944 public void setLabelFor(View labeled) { 3945 setLabelFor(labeled, AccessibilityNodeProvider.HOST_VIEW_ID); 3946 } 3947 3948 /** 3949 * Sets the view for which the view represented by this info serves as a 3950 * label for accessibility purposes. If <code>virtualDescendantId</code> 3951 * is {@link View#NO_ID} the root is set as the labeled. 3952 * <p> 3953 * A virtual descendant is an imaginary View that is reported as a part of the view 3954 * hierarchy for accessibility purposes. This enables custom views that draw complex 3955 * content to report themselves as a tree of virtual views, thus conveying their 3956 * logical structure. 3957 * </p> 3958 * <p> 3959 * <strong>Note:</strong> Cannot be called from an 3960 * {@link android.accessibilityservice.AccessibilityService}. 3961 * This class is made immutable before being delivered to an AccessibilityService. 3962 * </p> 3963 * 3964 * @deprecated Use {@link #addLabeledBy(View)} on the labeled node instead, 3965 * since {@link #getLabeledByList()} and {@link #getLabeledBy()} on the 3966 * labeled node are not automatically populated when this method is used. 3967 * 3968 * @param root The root whose virtual descendant serves as a label. 3969 * @param virtualDescendantId The id of the virtual descendant. 3970 */ 3971 @FlaggedApi(Flags.FLAG_DEPRECATE_ANI_LABEL_FOR_APIS) 3972 @Deprecated setLabelFor(View root, int virtualDescendantId)3973 public void setLabelFor(View root, int virtualDescendantId) { 3974 enforceNotSealed(); 3975 final int rootAccessibilityViewId = (root != null) 3976 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 3977 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 3978 } 3979 3980 /** 3981 * Gets the node info for which the view represented by this info serves as 3982 * a label for accessibility purposes. 3983 * 3984 * @deprecated Use {@link #getLabeledByList()} on the labeled node instead, 3985 * since calling {@link #addLabeledBy(View)} or {@link #addLabeledBy(View, int)} 3986 * on the labeled node do not automatically provide that node from this method. 3987 * 3988 * @return The labeled info. 3989 */ 3990 @FlaggedApi(Flags.FLAG_DEPRECATE_ANI_LABEL_FOR_APIS) 3991 @Deprecated getLabelFor()3992 public AccessibilityNodeInfo getLabelFor() { 3993 enforceSealed(); 3994 return getNodeForAccessibilityId(mConnectionId, mWindowId, mLabelForId); 3995 } 3996 3997 /** 3998 * Adds the view which serves as the label of the view represented by 3999 * this info for accessibility purposes. When multiple labels are 4000 * added, the content from each label is combined in the order that 4001 * they are added. 4002 * <p> 4003 * If visible text can be used to describe or give meaning to this UI, 4004 * this method is preferred. For example, a TextView before an EditText 4005 * in the UI usually specifies what information is contained in the 4006 * EditText. Hence, the EditText is labeled by the TextView. 4007 * </p> 4008 * 4009 * @param label A view that labels this node's source. 4010 */ 4011 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) addLabeledBy(@onNull View label)4012 public void addLabeledBy(@NonNull View label) { 4013 addLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID); 4014 } 4015 4016 /** 4017 * Adds the view which serves as the label of the view represented by 4018 * this info for accessibility purposes. If <code>virtualDescendantId</code> 4019 * is {@link View#NO_ID} the root is set as the label. When multiple 4020 * labels are added, the content from each label is combined in the order 4021 * that they are added. 4022 * <p> 4023 * A virtual descendant is an imaginary View that is reported as a part of the view 4024 * hierarchy for accessibility purposes. This enables custom views that draw complex 4025 * content to report themselves as a tree of virtual views, thus conveying their 4026 * logical structure. 4027 * </p> 4028 * <p> 4029 * If visible text can be used to describe or give meaning to this UI, 4030 * this method is preferred. For example, a TextView before an EditText 4031 * in the UI usually specifies what information is contained in the 4032 * EditText. Hence, the EditText is labeled by the TextView. 4033 * </p> 4034 * <p> 4035 * <strong>Note:</strong> Cannot be called from an 4036 * {@link android.accessibilityservice.AccessibilityService}. 4037 * This class is made immutable before being delivered to an AccessibilityService. 4038 * </p> 4039 * 4040 * @param root A root whose virtual descendant labels this node's source. 4041 * @param virtualDescendantId The id of the virtual descendant. 4042 */ 4043 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) addLabeledBy(@onNull View root, int virtualDescendantId)4044 public void addLabeledBy(@NonNull View root, int virtualDescendantId) { 4045 enforceNotSealed(); 4046 Preconditions.checkNotNull(root, "%s must not be null", root); 4047 if (mLabeledByIds == null) { 4048 mLabeledByIds = new LongArray(); 4049 } 4050 mLabeledById = makeNodeId(root.getAccessibilityViewId(), virtualDescendantId); 4051 mLabeledByIds.add(mLabeledById); 4052 } 4053 4054 /** 4055 * Gets the list of node infos which serve as the labels of the view represented by 4056 * this info for accessibility purposes. 4057 * 4058 * @return The list of labels in the order that they were added. 4059 */ 4060 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) getLabeledByList()4061 public @NonNull List<AccessibilityNodeInfo> getLabeledByList() { 4062 enforceSealed(); 4063 List<AccessibilityNodeInfo> labels = new ArrayList<>(); 4064 if (mLabeledByIds == null) { 4065 return labels; 4066 } 4067 for (int i = 0; i < mLabeledByIds.size(); i++) { 4068 labels.add(getNodeForAccessibilityId(mConnectionId, mWindowId, mLabeledByIds.get(i))); 4069 } 4070 return labels; 4071 } 4072 4073 /** 4074 * Removes a label. If the label was not previously added to the node, 4075 * calling this method has no effect. 4076 * <p> 4077 * <strong>Note:</strong> Cannot be called from an 4078 * {@link android.accessibilityservice.AccessibilityService}. 4079 * This class is made immutable before being delivered to an AccessibilityService. 4080 * </p> 4081 * 4082 * @param label The node which serves as this node's label. 4083 * @return true if the label was present 4084 * @see #addLabeledBy(View) 4085 */ 4086 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) removeLabeledBy(@onNull View label)4087 public boolean removeLabeledBy(@NonNull View label) { 4088 return removeLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID); 4089 } 4090 4091 /** 4092 * Removes a label which is a virtual descendant of the given 4093 * <code>root</code>. If <code>virtualDescendantId</code> is 4094 * {@link View#NO_ID} the root is set as the label. If the label 4095 * was not previously added to the node, calling this method has 4096 * no effect. 4097 * 4098 * @param root The root of the virtual subtree. 4099 * @param virtualDescendantId The id of the virtual node which serves as this node's label. 4100 * @return true if the label was present 4101 * @see #addLabeledBy(View, int) 4102 */ 4103 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) removeLabeledBy(@onNull View root, int virtualDescendantId)4104 public boolean removeLabeledBy(@NonNull View root, int virtualDescendantId) { 4105 enforceNotSealed(); 4106 final LongArray labeledByIds = mLabeledByIds; 4107 if (labeledByIds == null) { 4108 return false; 4109 } 4110 final int rootAccessibilityViewId = 4111 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 4112 final long labeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 4113 if (mLabeledById == labeledById) { 4114 mLabeledById = UNDEFINED_NODE_ID; 4115 } 4116 final int index = labeledByIds.indexOf(labeledById); 4117 if (index < 0) { 4118 return false; 4119 } 4120 labeledByIds.remove(index); 4121 return true; 4122 } 4123 4124 /** 4125 * Sets the view which serves as the label of the view represented by 4126 * this info for accessibility purposes. 4127 * 4128 * @deprecated Use {@link #addLabeledBy(View)} or {@link #removeLabeledBy(View)} instead. 4129 * 4130 * @param label The view that labels this node's source. 4131 */ 4132 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) 4133 @Deprecated setLabeledBy(View label)4134 public void setLabeledBy(View label) { 4135 setLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID); 4136 } 4137 4138 /** 4139 * Sets the view which serves as the label of the view represented by 4140 * this info for accessibility purposes. If <code>virtualDescendantId</code> 4141 * is {@link View#NO_ID} the root is set as the label. 4142 * <p> 4143 * A virtual descendant is an imaginary View that is reported as a part of the view 4144 * hierarchy for accessibility purposes. This enables custom views that draw complex 4145 * content to report themselves as a tree of virtual views, thus conveying their 4146 * logical structure. 4147 * </p> 4148 * <p> 4149 * <strong>Note:</strong> Cannot be called from an 4150 * {@link android.accessibilityservice.AccessibilityService}. 4151 * This class is made immutable before being delivered to an AccessibilityService. 4152 * </p> 4153 * 4154 * @deprecated Use {@link #addLabeledBy(View, int)} or {@link #removeLabeledBy(View, int)} 4155 * instead. 4156 * 4157 * @param root The root whose virtual descendant labels this node's source. 4158 * @param virtualDescendantId The id of the virtual descendant. 4159 */ 4160 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) 4161 @Deprecated setLabeledBy(View root, int virtualDescendantId)4162 public void setLabeledBy(View root, int virtualDescendantId) { 4163 enforceNotSealed(); 4164 final int rootAccessibilityViewId = (root != null) 4165 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; 4166 if (Flags.supportMultipleLabeledby()) { 4167 if (mLabeledByIds == null) { 4168 mLabeledByIds = new LongArray(); 4169 } else { 4170 mLabeledByIds.clear(); 4171 } 4172 } 4173 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId); 4174 if (Flags.supportMultipleLabeledby()) { 4175 mLabeledByIds.add(mLabeledById); 4176 } 4177 } 4178 4179 /** 4180 * Gets the node info which serves as the label of the view represented by 4181 * this info for accessibility purposes. 4182 * 4183 * @deprecated Use {@link #getLabeledByList()} instead. 4184 * 4185 * @return The label. 4186 */ 4187 @FlaggedApi(Flags.FLAG_SUPPORT_MULTIPLE_LABELEDBY) 4188 @Deprecated getLabeledBy()4189 public AccessibilityNodeInfo getLabeledBy() { 4190 enforceSealed(); 4191 return getNodeForAccessibilityId(mConnectionId, mWindowId, mLabeledById); 4192 } 4193 4194 /** 4195 * Sets the fully qualified resource name of the source view's id. 4196 * 4197 * <p> 4198 * <strong>Note:</strong> Cannot be called from an 4199 * {@link android.accessibilityservice.AccessibilityService}. 4200 * This class is made immutable before being delivered to an AccessibilityService. 4201 * </p> 4202 * 4203 * @param viewIdResName The id resource name. 4204 */ setViewIdResourceName(String viewIdResName)4205 public void setViewIdResourceName(String viewIdResName) { 4206 enforceNotSealed(); 4207 mViewIdResourceName = viewIdResName; 4208 } 4209 4210 /** 4211 * Gets the fully qualified resource name of the source view's id. 4212 * 4213 * <p> 4214 * <strong>Note:</strong> The primary usage of this API is for UI test automation 4215 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the 4216 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS} 4217 * flag when configuring the {@link android.accessibilityservice.AccessibilityService}. 4218 * </p> 4219 4220 * @return The id resource name. 4221 */ getViewIdResourceName()4222 public String getViewIdResourceName() { 4223 return mViewIdResourceName; 4224 } 4225 4226 /** 4227 * Gets the text selection start or the cursor position. 4228 * <p> 4229 * If no text is selected, both this method and 4230 * {@link AccessibilityNodeInfo#getTextSelectionEnd()} return the same value: 4231 * the current location of the cursor. 4232 * </p> 4233 * 4234 * @return The text selection start, the cursor location if there is no selection, or -1 if 4235 * there is no text selection and no cursor. 4236 */ getTextSelectionStart()4237 public int getTextSelectionStart() { 4238 if (Flags.a11ySelectionApi()) { 4239 Selection current = getSelection(); 4240 if ((current != null) 4241 && current.getStart().usesNode(this) 4242 && current.getEnd().usesNode(this)) { 4243 return current.getStart().getOffset(); 4244 } 4245 return UNDEFINED_SELECTION_INDEX; 4246 } 4247 return mTextSelectionStart; 4248 } 4249 4250 /** 4251 * Gets the text selection end if text is selected. 4252 * <p> 4253 * If no text is selected, both this method and 4254 * {@link AccessibilityNodeInfo#getTextSelectionStart()} return the same value: 4255 * the current location of the cursor. 4256 * </p> 4257 * 4258 * @return The text selection end, the cursor location if there is no selection, or -1 if 4259 * there is no text selection and no cursor. 4260 */ getTextSelectionEnd()4261 public int getTextSelectionEnd() { 4262 if (Flags.a11ySelectionApi()) { 4263 Selection current = getSelection(); 4264 if ((current != null) 4265 && current.getStart().usesNode(this) 4266 && current.getEnd().usesNode(this)) { 4267 return current.getEnd().getOffset(); 4268 } 4269 return UNDEFINED_SELECTION_INDEX; 4270 } 4271 return mTextSelectionEnd; 4272 } 4273 4274 /** 4275 * Sets the text selection start and end. 4276 * <p> 4277 * <strong>Note:</strong> Cannot be called from an 4278 * {@link android.accessibilityservice.AccessibilityService}. 4279 * This class is made immutable before being delivered to an AccessibilityService. 4280 * </p> 4281 * 4282 * @param start The text selection start. 4283 * @param end The text selection end. 4284 * 4285 * @throws IllegalStateException If called from an AccessibilityService. 4286 */ setTextSelection(int start, int end)4287 public void setTextSelection(int start, int end) { 4288 enforceNotSealed(); 4289 if (Flags.a11ySelectionApi()) { 4290 Selection selection = 4291 new Selection( 4292 new SelectionPosition(this, start), new SelectionPosition(this, end)); 4293 setSelection(selection); 4294 return; 4295 } 4296 mTextSelectionStart = start; 4297 mTextSelectionEnd = end; 4298 } 4299 4300 /** 4301 * Gets the input type of the source as defined by {@link InputType}. 4302 * 4303 * @return The input type. 4304 */ getInputType()4305 public int getInputType() { 4306 return mInputType; 4307 } 4308 4309 /** 4310 * Sets the input type of the source as defined by {@link InputType}. 4311 * <p> 4312 * <strong>Note:</strong> Cannot be called from an 4313 * {@link android.accessibilityservice.AccessibilityService}. 4314 * This class is made immutable before being delivered to an 4315 * AccessibilityService. 4316 * </p> 4317 * 4318 * @param inputType The input type. 4319 * 4320 * @throws IllegalStateException If called from an AccessibilityService. 4321 */ setInputType(int inputType)4322 public void setInputType(int inputType) { 4323 enforceNotSealed(); 4324 mInputType = inputType; 4325 } 4326 4327 /** 4328 * Gets an optional bundle with extra data. The bundle 4329 * is lazily created and never <code>null</code>. 4330 * <p> 4331 * <strong>Note:</strong> It is recommended to use the package 4332 * name of your application as a prefix for the keys to avoid 4333 * collisions which may confuse an accessibility service if the 4334 * same key has different meaning when emitted from different 4335 * applications. 4336 * </p> 4337 * 4338 * @return The bundle. 4339 */ getExtras()4340 public Bundle getExtras() { 4341 if (mExtras == null) { 4342 mExtras = new Bundle(); 4343 } 4344 return mExtras; 4345 } 4346 4347 /** 4348 * Check if a node has an extras bundle 4349 * @hide 4350 */ hasExtras()4351 public boolean hasExtras() { 4352 return mExtras != null; 4353 } 4354 4355 /** 4356 * Get the {@link TouchDelegateInfo} for touch delegate behavior with the represented view. 4357 * It is possible for the same node to be pointed to by several regions. Use 4358 * {@link TouchDelegateInfo#getRegionAt(int)} to get touch delegate target {@link Region}, and 4359 * {@link TouchDelegateInfo#getTargetForRegion(Region)} for {@link AccessibilityNodeInfo} from 4360 * the given region. 4361 * 4362 * @return {@link TouchDelegateInfo} or {@code null} if there are no touch delegates. 4363 */ 4364 @Nullable getTouchDelegateInfo()4365 public TouchDelegateInfo getTouchDelegateInfo() { 4366 if (mTouchDelegateInfo != null) { 4367 mTouchDelegateInfo.setConnectionId(mConnectionId); 4368 mTouchDelegateInfo.setWindowId(mWindowId); 4369 } 4370 return mTouchDelegateInfo; 4371 } 4372 4373 /** 4374 * Set touch delegate info if the represented view has a {@link TouchDelegate}. 4375 * <p> 4376 * <strong>Note:</strong> Cannot be called from an 4377 * {@link android.accessibilityservice.AccessibilityService}. 4378 * This class is made immutable before being delivered to an 4379 * AccessibilityService. 4380 * </p> 4381 * 4382 * @param delegatedInfo {@link TouchDelegateInfo} returned from 4383 * {@link TouchDelegate#getTouchDelegateInfo()}. 4384 * 4385 * @throws IllegalStateException If called from an AccessibilityService. 4386 */ setTouchDelegateInfo(@onNull TouchDelegateInfo delegatedInfo)4387 public void setTouchDelegateInfo(@NonNull TouchDelegateInfo delegatedInfo) { 4388 enforceNotSealed(); 4389 mTouchDelegateInfo = delegatedInfo; 4390 } 4391 4392 /** 4393 * Gets the value of a boolean property. 4394 * 4395 * @param property The property. 4396 * @return The value. 4397 */ getBooleanProperty(int property)4398 private boolean getBooleanProperty(int property) { 4399 return (mBooleanProperties & property) != 0; 4400 } 4401 4402 /** 4403 * Sets a boolean property. 4404 * 4405 * @param property The property. 4406 * @param value The value. 4407 * 4408 * @throws IllegalStateException If called from an AccessibilityService. 4409 */ setBooleanProperty(int property, boolean value)4410 private void setBooleanProperty(int property, boolean value) { 4411 enforceNotSealed(); 4412 if (value) { 4413 mBooleanProperties |= property; 4414 } else { 4415 mBooleanProperties &= ~property; 4416 } 4417 } 4418 4419 /** 4420 * Sets the unique id of the IAccessibilityServiceConnection over which 4421 * this instance can send requests to the system. 4422 * 4423 * @param connectionId The connection id. 4424 * 4425 * @hide 4426 */ setConnectionId(int connectionId)4427 public void setConnectionId(int connectionId) { 4428 enforceNotSealed(); 4429 mConnectionId = connectionId; 4430 } 4431 4432 /** 4433 * Get the connection ID. 4434 * 4435 * @return The connection id 4436 * 4437 * @hide 4438 */ getConnectionId()4439 public int getConnectionId() { 4440 return mConnectionId; 4441 } 4442 4443 /** 4444 * {@inheritDoc} 4445 */ 4446 @Override describeContents()4447 public int describeContents() { 4448 return 0; 4449 } 4450 4451 /** 4452 * Sets the id of the source node. 4453 * 4454 * @param sourceId The id. 4455 * @param windowId The window id. 4456 * 4457 * @hide 4458 */ setSourceNodeId(long sourceId, int windowId)4459 public void setSourceNodeId(long sourceId, int windowId) { 4460 enforceNotSealed(); 4461 mSourceNodeId = sourceId; 4462 mWindowId = windowId; 4463 } 4464 4465 /** 4466 * Gets the id of the source node. 4467 * 4468 * @return The id. 4469 * 4470 * @hide 4471 */ 4472 @UnsupportedAppUsage 4473 @TestApi getSourceNodeId()4474 public long getSourceNodeId() { 4475 return mSourceNodeId; 4476 } 4477 4478 /** 4479 * Sets the unique id to act as a key to identify the node. If the node instance is replaced 4480 * after refreshing the layout, calling this API to assign the same unique id to the new 4481 * alike node can help accessibility service to identify it. 4482 * 4483 * @param uniqueId The unique id that is associated with a visible node on the screen 4484 */ setUniqueId(@ullable String uniqueId)4485 public void setUniqueId(@Nullable String uniqueId) { 4486 enforceNotSealed(); 4487 mUniqueId = uniqueId; 4488 } 4489 4490 /** 4491 * Gets the unique id of the node. 4492 * 4493 * @return The unique id 4494 */ 4495 @Nullable getUniqueId()4496 public String getUniqueId() { 4497 return mUniqueId; 4498 } 4499 4500 /** 4501 * Sets the container title for app-developer-defined container which can be any type of 4502 * ViewGroup or layout. 4503 * Container title will be used to group together related controls, similar to HTML fieldset. 4504 * Or container title may identify a large piece of the UI that is visibly grouped together, 4505 * such as a toolbar or a card, etc. 4506 * <p> 4507 * Container title helps to assist in navigation across containers and other groups. 4508 * For example, a screen reader may use this to determine where to put accessibility focus. 4509 * </p> 4510 * <p> 4511 * Container title is different from pane title{@link #setPaneTitle} which indicates that the 4512 * node represents a window or activity. 4513 * </p> 4514 * 4515 * <p> 4516 * Example: An app can set container titles on several non-modal menus, containing TextViews 4517 * or ImageButtons that have content descriptions, text, etc. Screen readers can quickly 4518 * switch accessibility focus among menus instead of child views. Other accessibility-services 4519 * can easily find the menu. 4520 * </p> 4521 * 4522 * @param containerTitle The container title that is associated with a ViewGroup/Layout on the 4523 * screen. 4524 */ setContainerTitle(@ullable CharSequence containerTitle)4525 public void setContainerTitle(@Nullable CharSequence containerTitle) { 4526 enforceNotSealed(); 4527 mContainerTitle = (containerTitle == null) ? null 4528 : containerTitle.subSequence(0, containerTitle.length()); 4529 } 4530 4531 /** 4532 * Returns the container title. 4533 * 4534 * @see #setContainerTitle 4535 */ 4536 @Nullable getContainerTitle()4537 public CharSequence getContainerTitle() { 4538 return mContainerTitle; 4539 } 4540 4541 /** 4542 * Sets the token and node id of the leashed parent. 4543 * 4544 * @param token The token. 4545 * @param viewId The accessibility view id. 4546 * @hide 4547 */ 4548 @TestApi setLeashedParent(@ullable IBinder token, int viewId)4549 public void setLeashedParent(@Nullable IBinder token, int viewId) { 4550 enforceNotSealed(); 4551 mLeashedParent = token; 4552 mLeashedParentNodeId = makeNodeId(viewId, AccessibilityNodeProvider.HOST_VIEW_ID); 4553 } 4554 4555 /** 4556 * Gets the token of the leashed parent. 4557 * 4558 * @return The token. 4559 * @hide 4560 */ getLeashedParent()4561 public @Nullable IBinder getLeashedParent() { 4562 return mLeashedParent; 4563 } 4564 4565 /** 4566 * Gets the node id of the leashed parent. 4567 * 4568 * @return The accessibility node id. 4569 * @hide 4570 */ getLeashedParentNodeId()4571 public long getLeashedParentNodeId() { 4572 return mLeashedParentNodeId; 4573 } 4574 4575 /** 4576 * Connects this node to the View's root so that operations on this node can query the entire 4577 * {@link AccessibilityNodeInfo} tree and perform accessibility actions on nodes. 4578 * 4579 * <p> 4580 * Testing or debugging tools should create this {@link AccessibilityNodeInfo} node using 4581 * {@link View#createAccessibilityNodeInfo()} or {@link AccessibilityNodeProvider} and call this 4582 * method, then navigate and interact with the node tree by calling methods on the node. 4583 * Calling this method more than once on the same node is a no-op. After calling this method, 4584 * all nodes linked to this node (children, ancestors, etc.) are also queryable. 4585 * </p> 4586 * 4587 * <p> 4588 * Here "query" refers to the following node operations: 4589 * <li>check properties of this node (example: {@link #isScrollable()})</li> 4590 * <li>find and query children (example: {@link #getChild(int)})</li> 4591 * <li>find and query the parent (example: {@link #getParent()})</li> 4592 * <li>find focus (examples: {@link #findFocus(int)}, {@link #focusSearch(int)})</li> 4593 * <li>find and query other nodes (example: {@link #findAccessibilityNodeInfosByText(String)}, 4594 * {@link #findAccessibilityNodeInfosByViewId(String)})</li> 4595 * <li>perform actions (example: {@link #performAction(int)})</li> 4596 * </p> 4597 * 4598 * <p> 4599 * This is intended for short-lived inspections from testing or debugging tools in the app 4600 * process, as operations on this node tree will only succeed as long as the associated 4601 * view hierarchy remains attached to a window. {@link AccessibilityNodeInfo} objects can 4602 * quickly become out of sync with their corresponding {@link View} objects; if you wish to 4603 * inspect a changed or different view hierarchy then create a new node from any view in that 4604 * hierarchy and call this method on that new node, instead of disabling & re-enabling the 4605 * connection on the previous node. 4606 * </p> 4607 * 4608 * @param view The view that generated this node, or any view in the same view-root hierarchy. 4609 * @param enabled Whether to enable (true) or disable (false) querying from the app process. 4610 * @throws IllegalStateException If called from an {@link AccessibilityService}, or if provided 4611 * a {@link View} that is not attached to a window. 4612 */ setQueryFromAppProcessEnabled(@onNull View view, boolean enabled)4613 public void setQueryFromAppProcessEnabled(@NonNull View view, boolean enabled) { 4614 enforceNotSealed(); 4615 4616 if (!enabled) { 4617 setConnectionId(UNDEFINED_CONNECTION_ID); 4618 return; 4619 } 4620 4621 if (mConnectionId != UNDEFINED_CONNECTION_ID) { 4622 return; 4623 } 4624 4625 ViewRootImpl viewRootImpl = view.getViewRootImpl(); 4626 if (viewRootImpl == null) { 4627 throw new IllegalStateException( 4628 "Cannot link a node to a view that is not attached to a window."); 4629 } 4630 setConnectionId(viewRootImpl.getDirectAccessibilityConnectionId()); 4631 } 4632 4633 /** 4634 * Sets if this instance is sealed. 4635 * 4636 * @param sealed Whether is sealed. 4637 * 4638 * @hide 4639 */ 4640 @UnsupportedAppUsage setSealed(boolean sealed)4641 public void setSealed(boolean sealed) { 4642 mSealed = sealed; 4643 } 4644 4645 /** 4646 * Gets if this instance is sealed. 4647 * 4648 * @return Whether is sealed. 4649 * 4650 * @hide 4651 */ 4652 @UnsupportedAppUsage isSealed()4653 public boolean isSealed() { 4654 return mSealed; 4655 } 4656 usingDirectConnection(int connectionId)4657 private static boolean usingDirectConnection(int connectionId) { 4658 return AccessibilityInteractionClient.getConnection( 4659 connectionId) instanceof DirectAccessibilityConnection; 4660 } 4661 4662 /** 4663 * Enforces that this instance is sealed, unless using a {@link DirectAccessibilityConnection} 4664 * which allows queries while the node is not sealed. 4665 * 4666 * @throws IllegalStateException If this instance is not sealed. 4667 * 4668 * @hide 4669 */ enforceSealed()4670 protected void enforceSealed() { 4671 if (!usingDirectConnection(mConnectionId) && !isSealed()) { 4672 throw new IllegalStateException("Cannot perform this " 4673 + "action on a not sealed instance."); 4674 } 4675 } 4676 enforceValidFocusDirection(int direction)4677 private void enforceValidFocusDirection(int direction) { 4678 switch (direction) { 4679 case View.FOCUS_DOWN: 4680 case View.FOCUS_UP: 4681 case View.FOCUS_LEFT: 4682 case View.FOCUS_RIGHT: 4683 case View.FOCUS_FORWARD: 4684 case View.FOCUS_BACKWARD: 4685 return; 4686 default: 4687 throw new IllegalArgumentException("Unknown direction: " + direction); 4688 } 4689 } 4690 enforceValidFocusType(int focusType)4691 private void enforceValidFocusType(int focusType) { 4692 switch (focusType) { 4693 case FOCUS_INPUT: 4694 case FOCUS_ACCESSIBILITY: 4695 return; 4696 default: 4697 throw new IllegalArgumentException("Unknown focus type: " + focusType); 4698 } 4699 } 4700 enforceValidExpandedState(int state)4701 private void enforceValidExpandedState(int state) { 4702 if (Flags.a11yExpansionStateApi()) { 4703 switch (state) { 4704 case EXPANDED_STATE_UNDEFINED: 4705 case EXPANDED_STATE_COLLAPSED: 4706 case EXPANDED_STATE_PARTIAL: 4707 case EXPANDED_STATE_FULL: 4708 return; 4709 default: 4710 throw new IllegalArgumentException("Unknown expanded state: " + state); 4711 } 4712 } 4713 } 4714 4715 /** 4716 * Enforces that this instance is not sealed. 4717 * 4718 * @throws IllegalStateException If this instance is sealed. 4719 * 4720 * @hide 4721 */ enforceNotSealed()4722 protected void enforceNotSealed() { 4723 if (isSealed()) { 4724 throw new IllegalStateException("Cannot perform this " 4725 + "action on a sealed instance."); 4726 } 4727 } 4728 4729 /** 4730 * Returns a cached instance if such is available otherwise a new one 4731 * and sets the source. 4732 * 4733 * @deprecated Object pooling has been discontinued. Create a new instance using the 4734 * constructor {@link #AccessibilityNodeInfo(View)} instead. 4735 * @param source The source view. 4736 * @return An instance. 4737 * 4738 * @see #setSource(View) 4739 */ 4740 @Deprecated obtain(View source)4741 public static AccessibilityNodeInfo obtain(View source) { 4742 return new AccessibilityNodeInfo(source); 4743 } 4744 4745 /** 4746 * Returns a cached instance if such is available otherwise a new one 4747 * and sets the source. 4748 * 4749 * @deprecated Object pooling has been discontinued. Create a new instance using the 4750 * constructor {@link #AccessibilityNodeInfo(View, int)} instead. 4751 * 4752 * @param root The root of the virtual subtree. 4753 * @param virtualDescendantId The id of the virtual descendant. 4754 * @return An instance. 4755 * 4756 * @see #setSource(View, int) 4757 */ 4758 @Deprecated obtain(View root, int virtualDescendantId)4759 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) { 4760 return new AccessibilityNodeInfo(root, virtualDescendantId); 4761 } 4762 4763 /** 4764 * Instantiates a new AccessibilityNodeInfo. 4765 * 4766 * @deprecated Object pooling has been discontinued. Create a new instance using the 4767 * constructor {@link #AccessibilityNodeInfo()} instead. 4768 * @return An instance. 4769 */ 4770 @Deprecated obtain()4771 public static AccessibilityNodeInfo obtain() { 4772 return new AccessibilityNodeInfo(); 4773 } 4774 4775 /** 4776 * Instantiates a new AccessibilityNodeInfo initialized from the given 4777 * <code>info</code>. 4778 * 4779 * @deprecated Object pooling has been discontinued. Create a new instance using the 4780 * constructor {@link #AccessibilityNodeInfo(AccessibilityNodeInfo)} instead. 4781 * @param info The other info. 4782 * @return An instance. 4783 */ 4784 @Deprecated obtain(AccessibilityNodeInfo info)4785 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) { 4786 return new AccessibilityNodeInfo(info); 4787 } 4788 4789 /** 4790 * Would previously return an instance back to be reused. 4791 * 4792 * @deprecated Object pooling has been discontinued. Calling this function now will have 4793 * no effect. 4794 */ 4795 @Deprecated recycle()4796 public void recycle() {} 4797 4798 /** 4799 * {@inheritDoc} 4800 * <p> 4801 * <strong>Note:</strong> After the instance is written to a parcel it 4802 * is recycled. You must not touch the object after calling this function. 4803 * </p> 4804 */ 4805 @Override writeToParcel(Parcel parcel, int flags)4806 public void writeToParcel(Parcel parcel, int flags) { 4807 writeToParcelNoRecycle(parcel, flags); 4808 // Since instances of this class are fetched via synchronous i.e. blocking 4809 // calls in IPCs we always recycle as soon as the instance is marshaled. 4810 } 4811 4812 /** @hide */ 4813 @TestApi writeToParcelNoRecycle(Parcel parcel, int flags)4814 public void writeToParcelNoRecycle(Parcel parcel, int flags) { 4815 // Write bit set of indices of fields with values differing from default 4816 long nonDefaultFields = 0; 4817 int fieldIndex = 0; // index of the current field 4818 if (isSealed() != DEFAULT.isSealed()) nonDefaultFields |= bitAt(fieldIndex); 4819 fieldIndex++; 4820 if (mSourceNodeId != DEFAULT.mSourceNodeId) nonDefaultFields |= bitAt(fieldIndex); 4821 fieldIndex++; 4822 if (mWindowId != DEFAULT.mWindowId) nonDefaultFields |= bitAt(fieldIndex); 4823 fieldIndex++; 4824 if (mParentNodeId != DEFAULT.mParentNodeId) nonDefaultFields |= bitAt(fieldIndex); 4825 fieldIndex++; 4826 if (mLabelForId != DEFAULT.mLabelForId) nonDefaultFields |= bitAt(fieldIndex); 4827 fieldIndex++; 4828 if (mLabeledById != DEFAULT.mLabeledById) nonDefaultFields |= bitAt(fieldIndex); 4829 fieldIndex++; 4830 if (!LongArray.elementsEqual(mLabeledByIds, DEFAULT.mLabeledByIds)) { 4831 nonDefaultFields |= bitAt(fieldIndex); 4832 } 4833 fieldIndex++; 4834 if (mTraversalBefore != DEFAULT.mTraversalBefore) nonDefaultFields |= bitAt(fieldIndex); 4835 fieldIndex++; 4836 if (mTraversalAfter != DEFAULT.mTraversalAfter) nonDefaultFields |= bitAt(fieldIndex); 4837 fieldIndex++; 4838 if (mMinDurationBetweenContentChanges 4839 != DEFAULT.mMinDurationBetweenContentChanges) { 4840 nonDefaultFields |= bitAt(fieldIndex); 4841 } 4842 fieldIndex++; 4843 if (mConnectionId != DEFAULT.mConnectionId) nonDefaultFields |= bitAt(fieldIndex); 4844 fieldIndex++; 4845 if (!LongArray.elementsEqual(mChildNodeIds, DEFAULT.mChildNodeIds)) { 4846 nonDefaultFields |= bitAt(fieldIndex); 4847 } 4848 fieldIndex++; 4849 if (!Objects.equals(mBoundsInParent, DEFAULT.mBoundsInParent)) { 4850 nonDefaultFields |= bitAt(fieldIndex); 4851 } 4852 fieldIndex++; 4853 if (!Objects.equals(mBoundsInScreen, DEFAULT.mBoundsInScreen)) { 4854 nonDefaultFields |= bitAt(fieldIndex); 4855 } 4856 fieldIndex++; 4857 if (!Objects.equals(mBoundsInWindow, DEFAULT.mBoundsInWindow)) { 4858 nonDefaultFields |= bitAt(fieldIndex); 4859 } 4860 fieldIndex++; 4861 4862 if (!Objects.equals(mActions, DEFAULT.mActions)) nonDefaultFields |= bitAt(fieldIndex); 4863 fieldIndex++; 4864 if (mMaxTextLength != DEFAULT.mMaxTextLength) nonDefaultFields |= bitAt(fieldIndex); 4865 fieldIndex++; 4866 if (mMovementGranularities != DEFAULT.mMovementGranularities) { 4867 nonDefaultFields |= bitAt(fieldIndex); 4868 } 4869 fieldIndex++; 4870 if (mBooleanProperties != DEFAULT.mBooleanProperties) nonDefaultFields |= bitAt(fieldIndex); 4871 fieldIndex++; 4872 if (!Objects.equals(mPackageName, DEFAULT.mPackageName)) { 4873 nonDefaultFields |= bitAt(fieldIndex); 4874 } 4875 fieldIndex++; 4876 if (!Objects.equals(mClassName, DEFAULT.mClassName)) nonDefaultFields |= bitAt(fieldIndex); 4877 fieldIndex++; 4878 if (!Objects.equals(mText, DEFAULT.mText)) nonDefaultFields |= bitAt(fieldIndex); 4879 fieldIndex++; 4880 if (!Objects.equals(mHintText, DEFAULT.mHintText)) { 4881 nonDefaultFields |= bitAt(fieldIndex); 4882 } 4883 fieldIndex++; 4884 if (!Objects.equals(mError, DEFAULT.mError)) nonDefaultFields |= bitAt(fieldIndex); 4885 fieldIndex++; 4886 if (!Objects.equals(mStateDescription, DEFAULT.mStateDescription)) { 4887 nonDefaultFields |= bitAt(fieldIndex); 4888 } 4889 fieldIndex++; 4890 if (!Objects.equals(mContentDescription, DEFAULT.mContentDescription)) { 4891 nonDefaultFields |= bitAt(fieldIndex); 4892 } 4893 fieldIndex++; 4894 if (!Objects.equals(mSupplementalDescription, DEFAULT.mSupplementalDescription)) { 4895 nonDefaultFields |= bitAt(fieldIndex); 4896 } 4897 fieldIndex++; 4898 if (!Objects.equals(mPaneTitle, DEFAULT.mPaneTitle)) { 4899 nonDefaultFields |= bitAt(fieldIndex); 4900 } 4901 fieldIndex++; 4902 if (!Objects.equals(mTooltipText, DEFAULT.mTooltipText)) { 4903 nonDefaultFields |= bitAt(fieldIndex); 4904 } 4905 fieldIndex++; 4906 if (!Objects.equals(mContainerTitle, DEFAULT.mContainerTitle)) { 4907 nonDefaultFields |= bitAt(fieldIndex); 4908 } 4909 fieldIndex++; 4910 if (!Objects.equals(mViewIdResourceName, DEFAULT.mViewIdResourceName)) { 4911 nonDefaultFields |= bitAt(fieldIndex); 4912 } 4913 fieldIndex++; 4914 if (!Objects.equals(mUniqueId, DEFAULT.mUniqueId)) { 4915 nonDefaultFields |= bitAt(fieldIndex); 4916 } 4917 fieldIndex++; 4918 if (mTextSelectionStart != DEFAULT.mTextSelectionStart) { 4919 nonDefaultFields |= bitAt(fieldIndex); 4920 } 4921 fieldIndex++; 4922 if (mTextSelectionEnd != DEFAULT.mTextSelectionEnd) { 4923 nonDefaultFields |= bitAt(fieldIndex); 4924 } 4925 fieldIndex++; 4926 if (mInputType != DEFAULT.mInputType) nonDefaultFields |= bitAt(fieldIndex); 4927 fieldIndex++; 4928 if (mLiveRegion != DEFAULT.mLiveRegion) nonDefaultFields |= bitAt(fieldIndex); 4929 fieldIndex++; 4930 if (mDrawingOrderInParent != DEFAULT.mDrawingOrderInParent) { 4931 nonDefaultFields |= bitAt(fieldIndex); 4932 } 4933 fieldIndex++; 4934 if (!Objects.equals(mExtraDataKeys, DEFAULT.mExtraDataKeys)) { 4935 nonDefaultFields |= bitAt(fieldIndex); 4936 } 4937 fieldIndex++; 4938 if (!Objects.equals(mExtras, DEFAULT.mExtras)) nonDefaultFields |= bitAt(fieldIndex); 4939 fieldIndex++; 4940 if (!Objects.equals(mRangeInfo, DEFAULT.mRangeInfo)) nonDefaultFields |= bitAt(fieldIndex); 4941 fieldIndex++; 4942 if (!Objects.equals(mCollectionInfo, DEFAULT.mCollectionInfo)) { 4943 nonDefaultFields |= bitAt(fieldIndex); 4944 } 4945 fieldIndex++; 4946 if (!Objects.equals(mCollectionItemInfo, DEFAULT.mCollectionItemInfo)) { 4947 nonDefaultFields |= bitAt(fieldIndex); 4948 } 4949 fieldIndex++; 4950 if (!Objects.equals(mTouchDelegateInfo, DEFAULT.mTouchDelegateInfo)) { 4951 nonDefaultFields |= bitAt(fieldIndex); 4952 } 4953 fieldIndex++; 4954 if (!Objects.equals(mExtraRenderingInfo, DEFAULT.mExtraRenderingInfo)) { 4955 nonDefaultFields |= bitAt(fieldIndex); 4956 } 4957 fieldIndex++; 4958 if (mLeashedChild != DEFAULT.mLeashedChild) { 4959 nonDefaultFields |= bitAt(fieldIndex); 4960 } 4961 fieldIndex++; 4962 if (mLeashedParent != DEFAULT.mLeashedParent) { 4963 nonDefaultFields |= bitAt(fieldIndex); 4964 } 4965 fieldIndex++; 4966 if (mLeashedParentNodeId != DEFAULT.mLeashedParentNodeId) { 4967 nonDefaultFields |= bitAt(fieldIndex); 4968 } 4969 fieldIndex++; 4970 if (!Objects.equals(mSelection, DEFAULT.mSelection)) { 4971 nonDefaultFields |= bitAt(fieldIndex); 4972 } 4973 fieldIndex++; 4974 if (mChecked != DEFAULT.mChecked) { 4975 nonDefaultFields |= bitAt(fieldIndex); 4976 } 4977 fieldIndex++; 4978 if (mExpandedState != DEFAULT.mExpandedState) { 4979 nonDefaultFields |= bitAt(fieldIndex); 4980 } 4981 4982 int totalFields = fieldIndex; 4983 parcel.writeLong(nonDefaultFields); 4984 4985 fieldIndex = 0; 4986 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(isSealed() ? 1 : 0); 4987 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mSourceNodeId); 4988 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mWindowId); 4989 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mParentNodeId); 4990 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabelForId); 4991 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabeledById); 4992 if (isBitSet(nonDefaultFields, fieldIndex++)) { 4993 final LongArray labeledByIds = mLabeledByIds; 4994 if (labeledByIds == null) { 4995 parcel.writeInt(0); 4996 } else { 4997 final int labeledByIdsSize = labeledByIds.size(); 4998 parcel.writeInt(labeledByIdsSize); 4999 for (int i = 0; i < labeledByIdsSize; i++) { 5000 parcel.writeLong(labeledByIds.get(i)); 5001 } 5002 } 5003 } 5004 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalBefore); 5005 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalAfter); 5006 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5007 parcel.writeLong(mMinDurationBetweenContentChanges); 5008 } 5009 5010 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mConnectionId); 5011 5012 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5013 final LongArray childIds = mChildNodeIds; 5014 if (childIds == null) { 5015 parcel.writeInt(0); 5016 } else { 5017 final int childIdsSize = childIds.size(); 5018 parcel.writeInt(childIdsSize); 5019 for (int i = 0; i < childIdsSize; i++) { 5020 parcel.writeLong(childIds.get(i)); 5021 } 5022 } 5023 } 5024 5025 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5026 parcel.writeInt(mBoundsInParent.top); 5027 parcel.writeInt(mBoundsInParent.bottom); 5028 parcel.writeInt(mBoundsInParent.left); 5029 parcel.writeInt(mBoundsInParent.right); 5030 } 5031 5032 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5033 parcel.writeInt(mBoundsInScreen.top); 5034 parcel.writeInt(mBoundsInScreen.bottom); 5035 parcel.writeInt(mBoundsInScreen.left); 5036 parcel.writeInt(mBoundsInScreen.right); 5037 } 5038 5039 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5040 parcel.writeInt(mBoundsInWindow.top); 5041 parcel.writeInt(mBoundsInWindow.bottom); 5042 parcel.writeInt(mBoundsInWindow.left); 5043 parcel.writeInt(mBoundsInWindow.right); 5044 } 5045 5046 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5047 if (mActions != null && !mActions.isEmpty()) { 5048 final int actionCount = mActions.size(); 5049 5050 int nonStandardActionCount = 0; 5051 long defaultStandardActions = 0; 5052 for (int i = 0; i < actionCount; i++) { 5053 AccessibilityAction action = mActions.get(i); 5054 if (isDefaultStandardAction(action)) { 5055 defaultStandardActions |= action.mSerializationFlag; 5056 } else { 5057 nonStandardActionCount++; 5058 } 5059 } 5060 parcel.writeLong(defaultStandardActions); 5061 5062 parcel.writeInt(nonStandardActionCount); 5063 for (int i = 0; i < actionCount; i++) { 5064 AccessibilityAction action = mActions.get(i); 5065 if (!isDefaultStandardAction(action)) { 5066 action.writeToParcel(parcel, flags); 5067 } 5068 } 5069 } else { 5070 parcel.writeLong(0); 5071 parcel.writeInt(0); 5072 } 5073 } 5074 5075 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMaxTextLength); 5076 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMovementGranularities); 5077 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mBooleanProperties); 5078 5079 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPackageName); 5080 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mClassName); 5081 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mText); 5082 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mHintText); 5083 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mError); 5084 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mStateDescription); 5085 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5086 parcel.writeCharSequence(mContentDescription); 5087 } 5088 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5089 parcel.writeCharSequence(mSupplementalDescription); 5090 } 5091 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPaneTitle); 5092 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mTooltipText); 5093 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mContainerTitle); 5094 5095 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeString(mViewIdResourceName); 5096 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeString(mUniqueId); 5097 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionStart); 5098 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionEnd); 5099 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mInputType); 5100 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mLiveRegion); 5101 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mDrawingOrderInParent); 5102 5103 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeStringList(mExtraDataKeys); 5104 5105 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeBundle(mExtras); 5106 5107 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5108 parcel.writeInt(mRangeInfo.getType()); 5109 parcel.writeFloat(mRangeInfo.getMin()); 5110 parcel.writeFloat(mRangeInfo.getMax()); 5111 parcel.writeFloat(mRangeInfo.getCurrent()); 5112 } 5113 5114 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5115 parcel.writeInt(mCollectionInfo.getRowCount()); 5116 parcel.writeInt(mCollectionInfo.getColumnCount()); 5117 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0); 5118 parcel.writeInt(mCollectionInfo.getSelectionMode()); 5119 parcel.writeInt(mCollectionInfo.getItemCount()); 5120 parcel.writeInt(mCollectionInfo.getImportantForAccessibilityItemCount()); 5121 } 5122 5123 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5124 parcel.writeString(mCollectionItemInfo.getRowTitle()); 5125 parcel.writeInt(mCollectionItemInfo.getRowIndex()); 5126 parcel.writeInt(mCollectionItemInfo.getRowSpan()); 5127 parcel.writeString(mCollectionItemInfo.getColumnTitle()); 5128 parcel.writeInt(mCollectionItemInfo.getColumnIndex()); 5129 parcel.writeInt(mCollectionItemInfo.getColumnSpan()); 5130 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0); 5131 parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0); 5132 } 5133 5134 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5135 mTouchDelegateInfo.writeToParcel(parcel, flags); 5136 } 5137 5138 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5139 parcel.writeValue(mExtraRenderingInfo.getLayoutSize()); 5140 parcel.writeFloat(mExtraRenderingInfo.getTextSizeInPx()); 5141 parcel.writeInt(mExtraRenderingInfo.getTextSizeUnit()); 5142 } 5143 5144 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5145 parcel.writeStrongBinder(mLeashedChild); 5146 } 5147 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5148 parcel.writeStrongBinder(mLeashedParent); 5149 } 5150 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5151 parcel.writeLong(mLeashedParentNodeId); 5152 } 5153 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5154 mSelection.writeToParcel(parcel, flags); 5155 } 5156 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5157 parcel.writeInt(mChecked); 5158 } 5159 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5160 parcel.writeInt(mExpandedState); 5161 } 5162 5163 if (DEBUG) { 5164 fieldIndex--; 5165 if (totalFields != fieldIndex) { 5166 throw new IllegalStateException("Number of fields mismatch: " + totalFields 5167 + " vs " + fieldIndex); 5168 } 5169 } 5170 } 5171 5172 /** 5173 * Initializes this instance from another one. 5174 * 5175 * @param other The other instance. 5176 */ init(AccessibilityNodeInfo other)5177 private void init(AccessibilityNodeInfo other) { 5178 mSealed = other.mSealed; 5179 mSourceNodeId = other.mSourceNodeId; 5180 mParentNodeId = other.mParentNodeId; 5181 mLabelForId = other.mLabelForId; 5182 mLabeledById = other.mLabeledById; 5183 mLabeledByIds = other.mLabeledByIds; 5184 mTraversalBefore = other.mTraversalBefore; 5185 mTraversalAfter = other.mTraversalAfter; 5186 mMinDurationBetweenContentChanges = other.mMinDurationBetweenContentChanges; 5187 mWindowId = other.mWindowId; 5188 mConnectionId = other.mConnectionId; 5189 mUniqueId = other.mUniqueId; 5190 mBoundsInParent.set(other.mBoundsInParent); 5191 mBoundsInScreen.set(other.mBoundsInScreen); 5192 mBoundsInWindow.set(other.mBoundsInWindow); 5193 mPackageName = other.mPackageName; 5194 mClassName = other.mClassName; 5195 mText = other.mText; 5196 mOriginalText = other.mOriginalText; 5197 mHintText = other.mHintText; 5198 mError = other.mError; 5199 mStateDescription = other.mStateDescription; 5200 mContentDescription = other.mContentDescription; 5201 mSupplementalDescription = other.mSupplementalDescription; 5202 mPaneTitle = other.mPaneTitle; 5203 mTooltipText = other.mTooltipText; 5204 mContainerTitle = other.mContainerTitle; 5205 mViewIdResourceName = other.mViewIdResourceName; 5206 5207 if (mActions != null) mActions.clear(); 5208 final ArrayList<AccessibilityAction> otherActions = other.mActions; 5209 if (otherActions != null && otherActions.size() > 0) { 5210 if (mActions == null) { 5211 mActions = new ArrayList(otherActions); 5212 } else { 5213 mActions.addAll(other.mActions); 5214 } 5215 } 5216 5217 mBooleanProperties = other.mBooleanProperties; 5218 mMaxTextLength = other.mMaxTextLength; 5219 mMovementGranularities = other.mMovementGranularities; 5220 5221 5222 if (mChildNodeIds != null) mChildNodeIds.clear(); 5223 final LongArray otherChildNodeIds = other.mChildNodeIds; 5224 if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) { 5225 if (mChildNodeIds == null) { 5226 mChildNodeIds = otherChildNodeIds.clone(); 5227 } else { 5228 mChildNodeIds.addAll(otherChildNodeIds); 5229 } 5230 } 5231 5232 mTextSelectionStart = other.mTextSelectionStart; 5233 mTextSelectionEnd = other.mTextSelectionEnd; 5234 mInputType = other.mInputType; 5235 mLiveRegion = other.mLiveRegion; 5236 mDrawingOrderInParent = other.mDrawingOrderInParent; 5237 5238 mExtraDataKeys = other.mExtraDataKeys; 5239 5240 mExtras = other.mExtras != null ? new Bundle(other.mExtras) : null; 5241 5242 initCopyInfos(other); 5243 5244 final TouchDelegateInfo otherInfo = other.mTouchDelegateInfo; 5245 mTouchDelegateInfo = (otherInfo != null) 5246 ? new TouchDelegateInfo(otherInfo.mTargetMap, true) : null; 5247 5248 mLeashedChild = other.mLeashedChild; 5249 mLeashedParent = other.mLeashedParent; 5250 mLeashedParentNodeId = other.mLeashedParentNodeId; 5251 mChecked = other.mChecked; 5252 mExpandedState = other.mExpandedState; 5253 } 5254 initCopyInfos(AccessibilityNodeInfo other)5255 private void initCopyInfos(AccessibilityNodeInfo other) { 5256 RangeInfo ri = other.mRangeInfo; 5257 mRangeInfo = (ri == null) ? null 5258 : new RangeInfo(ri.mType, ri.mMin, ri.mMax, ri.mCurrent); 5259 CollectionInfo ci = other.mCollectionInfo; 5260 mCollectionInfo = (ci == null) ? null 5261 : new CollectionInfo(ci.mRowCount, ci.mColumnCount, 5262 ci.mHierarchical, ci.mSelectionMode, ci.mItemCount, 5263 ci.mImportantForAccessibilityItemCount); 5264 CollectionItemInfo cii = other.mCollectionItemInfo; 5265 CollectionItemInfo.Builder builder = new CollectionItemInfo.Builder(); 5266 mCollectionItemInfo = (cii == null) ? null 5267 : builder.setRowTitle(cii.mRowTitle).setRowIndex(cii.mRowIndex).setRowSpan( 5268 cii.mRowSpan).setColumnTitle(cii.mColumnTitle).setColumnIndex( 5269 cii.mColumnIndex).setColumnSpan(cii.mColumnSpan).setHeading( 5270 cii.mHeading).setSelected(cii.mSelected).build(); 5271 ExtraRenderingInfo ti = other.mExtraRenderingInfo; 5272 mExtraRenderingInfo = (ti == null) ? null 5273 : new ExtraRenderingInfo(ti); 5274 5275 if (Flags.a11ySelectionApi()) { 5276 if (other.getSelection() != null) { 5277 SelectionPosition sps = other.getSelection().getStart(); 5278 SelectionPosition spe = other.getSelection().getEnd(); 5279 mSelection = 5280 new Selection( 5281 new SelectionPosition(sps.mSourceNodeId, sps.getOffset()), 5282 new SelectionPosition(spe.mSourceNodeId, spe.getOffset())); 5283 } 5284 } 5285 } 5286 5287 /** 5288 * Creates a new instance from a {@link Parcel}. 5289 * 5290 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}. 5291 */ initFromParcel(Parcel parcel)5292 private void initFromParcel(Parcel parcel) { 5293 // Bit mask of non-default-valued field indices 5294 long nonDefaultFields = parcel.readLong(); 5295 int fieldIndex = 0; 5296 final boolean sealed = isBitSet(nonDefaultFields, fieldIndex++) 5297 ? (parcel.readInt() == 1) 5298 : DEFAULT.mSealed; 5299 if (isBitSet(nonDefaultFields, fieldIndex++)) mSourceNodeId = parcel.readLong(); 5300 if (isBitSet(nonDefaultFields, fieldIndex++)) mWindowId = parcel.readInt(); 5301 if (isBitSet(nonDefaultFields, fieldIndex++)) mParentNodeId = parcel.readLong(); 5302 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabelForId = parcel.readLong(); 5303 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabeledById = parcel.readLong(); 5304 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5305 final int labeledByIdsSize = parcel.readInt(); 5306 if (labeledByIdsSize <= 0) { 5307 mLabeledByIds = null; 5308 } else { 5309 mLabeledByIds = new LongArray(labeledByIdsSize); 5310 for (int i = 0; i < labeledByIdsSize; i++) { 5311 final long labeledById = parcel.readLong(); 5312 mLabeledByIds.add(labeledById); 5313 } 5314 } 5315 } 5316 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalBefore = parcel.readLong(); 5317 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalAfter = parcel.readLong(); 5318 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5319 mMinDurationBetweenContentChanges = parcel.readLong(); 5320 } 5321 5322 if (isBitSet(nonDefaultFields, fieldIndex++)) mConnectionId = parcel.readInt(); 5323 5324 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5325 final int childrenSize = parcel.readInt(); 5326 if (childrenSize <= 0) { 5327 mChildNodeIds = null; 5328 } else { 5329 mChildNodeIds = new LongArray(childrenSize); 5330 for (int i = 0; i < childrenSize; i++) { 5331 final long childId = parcel.readLong(); 5332 mChildNodeIds.add(childId); 5333 } 5334 } 5335 } 5336 5337 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5338 mBoundsInParent.top = parcel.readInt(); 5339 mBoundsInParent.bottom = parcel.readInt(); 5340 mBoundsInParent.left = parcel.readInt(); 5341 mBoundsInParent.right = parcel.readInt(); 5342 } 5343 5344 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5345 mBoundsInScreen.top = parcel.readInt(); 5346 mBoundsInScreen.bottom = parcel.readInt(); 5347 mBoundsInScreen.left = parcel.readInt(); 5348 mBoundsInScreen.right = parcel.readInt(); 5349 } 5350 5351 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5352 mBoundsInWindow.top = parcel.readInt(); 5353 mBoundsInWindow.bottom = parcel.readInt(); 5354 mBoundsInWindow.left = parcel.readInt(); 5355 mBoundsInWindow.right = parcel.readInt(); 5356 } 5357 5358 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5359 final long standardActions = parcel.readLong(); 5360 addStandardActions(standardActions); 5361 final int nonStandardActionCount = parcel.readInt(); 5362 for (int i = 0; i < nonStandardActionCount; i++) { 5363 final AccessibilityAction action = 5364 AccessibilityAction.CREATOR.createFromParcel(parcel); 5365 addActionUnchecked(action); 5366 } 5367 } 5368 5369 if (isBitSet(nonDefaultFields, fieldIndex++)) mMaxTextLength = parcel.readInt(); 5370 if (isBitSet(nonDefaultFields, fieldIndex++)) mMovementGranularities = parcel.readInt(); 5371 if (isBitSet(nonDefaultFields, fieldIndex++)) mBooleanProperties = parcel.readInt(); 5372 5373 if (isBitSet(nonDefaultFields, fieldIndex++)) mPackageName = parcel.readCharSequence(); 5374 if (isBitSet(nonDefaultFields, fieldIndex++)) mClassName = parcel.readCharSequence(); 5375 if (isBitSet(nonDefaultFields, fieldIndex++)) mText = parcel.readCharSequence(); 5376 if (isBitSet(nonDefaultFields, fieldIndex++)) mHintText = parcel.readCharSequence(); 5377 if (isBitSet(nonDefaultFields, fieldIndex++)) mError = parcel.readCharSequence(); 5378 if (isBitSet(nonDefaultFields, fieldIndex++)) mStateDescription = parcel.readCharSequence(); 5379 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5380 mContentDescription = parcel.readCharSequence(); 5381 } 5382 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5383 mSupplementalDescription = parcel.readCharSequence(); 5384 } 5385 if (isBitSet(nonDefaultFields, fieldIndex++)) mPaneTitle = parcel.readCharSequence(); 5386 if (isBitSet(nonDefaultFields, fieldIndex++)) mTooltipText = parcel.readCharSequence(); 5387 if (isBitSet(nonDefaultFields, fieldIndex++)) mContainerTitle = parcel.readCharSequence(); 5388 if (isBitSet(nonDefaultFields, fieldIndex++)) mViewIdResourceName = parcel.readString(); 5389 if (isBitSet(nonDefaultFields, fieldIndex++)) mUniqueId = parcel.readString(); 5390 5391 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionStart = parcel.readInt(); 5392 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionEnd = parcel.readInt(); 5393 5394 if (isBitSet(nonDefaultFields, fieldIndex++)) mInputType = parcel.readInt(); 5395 if (isBitSet(nonDefaultFields, fieldIndex++)) mLiveRegion = parcel.readInt(); 5396 if (isBitSet(nonDefaultFields, fieldIndex++)) mDrawingOrderInParent = parcel.readInt(); 5397 5398 mExtraDataKeys = isBitSet(nonDefaultFields, fieldIndex++) 5399 ? parcel.createStringArrayList() 5400 : null; 5401 5402 mExtras = isBitSet(nonDefaultFields, fieldIndex++) 5403 ? parcel.readBundle() 5404 : null; 5405 5406 mRangeInfo = isBitSet(nonDefaultFields, fieldIndex++) 5407 ? new RangeInfo( 5408 parcel.readInt(), 5409 parcel.readFloat(), 5410 parcel.readFloat(), 5411 parcel.readFloat()) 5412 : null; 5413 5414 mCollectionInfo = isBitSet(nonDefaultFields, fieldIndex++) 5415 ? new CollectionInfo( 5416 parcel.readInt(), 5417 parcel.readInt(), 5418 parcel.readInt() == 1, 5419 parcel.readInt(), 5420 parcel.readInt(), 5421 parcel.readInt()) 5422 : null; 5423 5424 mCollectionItemInfo = isBitSet(nonDefaultFields, fieldIndex++) 5425 ? new CollectionItemInfo( 5426 parcel.readString(), 5427 parcel.readInt(), 5428 parcel.readInt(), 5429 parcel.readString(), 5430 parcel.readInt(), 5431 parcel.readInt(), 5432 parcel.readInt() == 1, 5433 parcel.readInt() == 1) 5434 : null; 5435 5436 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5437 mTouchDelegateInfo = TouchDelegateInfo.CREATOR.createFromParcel(parcel); 5438 } 5439 5440 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5441 mExtraRenderingInfo = new ExtraRenderingInfo(null); 5442 mExtraRenderingInfo.mLayoutSize = (Size) parcel.readValue(null); 5443 mExtraRenderingInfo.mTextSizeInPx = parcel.readFloat(); 5444 mExtraRenderingInfo.mTextSizeUnit = parcel.readInt(); 5445 } 5446 5447 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5448 mLeashedChild = parcel.readStrongBinder(); 5449 } 5450 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5451 mLeashedParent = parcel.readStrongBinder(); 5452 } 5453 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5454 mLeashedParentNodeId = parcel.readLong(); 5455 } 5456 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5457 mSelection = Selection.CREATOR.createFromParcel(parcel); 5458 } 5459 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5460 mChecked = parcel.readInt(); 5461 } 5462 if (isBitSet(nonDefaultFields, fieldIndex++)) { 5463 mExpandedState = parcel.readInt(); 5464 } 5465 5466 mSealed = sealed; 5467 } 5468 5469 /** 5470 * Clears the state of this instance. 5471 */ clear()5472 private void clear() { 5473 init(DEFAULT); 5474 } 5475 isDefaultStandardAction(AccessibilityAction action)5476 private static boolean isDefaultStandardAction(AccessibilityAction action) { 5477 return (action.mSerializationFlag != -1L) && TextUtils.isEmpty(action.getLabel()); 5478 } 5479 getActionSingleton(int actionId)5480 private static AccessibilityAction getActionSingleton(int actionId) { 5481 final int actions = AccessibilityAction.sStandardActions.size(); 5482 for (int i = 0; i < actions; i++) { 5483 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i); 5484 if (actionId == currentAction.getId()) { 5485 return currentAction; 5486 } 5487 } 5488 5489 return null; 5490 } 5491 getActionSingletonBySerializationFlag(long flag)5492 private static AccessibilityAction getActionSingletonBySerializationFlag(long flag) { 5493 final int actions = AccessibilityAction.sStandardActions.size(); 5494 for (int i = 0; i < actions; i++) { 5495 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i); 5496 if (flag == currentAction.mSerializationFlag) { 5497 return currentAction; 5498 } 5499 } 5500 5501 return null; 5502 } 5503 addStandardActions(long serializationIdMask)5504 private void addStandardActions(long serializationIdMask) { 5505 long remainingIds = serializationIdMask; 5506 while (remainingIds > 0) { 5507 final long id = 1L << Long.numberOfTrailingZeros(remainingIds); 5508 remainingIds &= ~id; 5509 AccessibilityAction action = getActionSingletonBySerializationFlag(id); 5510 addAction(action); 5511 } 5512 } 5513 5514 /** 5515 * Gets the human readable action symbolic name. 5516 * 5517 * @param action The action. 5518 * @return The symbolic name. 5519 */ getActionSymbolicName(int action)5520 private static String getActionSymbolicName(int action) { 5521 switch (action) { 5522 case ACTION_FOCUS: 5523 return "ACTION_FOCUS"; 5524 case ACTION_CLEAR_FOCUS: 5525 return "ACTION_CLEAR_FOCUS"; 5526 case ACTION_SELECT: 5527 return "ACTION_SELECT"; 5528 case ACTION_CLEAR_SELECTION: 5529 return "ACTION_CLEAR_SELECTION"; 5530 case ACTION_CLICK: 5531 return "ACTION_CLICK"; 5532 case ACTION_LONG_CLICK: 5533 return "ACTION_LONG_CLICK"; 5534 case ACTION_ACCESSIBILITY_FOCUS: 5535 return "ACTION_ACCESSIBILITY_FOCUS"; 5536 case ACTION_CLEAR_ACCESSIBILITY_FOCUS: 5537 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS"; 5538 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY: 5539 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY"; 5540 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: 5541 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY"; 5542 case ACTION_NEXT_HTML_ELEMENT: 5543 return "ACTION_NEXT_HTML_ELEMENT"; 5544 case ACTION_PREVIOUS_HTML_ELEMENT: 5545 return "ACTION_PREVIOUS_HTML_ELEMENT"; 5546 case ACTION_SCROLL_FORWARD: 5547 return "ACTION_SCROLL_FORWARD"; 5548 case ACTION_SCROLL_BACKWARD: 5549 return "ACTION_SCROLL_BACKWARD"; 5550 case ACTION_CUT: 5551 return "ACTION_CUT"; 5552 case ACTION_COPY: 5553 return "ACTION_COPY"; 5554 case ACTION_PASTE: 5555 return "ACTION_PASTE"; 5556 case ACTION_SET_SELECTION: 5557 return "ACTION_SET_SELECTION"; 5558 case ACTION_EXPAND: 5559 return "ACTION_EXPAND"; 5560 case ACTION_COLLAPSE: 5561 return "ACTION_COLLAPSE"; 5562 case ACTION_DISMISS: 5563 return "ACTION_DISMISS"; 5564 case ACTION_SET_TEXT: 5565 return "ACTION_SET_TEXT"; 5566 case R.id.accessibilityActionShowOnScreen: 5567 return "ACTION_SHOW_ON_SCREEN"; 5568 case R.id.accessibilityActionScrollToPosition: 5569 return "ACTION_SCROLL_TO_POSITION"; 5570 case R.id.accessibilityActionScrollUp: 5571 return "ACTION_SCROLL_UP"; 5572 case R.id.accessibilityActionScrollLeft: 5573 return "ACTION_SCROLL_LEFT"; 5574 case R.id.accessibilityActionScrollDown: 5575 return "ACTION_SCROLL_DOWN"; 5576 case R.id.accessibilityActionScrollRight: 5577 return "ACTION_SCROLL_RIGHT"; 5578 case R.id.accessibilityActionPageDown: 5579 return "ACTION_PAGE_DOWN"; 5580 case R.id.accessibilityActionPageUp: 5581 return "ACTION_PAGE_UP"; 5582 case R.id.accessibilityActionPageLeft: 5583 return "ACTION_PAGE_LEFT"; 5584 case R.id.accessibilityActionPageRight: 5585 return "ACTION_PAGE_RIGHT"; 5586 case R.id.accessibilityActionSetProgress: 5587 return "ACTION_SET_PROGRESS"; 5588 case R.id.accessibilityActionContextClick: 5589 return "ACTION_CONTEXT_CLICK"; 5590 case R.id.accessibilityActionShowTooltip: 5591 return "ACTION_SHOW_TOOLTIP"; 5592 case R.id.accessibilityActionHideTooltip: 5593 return "ACTION_HIDE_TOOLTIP"; 5594 case R.id.accessibilityActionPressAndHold: 5595 return "ACTION_PRESS_AND_HOLD"; 5596 case R.id.accessibilityActionImeEnter: 5597 return "ACTION_IME_ENTER"; 5598 case R.id.accessibilityActionDragStart: 5599 return "ACTION_DRAG"; 5600 case R.id.accessibilityActionDragCancel: 5601 return "ACTION_CANCEL_DRAG"; 5602 case R.id.accessibilityActionDragDrop: 5603 return "ACTION_DROP"; 5604 default: { 5605 if (action == R.id.accessibilityActionShowTextSuggestions) { 5606 return "ACTION_SHOW_TEXT_SUGGESTIONS"; 5607 } 5608 if (action == R.id.accessibilityActionScrollInDirection) { 5609 return "ACTION_SCROLL_IN_DIRECTION"; 5610 } 5611 if (action == R.id.accessibilityActionSetExtendedSelection) { 5612 return "ACTION_SET_EXTENDED_SELECTION"; 5613 } 5614 return "ACTION_UNKNOWN"; 5615 } 5616 } 5617 } 5618 5619 /** 5620 * Gets the human readable movement granularity symbolic name. 5621 * 5622 * @param granularity The granularity. 5623 * @return The symbolic name. 5624 */ getMovementGranularitySymbolicName(int granularity)5625 private static String getMovementGranularitySymbolicName(int granularity) { 5626 switch (granularity) { 5627 case MOVEMENT_GRANULARITY_CHARACTER: 5628 return "MOVEMENT_GRANULARITY_CHARACTER"; 5629 case MOVEMENT_GRANULARITY_WORD: 5630 return "MOVEMENT_GRANULARITY_WORD"; 5631 case MOVEMENT_GRANULARITY_LINE: 5632 return "MOVEMENT_GRANULARITY_LINE"; 5633 case MOVEMENT_GRANULARITY_PARAGRAPH: 5634 return "MOVEMENT_GRANULARITY_PARAGRAPH"; 5635 case MOVEMENT_GRANULARITY_PAGE: 5636 return "MOVEMENT_GRANULARITY_PAGE"; 5637 default: 5638 throw new IllegalArgumentException("Unknown movement granularity: " + granularity); 5639 } 5640 } 5641 canPerformRequestOverConnection(int connectionId, int windowId, long accessibilityNodeId)5642 private static boolean canPerformRequestOverConnection(int connectionId, 5643 int windowId, long accessibilityNodeId) { 5644 final boolean hasWindowId = windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; 5645 return ((usingDirectConnection(connectionId) || hasWindowId) 5646 && (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID) 5647 && (connectionId != UNDEFINED_CONNECTION_ID)); 5648 } 5649 5650 @Override equals(@ullable Object object)5651 public boolean equals(@Nullable Object object) { 5652 if (this == object) { 5653 return true; 5654 } 5655 if (object == null) { 5656 return false; 5657 } 5658 if (getClass() != object.getClass()) { 5659 return false; 5660 } 5661 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object; 5662 if (mSourceNodeId != other.mSourceNodeId) { 5663 return false; 5664 } 5665 if (mWindowId != other.mWindowId) { 5666 return false; 5667 } 5668 return true; 5669 } 5670 5671 @Override hashCode()5672 public int hashCode() { 5673 final int prime = 31; 5674 int result = 1; 5675 result = prime * result + getAccessibilityViewId(mSourceNodeId); 5676 result = prime * result + getVirtualDescendantId(mSourceNodeId); 5677 result = prime * result + mWindowId; 5678 return result; 5679 } 5680 5681 @Override toString()5682 public String toString() { 5683 StringBuilder builder = new StringBuilder(); 5684 builder.append(super.toString()); 5685 5686 if (DEBUG) { 5687 builder.append("; sourceNodeId: 0x").append(Long.toHexString(mSourceNodeId)); 5688 builder.append("; windowId: 0x").append(Long.toHexString(mWindowId)); 5689 builder.append("; accessibilityViewId: 0x") 5690 .append(Long.toHexString(getAccessibilityViewId(mSourceNodeId))); 5691 builder.append("; virtualDescendantId: 0x") 5692 .append(Long.toHexString(getVirtualDescendantId(mSourceNodeId))); 5693 builder.append("; mParentNodeId: 0x").append(Long.toHexString(mParentNodeId)); 5694 builder.append("; traversalBefore: 0x").append(Long.toHexString(mTraversalBefore)); 5695 builder.append("; traversalAfter: 0x").append(Long.toHexString(mTraversalAfter)); 5696 builder.append("; minDurationBetweenContentChanges: ") 5697 .append(mMinDurationBetweenContentChanges); 5698 5699 int granularities = mMovementGranularities; 5700 builder.append("; MovementGranularities: ["); 5701 while (granularities != 0) { 5702 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities); 5703 granularities &= ~granularity; 5704 builder.append(getMovementGranularitySymbolicName(granularity)); 5705 if (granularities != 0) { 5706 builder.append(", "); 5707 } 5708 } 5709 builder.append("]"); 5710 5711 builder.append("; childAccessibilityIds: ["); 5712 final LongArray childIds = mChildNodeIds; 5713 if (childIds != null) { 5714 for (int i = 0, count = childIds.size(); i < count; i++) { 5715 builder.append("0x").append(Long.toHexString(childIds.get(i))); 5716 if (i < count - 1) { 5717 builder.append(", "); 5718 } 5719 } 5720 } 5721 builder.append("]"); 5722 } 5723 5724 builder.append("; boundsInParent: ").append(mBoundsInParent); 5725 builder.append("; boundsInScreen: ").append(mBoundsInScreen); 5726 builder.append("; boundsInWindow: ").append(mBoundsInScreen); 5727 5728 builder.append("; packageName: ").append(mPackageName); 5729 builder.append("; className: ").append(mClassName); 5730 builder.append("; text: ").append(mText); 5731 builder.append("; error: ").append(mError); 5732 builder.append("; maxTextLength: ").append(mMaxTextLength); 5733 builder.append("; stateDescription: ").append(mStateDescription); 5734 builder.append("; contentDescription: ").append(mContentDescription); 5735 builder.append("; tooltipText: ").append(mTooltipText); 5736 builder.append("; containerTitle: ").append(mContainerTitle); 5737 builder.append("; viewIdResName: ").append(mViewIdResourceName); 5738 builder.append("; uniqueId: ").append(mUniqueId); 5739 builder.append("; checkable: ").append(isCheckable()); 5740 builder.append("; checked: ").append(isChecked()); 5741 builder.append("; focusable: ").append(isFocusable()); 5742 builder.append("; focused: ").append(isFocused()); 5743 builder.append("; selected: ").append(isSelected()); 5744 builder.append("; clickable: ").append(isClickable()); 5745 builder.append("; longClickable: ").append(isLongClickable()); 5746 builder.append("; contextClickable: ").append(isContextClickable()); 5747 builder.append("; enabled: ").append(isEnabled()); 5748 builder.append("; password: ").append(isPassword()); 5749 builder.append("; scrollable: ").append(isScrollable()); 5750 builder.append("; granularScrollingSupported: ").append(isGranularScrollingSupported()); 5751 builder.append("; importantForAccessibility: ").append(isImportantForAccessibility()); 5752 builder.append("; visible: ").append(isVisibleToUser()); 5753 builder.append("; actions: ").append(mActions); 5754 builder.append("; isTextSelectable: ").append(isTextSelectable()); 5755 5756 return builder.toString(); 5757 } 5758 getNodeForAccessibilityId(int connectionId, int windowId, long accessibilityId)5759 private static AccessibilityNodeInfo getNodeForAccessibilityId(int connectionId, 5760 int windowId, long accessibilityId) { 5761 return getNodeForAccessibilityId(connectionId, windowId, accessibilityId, 5762 FLAG_PREFETCH_ANCESTORS 5763 | FLAG_PREFETCH_DESCENDANTS_HYBRID | FLAG_PREFETCH_SIBLINGS); 5764 } 5765 getNodeForAccessibilityId(int connectionId, int windowId, long accessibilityId, @PrefetchingStrategy int prefetchingStrategy)5766 private static AccessibilityNodeInfo getNodeForAccessibilityId(int connectionId, 5767 int windowId, long accessibilityId, @PrefetchingStrategy int prefetchingStrategy) { 5768 if (!canPerformRequestOverConnection(connectionId, windowId, accessibilityId)) { 5769 return null; 5770 } 5771 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 5772 return client.findAccessibilityNodeInfoByAccessibilityId(connectionId, 5773 windowId, accessibilityId, false, prefetchingStrategy, null); 5774 } 5775 getNodeForAccessibilityId(int connectionId, IBinder leashToken, long accessibilityId)5776 private static AccessibilityNodeInfo getNodeForAccessibilityId(int connectionId, 5777 IBinder leashToken, long accessibilityId) { 5778 return getNodeForAccessibilityId(connectionId, leashToken, accessibilityId, 5779 FLAG_PREFETCH_ANCESTORS 5780 | FLAG_PREFETCH_DESCENDANTS_HYBRID | FLAG_PREFETCH_SIBLINGS); 5781 } 5782 getNodeForAccessibilityId(int connectionId, IBinder leashToken, long accessibilityId, @PrefetchingStrategy int prefetchingStrategy)5783 private static AccessibilityNodeInfo getNodeForAccessibilityId(int connectionId, 5784 IBinder leashToken, long accessibilityId, 5785 @PrefetchingStrategy int prefetchingStrategy) { 5786 if (!((leashToken != null) 5787 && (getAccessibilityViewId(accessibilityId) != UNDEFINED_ITEM_ID) 5788 && (connectionId != UNDEFINED_CONNECTION_ID))) { 5789 return null; 5790 } 5791 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 5792 return client.findAccessibilityNodeInfoByAccessibilityId(connectionId, 5793 leashToken, accessibilityId, false, prefetchingStrategy, null); 5794 } 5795 5796 /** @hide */ idToString(long accessibilityId)5797 public static String idToString(long accessibilityId) { 5798 int accessibilityViewId = getAccessibilityViewId(accessibilityId); 5799 int virtualDescendantId = getVirtualDescendantId(accessibilityId); 5800 return virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID 5801 ? idItemToString(accessibilityViewId) 5802 : idItemToString(accessibilityViewId) + ":" + idItemToString(virtualDescendantId); 5803 } 5804 idItemToString(int item)5805 private static String idItemToString(int item) { 5806 switch (item) { 5807 case ROOT_ITEM_ID: return "ROOT"; 5808 case UNDEFINED_ITEM_ID: return "UNDEFINED"; 5809 case AccessibilityNodeProvider.HOST_VIEW_ID: return "HOST"; 5810 default: return "" + item; 5811 } 5812 } 5813 5814 /** 5815 * A class which defines either the start or end of a selection that can span across multiple 5816 * AccessibilityNodeInfo objects. 5817 * 5818 * @see AccessibilityNodeInfo.Selection 5819 */ 5820 @FlaggedApi(Flags.FLAG_A11Y_SELECTION_API) 5821 public static final class SelectionPosition implements Parcelable { 5822 5823 private final int mOffset; 5824 private final long mSourceNodeId; 5825 private int mConnectionId; 5826 private int mWindowId; 5827 5828 /** 5829 * Instantiates a new SelectionPosition. 5830 * 5831 * @param node The {@link AccessibilityNodeInfo} for the node of this selection. 5832 * @param offset The offset for a {@link SelectionPosition} within {@code view}'s text 5833 * content, which should be a value between 0 and the length of {@code view}'s text. 5834 */ SelectionPosition(@onNull AccessibilityNodeInfo node, int offset)5835 public SelectionPosition(@NonNull AccessibilityNodeInfo node, int offset) { 5836 this(node.mSourceNodeId, offset); 5837 } 5838 5839 /** 5840 * Instantiates a new SelectionPosition. 5841 * 5842 * @param view The {@link View} containing the text associated with this selection 5843 * position. 5844 * @param offset The offset for a selection position within {@code view}'s text content, 5845 * which should be a value between 0 and the length of {@code view}'s text. 5846 */ SelectionPosition(@onNull View view, int offset)5847 public SelectionPosition(@NonNull View view, int offset) { 5848 this( 5849 makeNodeId( 5850 view.getAccessibilityViewId(), AccessibilityNodeProvider.HOST_VIEW_ID), 5851 offset); 5852 } 5853 5854 /** 5855 * Instantiates a new {@link SelectionPosition}. 5856 * 5857 * @param view The view whose virtual descendant is associated with the selection position. 5858 * @param virtualDescendantId The ID of the virtual descendant within {@code view}'s virtual 5859 * subtree that contains the selection position. 5860 * @param offset The offset for a selection position within the virtual descendant's text 5861 * content, which should be a value between 0 and the length of the descendant's text. 5862 * @see AccessibilityNodeProvider 5863 */ SelectionPosition(@onNull View view, int virtualDescendantId, int offset)5864 public SelectionPosition(@NonNull View view, int virtualDescendantId, int offset) { 5865 this(makeNodeId(view.getAccessibilityViewId(), virtualDescendantId), offset); 5866 } 5867 SelectionPosition(long sourceNodeId, int offset)5868 private SelectionPosition(long sourceNodeId, int offset) { 5869 mOffset = offset; 5870 mSourceNodeId = sourceNodeId; 5871 } 5872 SelectionPosition(Parcel in)5873 private SelectionPosition(Parcel in) { 5874 mOffset = in.readInt(); 5875 mSourceNodeId = in.readLong(); 5876 } 5877 setWindowId(int windowId)5878 private void setWindowId(int windowId) { 5879 mWindowId = windowId; 5880 } 5881 setConnectionId(int connectionId)5882 private void setConnectionId(int connectionId) { 5883 mConnectionId = connectionId; 5884 } 5885 5886 /** 5887 * Gets the node for {@code this} {@link SelectionPosition} 5888 * <br> 5889 * <strong>Note:</strong> This api can only be called from {@link AccessibilityService}. 5890 * 5891 * @return The node associated with {@code this} {@link SelectionPosition} 5892 */ getNode()5893 public @Nullable AccessibilityNodeInfo getNode() { 5894 return getNodeForAccessibilityId(mConnectionId, mWindowId, mSourceNodeId); 5895 } 5896 5897 /** 5898 * Gets the offset for {@code this} {@link SelectionPosition}. 5899 * 5900 * @return A value from 0 to the length of {@link #getNode()}'s content representing the 5901 * offset of the {@link SelectionPosition} 5902 */ getOffset()5903 public int getOffset() { 5904 return mOffset; 5905 } 5906 usesNode(@onNull AccessibilityNodeInfo node)5907 private boolean usesNode(@NonNull AccessibilityNodeInfo node) { 5908 return this.mSourceNodeId == node.mSourceNodeId 5909 && this.mConnectionId == node.mConnectionId 5910 && this.mWindowId == node.mWindowId; 5911 } 5912 5913 @Override equals(Object other)5914 public boolean equals(Object other) { 5915 if (other == null) { 5916 return false; 5917 } 5918 5919 if (other == this) { 5920 return true; 5921 } 5922 5923 if (getClass() != other.getClass()) { 5924 return false; 5925 } 5926 5927 SelectionPosition rhs = (SelectionPosition) other; 5928 if (getOffset() != rhs.getOffset()) { 5929 return false; 5930 } 5931 5932 return mSourceNodeId == rhs.mSourceNodeId; 5933 } 5934 5935 @Override hashCode()5936 public int hashCode() { 5937 final long prime = 877; 5938 long result = 1; 5939 5940 if (mOffset != 0) { 5941 result *= mOffset; 5942 } 5943 5944 if (mSourceNodeId != UNDEFINED_NODE_ID) { 5945 result *= mSourceNodeId; 5946 } 5947 5948 return Long.hashCode(result * prime); 5949 } 5950 5951 /** {@inheritDoc} */ 5952 @Override writeToParcel(@onNull Parcel dest, int flags)5953 public void writeToParcel(@NonNull Parcel dest, int flags) { 5954 dest.writeInt(mOffset); 5955 dest.writeLong(mSourceNodeId); 5956 } 5957 5958 /** {@inheritDoc} */ 5959 @Override describeContents()5960 public int describeContents() { 5961 return 0; 5962 } 5963 5964 /** 5965 * @see android.os.Parcelable.Creator 5966 */ 5967 @NonNull 5968 public static final Creator<SelectionPosition> CREATOR = 5969 new Creator<SelectionPosition>() { 5970 @Override 5971 public SelectionPosition createFromParcel(Parcel in) { 5972 return new SelectionPosition(in); 5973 } 5974 5975 @Override 5976 public SelectionPosition[] newArray(int size) { 5977 return new SelectionPosition[size]; 5978 } 5979 }; 5980 } 5981 5982 /** 5983 * Represents a selection of content that may extend across more than one {@link 5984 * AccessibilityNodeInfo} instance. 5985 * 5986 * @see AccessibilityNodeInfo.SelectionPosition 5987 */ 5988 @FlaggedApi(Flags.FLAG_A11Y_SELECTION_API) 5989 public static final class Selection implements Parcelable { 5990 5991 private final SelectionPosition mStart; 5992 private final SelectionPosition mEnd; 5993 5994 /** 5995 * Instantiates a new Selection. 5996 * 5997 * @param start The start of the extended selection. 5998 * @param end The end of the extended selection. 5999 */ Selection(@onNull SelectionPosition start, @NonNull SelectionPosition end)6000 public Selection(@NonNull SelectionPosition start, @NonNull SelectionPosition end) { 6001 this.mStart = start; 6002 this.mEnd = end; 6003 } 6004 Selection(Parcel in)6005 private Selection(Parcel in) { 6006 mStart = SelectionPosition.CREATOR.createFromParcel(in); 6007 mEnd = SelectionPosition.CREATOR.createFromParcel(in); 6008 } 6009 6010 /** 6011 * @return The start of the extended selection. 6012 */ getStart()6013 public @NonNull SelectionPosition getStart() { 6014 return mStart; 6015 } 6016 6017 /** 6018 * @return The end of the extended selection. 6019 */ getEnd()6020 public @NonNull SelectionPosition getEnd() { 6021 return mEnd; 6022 } 6023 6024 @Override equals(Object obj)6025 public boolean equals(Object obj) { 6026 if (obj == null) { 6027 return false; 6028 } 6029 6030 if (obj == this) { 6031 return true; 6032 } 6033 6034 if (getClass() != obj.getClass()) { 6035 return false; 6036 } 6037 6038 Selection rhs = (Selection) obj; 6039 return getStart().equals(rhs.getStart()) && getEnd().equals(rhs.getEnd()); 6040 } 6041 6042 @Override hashCode()6043 public int hashCode() { 6044 final int prime = 17; 6045 return prime * getStart().hashCode() * getEnd().hashCode(); 6046 } 6047 6048 /** {@inheritDoc} */ 6049 @Override writeToParcel(@onNull Parcel dest, int flags)6050 public void writeToParcel(@NonNull Parcel dest, int flags) { 6051 mStart.writeToParcel(dest, flags); 6052 mEnd.writeToParcel(dest, flags); 6053 } 6054 6055 /** {@inheritDoc} */ 6056 @Override describeContents()6057 public int describeContents() { 6058 return 0; 6059 } 6060 6061 /** 6062 * @see android.os.Parcelable.Creator 6063 */ 6064 @NonNull 6065 public static final Creator<Selection> CREATOR = 6066 new Creator<Selection>() { 6067 @Override 6068 public Selection createFromParcel(Parcel in) { 6069 return new Selection(in); 6070 } 6071 6072 @Override 6073 public Selection[] newArray(int size) { 6074 return new Selection[size]; 6075 } 6076 }; 6077 } 6078 6079 /** 6080 * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}. 6081 * Each action has a unique id that is mandatory and optional data. 6082 * <p> 6083 * There are three categories of actions: 6084 * <ul> 6085 * <li><strong>Standard actions</strong> - These are actions that are reported and 6086 * handled by the standard UI widgets in the platform. For each standard action 6087 * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}. 6088 * These actions will have {@code null} labels. 6089 * </li> 6090 * <li><strong>Custom actions action</strong> - These are actions that are reported 6091 * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For 6092 * example, an application may define a custom action for clearing the user history. 6093 * </li> 6094 * <li><strong>Overridden standard actions</strong> - These are actions that override 6095 * standard actions to customize them. For example, an app may add a label to the 6096 * standard {@link #ACTION_CLICK} action to indicate to the user that this action clears 6097 * browsing history. 6098 * </ul> 6099 * </p> 6100 * <p> 6101 * Actions are typically added to an {@link AccessibilityNodeInfo} by using 6102 * {@link AccessibilityNodeInfo#addAction(AccessibilityAction)} within 6103 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed 6104 * within {@link View#performAccessibilityAction(int, Bundle)}. 6105 * </p> 6106 * <p> 6107 * <aside class="note"> 6108 * <b>Note:</b> Views which support these actions should invoke 6109 * {@link View#setImportantForAccessibility(int)} with 6110 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService} 6111 * can discover the set of supported actions. </aside> 6112 * </p> 6113 * <p> 6114 * <aside class="note"> 6115 * <b>Note:</b> Use {@link androidx.core.view.ViewCompat#addAccessibilityAction(View, 6116 * CharSequence, AccessibilityViewCommand)} to register an action directly on the view. </aside> 6117 * </p> 6118 */ 6119 public static final class AccessibilityAction implements Parcelable { 6120 6121 /** @hide */ 6122 public static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>(); 6123 6124 /** 6125 * Action that gives input focus to the node. 6126 * <p>The focus request send an event of {@link AccessibilityEvent#TYPE_VIEW_FOCUSED} 6127 * if successful. In the View system, this is handled by {@link View#requestFocus}. 6128 * 6129 * <p>The node that is focused should return {@code true} for 6130 * {@link AccessibilityNodeInfo#isFocused()}. 6131 * 6132 * See {@link #ACTION_ACCESSIBILITY_FOCUS} for the difference between system and 6133 * accessibility focus. 6134 */ 6135 public static final AccessibilityAction ACTION_FOCUS = 6136 new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS); 6137 6138 /** 6139 * Action that clears input focus of the node. 6140 * <p>The node that is cleared should return {@code false} for 6141 * {@link AccessibilityNodeInfo#isFocused)}. 6142 */ 6143 public static final AccessibilityAction ACTION_CLEAR_FOCUS = 6144 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 6145 6146 /** 6147 * Action that selects the node. 6148 * The view the implements this should send a 6149 * {@link AccessibilityEvent#TYPE_VIEW_SELECTED} event. 6150 * @see AccessibilityAction#ACTION_CLEAR_SELECTION 6151 */ 6152 public static final AccessibilityAction ACTION_SELECT = 6153 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SELECT); 6154 6155 /** 6156 * Action that deselects the node. 6157 * @see AccessibilityAction#ACTION_SELECT 6158 */ 6159 public static final AccessibilityAction ACTION_CLEAR_SELECTION = 6160 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 6161 6162 /** 6163 * Action that clicks on the node info. 6164 * 6165 * <p>The UI element that implements this should send a 6166 * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} event. In the View system, 6167 * the default handling of this action when performed by a service is to call 6168 * {@link View#performClick()}, and setting a 6169 * {@link View#setOnClickListener(View.OnClickListener)} automatically adds this action. 6170 * 6171 * <p>{@link #isClickable()} should return true if this action is available. 6172 */ 6173 public static final AccessibilityAction ACTION_CLICK = 6174 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK); 6175 6176 /** 6177 * Action that long clicks on the node. 6178 * 6179 * <p>The UI element that implements this should send a 6180 * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED} event. In the View system, 6181 * the default handling of this action when performed by a service is to call 6182 * {@link View#performLongClick()}, and setting a 6183 * {@link View#setOnLongClickListener(View.OnLongClickListener)} automatically adds this 6184 * action. 6185 * 6186 * <p>{@link #isLongClickable()} should return true if this action is available. 6187 */ 6188 public static final AccessibilityAction ACTION_LONG_CLICK = 6189 new AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); 6190 6191 /** 6192 * Action that gives accessibility focus to the node. 6193 * 6194 * <p>The UI element that implements this should send a 6195 * {@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED} event 6196 * if successful. The node that is focused should return {@code true} for 6197 * {@link AccessibilityNodeInfo#isAccessibilityFocused()}. 6198 * 6199 * <p>This is intended to be used by screen readers to assist with user navigation. Apps 6200 * changing focus can confuse screen readers, so the resulting behavior can vary by device 6201 * and screen reader version. 6202 * <p>This is distinct from {@link #ACTION_FOCUS}, which refers to system focus. System 6203 * focus is typically used to convey targets for keyboard navigation. 6204 */ 6205 public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS = 6206 new AccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 6207 6208 /** 6209 * Action that clears accessibility focus of the node. 6210 * <p>The UI element that implements this should send a 6211 * {@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED} event if successful. The 6212 * node that is cleared should return {@code false} for 6213 * {@link AccessibilityNodeInfo#isAccessibilityFocused()}. 6214 */ 6215 public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS = 6216 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 6217 6218 /** 6219 * Action that requests to go to the next entity in this node's text 6220 * at a given movement granularity. For example, move to the next character, 6221 * word, etc. 6222 * <p> 6223 * <strong>Arguments:</strong> 6224 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 6225 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}, 6226 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 6227 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 6228 * <strong>Example:</strong> Move to the previous character and do not extend selection. 6229 * <code><pre><p> 6230 * Bundle arguments = new Bundle(); 6231 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 6232 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); 6233 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, 6234 * false); 6235 * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(), 6236 * arguments); 6237 * </code></pre></p> 6238 * </p> 6239 * 6240 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 6241 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 6242 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 6243 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 6244 * 6245 * @see AccessibilityNodeInfo#setMovementGranularities(int) 6246 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 6247 * @see AccessibilityNodeInfo#getMovementGranularities() 6248 * AccessibilityNodeInfo.getMovementGranularities() 6249 * 6250 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER 6251 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 6252 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD 6253 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 6254 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE 6255 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE 6256 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH 6257 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH 6258 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE 6259 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE 6260 */ 6261 public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 6262 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); 6263 6264 /** 6265 * Action that requests to go to the previous entity in this node's text 6266 * at a given movement granularity. For example, move to the next character, 6267 * word, etc. 6268 * <p> 6269 * <strong>Arguments:</strong> 6270 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 6271 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}, 6272 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 6273 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 6274 * <strong>Example:</strong> Move to the next character and do not extend selection. 6275 * <code><pre><p> 6276 * Bundle arguments = new Bundle(); 6277 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 6278 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); 6279 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, 6280 * false); 6281 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(), 6282 * arguments); 6283 * </code></pre></p> 6284 * </p> 6285 * 6286 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 6287 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 6288 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 6289 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 6290 * 6291 * @see AccessibilityNodeInfo#setMovementGranularities(int) 6292 * AccessibilityNodeInfo.setMovementGranularities(int) 6293 * @see AccessibilityNodeInfo#getMovementGranularities() 6294 * AccessibilityNodeInfo.getMovementGranularities() 6295 * 6296 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER 6297 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 6298 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD 6299 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 6300 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE 6301 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE 6302 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH 6303 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH 6304 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE 6305 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE 6306 */ 6307 public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 6308 new AccessibilityAction( 6309 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); 6310 6311 /** 6312 * Action to move to the next HTML element of a given type. For example, move 6313 * to the BUTTON, INPUT, TABLE, etc. 6314 * <p> 6315 * <strong>Arguments:</strong> 6316 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING 6317 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 6318 * <strong>Example:</strong> 6319 * <code><pre><p> 6320 * Bundle arguments = new Bundle(); 6321 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 6322 * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments); 6323 * </code></pre></p> 6324 * </p> 6325 */ 6326 public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT = 6327 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT); 6328 6329 /** 6330 * Action to move to the previous HTML element of a given type. For example, move 6331 * to the BUTTON, INPUT, TABLE, etc. 6332 * <p> 6333 * <strong>Arguments:</strong> 6334 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING 6335 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 6336 * <strong>Example:</strong> 6337 * <code><pre><p> 6338 * Bundle arguments = new Bundle(); 6339 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 6340 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments); 6341 * </code></pre></p> 6342 * </p> 6343 */ 6344 public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT = 6345 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT); 6346 6347 // TODO(316638728): restore ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT in javadoc 6348 /** 6349 * Action to scroll the node content forward. 6350 * 6351 * <p>The UI element that implements this should send a 6352 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. Depending on the orientation, 6353 * this element should also add the relevant directional scroll actions of 6354 * {@link #ACTION_SCROLL_LEFT}, {@link #ACTION_SCROLL_RIGHT}, 6355 * {@link #ACTION_SCROLL_UP}, and {@link #ACTION_SCROLL_DOWN}. If the scrolling brings 6356 * the next or previous element into view as the center element, such as in a ViewPager2, 6357 * use {@link #ACTION_PAGE_DOWN} and the other page actions instead of the directional 6358 * actions. 6359 * <p>Example: a scrolling UI of vertical orientation with a forward 6360 * scroll action should also add the scroll down action: 6361 * <pre class="prettyprint"><code> 6362 * onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 6363 * super.onInitializeAccessibilityNodeInfo(info); 6364 * if (canScrollForward) { 6365 * info.addAction(ACTION_SCROLL_FORWARD); 6366 * info.addAction(ACTION_SCROLL_DOWN); 6367 * } 6368 * } 6369 * performAccessibilityAction(int action, Bundle bundle) { 6370 * if (action == ACTION_SCROLL_FORWARD || action == ACTION_SCROLL_DOWN) { 6371 * scrollForward(); 6372 * } 6373 * } 6374 * scrollForward() { 6375 * ... 6376 * if (mAccessibilityManager.isEnabled()) { 6377 * event = new AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 6378 * event.setScrollDeltaX(dx); 6379 * event.setScrollDeltaY(dy); 6380 * event.setMaxScrollX(maxDx); 6381 * event.setMaxScrollY(maxDY); 6382 * sendAccessibilityEventUnchecked(event); 6383 * } 6384 * } 6385 * </code> 6386 * </pre></p> 6387 */ 6388 public static final AccessibilityAction ACTION_SCROLL_FORWARD = 6389 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); 6390 6391 // TODO(316638728): restore ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT in javadoc 6392 /** 6393 * Action to scroll the node content backward. 6394 * 6395 * <p>The UI element that implements this should send a 6396 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. Depending on the orientation, 6397 * this element should also add the relevant directional scroll actions of 6398 * {@link #ACTION_SCROLL_LEFT}, {@link #ACTION_SCROLL_RIGHT}, 6399 * {@link #ACTION_SCROLL_UP}, and {@link #ACTION_SCROLL_DOWN}. If the scrolling brings 6400 * the next or previous element into view as the center element, such as in a ViewPager2, 6401 * use {@link #ACTION_PAGE_DOWN} and the other page actions instead of the directional 6402 * actions. 6403 * <p> Example: a scrolling UI of horizontal orientation with a backward 6404 * scroll action should also add the scroll left/right action (LTR/RTL): 6405 * <pre class="prettyprint"><code> 6406 * onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 6407 * super.onInitializeAccessibilityNodeInfo(info); 6408 * if (canScrollBackward) { 6409 * info.addAction(ACTION_SCROLL_FORWARD); 6410 * if (leftToRight) { 6411 * info.addAction(ACTION_SCROLL_LEFT); 6412 * } else { 6413 * info.addAction(ACTION_SCROLL_RIGHT); 6414 * } 6415 * } 6416 * } 6417 * performAccessibilityAction(int action, Bundle bundle) { 6418 * if (action == ACTION_SCROLL_BACKWARD) { 6419 * scrollBackward(); 6420 * } else if (action == ACTION_SCROLL_LEFT) { 6421 * if (!isRTL()){ 6422 * scrollBackward(); 6423 * } 6424 * } else if (action == ACTION_SCROLL_RIGHT) { 6425 * if (isRTL()){ 6426 * scrollBackward(); 6427 * } 6428 * } 6429 * } 6430 * scrollBackward() { 6431 * ... 6432 * if (mAccessibilityManager.isEnabled()) { 6433 * event = new AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 6434 * event.setScrollDeltaX(dx); 6435 * event.setScrollDeltaY(dy); 6436 * event.setMaxScrollX(maxDx); 6437 * event.setMaxScrollY(maxDY); 6438 * sendAccessibilityEventUnchecked(event); 6439 * } 6440 * } 6441 * </code> 6442 * </pre></p> 6443 */ 6444 public static final AccessibilityAction ACTION_SCROLL_BACKWARD = 6445 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); 6446 6447 /** 6448 * Action to copy the current selection to the clipboard. 6449 */ 6450 public static final AccessibilityAction ACTION_COPY = 6451 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COPY); 6452 6453 /** 6454 * Action to paste the current clipboard content. 6455 */ 6456 public static final AccessibilityAction ACTION_PASTE = 6457 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PASTE); 6458 6459 /** 6460 * Action to cut the current selection and place it to the clipboard. 6461 */ 6462 public static final AccessibilityAction ACTION_CUT = 6463 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CUT); 6464 6465 /** 6466 * Action to set the selection. Performing this action with no arguments 6467 * clears the selection. 6468 * <p> 6469 * <strong>Arguments:</strong> 6470 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT 6471 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT}, 6472 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT 6473 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br> 6474 * <strong>Example:</strong> 6475 * <code><pre><p> 6476 * Bundle arguments = new Bundle(); 6477 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1); 6478 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2); 6479 * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments); 6480 * </code></pre></p> 6481 * </p> 6482 * <p> If this is a text selection, the UI element that implements this should send a 6483 * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} event if its selection is 6484 * updated. This element should also return {@code true} for 6485 * {@link AccessibilityNodeInfo#isTextSelectable()}. 6486 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT 6487 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT 6488 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT 6489 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT 6490 */ 6491 public static final AccessibilityAction ACTION_SET_SELECTION = 6492 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); 6493 6494 /** 6495 * Action to expand an expandable node. 6496 */ 6497 public static final AccessibilityAction ACTION_EXPAND = 6498 new AccessibilityAction(AccessibilityNodeInfo.ACTION_EXPAND); 6499 6500 /** 6501 * Action to collapse an expandable node. 6502 */ 6503 public static final AccessibilityAction ACTION_COLLAPSE = 6504 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE); 6505 6506 /** 6507 * Action to dismiss a dismissable node. 6508 */ 6509 public static final AccessibilityAction ACTION_DISMISS = 6510 new AccessibilityAction(AccessibilityNodeInfo.ACTION_DISMISS); 6511 6512 /** 6513 * Action that sets the text of the node. Performing the action without argument, 6514 * using <code> null</code> or empty {@link CharSequence} will clear the text. This 6515 * action will also put the cursor at the end of text. 6516 * <p> 6517 * <strong>Arguments:</strong> 6518 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE 6519 * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br> 6520 * <strong>Example:</strong> 6521 * <code><pre><p> 6522 * Bundle arguments = new Bundle(); 6523 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, 6524 * "android"); 6525 * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments); 6526 * </code></pre></p> 6527 * <p> The UI element that implements this should send a 6528 * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} event if its text is updated. 6529 * This element should also return {@code true} for 6530 * {@link AccessibilityNodeInfo#isEditable()}. 6531 */ 6532 public static final AccessibilityAction ACTION_SET_TEXT = 6533 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_TEXT); 6534 6535 /** 6536 * Action that requests the node make its bounding rectangle visible 6537 * on the screen, scrolling if necessary just enough. 6538 * <p>The UI element that implements this should send a 6539 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6540 * 6541 * @see View#requestRectangleOnScreen(Rect) 6542 */ 6543 public static final AccessibilityAction ACTION_SHOW_ON_SCREEN = 6544 new AccessibilityAction(R.id.accessibilityActionShowOnScreen); 6545 6546 /** 6547 * Action that scrolls the node to make the specified collection 6548 * position visible on screen. 6549 * <p> 6550 * <strong>Arguments:</strong> 6551 * <ul> 6552 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li> 6553 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li> 6554 * <ul> 6555 * <p>The UI element that implements this should send a 6556 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6557 * 6558 * @see AccessibilityNodeInfo#getCollectionInfo() 6559 */ 6560 public static final AccessibilityAction ACTION_SCROLL_TO_POSITION = 6561 new AccessibilityAction(R.id.accessibilityActionScrollToPosition); 6562 6563 /** 6564 * Action that brings fully on screen the next node in the specified direction. 6565 * 6566 * <p> 6567 * This should include wrapping around to the next/previous row, column, etc. in a 6568 * collection if one is available. If there is no node in that direction, the action 6569 * should fail and return false. 6570 * </p> 6571 * <p> 6572 * This action should be used instead of 6573 * {@link AccessibilityAction#ACTION_SCROLL_TO_POSITION} when a widget does not have 6574 * clear row and column semantics or if a directional search is needed to find a node in 6575 * a complex ViewGroup where individual nodes may span multiple rows or columns. The 6576 * implementing widget must send a 6577 * {@link AccessibilityEvent#TYPE_VIEW_TARGETED_BY_SCROLL} accessibility event with the 6578 * scroll target as the source. An accessibility service can listen for this event, 6579 * inspect its source, and use the result when determining where to place accessibility 6580 * focus. 6581 * <p> 6582 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_DIRECTION_INT}. This is a 6583 * required argument.<br> 6584 * </p> 6585 */ 6586 @NonNull public static final AccessibilityAction ACTION_SCROLL_IN_DIRECTION = 6587 new AccessibilityAction(R.id.accessibilityActionScrollInDirection); 6588 6589 // TODO(316638728): restore ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT in javadoc 6590 /** 6591 * Action to scroll the node content up. 6592 * 6593 * <p>The UI element that implements this should send a 6594 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6595 */ 6596 public static final AccessibilityAction ACTION_SCROLL_UP = 6597 new AccessibilityAction(R.id.accessibilityActionScrollUp); 6598 6599 // TODO(316638728): restore ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT in javadoc 6600 /** 6601 * Action to scroll the node content left. 6602 * 6603 * <p>The UI element that implements this should send a 6604 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6605 */ 6606 public static final AccessibilityAction ACTION_SCROLL_LEFT = 6607 new AccessibilityAction(R.id.accessibilityActionScrollLeft); 6608 6609 // TODO(316638728): restore ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT in javadoc 6610 /** 6611 * Action to scroll the node content down. 6612 * 6613 * <p>The UI element that implements this should send a 6614 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6615 */ 6616 public static final AccessibilityAction ACTION_SCROLL_DOWN = 6617 new AccessibilityAction(R.id.accessibilityActionScrollDown); 6618 6619 // TODO(316638728): restore ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT in javadoc 6620 /** 6621 * Action to scroll the node content right. 6622 * 6623 * <p>The UI element that implements this should send a 6624 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6625 */ 6626 public static final AccessibilityAction ACTION_SCROLL_RIGHT = 6627 new AccessibilityAction(R.id.accessibilityActionScrollRight); 6628 6629 /** 6630 * Action to move to the page above. 6631 * <p>The UI element that implements this should send a 6632 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6633 */ 6634 public static final AccessibilityAction ACTION_PAGE_UP = 6635 new AccessibilityAction(R.id.accessibilityActionPageUp); 6636 6637 /** 6638 * Action to move to the page below. 6639 * <p>The UI element that implements this should send a 6640 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6641 */ 6642 public static final AccessibilityAction ACTION_PAGE_DOWN = 6643 new AccessibilityAction(R.id.accessibilityActionPageDown); 6644 6645 /** 6646 * Action to move to the page left. 6647 * <p>The UI element that implements this should send a 6648 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6649 */ 6650 public static final AccessibilityAction ACTION_PAGE_LEFT = 6651 new AccessibilityAction(R.id.accessibilityActionPageLeft); 6652 6653 /** 6654 * Action to move to the page right. 6655 * <p>The UI element that implements this should send a 6656 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 6657 */ 6658 public static final AccessibilityAction ACTION_PAGE_RIGHT = 6659 new AccessibilityAction(R.id.accessibilityActionPageRight); 6660 6661 /** 6662 * Action that context clicks the node. 6663 * 6664 * <p>The UI element that implements this should send a 6665 * {@link AccessibilityEvent#TYPE_VIEW_CONTEXT_CLICKED} event. In the View system, 6666 * the default handling of this action when performed by a service is to call 6667 * {@link View#performContextClick()}, and setting a 6668 * {@link View#setOnContextClickListener(View.OnContextClickListener)} automatically adds 6669 * this action. 6670 * 6671 * <p>A context click usually occurs from a mouse pointer right-click or a stylus button 6672 * press. 6673 * 6674 * <p>{@link #isContextClickable()} should return true if this action is available. 6675 */ 6676 public static final AccessibilityAction ACTION_CONTEXT_CLICK = 6677 new AccessibilityAction(R.id.accessibilityActionContextClick); 6678 6679 /** 6680 * Action that sets progress between {@link RangeInfo#getMin() RangeInfo.getMin()} and 6681 * {@link RangeInfo#getMax() RangeInfo.getMax()}. It should use the same value type as 6682 * {@link RangeInfo#getType() RangeInfo.getType()} 6683 * <p> 6684 * <strong>Arguments:</strong> 6685 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_PROGRESS_VALUE} 6686 * 6687 * @see RangeInfo 6688 */ 6689 public static final AccessibilityAction ACTION_SET_PROGRESS = 6690 new AccessibilityAction(R.id.accessibilityActionSetProgress); 6691 6692 /** 6693 * Action to move a window to a new location. 6694 * <p> 6695 * <strong>Arguments:</strong> 6696 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_X} 6697 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_Y} 6698 */ 6699 public static final AccessibilityAction ACTION_MOVE_WINDOW = 6700 new AccessibilityAction(R.id.accessibilityActionMoveWindow); 6701 6702 /** 6703 * Action to show a tooltip. A node should expose this action only for views with tooltip 6704 * text that but are not currently showing a tooltip. 6705 */ 6706 public static final AccessibilityAction ACTION_SHOW_TOOLTIP = 6707 new AccessibilityAction(R.id.accessibilityActionShowTooltip); 6708 6709 /** 6710 * Action to hide a tooltip. A node should expose this action only for views that are 6711 * currently showing a tooltip. 6712 */ 6713 public static final AccessibilityAction ACTION_HIDE_TOOLTIP = 6714 new AccessibilityAction(R.id.accessibilityActionHideTooltip); 6715 6716 /** 6717 * Action that presses and holds a node. 6718 * <p> 6719 * This action is for nodes that have distinct behavior that depends on how long a press is 6720 * held. Nodes having a single action for long press should use {@link #ACTION_LONG_CLICK} 6721 * instead of this action, and nodes should not expose both actions. 6722 * <p> 6723 * When calling {@code performAction(ACTION_PRESS_AND_HOLD, bundle}, use 6724 * {@link #ACTION_ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT} to specify how long the 6725 * node is pressed. The first time an accessibility service performs ACTION_PRES_AND_HOLD 6726 * on a node, it must specify 0 as ACTION_ARGUMENT_PRESS_AND_HOLD, so the application is 6727 * notified that the held state has started. To ensure reasonable behavior, the values 6728 * must be increased incrementally and may not exceed 10,000. UIs requested 6729 * to hold for times outside of this range should ignore the action. 6730 * <p> 6731 * The total time the element is held could be specified by an accessibility user up-front, 6732 * or may depend on what happens on the UI as the user continues to request the hold. 6733 * <p> 6734 * <strong>Note:</strong> The time between dispatching the action and it arriving in the 6735 * UI process is not guaranteed. It is possible on a busy system for the time to expire 6736 * unexpectedly. For the case of holding down a key for a repeating action, a delayed 6737 * arrival should be benign. Please do not use this sort of action in cases where such 6738 * delays will lead to unexpected UI behavior. 6739 * <p> 6740 */ 6741 @NonNull public static final AccessibilityAction ACTION_PRESS_AND_HOLD = 6742 new AccessibilityAction(R.id.accessibilityActionPressAndHold); 6743 6744 /** 6745 * Action to send an ime actionId which is from 6746 * {@link android.view.inputmethod.EditorInfo#actionId}. This ime actionId sets by 6747 * {@link TextView#setImeActionLabel(CharSequence, int)}, or it would be 6748 * {@link android.view.inputmethod.EditorInfo#IME_ACTION_UNSPECIFIED} if no specific 6749 * actionId has set. A node should expose this action only for views that are currently 6750 * with input focus and editable. 6751 */ 6752 @NonNull public static final AccessibilityAction ACTION_IME_ENTER = 6753 new AccessibilityAction(R.id.accessibilityActionImeEnter); 6754 6755 /** 6756 * Action to start a drag. 6757 * <p> 6758 * This action initiates a drag & drop within the system. The source's dragged content is 6759 * prepared before the drag begins. In View, this action should prepare the arguments to 6760 * {@link View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)} and then 6761 * call {@link View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)} with 6762 * {@link View#DRAG_FLAG_ACCESSIBILITY_ACTION}. The equivalent should be performed for other 6763 * UI toolkits. 6764 * </p> 6765 * 6766 * @see AccessibilityEvent#CONTENT_CHANGE_TYPE_DRAG_STARTED 6767 */ 6768 @NonNull public static final AccessibilityAction ACTION_DRAG_START = 6769 new AccessibilityAction(R.id.accessibilityActionDragStart); 6770 6771 /** 6772 * Action to trigger a drop of the content being dragged. 6773 * <p> 6774 * This action is added to potential drop targets if the source started a drag with 6775 * {@link #ACTION_DRAG_START}. In View, these targets are Views that accepted 6776 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} and have an 6777 * {@link View.OnDragListener}, and the drop occurs at the center location of the View's 6778 * window bounds. 6779 * </p> 6780 * 6781 * @see AccessibilityEvent#CONTENT_CHANGE_TYPE_DRAG_DROPPED 6782 */ 6783 @NonNull public static final AccessibilityAction ACTION_DRAG_DROP = 6784 new AccessibilityAction(R.id.accessibilityActionDragDrop); 6785 6786 /** 6787 * Action to cancel a drag. 6788 * <p> 6789 * This action is added to the source that started a drag with {@link #ACTION_DRAG_START}. 6790 * </p> 6791 * 6792 * @see AccessibilityEvent#CONTENT_CHANGE_TYPE_DRAG_CANCELLED 6793 */ 6794 @NonNull public static final AccessibilityAction ACTION_DRAG_CANCEL = 6795 new AccessibilityAction(R.id.accessibilityActionDragCancel); 6796 6797 /** 6798 * Action to show suggestions for editable text. 6799 */ 6800 @NonNull public static final AccessibilityAction ACTION_SHOW_TEXT_SUGGESTIONS = 6801 new AccessibilityAction(R.id.accessibilityActionShowTextSuggestions); 6802 6803 /** 6804 * Action to set the extended selection. Performing this action with no arguments clears the 6805 * selection. 6806 * 6807 * <p><strong>Arguments:</strong> {@link 6808 * AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_PARCELABLE 6809 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_PARCELABLE}<br> 6810 * <strong>Example:</strong> <code><pre><p> 6811 * Bundle arguments = new Bundle(); 6812 * Selection selection = new Selection(null, null); 6813 * arguments.setParcelable( 6814 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_PARCELABLE, selection); 6815 * info.performAction( 6816 * AccessibilityAction.ACTION_SET_EXTENDED_SELECTION.getId(), arguments); 6817 * </pre></code> 6818 * 6819 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_PARCELABLE 6820 */ 6821 @FlaggedApi(Flags.FLAG_A11Y_SELECTION_API) 6822 @NonNull 6823 public static final AccessibilityAction ACTION_SET_EXTENDED_SELECTION = 6824 new AccessibilityAction(R.id.accessibilityActionSetExtendedSelection); 6825 6826 private final int mActionId; 6827 private final CharSequence mLabel; 6828 6829 /** @hide */ 6830 public long mSerializationFlag = -1L; 6831 6832 /** 6833 * Creates a new AccessibilityAction. For adding a standard action without a specific label, 6834 * use the static constants. 6835 * 6836 * You can also override the description for one the standard actions. Below is an example 6837 * how to override the standard click action by adding a custom label: 6838 * <pre> 6839 * AccessibilityAction action = new AccessibilityAction( 6840 * AccessibilityAction.ACTION_CLICK.getId(), getLocalizedLabel()); 6841 * node.addAction(action); 6842 * </pre> 6843 * 6844 * @param actionId The id for this action. This should either be one of the 6845 * standard actions or a specific action for your app. In that case it is 6846 * required to use a resource identifier. 6847 * @param label The label for the new AccessibilityAction. 6848 */ AccessibilityAction(int actionId, @Nullable CharSequence label)6849 public AccessibilityAction(int actionId, @Nullable CharSequence label) { 6850 mActionId = actionId; 6851 mLabel = label; 6852 } 6853 6854 /** 6855 * Constructor for a {@link #sStandardActions standard} action 6856 */ AccessibilityAction(int standardActionId)6857 private AccessibilityAction(int standardActionId) { 6858 this(standardActionId, null); 6859 6860 mSerializationFlag = bitAt(sStandardActions.size()); 6861 sStandardActions.add(this); 6862 } 6863 6864 /** 6865 * Gets the id for this action. 6866 * 6867 * @return The action id. 6868 */ getId()6869 public int getId() { 6870 return mActionId; 6871 } 6872 6873 /** 6874 * Gets the label for this action. Its purpose is to describe the 6875 * action to user. 6876 * 6877 * @return The label. 6878 */ getLabel()6879 public CharSequence getLabel() { 6880 return mLabel; 6881 } 6882 6883 @Override hashCode()6884 public int hashCode() { 6885 return mActionId; 6886 } 6887 6888 @Override equals(@ullable Object other)6889 public boolean equals(@Nullable Object other) { 6890 if (other == null) { 6891 return false; 6892 } 6893 6894 if (other == this) { 6895 return true; 6896 } 6897 6898 if (getClass() != other.getClass()) { 6899 return false; 6900 } 6901 6902 return mActionId == ((AccessibilityAction)other).mActionId; 6903 } 6904 6905 @Override toString()6906 public String toString() { 6907 return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel; 6908 } 6909 6910 /** 6911 * {@inheritDoc} 6912 */ 6913 @Override describeContents()6914 public int describeContents() { 6915 return 0; 6916 } 6917 6918 /** 6919 * Write data into a parcel. 6920 */ writeToParcel(@onNull Parcel out, int flags)6921 public void writeToParcel(@NonNull Parcel out, int flags) { 6922 out.writeInt(mActionId); 6923 out.writeCharSequence(mLabel); 6924 } 6925 6926 public static final @NonNull Parcelable.Creator<AccessibilityAction> CREATOR = 6927 new Parcelable.Creator<AccessibilityAction>() { 6928 public AccessibilityAction createFromParcel(Parcel in) { 6929 return new AccessibilityAction(in); 6930 } 6931 6932 public AccessibilityAction[] newArray(int size) { 6933 return new AccessibilityAction[size]; 6934 } 6935 }; 6936 AccessibilityAction(Parcel in)6937 private AccessibilityAction(Parcel in) { 6938 mActionId = in.readInt(); 6939 mLabel = in.readCharSequence(); 6940 } 6941 } 6942 6943 /** 6944 * Class with information if a node is a range. 6945 */ 6946 public static final class RangeInfo { 6947 /** @hide */ 6948 @IntDef(prefix = { "RANGE_TYPE_" }, value = { 6949 RANGE_TYPE_INT, 6950 RANGE_TYPE_FLOAT, 6951 RANGE_TYPE_PERCENT, 6952 RANGE_TYPE_INDETERMINATE 6953 }) 6954 @Retention(RetentionPolicy.SOURCE) 6955 public @interface RangeType {} 6956 6957 /** Range type: integer. */ 6958 public static final int RANGE_TYPE_INT = 0; 6959 /** Range type: float. */ 6960 public static final int RANGE_TYPE_FLOAT = 1; 6961 /** Range type: percent with values from zero to one hundred. */ 6962 public static final int RANGE_TYPE_PERCENT = 2; 6963 6964 /** 6965 * Range type: indeterminate. 6966 * 6967 * When using this type, the {@code min}, {@code max}, and {@code current} values used to 6968 * construct an instance may be ignored. 6969 * 6970 * @see #INDETERMINATE 6971 */ 6972 @FlaggedApi(Flags.FLAG_INDETERMINATE_RANGE_INFO) 6973 public static final int RANGE_TYPE_INDETERMINATE = 3; 6974 6975 /** 6976 * A {@link RangeInfo} type used to represent a node which may typically expose range 6977 * information but is presently in an indeterminate state, such as a {@link 6978 * android.widget.ProgressBar} representing a loading operation of unknown duration. 6979 */ 6980 @NonNull 6981 @FlaggedApi(Flags.FLAG_INDETERMINATE_RANGE_INFO) 6982 public static final RangeInfo INDETERMINATE = new RangeInfo(RANGE_TYPE_INDETERMINATE, 0.0f, 6983 0.0f, 0.0f); 6984 6985 private int mType; 6986 private float mMin; 6987 private float mMax; 6988 private float mCurrent; 6989 /** 6990 * Instantiates a new RangeInfo. 6991 * 6992 * @deprecated Object pooling has been discontinued. Create a new instance using the 6993 * constructor {@link AccessibilityNodeInfo.RangeInfo#RangeInfo(int, float, float, 6994 * float)} instead. 6995 * 6996 * @param type The type of the range. 6997 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no 6998 * minimum. 6999 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no 7000 * maximum. 7001 * @param current The current value. 7002 */ 7003 @Deprecated obtain(@angeType int type, float min, float max, float current)7004 public static RangeInfo obtain(@RangeType int type, float min, float max, float current) { 7005 return new RangeInfo(type, min, max, current); 7006 } 7007 7008 /** 7009 * Creates a new range. 7010 * 7011 * @param type The type of the range. 7012 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no 7013 * minimum. 7014 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no 7015 * maximum. 7016 * @param current The current value. 7017 */ RangeInfo(@angeType int type, float min, float max, float current)7018 public RangeInfo(@RangeType int type, float min, float max, float current) { 7019 mType = type; 7020 mMin = min; 7021 mMax = max; 7022 mCurrent = current; 7023 } 7024 7025 /** 7026 * Gets the range type. 7027 * 7028 * @return The range type. 7029 * 7030 * @see #RANGE_TYPE_INT 7031 * @see #RANGE_TYPE_FLOAT 7032 * @see #RANGE_TYPE_PERCENT 7033 */ 7034 @RangeType getType()7035 public int getType() { 7036 return mType; 7037 } 7038 7039 /** 7040 * Gets the minimum value. 7041 * 7042 * @return The minimum value, or {@code Float.NEGATIVE_INFINITY} if no minimum exists. 7043 */ getMin()7044 public float getMin() { 7045 return mMin; 7046 } 7047 7048 /** 7049 * Gets the maximum value. 7050 * 7051 * @return The maximum value, or {@code Float.POSITIVE_INFINITY} if no maximum exists. 7052 */ getMax()7053 public float getMax() { 7054 return mMax; 7055 } 7056 7057 /** 7058 * Gets the current value. 7059 * 7060 * @return The current value. 7061 */ getCurrent()7062 public float getCurrent() { 7063 return mCurrent; 7064 } 7065 7066 /** 7067 * Recycles this instance. 7068 * 7069 * @deprecated Object pooling has been discontinued. Calling this function now will have 7070 * no effect. 7071 */ 7072 @Deprecated recycle()7073 void recycle() {} 7074 clear()7075 private void clear() { 7076 mType = 0; 7077 mMin = 0; 7078 mMax = 0; 7079 mCurrent = 0; 7080 } 7081 } 7082 7083 /** 7084 * Class with information if a node is a collection. 7085 * <p> 7086 * A collection of items has rows and columns and may be hierarchical. 7087 * For example, a horizontal list is a collection with one column, as 7088 * many rows as the list items, and is not hierarchical; A table is a 7089 * collection with several rows, several columns, and is not hierarchical; 7090 * A vertical tree is a hierarchical collection with one column and 7091 * as many rows as the first level children. 7092 * </p> 7093 */ 7094 public static final class CollectionInfo { 7095 /** Selection mode where items are not selectable. */ 7096 public static final int SELECTION_MODE_NONE = 0; 7097 7098 /** Selection mode where a single item may be selected. */ 7099 public static final int SELECTION_MODE_SINGLE = 1; 7100 7101 /** Selection mode where multiple items may be selected. */ 7102 public static final int SELECTION_MODE_MULTIPLE = 2; 7103 7104 /** 7105 * Constant to denote a missing collection count. 7106 * 7107 * This should be used for {@code mItemCount} and 7108 * {@code mImportantForAccessibilityItemCount} when values for those fields are not known. 7109 */ 7110 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) 7111 public static final int UNDEFINED = -1; 7112 7113 private int mRowCount; 7114 private int mColumnCount; 7115 private boolean mHierarchical; 7116 private int mSelectionMode; 7117 private int mItemCount; 7118 private int mImportantForAccessibilityItemCount; 7119 7120 /** 7121 * Instantiates a CollectionInfo that is a clone of another one. 7122 * 7123 * @deprecated Object pooling has been discontinued. Create a new instance using the 7124 * constructor {@link 7125 * AccessibilityNodeInfo.CollectionInfo#CollectionInfo} instead. 7126 * 7127 * @param other The instance to clone. 7128 * @hide 7129 */ obtain(CollectionInfo other)7130 public static CollectionInfo obtain(CollectionInfo other) { 7131 return new CollectionInfo(other.mRowCount, other.mColumnCount, other.mHierarchical, 7132 other.mSelectionMode, other.mItemCount, 7133 other.mImportantForAccessibilityItemCount); 7134 } 7135 7136 /** 7137 * Obtains a pooled instance. 7138 * 7139 * @deprecated Object pooling has been discontinued. Create a new instance using the 7140 * constructor {@link 7141 * AccessibilityNodeInfo.CollectionInfo#CollectionInfo(int, int, 7142 * boolean)} instead. 7143 * 7144 * @param rowCount The number of rows, or -1 if count is unknown. 7145 * @param columnCount The number of columns, or -1 if count is unknown. 7146 * @param hierarchical Whether the collection is hierarchical. 7147 */ obtain(int rowCount, int columnCount, boolean hierarchical)7148 public static CollectionInfo obtain(int rowCount, int columnCount, 7149 boolean hierarchical) { 7150 return new CollectionInfo(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE); 7151 } 7152 7153 /** 7154 * Obtains a pooled instance. 7155 * 7156 * @deprecated Object pooling has been discontinued. Create a new instance using the 7157 * constructor {@link 7158 * AccessibilityNodeInfo.CollectionInfo#CollectionInfo(int, int, 7159 * boolean, int)} instead. 7160 * 7161 * @param rowCount The number of rows. 7162 * @param columnCount The number of columns. 7163 * @param hierarchical Whether the collection is hierarchical. 7164 * @param selectionMode The collection's selection mode, one of: 7165 * <ul> 7166 * <li>{@link #SELECTION_MODE_NONE} 7167 * <li>{@link #SELECTION_MODE_SINGLE} 7168 * <li>{@link #SELECTION_MODE_MULTIPLE} 7169 * </ul> 7170 */ obtain(int rowCount, int columnCount, boolean hierarchical, int selectionMode)7171 public static CollectionInfo obtain(int rowCount, int columnCount, 7172 boolean hierarchical, int selectionMode) { 7173 return new CollectionInfo(rowCount, columnCount, hierarchical, selectionMode); 7174 } 7175 7176 /** 7177 * Creates a new instance. 7178 * 7179 * @param rowCount The number of rows. 7180 * @param columnCount The number of columns. 7181 * @param hierarchical Whether the collection is hierarchical. 7182 */ CollectionInfo(int rowCount, int columnCount, boolean hierarchical)7183 public CollectionInfo(int rowCount, int columnCount, boolean hierarchical) { 7184 this(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE); 7185 } 7186 7187 /** 7188 * Creates a new instance. 7189 * 7190 * @param rowCount The number of rows. 7191 * @param columnCount The number of columns. 7192 * @param hierarchical Whether the collection is hierarchical. 7193 * @param selectionMode The collection's selection mode. 7194 */ CollectionInfo(int rowCount, int columnCount, boolean hierarchical, int selectionMode)7195 public CollectionInfo(int rowCount, int columnCount, boolean hierarchical, 7196 int selectionMode) { 7197 mRowCount = rowCount; 7198 mColumnCount = columnCount; 7199 mHierarchical = hierarchical; 7200 mSelectionMode = selectionMode; 7201 mItemCount = UNDEFINED; 7202 mImportantForAccessibilityItemCount = UNDEFINED; 7203 } 7204 7205 /** 7206 * Creates a new instance. 7207 * 7208 * @param rowCount The number of rows. 7209 * @param columnCount The number of columns. 7210 * @param hierarchical Whether the collection is hierarchical. 7211 * @param selectionMode The collection's selection mode. 7212 * @param itemCount The collection's item count, which includes items that are unimportant 7213 * for accessibility. When ViewGroups map cleanly to both row and column 7214 * semantics, clients should populate the row and column counts and 7215 * optionally populate this field. In all other cases, clients should 7216 * populate this field so that accessibility services can use it to relay 7217 * the collection size to users. This should be set to {@code UNDEFINED} if 7218 * the item count is not known. 7219 * @param importantForAccessibilityItemCount The count of the collection's views considered 7220 * important for accessibility. 7221 * @hide 7222 */ CollectionInfo(int rowCount, int columnCount, boolean hierarchical, int selectionMode, int itemCount, int importantForAccessibilityItemCount)7223 public CollectionInfo(int rowCount, int columnCount, boolean hierarchical, 7224 int selectionMode, int itemCount, int importantForAccessibilityItemCount) { 7225 mRowCount = rowCount; 7226 mColumnCount = columnCount; 7227 mHierarchical = hierarchical; 7228 mSelectionMode = selectionMode; 7229 mItemCount = itemCount; 7230 mImportantForAccessibilityItemCount = importantForAccessibilityItemCount; 7231 } 7232 7233 /** 7234 * Gets the number of rows. 7235 * 7236 * @return The row count, or -1 if count is unknown. 7237 */ getRowCount()7238 public int getRowCount() { 7239 return mRowCount; 7240 } 7241 7242 /** 7243 * Gets the number of columns. 7244 * 7245 * @return The column count, or -1 if count is unknown. 7246 */ getColumnCount()7247 public int getColumnCount() { 7248 return mColumnCount; 7249 } 7250 7251 /** 7252 * Gets if the collection is a hierarchically ordered. 7253 * 7254 * @return Whether the collection is hierarchical. 7255 */ isHierarchical()7256 public boolean isHierarchical() { 7257 return mHierarchical; 7258 } 7259 7260 /** 7261 * Gets the collection's selection mode. 7262 * 7263 * @return The collection's selection mode, one of: 7264 * <ul> 7265 * <li>{@link #SELECTION_MODE_NONE} 7266 * <li>{@link #SELECTION_MODE_SINGLE} 7267 * <li>{@link #SELECTION_MODE_MULTIPLE} 7268 * </ul> 7269 */ getSelectionMode()7270 public int getSelectionMode() { 7271 return mSelectionMode; 7272 } 7273 7274 /** 7275 * Gets the number of items in the collection. 7276 * 7277 * @return The count of items, which may be {@code UNDEFINED} if the count is not known. 7278 */ 7279 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) getItemCount()7280 public int getItemCount() { 7281 return mItemCount; 7282 } 7283 7284 /** 7285 * Gets the number of items in the collection considered important for accessibility. 7286 * 7287 * @return The count of items important for accessibility, which may be {@code UNDEFINED} 7288 * if the count is not known. 7289 */ 7290 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) getImportantForAccessibilityItemCount()7291 public int getImportantForAccessibilityItemCount() { 7292 return mImportantForAccessibilityItemCount; 7293 } 7294 7295 /** 7296 * Previously would recycle this instance. 7297 * 7298 * @deprecated Object pooling has been discontinued. Calling this function now will have 7299 * no effect. 7300 */ 7301 @Deprecated recycle()7302 void recycle() {} 7303 clear()7304 private void clear() { 7305 mRowCount = 0; 7306 mColumnCount = 0; 7307 mHierarchical = false; 7308 mSelectionMode = SELECTION_MODE_NONE; 7309 mItemCount = UNDEFINED; 7310 mImportantForAccessibilityItemCount = UNDEFINED; 7311 } 7312 7313 /** 7314 * The builder for CollectionInfo. 7315 */ 7316 7317 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) 7318 public static final class Builder { 7319 private int mRowCount = 0; 7320 private int mColumnCount = 0; 7321 private boolean mHierarchical = false; 7322 private int mSelectionMode; 7323 private int mItemCount = UNDEFINED; 7324 private int mImportantForAccessibilityItemCount = UNDEFINED; 7325 7326 /** 7327 * Creates a new Builder. 7328 */ 7329 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) Builder()7330 public Builder() { 7331 } 7332 7333 /** 7334 * Sets the row count. 7335 * @param rowCount The number of rows in the collection. 7336 * @return This builder. 7337 */ 7338 @NonNull 7339 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) setRowCount(int rowCount)7340 public CollectionInfo.Builder setRowCount(int rowCount) { 7341 mRowCount = rowCount; 7342 return this; 7343 } 7344 7345 /** 7346 * Sets the column count. 7347 * @param columnCount The number of columns in the collection. 7348 * @return This builder. 7349 */ 7350 @NonNull 7351 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) setColumnCount(int columnCount)7352 public CollectionInfo.Builder setColumnCount(int columnCount) { 7353 mColumnCount = columnCount; 7354 return this; 7355 } 7356 /** 7357 * Sets whether the collection is hierarchical. 7358 * @param hierarchical Whether the collection is hierarchical. 7359 * @return This builder. 7360 */ 7361 @NonNull 7362 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) setHierarchical(boolean hierarchical)7363 public CollectionInfo.Builder setHierarchical(boolean hierarchical) { 7364 mHierarchical = hierarchical; 7365 return this; 7366 } 7367 7368 /** 7369 * Sets the selection mode. 7370 * @param selectionMode The selection mode. 7371 * @return This builder. 7372 */ 7373 @NonNull 7374 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) setSelectionMode(int selectionMode)7375 public CollectionInfo.Builder setSelectionMode(int selectionMode) { 7376 mSelectionMode = selectionMode; 7377 return this; 7378 } 7379 7380 /** 7381 * Sets the number of items in the collection. Can be optionally set for ViewGroups with 7382 * clear row and column semantics; should be set for all other clients. 7383 * 7384 * @param itemCount The number of items in the collection. This should be set to 7385 * {@code UNDEFINED} if the item count is not known. 7386 * @return This builder. 7387 */ 7388 @NonNull 7389 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) setItemCount(int itemCount)7390 public CollectionInfo.Builder setItemCount(int itemCount) { 7391 mItemCount = itemCount; 7392 return this; 7393 } 7394 7395 /** 7396 * Sets the number of views considered important for accessibility. 7397 * @param importantForAccessibilityItemCount The number of items important for 7398 * accessibility. 7399 * @return This builder. 7400 */ 7401 @NonNull 7402 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) setImportantForAccessibilityItemCount( int importantForAccessibilityItemCount)7403 public CollectionInfo.Builder setImportantForAccessibilityItemCount( 7404 int importantForAccessibilityItemCount) { 7405 mImportantForAccessibilityItemCount = importantForAccessibilityItemCount; 7406 return this; 7407 } 7408 7409 /** 7410 * Creates a new {@link CollectionInfo} instance. 7411 */ 7412 @NonNull 7413 @FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) build()7414 public CollectionInfo build() { 7415 CollectionInfo collectionInfo = new CollectionInfo(mRowCount, mColumnCount, 7416 mHierarchical); 7417 collectionInfo.mSelectionMode = mSelectionMode; 7418 collectionInfo.mItemCount = mItemCount; 7419 collectionInfo.mImportantForAccessibilityItemCount = 7420 mImportantForAccessibilityItemCount; 7421 return collectionInfo; 7422 } 7423 } 7424 } 7425 7426 /** 7427 * Class with information if a node is a collection item. 7428 * <p> 7429 * A collection item is contained in a collection, it starts at 7430 * a given row and column in the collection, and spans one or 7431 * more rows and columns. For example, a header of two related 7432 * table columns starts at the first row and the first column, 7433 * spans one row and two columns. 7434 * </p> 7435 */ 7436 public static final class CollectionItemInfo { 7437 /** 7438 * Instantiates a CollectionItemInfo that is a clone of another one. 7439 * 7440 * @deprecated Object pooling has been discontinued. Create a new instance using the 7441 * constructor {@link 7442 * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo} 7443 * instead. 7444 * 7445 * @param other The instance to clone. 7446 * @hide 7447 */ 7448 @Deprecated obtain(CollectionItemInfo other)7449 public static CollectionItemInfo obtain(CollectionItemInfo other) { 7450 return new CollectionItemInfo(other.mRowTitle, other.mRowIndex, other.mRowSpan, 7451 other.mColumnTitle, other.mColumnIndex, other.mColumnSpan, other.mHeading, 7452 other.mSelected); 7453 } 7454 7455 /** 7456 * Instantiates a new CollectionItemInfo. 7457 * 7458 * @deprecated Object pooling has been discontinued. Create a new instance using the 7459 * constructor {@link 7460 * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo(int, 7461 * int, int, int, boolean)} instead. 7462 * @param rowIndex The row index at which the item is located. 7463 * @param rowSpan The number of rows the item spans. 7464 * @param columnIndex The column index at which the item is located. 7465 * @param columnSpan The number of columns the item spans. 7466 * @param heading Whether the item is a heading. (Prefer 7467 * {@link AccessibilityNodeInfo#setHeading(boolean)}). 7468 */ 7469 @Deprecated obtain(int rowIndex, int rowSpan, int columnIndex, int columnSpan, boolean heading)7470 public static CollectionItemInfo obtain(int rowIndex, int rowSpan, 7471 int columnIndex, int columnSpan, boolean heading) { 7472 return new CollectionItemInfo(rowIndex, rowSpan, columnIndex, columnSpan, heading, 7473 false); 7474 } 7475 7476 /** 7477 * Instantiates a new CollectionItemInfo. 7478 * 7479 * @deprecated Object pooling has been discontinued. Create a new instance using the 7480 * constructor {@link 7481 * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo(int, 7482 * int, int, int, boolean)} instead. 7483 * @param rowIndex The row index at which the item is located. 7484 * @param rowSpan The number of rows the item spans. 7485 * @param columnIndex The column index at which the item is located. 7486 * @param columnSpan The number of columns the item spans. 7487 * @param heading Whether the item is a heading. (Prefer 7488 * {@link AccessibilityNodeInfo#setHeading(boolean)}). 7489 * @param selected Whether the item is selected. 7490 */ 7491 @Deprecated obtain(int rowIndex, int rowSpan, int columnIndex, int columnSpan, boolean heading, boolean selected)7492 public static CollectionItemInfo obtain(int rowIndex, int rowSpan, 7493 int columnIndex, int columnSpan, boolean heading, boolean selected) { 7494 return new CollectionItemInfo(rowIndex, rowSpan, columnIndex, columnSpan, heading, 7495 selected); 7496 } 7497 7498 /** 7499 * Instantiates a new CollectionItemInfo. 7500 * 7501 * @deprecated Object pooling has been discontinued. Creates a new instance using the 7502 * constructor {@link 7503 * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo(int, 7504 * int, int, int, boolean, boolean)} instead. 7505 * 7506 * @param rowTitle The row title at which the item is located. 7507 * @param rowIndex The row index at which the item is located. 7508 * @param rowSpan The number of rows the item spans. 7509 * @param columnTitle The column title at which the item is located. 7510 * @param columnIndex The column index at which the item is located. 7511 * @param columnSpan The number of columns the item spans. 7512 * @param heading Whether the item is a heading. (Prefer 7513 * {@link AccessibilityNodeInfo#setHeading(boolean)}) 7514 * @param selected Whether the item is selected. 7515 * @removed 7516 */ 7517 @Deprecated 7518 @NonNull obtain(@ullable String rowTitle, int rowIndex, int rowSpan, @Nullable String columnTitle, int columnIndex, int columnSpan, boolean heading, boolean selected)7519 public static CollectionItemInfo obtain(@Nullable String rowTitle, int rowIndex, 7520 int rowSpan, @Nullable String columnTitle, int columnIndex, int columnSpan, 7521 boolean heading, boolean selected) { 7522 return new CollectionItemInfo(rowTitle, rowIndex, rowSpan, columnTitle, columnIndex, 7523 columnSpan, heading, selected); 7524 } 7525 7526 private boolean mHeading; 7527 private int mColumnIndex; 7528 private int mRowIndex; 7529 private int mColumnSpan; 7530 private int mRowSpan; 7531 private boolean mSelected; 7532 private String mRowTitle; 7533 private String mColumnTitle; 7534 CollectionItemInfo()7535 private CollectionItemInfo() { 7536 /* do nothing */ 7537 } 7538 7539 /** 7540 * Creates a new instance. 7541 * 7542 * @param rowIndex The row index at which the item is located. 7543 * @param rowSpan The number of rows the item spans. 7544 * @param columnIndex The column index at which the item is located. 7545 * @param columnSpan The number of columns the item spans. 7546 * @param heading Whether the item is a heading. 7547 */ CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan, boolean heading)7548 public CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan, 7549 boolean heading) { 7550 this(rowIndex, rowSpan, columnIndex, columnSpan, heading, false); 7551 } 7552 7553 /** 7554 * Creates a new instance. 7555 * 7556 * @param rowIndex The row index at which the item is located. 7557 * @param rowSpan The number of rows the item spans. 7558 * @param columnIndex The column index at which the item is located. 7559 * @param columnSpan The number of columns the item spans. 7560 * @param heading Whether the item is a heading. 7561 * @param selected Whether the item is selected. 7562 */ CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan, boolean heading, boolean selected)7563 public CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan, 7564 boolean heading, boolean selected) { 7565 this(null, rowIndex, rowSpan, null, columnIndex, columnSpan, 7566 heading, selected); 7567 } 7568 7569 /** 7570 * Creates a new instance. 7571 * 7572 * @param rowTitle The row title at which the item is located. 7573 * @param rowIndex The row index at which the item is located. 7574 * @param rowSpan The number of rows the item spans. 7575 * @param columnTitle The column title at which the item is located. 7576 * @param columnIndex The column index at which the item is located. 7577 * @param columnSpan The number of columns the item spans. 7578 * @param heading Whether the item is a heading. 7579 * @param selected Whether the item is selected. 7580 * @hide 7581 */ CollectionItemInfo(@ullable String rowTitle, int rowIndex, int rowSpan, @Nullable String columnTitle, int columnIndex, int columnSpan, boolean heading, boolean selected)7582 public CollectionItemInfo(@Nullable String rowTitle, int rowIndex, int rowSpan, 7583 @Nullable String columnTitle, int columnIndex, int columnSpan, boolean heading, 7584 boolean selected) { 7585 mRowIndex = rowIndex; 7586 mRowSpan = rowSpan; 7587 mColumnIndex = columnIndex; 7588 mColumnSpan = columnSpan; 7589 mHeading = heading; 7590 mSelected = selected; 7591 mRowTitle = rowTitle; 7592 mColumnTitle = columnTitle; 7593 } 7594 7595 /** 7596 * Gets the column index at which the item is located. 7597 * 7598 * @return The column index. 7599 */ getColumnIndex()7600 public int getColumnIndex() { 7601 return mColumnIndex; 7602 } 7603 7604 /** 7605 * Gets the row index at which the item is located. 7606 * 7607 * @return The row index. 7608 */ getRowIndex()7609 public int getRowIndex() { 7610 return mRowIndex; 7611 } 7612 7613 /** 7614 * Gets the number of columns the item spans. 7615 * 7616 * @return The column span. 7617 */ getColumnSpan()7618 public int getColumnSpan() { 7619 return mColumnSpan; 7620 } 7621 7622 /** 7623 * Gets the number of rows the item spans. 7624 * 7625 * @return The row span. 7626 */ getRowSpan()7627 public int getRowSpan() { 7628 return mRowSpan; 7629 } 7630 7631 /** 7632 * Gets if the collection item is a heading. For example, section 7633 * heading, table header, etc. 7634 * 7635 * @return If the item is a heading. 7636 * @deprecated Use {@link AccessibilityNodeInfo#isHeading()} 7637 */ isHeading()7638 public boolean isHeading() { 7639 return mHeading; 7640 } 7641 7642 /** 7643 * Gets if the collection item is selected. 7644 * 7645 * @return If the item is selected. 7646 */ isSelected()7647 public boolean isSelected() { 7648 return mSelected; 7649 } 7650 7651 /** 7652 * Gets the row title at which the item is located. 7653 * 7654 * @return The row title. 7655 */ 7656 @Nullable getRowTitle()7657 public String getRowTitle() { 7658 return mRowTitle; 7659 } 7660 7661 /** 7662 * Gets the column title at which the item is located. 7663 * 7664 * @return The column title. 7665 */ 7666 @Nullable getColumnTitle()7667 public String getColumnTitle() { 7668 return mColumnTitle; 7669 } 7670 7671 /** 7672 * Recycles this instance. 7673 * 7674 * @deprecated Object pooling has been discontinued. Calling this function now will have 7675 * no effect. 7676 */ 7677 @Deprecated recycle()7678 void recycle() {} 7679 clear()7680 private void clear() { 7681 mColumnIndex = 0; 7682 mColumnSpan = 0; 7683 mRowIndex = 0; 7684 mRowSpan = 0; 7685 mHeading = false; 7686 mSelected = false; 7687 mRowTitle = null; 7688 mColumnTitle = null; 7689 } 7690 7691 /** 7692 * Builder for creating {@link CollectionItemInfo} objects. 7693 */ 7694 public static final class Builder { 7695 private boolean mHeading; 7696 private int mColumnIndex; 7697 private int mRowIndex; 7698 private int mColumnSpan; 7699 private int mRowSpan; 7700 private boolean mSelected; 7701 private String mRowTitle; 7702 private String mColumnTitle; 7703 7704 /** 7705 * Creates a new Builder. 7706 */ Builder()7707 public Builder() { 7708 } 7709 7710 /** 7711 * Sets the collection item is a heading. 7712 * 7713 * @param heading The heading state 7714 * @return This builder 7715 */ 7716 @NonNull setHeading(boolean heading)7717 public CollectionItemInfo.Builder setHeading(boolean heading) { 7718 mHeading = heading; 7719 return this; 7720 } 7721 7722 /** 7723 * Sets the column index at which the item is located. 7724 * 7725 * @param columnIndex The column index 7726 * @return This builder 7727 */ 7728 @NonNull setColumnIndex(int columnIndex)7729 public CollectionItemInfo.Builder setColumnIndex(int columnIndex) { 7730 mColumnIndex = columnIndex; 7731 return this; 7732 } 7733 7734 /** 7735 * Sets the row index at which the item is located. 7736 * 7737 * @param rowIndex The row index 7738 * @return This builder 7739 */ 7740 @NonNull setRowIndex(int rowIndex)7741 public CollectionItemInfo.Builder setRowIndex(int rowIndex) { 7742 mRowIndex = rowIndex; 7743 return this; 7744 } 7745 7746 /** 7747 * Sets the number of columns the item spans. 7748 * 7749 * @param columnSpan The number of columns spans 7750 * @return This builder 7751 */ 7752 @NonNull setColumnSpan(int columnSpan)7753 public CollectionItemInfo.Builder setColumnSpan(int columnSpan) { 7754 mColumnSpan = columnSpan; 7755 return this; 7756 } 7757 7758 /** 7759 * Sets the number of rows the item spans. 7760 * 7761 * @param rowSpan The number of rows spans 7762 * @return This builder 7763 */ 7764 @NonNull setRowSpan(int rowSpan)7765 public CollectionItemInfo.Builder setRowSpan(int rowSpan) { 7766 mRowSpan = rowSpan; 7767 return this; 7768 } 7769 7770 /** 7771 * Sets the collection item is selected. 7772 * 7773 * @param selected The number of rows spans 7774 * @return This builder 7775 */ 7776 @NonNull setSelected(boolean selected)7777 public CollectionItemInfo.Builder setSelected(boolean selected) { 7778 mSelected = selected; 7779 return this; 7780 } 7781 7782 /** 7783 * Sets the row title at which the item is located. 7784 * 7785 * @param rowTitle The row title 7786 * @return This builder 7787 */ 7788 @NonNull setRowTitle(@ullable String rowTitle)7789 public CollectionItemInfo.Builder setRowTitle(@Nullable String rowTitle) { 7790 mRowTitle = rowTitle; 7791 return this; 7792 } 7793 7794 /** 7795 * Sets the column title at which the item is located. 7796 * 7797 * @param columnTitle The column title 7798 * @return This builder 7799 */ 7800 @NonNull setColumnTitle(@ullable String columnTitle)7801 public CollectionItemInfo.Builder setColumnTitle(@Nullable String columnTitle) { 7802 mColumnTitle = columnTitle; 7803 return this; 7804 } 7805 7806 /** 7807 * Builds and returns a {@link CollectionItemInfo}. 7808 */ 7809 @NonNull build()7810 public CollectionItemInfo build() { 7811 CollectionItemInfo collectionItemInfo = new CollectionItemInfo(); 7812 collectionItemInfo.mHeading = mHeading; 7813 collectionItemInfo.mColumnIndex = mColumnIndex; 7814 collectionItemInfo.mRowIndex = mRowIndex; 7815 collectionItemInfo.mColumnSpan = mColumnSpan; 7816 collectionItemInfo.mRowSpan = mRowSpan; 7817 collectionItemInfo.mSelected = mSelected; 7818 collectionItemInfo.mRowTitle = mRowTitle; 7819 collectionItemInfo.mColumnTitle = mColumnTitle; 7820 7821 return collectionItemInfo; 7822 } 7823 } 7824 } 7825 7826 /** 7827 * Class with information of touch delegated views and regions from {@link TouchDelegate} for 7828 * the {@link AccessibilityNodeInfo}. 7829 * 7830 * @see AccessibilityNodeInfo#setTouchDelegateInfo(TouchDelegateInfo) 7831 */ 7832 public static final class TouchDelegateInfo implements Parcelable { 7833 private ArrayMap<Region, Long> mTargetMap; 7834 // Two ids are initialized lazily in AccessibilityNodeInfo#getTouchDelegateInfo 7835 private int mConnectionId; 7836 private int mWindowId; 7837 7838 /** 7839 * Create a new instance of {@link TouchDelegateInfo}. 7840 * 7841 * @param targetMap A map from regions (in view coordinates) to delegated views. 7842 * @throws IllegalArgumentException if targetMap is empty or {@code null} in 7843 * Regions or Views. 7844 */ TouchDelegateInfo(@onNull Map<Region, View> targetMap)7845 public TouchDelegateInfo(@NonNull Map<Region, View> targetMap) { 7846 Preconditions.checkArgument(!targetMap.isEmpty() 7847 && !targetMap.containsKey(null) && !targetMap.containsValue(null)); 7848 mTargetMap = new ArrayMap<>(targetMap.size()); 7849 for (final Region region : targetMap.keySet()) { 7850 final View view = targetMap.get(region); 7851 mTargetMap.put(region, (long) view.getAccessibilityViewId()); 7852 } 7853 } 7854 7855 /** 7856 * Create a new instance from target map. 7857 * 7858 * @param targetMap A map from regions (in view coordinates) to delegated views' 7859 * accessibility id. 7860 * @param doCopy True if shallow copy targetMap. 7861 * @throws IllegalArgumentException if targetMap is empty or {@code null} in 7862 * Regions or Views. 7863 */ TouchDelegateInfo(@onNull ArrayMap<Region, Long> targetMap, boolean doCopy)7864 TouchDelegateInfo(@NonNull ArrayMap<Region, Long> targetMap, boolean doCopy) { 7865 Preconditions.checkArgument(!targetMap.isEmpty() 7866 && !targetMap.containsKey(null) && !targetMap.containsValue(null)); 7867 if (doCopy) { 7868 mTargetMap = new ArrayMap<>(targetMap.size()); 7869 mTargetMap.putAll(targetMap); 7870 } else { 7871 mTargetMap = targetMap; 7872 } 7873 } 7874 7875 /** 7876 * Set the connection ID. 7877 * 7878 * @param connectionId The connection id. 7879 */ setConnectionId(int connectionId)7880 private void setConnectionId(int connectionId) { 7881 mConnectionId = connectionId; 7882 } 7883 7884 /** 7885 * Set the window ID. 7886 * 7887 * @param windowId The window id. 7888 */ setWindowId(int windowId)7889 private void setWindowId(int windowId) { 7890 mWindowId = windowId; 7891 } 7892 7893 /** 7894 * Returns the number of touch delegate target region. 7895 * 7896 * @return Number of touch delegate target region. 7897 */ getRegionCount()7898 public int getRegionCount() { 7899 return mTargetMap.size(); 7900 } 7901 7902 /** 7903 * Return the {@link Region} at the given index in the {@link TouchDelegateInfo}. 7904 * 7905 * @param index The desired index, must be between 0 and {@link #getRegionCount()}-1. 7906 * @return Returns the {@link Region} stored at the given index. 7907 */ 7908 @NonNull getRegionAt(int index)7909 public Region getRegionAt(int index) { 7910 return mTargetMap.keyAt(index); 7911 } 7912 7913 /** 7914 * Return the target {@link AccessibilityNodeInfo} for the given {@link Region}. 7915 * <p> 7916 * <strong>Note:</strong> This api can only be called from {@link AccessibilityService}. 7917 * </p> 7918 * 7919 * @param region The region retrieved from {@link #getRegionAt(int)}. 7920 * @return The target node associates with the given region. 7921 */ 7922 @Nullable getTargetForRegion(@onNull Region region)7923 public AccessibilityNodeInfo getTargetForRegion(@NonNull Region region) { 7924 return getNodeForAccessibilityId(mConnectionId, mWindowId, mTargetMap.get(region)); 7925 } 7926 7927 /** 7928 * Return the accessibility id of target node. 7929 * 7930 * @param region The region retrieved from {@link #getRegionAt(int)}. 7931 * @return The accessibility id of target node. 7932 * 7933 * @hide 7934 */ 7935 @TestApi getAccessibilityIdForRegion(@onNull Region region)7936 public long getAccessibilityIdForRegion(@NonNull Region region) { 7937 return mTargetMap.get(region); 7938 } 7939 7940 /** 7941 * {@inheritDoc} 7942 */ 7943 @Override describeContents()7944 public int describeContents() { 7945 return 0; 7946 } 7947 7948 /** 7949 * {@inheritDoc} 7950 */ 7951 @Override writeToParcel(Parcel dest, int flags)7952 public void writeToParcel(Parcel dest, int flags) { 7953 dest.writeInt(mTargetMap.size()); 7954 for (int i = 0; i < mTargetMap.size(); i++) { 7955 final Region region = mTargetMap.keyAt(i); 7956 final Long accessibilityId = mTargetMap.valueAt(i); 7957 region.writeToParcel(dest, flags); 7958 dest.writeLong(accessibilityId); 7959 } 7960 } 7961 7962 /** 7963 * @see android.os.Parcelable.Creator 7964 */ 7965 public static final @NonNull Parcelable.Creator<TouchDelegateInfo> CREATOR = 7966 new Parcelable.Creator<TouchDelegateInfo>() { 7967 @Override 7968 public TouchDelegateInfo createFromParcel(Parcel parcel) { 7969 final int size = parcel.readInt(); 7970 if (size == 0) { 7971 return null; 7972 } 7973 final ArrayMap<Region, Long> targetMap = new ArrayMap<>(size); 7974 for (int i = 0; i < size; i++) { 7975 final Region region = Region.CREATOR.createFromParcel(parcel); 7976 final long accessibilityId = parcel.readLong(); 7977 targetMap.put(region, accessibilityId); 7978 } 7979 final TouchDelegateInfo touchDelegateInfo = new TouchDelegateInfo( 7980 targetMap, false); 7981 return touchDelegateInfo; 7982 } 7983 7984 @Override 7985 public TouchDelegateInfo[] newArray(int size) { 7986 return new TouchDelegateInfo[size]; 7987 } 7988 }; 7989 } 7990 7991 /** 7992 * Class with information of a view useful to evaluate accessibility needs. Developers can 7993 * refresh the node with the key {@link #EXTRA_DATA_RENDERING_INFO_KEY} to fetch the text size 7994 * and unit if it is {@link TextView} and the height and the width of layout params from 7995 * {@link ViewGroup} or {@link TextView}. 7996 * 7997 * @see #EXTRA_DATA_RENDERING_INFO_KEY 7998 * @see #refreshWithExtraData(String, Bundle) 7999 */ 8000 public static final class ExtraRenderingInfo { 8001 private static final int UNDEFINED_VALUE = -1; 8002 8003 private Size mLayoutSize; 8004 private float mTextSizeInPx = UNDEFINED_VALUE; 8005 private int mTextSizeUnit = UNDEFINED_VALUE; 8006 8007 /** 8008 * Instantiates an ExtraRenderingInfo, by copying an existing one. 8009 * 8010 * @hide 8011 * @deprecated Object pooling has been discontinued. Create a new instance using the 8012 * constructor {@link #ExtraRenderingInfo(ExtraRenderingInfo)} instead. 8013 */ 8014 @Deprecated 8015 @NonNull obtain()8016 public static ExtraRenderingInfo obtain() { 8017 return new ExtraRenderingInfo(null); 8018 } 8019 8020 /** 8021 * Instantiates an ExtraRenderingInfo, by copying an existing one. 8022 * 8023 * @deprecated Object pooling has been discontinued. Create a new instance using the 8024 * constructor {@link #ExtraRenderingInfo(ExtraRenderingInfo)} instead. 8025 * @param other 8026 */ 8027 @Deprecated obtain(ExtraRenderingInfo other)8028 private static ExtraRenderingInfo obtain(ExtraRenderingInfo other) { 8029 return new ExtraRenderingInfo(other); 8030 } 8031 8032 /** 8033 * Creates a new rendering info of a view, and this new instance is initialized from 8034 * the given <code>other</code>. 8035 * 8036 * @param other The instance to clone. 8037 */ ExtraRenderingInfo(@ullable ExtraRenderingInfo other)8038 private ExtraRenderingInfo(@Nullable ExtraRenderingInfo other) { 8039 if (other != null) { 8040 mLayoutSize = other.mLayoutSize; 8041 mTextSizeInPx = other.mTextSizeInPx; 8042 mTextSizeUnit = other.mTextSizeUnit; 8043 } 8044 } 8045 8046 /** 8047 * Gets the size object containing the height and the width of 8048 * {@link android.view.ViewGroup.LayoutParams} if the node is a {@link ViewGroup} or 8049 * a {@link TextView}, or null otherwise. Useful for some accessibility services to 8050 * understand whether the text is scalable and fits the view or not. 8051 * 8052 * @return a {@link Size} stores layout height and layout width of the view, or null 8053 * otherwise. And the size value may be in pixels, 8054 * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, 8055 * or {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} 8056 */ getLayoutSize()8057 public @Nullable Size getLayoutSize() { 8058 return mLayoutSize; 8059 } 8060 8061 /** 8062 * Sets layout width and layout height of the view. 8063 * 8064 * @param width The layout width. 8065 * @param height The layout height. 8066 * @hide 8067 */ setLayoutSize(int width, int height)8068 public void setLayoutSize(int width, int height) { 8069 mLayoutSize = new Size(width, height); 8070 } 8071 8072 /** 8073 * Gets the text size if the node is a {@link TextView}, or -1 otherwise. Useful for some 8074 * accessibility services to understand whether the text is scalable and fits the view or 8075 * not. 8076 * 8077 * @return the text size of a {@code TextView}, or -1 otherwise. 8078 */ getTextSizeInPx()8079 public float getTextSizeInPx() { 8080 return mTextSizeInPx; 8081 } 8082 8083 /** 8084 * Sets text size of the view. 8085 * 8086 * @param textSizeInPx The text size in pixels. 8087 * @hide 8088 */ setTextSizeInPx(float textSizeInPx)8089 public void setTextSizeInPx(float textSizeInPx) { 8090 mTextSizeInPx = textSizeInPx; 8091 } 8092 8093 /** 8094 * Gets the text size unit if the node is a {@link TextView}, or -1 otherwise. 8095 * Text size returned from {@link #getTextSizeInPx} in raw pixels may scale by factors and 8096 * convert from other units. Useful for some accessibility services to understand whether 8097 * the text is scalable and fits the view or not. 8098 * 8099 * @return the text size unit which type is {@link TypedValue#TYPE_DIMENSION} of a 8100 * {@code TextView}, or -1 otherwise. 8101 * 8102 * @see TypedValue#TYPE_DIMENSION 8103 */ getTextSizeUnit()8104 public int getTextSizeUnit() { 8105 return mTextSizeUnit; 8106 } 8107 8108 /** 8109 * Sets text size unit of the view. 8110 * 8111 * @param textSizeUnit The text size unit. 8112 * @hide 8113 */ setTextSizeUnit(int textSizeUnit)8114 public void setTextSizeUnit(int textSizeUnit) { 8115 mTextSizeUnit = textSizeUnit; 8116 } 8117 8118 /** 8119 * Previously would recycle this instance. 8120 * 8121 * @deprecated Object pooling has been discontinued. Calling this function now will have 8122 * no effect. 8123 */ 8124 @Deprecated recycle()8125 void recycle() {} 8126 clear()8127 private void clear() { 8128 mLayoutSize = null; 8129 mTextSizeInPx = UNDEFINED_VALUE; 8130 mTextSizeUnit = UNDEFINED_VALUE; 8131 } 8132 } 8133 8134 /** 8135 * @see android.os.Parcelable.Creator 8136 */ 8137 public static final @NonNull Parcelable.Creator<AccessibilityNodeInfo> CREATOR = 8138 new Parcelable.Creator<AccessibilityNodeInfo>() { 8139 @Override 8140 public AccessibilityNodeInfo createFromParcel(Parcel parcel) { 8141 AccessibilityNodeInfo info = new AccessibilityNodeInfo(); 8142 info.initFromParcel(parcel); 8143 return info; 8144 } 8145 8146 @Override 8147 public AccessibilityNodeInfo[] newArray(int size) { 8148 return new AccessibilityNodeInfo[size]; 8149 } 8150 }; 8151 } 8152