• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &lt; 0 || index &gt;=
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