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