blob: 9bdd3ffc9fb2d2439b3a81a831e5cabee33ec0c7 [file] [log] [blame]
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001/*
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
17package android.view.accessibility;
18
Eugene Susla0eb2b6e2017-05-15 14:06:32 -070019import static com.android.internal.util.BitUtils.bitAt;
20import static com.android.internal.util.BitUtils.isBitSet;
21
Phil Weaverc2e28932016-12-08 12:29:25 -080022import static java.util.Collections.EMPTY_LIST;
23
Casey Burkhardt7ef48be2016-01-31 11:51:09 -080024import android.accessibilityservice.AccessibilityService;
Svetoslav Ganov80943d82013-01-02 10:25:37 -080025import android.accessibilityservice.AccessibilityServiceInfo;
Kristian Monsen74bc1942014-04-29 11:00:17 -070026import android.annotation.Nullable;
Phil Weaver62d20fa2016-09-15 11:05:55 -070027import android.annotation.TestApi;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070028import android.graphics.Rect;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070029import android.os.Bundle;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070030import android.os.Parcel;
31import android.os.Parcelable;
Svetoslav6254f482013-06-04 17:22:14 -070032import android.text.InputType;
Phil Weaver193520e2016-12-13 09:39:06 -080033import android.text.Spannable;
Phil Weaver0ebe6bd2017-02-21 16:24:31 -080034import android.text.SpannableStringBuilder;
Phil Weaver193520e2016-12-13 09:39:06 -080035import android.text.Spanned;
Kristian Monsen74bc1942014-04-29 11:00:17 -070036import android.text.TextUtils;
Phil Weaver193520e2016-12-13 09:39:06 -080037import android.text.style.AccessibilityClickableSpan;
38import android.text.style.AccessibilityURLSpan;
39import android.text.style.ClickableSpan;
40import android.text.style.URLSpan;
Kristian Monsen74bc1942014-04-29 11:00:17 -070041import android.util.ArraySet;
Alan Viverettef0aed092013-11-06 15:33:03 -080042import android.util.LongArray;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -080043import android.util.Pools.SynchronizedPool;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070044import android.view.View;
45
Alan Viverette26c44ee2015-03-25 14:54:13 -070046import com.android.internal.R;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -070047import com.android.internal.util.CollectionUtils;
Alan Viverette26c44ee2015-03-25 14:54:13 -070048
Kristian Monsen74bc1942014-04-29 11:00:17 -070049import java.util.ArrayList;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070050import java.util.Collections;
51import java.util.List;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -070052import java.util.Objects;
Phil Weaverb010b122016-08-17 17:47:48 -070053import java.util.concurrent.atomic.AtomicInteger;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070054
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070055/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070056 * This class represents a node of the window content as well as actions that
57 * can be requested from its source. From the point of view of an
Phil Weaver40ded282016-01-25 15:49:02 -080058 * {@link android.accessibilityservice.AccessibilityService} a window's content is
59 * presented as a tree of accessibility node infos, which may or may not map one-to-one
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070060 * to the view hierarchy. In other words, a custom view is free to report itself as
61 * a tree of accessibility node info.
62 * </p>
63 * <p>
64 * Once an accessibility node info is delivered to an accessibility service it is
65 * made immutable and calling a state mutation method generates an error.
66 * </p>
67 * <p>
68 * Please refer to {@link android.accessibilityservice.AccessibilityService} for
69 * details about how to obtain a handle to window content as a tree of accessibility
Phil Weaver40ded282016-01-25 15:49:02 -080070 * node info as well as details about the security model.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070071 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080072 * <div class="special reference">
73 * <h3>Developer Guides</h3>
74 * <p>For more information about making applications accessible, read the
75 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
76 * developer guide.</p>
77 * </div>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070078 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070079 * @see android.accessibilityservice.AccessibilityService
80 * @see AccessibilityEvent
81 * @see AccessibilityManager
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070082 */
83public class AccessibilityNodeInfo implements Parcelable {
84
85 private static final boolean DEBUG = false;
86
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080087 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080088 public static final int UNDEFINED_CONNECTION_ID = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080089
90 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080091 public static final int UNDEFINED_SELECTION_INDEX = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080092
93 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080094 public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE;
95
96 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -080097 public static final int ROOT_ITEM_ID = Integer.MAX_VALUE - 1;
Svetoslav8e3feb12014-02-24 13:46:47 -080098
99 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -0800100 public static final long UNDEFINED_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800101
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800102 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -0800103 public static final long ROOT_NODE_ID = makeNodeId(ROOT_ITEM_ID,
104 AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav1e0d4af2014-04-10 17:41:29 -0700105
106 /** @hide */
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800107 public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
108
109 /** @hide */
110 public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
111
112 /** @hide */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700113 public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004;
114
115 /** @hide */
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800116 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008;
117
118 /** @hide */
119 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800120
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700121 // Actions.
122
123 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700124 * Action that gives input focus to the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700125 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700126 public static final int ACTION_FOCUS = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700127
128 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700129 * Action that clears input focus of the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700130 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700131 public static final int ACTION_CLEAR_FOCUS = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700132
133 /**
134 * Action that selects the node.
135 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700136 public static final int ACTION_SELECT = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700137
138 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -0700139 * Action that deselects the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700140 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700141 public static final int ACTION_CLEAR_SELECTION = 0x00000008;
142
143 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700144 * Action that clicks on the node info.
Maxim Bogatov219b41d2015-05-01 14:00:24 -0700145 *
146 * See {@link AccessibilityAction#ACTION_CLICK}
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700147 */
148 public static final int ACTION_CLICK = 0x00000010;
149
150 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700151 * Action that long clicks on the node.
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700152 */
153 public static final int ACTION_LONG_CLICK = 0x00000020;
154
155 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700156 * Action that gives accessibility focus to the node.
157 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700158 public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700159
160 /**
161 * Action that clears accessibility focus of the node.
162 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700163 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700164
165 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700166 * Action that requests to go to the next entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700167 * at a given movement granularity. For example, move to the next character,
168 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700169 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800170 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
171 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
172 * <strong>Example:</strong> Move to the previous character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700173 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700174 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700175 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
176 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800177 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
178 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700179 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700180 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700181 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700182 *
Svetoslav7c512842013-01-30 23:02:08 -0800183 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
184 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
185 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700186 * @see #setMovementGranularities(int)
187 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700188 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700189 * @see #MOVEMENT_GRANULARITY_CHARACTER
190 * @see #MOVEMENT_GRANULARITY_WORD
191 * @see #MOVEMENT_GRANULARITY_LINE
192 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
193 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700194 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700195 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700196
197 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700198 * Action that requests to go to the previous entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700199 * at a given movement granularity. For example, move to the next character,
200 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700201 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800202 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
203 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
204 * <strong>Example:</strong> Move to the next character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700205 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700206 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700207 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
208 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800209 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
210 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700211 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
212 * arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700213 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700214 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700215 *
Svetoslav7c512842013-01-30 23:02:08 -0800216 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
217 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
218 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700219 * @see #setMovementGranularities(int)
220 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700221 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700222 * @see #MOVEMENT_GRANULARITY_CHARACTER
223 * @see #MOVEMENT_GRANULARITY_WORD
224 * @see #MOVEMENT_GRANULARITY_LINE
225 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
226 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700227 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700228 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700229
230 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700231 * Action to move to the next HTML element of a given type. For example, move
232 * to the BUTTON, INPUT, TABLE, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700233 * <p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700234 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
235 * <strong>Example:</strong>
236 * <code><pre><p>
237 * Bundle arguments = new Bundle();
238 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
239 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
240 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700241 * </p>
242 */
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700243 public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
244
245 /**
246 * Action to move to the previous HTML element of a given type. For example, move
247 * to the BUTTON, INPUT, TABLE, etc.
248 * <p>
249 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
250 * <strong>Example:</strong>
251 * <code><pre><p>
252 * Bundle arguments = new Bundle();
253 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
254 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
255 * </code></pre></p>
256 * </p>
257 */
258 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
259
260 /**
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700261 * Action to scroll the node content forward.
262 */
263 public static final int ACTION_SCROLL_FORWARD = 0x00001000;
264
265 /**
266 * Action to scroll the node content backward.
267 */
268 public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
269
270 /**
Svetoslav7c512842013-01-30 23:02:08 -0800271 * Action to copy the current selection to the clipboard.
272 */
273 public static final int ACTION_COPY = 0x00004000;
274
275 /**
276 * Action to paste the current clipboard content.
277 */
278 public static final int ACTION_PASTE = 0x00008000;
279
280 /**
281 * Action to cut the current selection and place it to the clipboard.
282 */
283 public static final int ACTION_CUT = 0x00010000;
284
285 /**
286 * Action to set the selection. Performing this action with no arguments
287 * clears the selection.
288 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700289 * <strong>Arguments:</strong>
290 * {@link #ACTION_ARGUMENT_SELECTION_START_INT},
Svetoslav7c512842013-01-30 23:02:08 -0800291 * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
292 * <strong>Example:</strong>
293 * <code><pre><p>
294 * Bundle arguments = new Bundle();
295 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
296 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
297 * info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
298 * </code></pre></p>
299 * </p>
300 *
301 * @see #ACTION_ARGUMENT_SELECTION_START_INT
302 * @see #ACTION_ARGUMENT_SELECTION_END_INT
303 */
304 public static final int ACTION_SET_SELECTION = 0x00020000;
305
306 /**
Svetoslav3577a282013-06-06 14:09:10 -0700307 * Action to expand an expandable node.
308 */
309 public static final int ACTION_EXPAND = 0x00040000;
310
311 /**
312 * Action to collapse an expandable node.
313 */
314 public static final int ACTION_COLLAPSE = 0x00080000;
315
316 /**
317 * Action to dismiss a dismissable node.
318 */
319 public static final int ACTION_DISMISS = 0x00100000;
320
Guang Zhu4cd353c2014-02-12 19:54:30 -0800321 /**
322 * Action that sets the text of the node. Performing the action without argument, using <code>
323 * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
324 * cursor at the end of text.
325 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700326 * <strong>Arguments:</strong>
327 * {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800328 * <strong>Example:</strong>
329 * <code><pre><p>
330 * Bundle arguments = new Bundle();
331 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
332 * "android");
333 * info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
334 * </code></pre></p>
335 */
336 public static final int ACTION_SET_TEXT = 0x00200000;
337
Eugene Susla554edd32017-05-24 16:49:59 -0700338 /** @hide */
339 public static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
Kristian Monsen74bc1942014-04-29 11:00:17 -0700340
341 /**
342 * Mask to see if the value is larger than the largest ACTION_ constant
343 */
344 private static final int ACTION_TYPE_MASK = 0xFF000000;
345
Svetoslav3577a282013-06-06 14:09:10 -0700346 // Action arguments
347
348 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700349 * Argument for which movement granularity to be used when traversing the node text.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700350 * <p>
351 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700352 * <strong>Actions:</strong>
353 * <ul>
354 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
355 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
356 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700357 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800358 *
Alan Viverette23f44322015-04-06 16:04:56 -0700359 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
360 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700361 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700362 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
Svetoslav7c512842013-01-30 23:02:08 -0800363 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700364
365 /**
366 * Argument for which HTML element to get moving to the next/previous HTML element.
367 * <p>
368 * <strong>Type:</strong> String<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700369 * <strong>Actions:</strong>
370 * <ul>
371 * <li>{@link AccessibilityAction#ACTION_NEXT_HTML_ELEMENT}</li>
372 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT}</li>
373 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700374 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800375 *
Alan Viverette23f44322015-04-06 16:04:56 -0700376 * @see AccessibilityAction#ACTION_NEXT_HTML_ELEMENT
377 * @see AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700378 */
379 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
Svetoslav7c512842013-01-30 23:02:08 -0800380 "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
381
382 /**
383 * Argument for whether when moving at granularity to extend the selection
384 * or to move it otherwise.
385 * <p>
386 * <strong>Type:</strong> boolean<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700387 * <strong>Actions:</strong>
388 * <ul>
389 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
390 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
391 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800392 *
Alan Viverette23f44322015-04-06 16:04:56 -0700393 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
394 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav7c512842013-01-30 23:02:08 -0800395 */
396 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
397 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
398
399 /**
400 * Argument for specifying the selection start.
401 * <p>
402 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700403 * <strong>Actions:</strong>
404 * <ul>
405 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
406 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800407 *
Alan Viverette23f44322015-04-06 16:04:56 -0700408 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800409 */
410 public static final String ACTION_ARGUMENT_SELECTION_START_INT =
411 "ACTION_ARGUMENT_SELECTION_START_INT";
412
413 /**
414 * Argument for specifying the selection end.
415 * <p>
416 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700417 * <strong>Actions:</strong>
418 * <ul>
419 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
420 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800421 *
Alan Viverette23f44322015-04-06 16:04:56 -0700422 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800423 */
424 public static final String ACTION_ARGUMENT_SELECTION_END_INT =
425 "ACTION_ARGUMENT_SELECTION_END_INT";
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700426
Guang Zhu4cd353c2014-02-12 19:54:30 -0800427 /**
Alan Viverette23f44322015-04-06 16:04:56 -0700428 * Argument for specifying the text content to set.
Guang Zhu4cd353c2014-02-12 19:54:30 -0800429 * <p>
430 * <strong>Type:</strong> CharSequence<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700431 * <strong>Actions:</strong>
432 * <ul>
433 * <li>{@link AccessibilityAction#ACTION_SET_TEXT}</li>
434 * </ul>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800435 *
Alan Viverette23f44322015-04-06 16:04:56 -0700436 * @see AccessibilityAction#ACTION_SET_TEXT
Guang Zhu4cd353c2014-02-12 19:54:30 -0800437 */
438 public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
439 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
440
Alan Viverette23f44322015-04-06 16:04:56 -0700441 /**
442 * Argument for specifying the collection row to make visible on screen.
443 * <p>
444 * <strong>Type:</strong> int<br>
445 * <strong>Actions:</strong>
446 * <ul>
447 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
448 * </ul>
449 *
450 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
451 */
452 public static final String ACTION_ARGUMENT_ROW_INT =
453 "android.view.accessibility.action.ARGUMENT_ROW_INT";
454
455 /**
456 * Argument for specifying the collection column to make visible on screen.
457 * <p>
458 * <strong>Type:</strong> int<br>
459 * <strong>Actions:</strong>
460 * <ul>
461 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
462 * </ul>
463 *
464 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
465 */
466 public static final String ACTION_ARGUMENT_COLUMN_INT =
467 "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
468
Maxim Bogatov32e59d52015-04-30 16:57:33 -0700469 /**
470 * Argument for specifying the progress value to set.
471 * <p>
472 * <strong>Type:</strong> float<br>
473 * <strong>Actions:</strong>
474 * <ul>
475 * <li>{@link AccessibilityAction#ACTION_SET_PROGRESS}</li>
476 * </ul>
477 *
478 * @see AccessibilityAction#ACTION_SET_PROGRESS
479 */
480 public static final String ACTION_ARGUMENT_PROGRESS_VALUE =
481 "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
482
Phil Weaver193520e2016-12-13 09:39:06 -0800483 /**
Phil Weaverf00cd142017-03-03 13:44:00 -0800484 * Argument for specifying the x coordinate to which to move a window.
485 * <p>
486 * <strong>Type:</strong> int<br>
487 * <strong>Actions:</strong>
488 * <ul>
489 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
490 * </ul>
491 *
492 * @see AccessibilityAction#ACTION_MOVE_WINDOW
493 */
494 public static final String ACTION_ARGUMENT_MOVE_WINDOW_X =
Phil Weaverbe2922f2017-04-28 14:58:35 -0700495 "ACTION_ARGUMENT_MOVE_WINDOW_X";
Phil Weaverf00cd142017-03-03 13:44:00 -0800496
497 /**
498 * Argument for specifying the y coordinate to which to move a window.
499 * <p>
500 * <strong>Type:</strong> int<br>
501 * <strong>Actions:</strong>
502 * <ul>
503 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
504 * </ul>
505 *
506 * @see AccessibilityAction#ACTION_MOVE_WINDOW
507 */
508 public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y =
Phil Weaverbe2922f2017-04-28 14:58:35 -0700509 "ACTION_ARGUMENT_MOVE_WINDOW_Y";
Phil Weaverf00cd142017-03-03 13:44:00 -0800510
511 /**
Phil Weaver193520e2016-12-13 09:39:06 -0800512 * Argument to pass the {@link AccessibilityClickableSpan}.
513 * For use with R.id.accessibilityActionClickOnClickableSpan
514 * @hide
515 */
516 public static final String ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN =
517 "android.view.accessibility.action.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN";
518
Svetoslav3577a282013-06-06 14:09:10 -0700519 // Focus types
520
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700521 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700522 * The input focus.
523 */
524 public static final int FOCUS_INPUT = 1;
525
526 /**
527 * The accessibility focus.
528 */
529 public static final int FOCUS_ACCESSIBILITY = 2;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700530
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700531 // Movement granularities
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700532
533 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700534 * Movement granularity bit for traversing the text of a node by character.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700535 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700536 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700537
538 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700539 * Movement granularity bit for traversing the text of a node by word.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700540 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700541 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700542
543 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700544 * Movement granularity bit for traversing the text of a node by line.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700545 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700546 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700547
548 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700549 * Movement granularity bit for traversing the text of a node by paragraph.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700550 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700551 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700552
553 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700554 * Movement granularity bit for traversing the text of a node by page.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700555 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700556 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700557
Phil Weaverc2e28932016-12-08 12:29:25 -0800558 /**
559 * Key used to request and locate extra data for text character location. This key requests that
560 * an array of {@link android.graphics.RectF}s be added to the extras. This request is made with
561 * {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by this request are two
562 * integers: {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and
563 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index must be valid
564 * inside the CharSequence returned by {@link #getText()}, and the length must be positive.
565 * <p>
566 * The data can be retrieved from the {@code Bundle} returned by {@link #getExtras()} using this
567 * string as a key for {@link Bundle#getParcelableArray(String)}. The
568 * {@link android.graphics.RectF} will be null for characters that either do not exist or are
569 * off the screen.
570 *
571 * {@see #refreshWithExtraData(String, Bundle)}
572 */
573 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY =
574 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
575
576 /**
577 * Integer argument specifying the start index of the requested text location data. Must be
578 * valid inside the CharSequence returned by {@link #getText()}.
579 *
580 * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
581 */
582 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX =
583 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
584
585 /**
586 * Integer argument specifying the end index of the requested text location data. Must be
587 * positive.
588 *
589 * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
590 */
591 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH =
592 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
593
594 /** @hide */
595 public static final String EXTRA_DATA_REQUESTED_KEY =
596 "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested";
597
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700598 // Boolean attributes.
599
Svetoslavbcc46a02013-02-06 11:56:00 -0800600 private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700601
Svetoslavbcc46a02013-02-06 11:56:00 -0800602 private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700603
Svetoslavbcc46a02013-02-06 11:56:00 -0800604 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700605
Svetoslavbcc46a02013-02-06 11:56:00 -0800606 private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700607
Svetoslavbcc46a02013-02-06 11:56:00 -0800608 private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700609
Svetoslavbcc46a02013-02-06 11:56:00 -0800610 private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700611
Svetoslavbcc46a02013-02-06 11:56:00 -0800612 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700613
Svetoslavbcc46a02013-02-06 11:56:00 -0800614 private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700615
Svetoslavbcc46a02013-02-06 11:56:00 -0800616 private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700617
Svetoslavbcc46a02013-02-06 11:56:00 -0800618 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
Svetoslav Ganova0156172011-06-26 17:55:44 -0700619
Svetoslavbcc46a02013-02-06 11:56:00 -0800620 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700621
Svetoslavbcc46a02013-02-06 11:56:00 -0800622 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
623
624 private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -0700625
Alan Viverette77e9a282013-09-12 17:16:09 -0700626 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
Svetoslav3577a282013-06-06 14:09:10 -0700627
Alan Viverette77e9a282013-09-12 17:16:09 -0700628 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
Svetoslav3577a282013-06-06 14:09:10 -0700629
Alan Viverette77e9a282013-09-12 17:16:09 -0700630 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
Svetoslav3577a282013-06-06 14:09:10 -0700631
Alan Viverette77e9a282013-09-12 17:16:09 -0700632 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
Svetoslav3577a282013-06-06 14:09:10 -0700633
Mady Mellore8608912015-06-05 09:02:55 -0700634 private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
Mady Mellore82067b2015-04-30 09:58:35 -0700635
Casey Burkhardt2d80ae42016-01-31 12:52:23 -0800636 private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
637
Phil Weaver776afc22016-12-21 10:55:13 -0800638 private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
639
Svetoslav Ganov02107852011-10-03 17:06:56 -0700640 /**
641 * Bits that provide the id of a virtual descendant of a view.
642 */
643 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700644 /**
645 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
646 * virtual descendant of a view. Such a descendant does not exist in the view
647 * hierarchy and is only reported via the accessibility APIs.
648 */
649 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
650
Phil Weaver62d20fa2016-09-15 11:05:55 -0700651 private static AtomicInteger sNumInstancesInUse;
Phil Weaverb010b122016-08-17 17:47:48 -0700652
Svetoslav Ganov02107852011-10-03 17:06:56 -0700653 /**
Phil Weavere1951292017-08-18 17:56:04 +0000654 * Gets the accessibility view id which identifies a View in the view three.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700655 *
656 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
657 * @return The accessibility view id part of the node id.
658 *
659 * @hide
660 */
661 public static int getAccessibilityViewId(long accessibilityNodeId) {
662 return (int) accessibilityNodeId;
663 }
664
665 /**
666 * Gets the virtual descendant id which identifies an imaginary view in a
667 * containing View.
668 *
669 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
670 * @return The virtual view id part of the node id.
671 *
672 * @hide
673 */
674 public static int getVirtualDescendantId(long accessibilityNodeId) {
675 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
676 >> VIRTUAL_DESCENDANT_ID_SHIFT);
677 }
678
679 /**
680 * Makes a node id by shifting the <code>virtualDescendantId</code>
681 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
682 * the bitwise or with the <code>accessibilityViewId</code>.
683 *
684 * @param accessibilityViewId A View accessibility id.
685 * @param virtualDescendantId A virtual descendant id.
686 * @return The node id.
687 *
688 * @hide
689 */
690 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
691 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
692 }
693
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700694 // Housekeeping.
695 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800696 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -0700697 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800698
Eugene Susla0eb2b6e2017-05-15 14:06:32 -0700699 private static final AccessibilityNodeInfo DEFAULT = new AccessibilityNodeInfo();
700
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700701 private boolean mSealed;
702
703 // Data.
Phil Weaver23161e72017-04-19 12:16:36 -0700704 private int mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Phil Weaverf00cd142017-03-03 13:44:00 -0800705 private long mSourceNodeId = UNDEFINED_NODE_ID;
706 private long mParentNodeId = UNDEFINED_NODE_ID;
707 private long mLabelForId = UNDEFINED_NODE_ID;
708 private long mLabeledById = UNDEFINED_NODE_ID;
709 private long mTraversalBefore = UNDEFINED_NODE_ID;
710 private long mTraversalAfter = UNDEFINED_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800711
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700712 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700713 private final Rect mBoundsInParent = new Rect();
714 private final Rect mBoundsInScreen = new Rect();
Phil Weaver1f222542016-01-08 11:49:32 -0800715 private int mDrawingOrderInParent;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700716
717 private CharSequence mPackageName;
718 private CharSequence mClassName;
Phil Weaver193520e2016-12-13 09:39:06 -0800719 // Hidden, unparceled value used to hold the original value passed to setText
720 private CharSequence mOriginalText;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700721 private CharSequence mText;
Phil Weaver776afc22016-12-21 10:55:13 -0800722 private CharSequence mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -0700723 private CharSequence mError;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700724 private CharSequence mContentDescription;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700725 private String mViewIdResourceName;
Phil Weaverc2e28932016-12-08 12:29:25 -0800726 private ArrayList<String> mExtraDataKeys;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700727
Alan Viverettef0aed092013-11-06 15:33:03 -0800728 private LongArray mChildNodeIds;
Kristian Monsen74bc1942014-04-29 11:00:17 -0700729 private ArrayList<AccessibilityAction> mActions;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700730
Alan Viverette029942f2014-08-12 14:55:56 -0700731 private int mMaxTextLength = -1;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700732 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700733
Svetoslav8e3feb12014-02-24 13:46:47 -0800734 private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
735 private int mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
Svetoslav6254f482013-06-04 17:22:14 -0700736 private int mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -0700737 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav6254f482013-06-04 17:22:14 -0700738
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -0700739 private Bundle mExtras;
Svetoslavbcc46a02013-02-06 11:56:00 -0800740
Svetoslav8e3feb12014-02-24 13:46:47 -0800741 private int mConnectionId = UNDEFINED_CONNECTION_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700742
Svetoslav3577a282013-06-06 14:09:10 -0700743 private RangeInfo mRangeInfo;
744 private CollectionInfo mCollectionInfo;
745 private CollectionItemInfo mCollectionItemInfo;
746
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700747 /**
748 * Hide constructor from clients.
749 */
750 private AccessibilityNodeInfo() {
751 /* do nothing */
752 }
753
754 /**
755 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700756 * <p>
757 * <strong>Note:</strong> Cannot be called from an
758 * {@link android.accessibilityservice.AccessibilityService}.
759 * This class is made immutable before being delivered to an AccessibilityService.
760 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700761 *
762 * @param source The info source.
763 */
764 public void setSource(View source) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800765 setSource(source, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700766 }
767
768 /**
769 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700770 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700771 * is set as the source.
772 * <p>
773 * A virtual descendant is an imaginary View that is reported as a part of the view
774 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700775 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700776 * logical structure.
777 * </p>
778 * <p>
779 * <strong>Note:</strong> Cannot be called from an
780 * {@link android.accessibilityservice.AccessibilityService}.
781 * This class is made immutable before being delivered to an AccessibilityService.
782 * </p>
783 *
784 * @param root The root of the virtual subtree.
785 * @param virtualDescendantId The id of the virtual descendant.
786 */
787 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700788 enforceNotSealed();
Svetoslav8e3feb12014-02-24 13:46:47 -0800789 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700790 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -0800791 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700792 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700793 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700794
Svetoslav Ganov42138042012-03-20 11:51:39 -0700795 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700796 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700797 * the view represented by this node info.
798 *
799 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
800 * {@link #FOCUS_ACCESSIBILITY}.
801 * @return The node info of the focused view or null.
802 *
803 * @see #FOCUS_INPUT
804 * @see #FOCUS_ACCESSIBILITY
805 */
806 public AccessibilityNodeInfo findFocus(int focus) {
807 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700808 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700809 if (!canPerformRequestOverConnection(mSourceNodeId)) {
810 return null;
811 }
812 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
813 mSourceNodeId, focus);
814 }
815
816 /**
817 * Searches for the nearest view in the specified direction that can take
818 * the input focus.
819 *
820 * @param direction The direction. Can be one of:
821 * {@link View#FOCUS_DOWN},
822 * {@link View#FOCUS_UP},
823 * {@link View#FOCUS_LEFT},
824 * {@link View#FOCUS_RIGHT},
825 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700826 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700827 *
828 * @return The node info for the view that can take accessibility focus.
829 */
830 public AccessibilityNodeInfo focusSearch(int direction) {
831 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700832 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700833 if (!canPerformRequestOverConnection(mSourceNodeId)) {
834 return null;
835 }
836 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
837 mSourceNodeId, direction);
838 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700839
840 /**
841 * Gets the id of the window from which the info comes from.
842 *
843 * @return The window id.
844 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700845 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700846 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700847 }
848
849 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800850 * Refreshes this info with the latest state of the view it represents.
851 * <p>
852 * <strong>Note:</strong> If this method returns false this info is obsolete
853 * since it represents a view that is no longer in the view tree and should
854 * be recycled.
855 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700856 *
857 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800858 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700859 *
860 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800861 */
Phil Weaverc2e28932016-12-08 12:29:25 -0800862 public boolean refresh(Bundle arguments, boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800863 enforceSealed();
864 if (!canPerformRequestOverConnection(mSourceNodeId)) {
865 return false;
866 }
867 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
868 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Phil Weaverc2e28932016-12-08 12:29:25 -0800869 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0, arguments);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800870 if (refreshedInfo == null) {
871 return false;
872 }
Phil Weavercc797d52017-08-21 12:45:11 -0700873 // Hard-to-reproduce bugs seem to be due to some tools recycling a node on another
874 // thread. If that happens, the init will re-seal the node, which then is in a bad state
875 // when it is obtained. Enforce sealing again before we init to fail when a node has been
876 // recycled during a refresh to catch such errors earlier.
877 enforceSealed();
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800878 init(refreshedInfo);
879 refreshedInfo.recycle();
880 return true;
881 }
882
883 /**
Svetoslav6254f482013-06-04 17:22:14 -0700884 * Refreshes this info with the latest state of the view it represents.
Phil Weaverc2e28932016-12-08 12:29:25 -0800885 *
886 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
887 * by this node is no longer in the view tree (and thus this node is obsolete and should be
888 * recycled).
Svetoslav6254f482013-06-04 17:22:14 -0700889 */
890 public boolean refresh() {
Phil Weaverc2e28932016-12-08 12:29:25 -0800891 return refresh(null, true);
892 }
893
894 /**
895 * Refreshes this info with the latest state of the view it represents, and request new
896 * data be added by the View.
897 *
898 * @param extraDataKey A bitmask of the extra data requested. Data that must be requested
899 * with this mechanism is generally expensive to retrieve, so should only be
900 * requested when needed. See
901 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
902 * {@link #getAvailableExtraData()}.
903 * @param args A bundle of arguments for the request. These depend on the particular request.
904 *
905 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
906 * by this node is no longer in the view tree (and thus this node is obsolete and should be
907 * recycled).
908 */
909 public boolean refreshWithExtraData(String extraDataKey, Bundle args) {
910 args.putString(EXTRA_DATA_REQUESTED_KEY, extraDataKey);
911 return refresh(args, true);
Svetoslav6254f482013-06-04 17:22:14 -0700912 }
913
914 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800915 * Returns the array containing the IDs of this node's children.
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800916 *
917 * @hide
918 */
Alan Viverettef0aed092013-11-06 15:33:03 -0800919 public LongArray getChildNodeIds() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800920 return mChildNodeIds;
921 }
922
923 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800924 * Returns the id of the child at the specified index.
925 *
926 * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt;=
927 * getChildCount()
928 * @hide
929 */
930 public long getChildId(int index) {
931 if (mChildNodeIds == null) {
932 throw new IndexOutOfBoundsException();
933 }
934 return mChildNodeIds.get(index);
935 }
936
937 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700938 * Gets the number of children.
939 *
940 * @return The child count.
941 */
942 public int getChildCount() {
Alan Viverettef0aed092013-11-06 15:33:03 -0800943 return mChildNodeIds == null ? 0 : mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700944 }
945
946 /**
947 * Get the child at given index.
948 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700949 * <strong>Note:</strong> It is a client responsibility to recycle the
950 * received info by calling {@link AccessibilityNodeInfo#recycle()}
951 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700952 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700953 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700954 * @param index The child index.
955 * @return The child node.
956 *
957 * @throws IllegalStateException If called outside of an AccessibilityService.
958 *
959 */
960 public AccessibilityNodeInfo getChild(int index) {
961 enforceSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -0800962 if (mChildNodeIds == null) {
963 return null;
964 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700965 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700966 return null;
967 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800968 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700969 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800970 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Phil Weaverc2e28932016-12-08 12:29:25 -0800971 childId, false, FLAG_PREFETCH_DESCENDANTS, null);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700972 }
973
974 /**
975 * Adds a child.
976 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700977 * <strong>Note:</strong> Cannot be called from an
978 * {@link android.accessibilityservice.AccessibilityService}.
979 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700980 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700981 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700982 * @param child The child.
983 *
984 * @throws IllegalStateException If called from an AccessibilityService.
985 */
986 public void addChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800987 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, true);
Alan Viverettef0aed092013-11-06 15:33:03 -0800988 }
989
990 /**
991 * Unchecked version of {@link #addChild(View)} that does not verify
992 * uniqueness. For framework use only.
993 *
994 * @hide
995 */
996 public void addChildUnchecked(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800997 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, false);
Alan Viverettef0aed092013-11-06 15:33:03 -0800998 }
999
1000 /**
1001 * Removes a child. If the child was not previously added to the node,
1002 * calling this method has no effect.
1003 * <p>
1004 * <strong>Note:</strong> Cannot be called from an
1005 * {@link android.accessibilityservice.AccessibilityService}.
1006 * This class is made immutable before being delivered to an AccessibilityService.
1007 * </p>
1008 *
1009 * @param child The child.
1010 * @return true if the child was present
1011 *
1012 * @throws IllegalStateException If called from an AccessibilityService.
1013 */
1014 public boolean removeChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001015 return removeChild(child, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001016 }
1017
1018 /**
1019 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -07001020 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -07001021 * is added as a child.
1022 * <p>
1023 * A virtual descendant is an imaginary View that is reported as a part of the view
1024 * hierarchy for accessibility purposes. This enables custom views that draw complex
1025 * content to report them selves as a tree of virtual views, thus conveying their
1026 * logical structure.
1027 * </p>
1028 *
1029 * @param root The root of the virtual subtree.
1030 * @param virtualDescendantId The id of the virtual child.
1031 */
1032 public void addChild(View root, int virtualDescendantId) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001033 addChildInternal(root, virtualDescendantId, true);
1034 }
1035
1036 private void addChildInternal(View root, int virtualDescendantId, boolean checked) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001037 enforceNotSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -08001038 if (mChildNodeIds == null) {
1039 mChildNodeIds = new LongArray();
1040 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07001041 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001042 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001043 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Alan Viverettef0aed092013-11-06 15:33:03 -08001044 // If we're checking uniqueness and the ID already exists, abort.
1045 if (checked && mChildNodeIds.indexOf(childNodeId) >= 0) {
1046 return;
1047 }
1048 mChildNodeIds.add(childNodeId);
1049 }
1050
1051 /**
1052 * Removes a virtual child which is a descendant of the given
1053 * <code>root</code>. If the child was not previously added to the node,
1054 * calling this method has no effect.
1055 *
1056 * @param root The root of the virtual subtree.
1057 * @param virtualDescendantId The id of the virtual child.
1058 * @return true if the child was present
1059 * @see #addChild(View, int)
1060 */
1061 public boolean removeChild(View root, int virtualDescendantId) {
1062 enforceNotSealed();
1063 final LongArray childIds = mChildNodeIds;
1064 if (childIds == null) {
1065 return false;
1066 }
1067 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001068 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Alan Viverettef0aed092013-11-06 15:33:03 -08001069 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1070 final int index = childIds.indexOf(childNodeId);
1071 if (index < 0) {
1072 return false;
1073 }
1074 childIds.remove(index);
1075 return true;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001076 }
1077
1078 /**
1079 * Gets the actions that can be performed on the node.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001080 */
1081 public List<AccessibilityAction> getActionList() {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07001082 return CollectionUtils.emptyIfNull(mActions);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001083 }
1084
1085 /**
1086 * Gets the actions that can be performed on the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001087 *
1088 * @return The bit mask of with actions.
1089 *
1090 * @see AccessibilityNodeInfo#ACTION_FOCUS
1091 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
1092 * @see AccessibilityNodeInfo#ACTION_SELECT
1093 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07001094 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
1095 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
1096 * @see AccessibilityNodeInfo#ACTION_CLICK
1097 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
1098 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1099 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1100 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
1101 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
1102 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
1103 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Kristian Monsen74bc1942014-04-29 11:00:17 -07001104 *
1105 * @deprecated Use {@link #getActionList()}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001106 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001107 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001108 public int getActions() {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001109 int returnValue = 0;
1110
1111 if (mActions == null) {
1112 return returnValue;
1113 }
1114
1115 final int actionSize = mActions.size();
1116 for (int i = 0; i < actionSize; i++) {
1117 int actionId = mActions.get(i).getId();
1118 if (actionId <= LAST_LEGACY_STANDARD_ACTION) {
1119 returnValue |= actionId;
1120 }
1121 }
1122
1123 return returnValue;
1124 }
1125
1126 /**
1127 * Adds an action that can be performed on the node.
1128 * <p>
1129 * To add a standard action use the static constants on {@link AccessibilityAction}.
1130 * To add a custom action create a new {@link AccessibilityAction} by passing in a
1131 * resource id from your application as the action id and an optional label that
1132 * describes the action. To override one of the standard actions use as the action
1133 * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that
1134 * describes the action.
1135 * </p>
1136 * <p>
1137 * <strong>Note:</strong> Cannot be called from an
1138 * {@link android.accessibilityservice.AccessibilityService}.
1139 * This class is made immutable before being delivered to an AccessibilityService.
1140 * </p>
1141 *
1142 * @param action The action.
1143 *
1144 * @throws IllegalStateException If called from an AccessibilityService.
1145 */
1146 public void addAction(AccessibilityAction action) {
1147 enforceNotSealed();
1148
Alan Viverettec921f272015-05-14 12:26:49 -07001149 addActionUnchecked(action);
1150 }
1151
1152 private void addActionUnchecked(AccessibilityAction action) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001153 if (action == null) {
1154 return;
1155 }
1156
1157 if (mActions == null) {
Alan Viverette23f44322015-04-06 16:04:56 -07001158 mActions = new ArrayList<>();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001159 }
1160
1161 mActions.remove(action);
1162 mActions.add(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001163 }
1164
1165 /**
1166 * Adds an action that can be performed on the node.
1167 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001168 * <strong>Note:</strong> Cannot be called from an
1169 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001170 * This class is made immutable before being delivered to an AccessibilityService.
1171 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001172 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001173 * @param action The action.
1174 *
1175 * @throws IllegalStateException If called from an AccessibilityService.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001176 * @throws IllegalArgumentException If the argument is not one of the standard actions.
1177 *
1178 * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)}
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001179 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001180 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001181 public void addAction(int action) {
1182 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001183
Kristian Monsen8d5f3fa2014-05-20 13:16:19 -07001184 if ((action & ACTION_TYPE_MASK) != 0) {
1185 throw new IllegalArgumentException("Action is not a combination of the standard " +
1186 "actions: " + action);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001187 }
1188
Eugene Susla554edd32017-05-24 16:49:59 -07001189 addStandardActions(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001190 }
1191
1192 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08001193 * Removes an action that can be performed on the node. If the action was
1194 * not already added to the node, calling this method has no effect.
1195 * <p>
1196 * <strong>Note:</strong> Cannot be called from an
1197 * {@link android.accessibilityservice.AccessibilityService}.
1198 * This class is made immutable before being delivered to an AccessibilityService.
1199 * </p>
1200 *
Kristian Monsen74bc1942014-04-29 11:00:17 -07001201 * @param action The action to be removed.
1202 *
1203 * @throws IllegalStateException If called from an AccessibilityService.
1204 * @deprecated Use {@link #removeAction(AccessibilityAction)}
1205 */
1206 @Deprecated
1207 public void removeAction(int action) {
1208 enforceNotSealed();
1209
1210 removeAction(getActionSingleton(action));
1211 }
1212
1213 /**
1214 * Removes an action that can be performed on the node. If the action was
1215 * not already added to the node, calling this method has no effect.
1216 * <p>
1217 * <strong>Note:</strong> Cannot be called from an
1218 * {@link android.accessibilityservice.AccessibilityService}.
1219 * This class is made immutable before being delivered to an AccessibilityService.
1220 * </p>
1221 *
1222 * @param action The action to be removed.
1223 * @return The action removed from the list of actions.
Alan Viverettef0aed092013-11-06 15:33:03 -08001224 *
1225 * @throws IllegalStateException If called from an AccessibilityService.
1226 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001227 public boolean removeAction(AccessibilityAction action) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001228 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001229
1230 if (mActions == null || action == null) {
1231 return false;
1232 }
1233
1234 return mActions.remove(action);
Alan Viverettef0aed092013-11-06 15:33:03 -08001235 }
1236
1237 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08001238 * Removes all actions.
1239 *
1240 * @hide
1241 */
1242 public void removeAllActions() {
1243 if (mActions != null) {
1244 mActions.clear();
1245 }
1246 }
1247
1248 /**
Svetoslav6c702902014-10-09 18:40:56 -07001249 * Gets the node before which this one is visited during traversal. A screen-reader
1250 * must visit the content of this node before the content of the one it precedes.
1251 *
1252 * @return The succeeding node if such or <code>null</code>.
1253 *
1254 * @see #setTraversalBefore(android.view.View)
1255 * @see #setTraversalBefore(android.view.View, int)
1256 */
1257 public AccessibilityNodeInfo getTraversalBefore() {
1258 enforceSealed();
1259 return getNodeForAccessibilityId(mTraversalBefore);
1260 }
1261
1262 /**
1263 * Sets the view before whose node this one should be visited during traversal. A
1264 * screen-reader must visit the content of this node before the content of the one
1265 * it precedes.
1266 * <p>
1267 * <strong>Note:</strong> Cannot be called from an
1268 * {@link android.accessibilityservice.AccessibilityService}.
1269 * This class is made immutable before being delivered to an AccessibilityService.
1270 * </p>
1271 *
1272 * @param view The view providing the preceding node.
1273 *
1274 * @see #getTraversalBefore()
1275 */
1276 public void setTraversalBefore(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001277 setTraversalBefore(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001278 }
1279
1280 /**
1281 * Sets the node before which this one is visited during traversal. A screen-reader
1282 * must visit the content of this node before the content of the one it precedes.
1283 * The successor is a virtual descendant of the given <code>root</code>. If
1284 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
1285 * as the successor.
1286 * <p>
1287 * A virtual descendant is an imaginary View that is reported as a part of the view
1288 * hierarchy for accessibility purposes. This enables custom views that draw complex
1289 * content to report them selves as a tree of virtual views, thus conveying their
1290 * logical structure.
1291 * </p>
1292 * <p>
1293 * <strong>Note:</strong> Cannot be called from an
1294 * {@link android.accessibilityservice.AccessibilityService}.
1295 * This class is made immutable before being delivered to an AccessibilityService.
1296 * </p>
1297 *
1298 * @param root The root of the virtual subtree.
1299 * @param virtualDescendantId The id of the virtual descendant.
1300 */
1301 public void setTraversalBefore(View root, int virtualDescendantId) {
1302 enforceNotSealed();
1303 final int rootAccessibilityViewId = (root != null)
1304 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1305 mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1306 }
1307
1308 /**
1309 * Gets the node after which this one is visited in accessibility traversal.
1310 * A screen-reader must visit the content of the other node before the content
1311 * of this one.
1312 *
1313 * @return The succeeding node if such or <code>null</code>.
1314 *
1315 * @see #setTraversalAfter(android.view.View)
1316 * @see #setTraversalAfter(android.view.View, int)
1317 */
1318 public AccessibilityNodeInfo getTraversalAfter() {
1319 enforceSealed();
1320 return getNodeForAccessibilityId(mTraversalAfter);
1321 }
1322
1323 /**
1324 * Sets the view whose node is visited after this one in accessibility traversal.
1325 * A screen-reader must visit the content of the other node before the content
1326 * of this one.
1327 * <p>
1328 * <strong>Note:</strong> Cannot be called from an
1329 * {@link android.accessibilityservice.AccessibilityService}.
1330 * This class is made immutable before being delivered to an AccessibilityService.
1331 * </p>
1332 *
1333 * @param view The previous view.
1334 *
1335 * @see #getTraversalAfter()
1336 */
1337 public void setTraversalAfter(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001338 setTraversalAfter(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001339 }
1340
1341 /**
1342 * Sets the node after which this one is visited in accessibility traversal.
1343 * A screen-reader must visit the content of the other node before the content
1344 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
1345 * the root is set as the predecessor.
1346 * <p>
1347 * A virtual descendant is an imaginary View that is reported as a part of the view
1348 * hierarchy for accessibility purposes. This enables custom views that draw complex
1349 * content to report them selves as a tree of virtual views, thus conveying their
1350 * logical structure.
1351 * </p>
1352 * <p>
1353 * <strong>Note:</strong> Cannot be called from an
1354 * {@link android.accessibilityservice.AccessibilityService}.
1355 * This class is made immutable before being delivered to an AccessibilityService.
1356 * </p>
1357 *
1358 * @param root The root of the virtual subtree.
1359 * @param virtualDescendantId The id of the virtual descendant.
1360 */
1361 public void setTraversalAfter(View root, int virtualDescendantId) {
1362 enforceNotSealed();
1363 final int rootAccessibilityViewId = (root != null)
1364 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1365 mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1366 }
1367
1368 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08001369 * Get the extra data available for this node.
1370 * <p>
1371 * Some data that is useful for some accessibility services is expensive to compute, and would
1372 * place undue overhead on apps to compute all the time. That data can be requested with
1373 * {@link #refreshWithExtraData(String, Bundle)}.
1374 *
1375 * @return An unmodifiable list of keys corresponding to extra data that can be requested.
1376 * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
1377 */
1378 public List<String> getAvailableExtraData() {
1379 if (mExtraDataKeys != null) {
1380 return Collections.unmodifiableList(mExtraDataKeys);
1381 } else {
1382 return EMPTY_LIST;
1383 }
1384 }
1385
1386 /**
1387 * Set the extra data available for this node.
1388 * <p>
1389 * <strong>Note:</strong> When a {@code View} passes in a non-empty list, it promises that
1390 * it will populate the node's extras with corresponding pieces of information in
1391 * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)}.
1392 * <p>
1393 * <strong>Note:</strong> Cannot be called from an
1394 * {@link android.accessibilityservice.AccessibilityService}.
1395 * This class is made immutable before being delivered to an AccessibilityService.
1396 *
1397 * @param extraDataKeys A list of types of extra data that are available.
1398 * @see #getAvailableExtraData()
1399 *
1400 * @throws IllegalStateException If called from an AccessibilityService.
1401 */
1402 public void setAvailableExtraData(List<String> extraDataKeys) {
1403 enforceNotSealed();
1404 mExtraDataKeys = new ArrayList<>(extraDataKeys);
1405 }
1406
1407 /**
Alan Viverette029942f2014-08-12 14:55:56 -07001408 * Sets the maximum text length, or -1 for no limit.
1409 * <p>
1410 * Typically used to indicate that an editable text field has a limit on
1411 * the number of characters entered.
1412 * <p>
1413 * <strong>Note:</strong> Cannot be called from an
1414 * {@link android.accessibilityservice.AccessibilityService}.
1415 * This class is made immutable before being delivered to an AccessibilityService.
1416 *
1417 * @param max The maximum text length.
1418 * @see #getMaxTextLength()
1419 *
1420 * @throws IllegalStateException If called from an AccessibilityService.
1421 */
1422 public void setMaxTextLength(int max) {
1423 enforceNotSealed();
1424 mMaxTextLength = max;
1425 }
1426
1427 /**
1428 * Returns the maximum text length for this node.
1429 *
1430 * @return The maximum text length, or -1 for no limit.
1431 * @see #setMaxTextLength(int)
1432 */
1433 public int getMaxTextLength() {
1434 return mMaxTextLength;
1435 }
1436
1437 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001438 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001439 * <p>
1440 * <strong>Note:</strong> Cannot be called from an
1441 * {@link android.accessibilityservice.AccessibilityService}.
1442 * This class is made immutable before being delivered to an AccessibilityService.
1443 * </p>
1444 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001445 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001446 *
1447 * @throws IllegalStateException If called from an AccessibilityService.
1448 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001449 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001450 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001451 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001452 }
1453
1454 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001455 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001456 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001457 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001458 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001459 public int getMovementGranularities() {
1460 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001461 }
1462
1463 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001464 * Performs an action on the node.
1465 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001466 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001467 * from an {@link android.accessibilityservice.AccessibilityService}.
1468 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001469 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001470 * @param action The action to perform.
1471 * @return True if the action was performed.
1472 *
1473 * @throws IllegalStateException If called outside of an AccessibilityService.
1474 */
1475 public boolean performAction(int action) {
1476 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001477 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001478 return false;
1479 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001480 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001481 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1482 action, null);
1483 }
1484
1485 /**
1486 * Performs an action on the node.
1487 * <p>
1488 * <strong>Note:</strong> An action can be performed only if the request is made
1489 * from an {@link android.accessibilityservice.AccessibilityService}.
1490 * </p>
1491 *
1492 * @param action The action to perform.
1493 * @param arguments A bundle with additional arguments.
1494 * @return True if the action was performed.
1495 *
1496 * @throws IllegalStateException If called outside of an AccessibilityService.
1497 */
1498 public boolean performAction(int action, Bundle arguments) {
1499 enforceSealed();
1500 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1501 return false;
1502 }
1503 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1504 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1505 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001506 }
1507
1508 /**
1509 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001510 * insensitive containment. The search is relative to this info i.e.
1511 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07001512 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001513 * <p>
1514 * <strong>Note:</strong> It is a client responsibility to recycle the
1515 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1516 * to avoid creating of multiple instances.
1517 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001518 *
1519 * @param text The searched text.
1520 * @return A list of node info.
1521 */
1522 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
1523 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001524 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001525 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001526 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001527 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -08001528 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
1529 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001530 }
1531
1532 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001533 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
1534 * name where a fully qualified id is of the from "package:id/id_resource_name".
1535 * For example, if the target application's package is "foo.bar" and the id
1536 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
1537 *
1538 * <p>
1539 * <strong>Note:</strong> It is a client responsibility to recycle the
1540 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1541 * to avoid creating of multiple instances.
1542 * </p>
1543 * <p>
1544 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1545 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
1546 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001547 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001548 * </p>
1549 *
1550 * @param viewId The fully qualified resource name of the view id to find.
1551 * @return A list of node info.
1552 */
1553 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
1554 enforceSealed();
1555 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1556 return Collections.emptyList();
1557 }
1558 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1559 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
1560 viewId);
1561 }
1562
1563 /**
Svetoslav8e3feb12014-02-24 13:46:47 -08001564 * Gets the window to which this node belongs.
1565 *
1566 * @return The window.
1567 *
1568 * @see android.accessibilityservice.AccessibilityService#getWindows()
1569 */
1570 public AccessibilityWindowInfo getWindow() {
1571 enforceSealed();
1572 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1573 return null;
1574 }
1575 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1576 return client.getWindow(mConnectionId, mWindowId);
1577 }
1578
1579 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001580 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001581 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001582 * <strong>Note:</strong> It is a client responsibility to recycle the
1583 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1584 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001585 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001586 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001587 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001588 */
1589 public AccessibilityNodeInfo getParent() {
1590 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07001591 return getNodeForAccessibilityId(mParentNodeId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08001592 }
1593
1594 /**
1595 * @return The parent node id.
1596 *
1597 * @hide
1598 */
1599 public long getParentNodeId() {
1600 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001601 }
1602
1603 /**
1604 * Sets the parent.
1605 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001606 * <strong>Note:</strong> Cannot be called from an
1607 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001608 * This class is made immutable before being delivered to an AccessibilityService.
1609 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001610 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001611 * @param parent The parent.
1612 *
1613 * @throws IllegalStateException If called from an AccessibilityService.
1614 */
1615 public void setParent(View parent) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001616 setParent(parent, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001617 }
1618
1619 /**
1620 * Sets the parent to be a virtual descendant of the given <code>root</code>.
1621 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1622 * is set as the parent.
1623 * <p>
1624 * A virtual descendant is an imaginary View that is reported as a part of the view
1625 * hierarchy for accessibility purposes. This enables custom views that draw complex
1626 * content to report them selves as a tree of virtual views, thus conveying their
1627 * logical structure.
1628 * </p>
1629 * <p>
1630 * <strong>Note:</strong> Cannot be called from an
1631 * {@link android.accessibilityservice.AccessibilityService}.
1632 * This class is made immutable before being delivered to an AccessibilityService.
1633 * </p>
1634 *
1635 * @param root The root of the virtual subtree.
1636 * @param virtualDescendantId The id of the virtual descendant.
1637 */
1638 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001639 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001640 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001641 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001642 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001643 }
1644
1645 /**
1646 * Gets the node bounds in parent coordinates.
1647 *
1648 * @param outBounds The output node bounds.
1649 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001650 public void getBoundsInParent(Rect outBounds) {
1651 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
1652 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001653 }
1654
1655 /**
1656 * Sets the node bounds in parent coordinates.
1657 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001658 * <strong>Note:</strong> Cannot be called from an
1659 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001660 * This class is made immutable before being delivered to an AccessibilityService.
1661 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001662 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001663 * @param bounds The node bounds.
1664 *
1665 * @throws IllegalStateException If called from an AccessibilityService.
1666 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001667 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001668 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001669 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1670 }
1671
1672 /**
1673 * Gets the node bounds in screen coordinates.
1674 *
1675 * @param outBounds The output node bounds.
1676 */
1677 public void getBoundsInScreen(Rect outBounds) {
1678 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1679 mBoundsInScreen.right, mBoundsInScreen.bottom);
1680 }
1681
1682 /**
Alan Viverettea7ea65e2015-05-15 11:30:21 -07001683 * Returns the actual rect containing the node bounds in screen coordinates.
1684 *
1685 * @hide Not safe to expose outside the framework.
1686 */
1687 public Rect getBoundsInScreen() {
1688 return mBoundsInScreen;
1689 }
1690
1691 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001692 * Sets the node bounds in screen coordinates.
1693 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001694 * <strong>Note:</strong> Cannot be called from an
1695 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001696 * This class is made immutable before being delivered to an AccessibilityService.
1697 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001698 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001699 * @param bounds The node bounds.
1700 *
1701 * @throws IllegalStateException If called from an AccessibilityService.
1702 */
1703 public void setBoundsInScreen(Rect bounds) {
1704 enforceNotSealed();
1705 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001706 }
1707
1708 /**
1709 * Gets whether this node is checkable.
1710 *
1711 * @return True if the node is checkable.
1712 */
1713 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001714 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001715 }
1716
1717 /**
1718 * Sets whether this node is checkable.
1719 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001720 * <strong>Note:</strong> Cannot be called from an
1721 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001722 * This class is made immutable before being delivered to an AccessibilityService.
1723 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001724 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001725 * @param checkable True if the node is checkable.
1726 *
1727 * @throws IllegalStateException If called from an AccessibilityService.
1728 */
1729 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001730 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001731 }
1732
1733 /**
1734 * Gets whether this node is checked.
1735 *
1736 * @return True if the node is checked.
1737 */
1738 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001739 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001740 }
1741
1742 /**
1743 * Sets whether this node is checked.
1744 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001745 * <strong>Note:</strong> Cannot be called from an
1746 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001747 * This class is made immutable before being delivered to an AccessibilityService.
1748 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001749 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001750 * @param checked True if the node is checked.
1751 *
1752 * @throws IllegalStateException If called from an AccessibilityService.
1753 */
1754 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001755 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001756 }
1757
1758 /**
1759 * Gets whether this node is focusable.
1760 *
1761 * @return True if the node is focusable.
1762 */
1763 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001764 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001765 }
1766
1767 /**
1768 * Sets whether this node is focusable.
1769 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001770 * <strong>Note:</strong> Cannot be called from an
1771 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001772 * This class is made immutable before being delivered to an AccessibilityService.
1773 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001774 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001775 * @param focusable True if the node is focusable.
1776 *
1777 * @throws IllegalStateException If called from an AccessibilityService.
1778 */
1779 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001780 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001781 }
1782
1783 /**
1784 * Gets whether this node is focused.
1785 *
1786 * @return True if the node is focused.
1787 */
1788 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001789 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001790 }
1791
1792 /**
1793 * Sets whether this node is focused.
1794 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001795 * <strong>Note:</strong> Cannot be called from an
1796 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001797 * This class is made immutable before being delivered to an AccessibilityService.
1798 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001799 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001800 * @param focused True if the node is focused.
1801 *
1802 * @throws IllegalStateException If called from an AccessibilityService.
1803 */
1804 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001805 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001806 }
1807
1808 /**
Alan Viverette1579edc2015-04-01 13:23:06 -07001809 * Gets whether this node is visible to the user.
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001810 *
1811 * @return Whether the node is visible to the user.
1812 */
1813 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001814 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001815 }
1816
1817 /**
1818 * Sets whether this node is visible to the user.
1819 * <p>
1820 * <strong>Note:</strong> Cannot be called from an
1821 * {@link android.accessibilityservice.AccessibilityService}.
1822 * This class is made immutable before being delivered to an AccessibilityService.
1823 * </p>
1824 *
1825 * @param visibleToUser Whether the node is visible to the user.
1826 *
1827 * @throws IllegalStateException If called from an AccessibilityService.
1828 */
1829 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001830 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001831 }
1832
1833 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001834 * Gets whether this node is accessibility focused.
1835 *
1836 * @return True if the node is accessibility focused.
1837 */
1838 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001839 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001840 }
1841
1842 /**
1843 * Sets whether this node is accessibility focused.
1844 * <p>
1845 * <strong>Note:</strong> Cannot be called from an
1846 * {@link android.accessibilityservice.AccessibilityService}.
1847 * This class is made immutable before being delivered to an AccessibilityService.
1848 * </p>
1849 *
1850 * @param focused True if the node is accessibility focused.
1851 *
1852 * @throws IllegalStateException If called from an AccessibilityService.
1853 */
1854 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001855 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001856 }
1857
1858 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001859 * Gets whether this node is selected.
1860 *
1861 * @return True if the node is selected.
1862 */
1863 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001864 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001865 }
1866
1867 /**
1868 * Sets whether this node is selected.
1869 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001870 * <strong>Note:</strong> Cannot be called from an
1871 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001872 * This class is made immutable before being delivered to an AccessibilityService.
1873 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001874 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001875 * @param selected True if the node is selected.
1876 *
1877 * @throws IllegalStateException If called from an AccessibilityService.
1878 */
1879 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001880 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001881 }
1882
1883 /**
1884 * Gets whether this node is clickable.
1885 *
1886 * @return True if the node is clickable.
1887 */
1888 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001889 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001890 }
1891
1892 /**
1893 * Sets whether this node is clickable.
1894 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001895 * <strong>Note:</strong> Cannot be called from an
1896 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001897 * This class is made immutable before being delivered to an AccessibilityService.
1898 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001899 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001900 * @param clickable True if the node is clickable.
1901 *
1902 * @throws IllegalStateException If called from an AccessibilityService.
1903 */
1904 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001905 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001906 }
1907
1908 /**
1909 * Gets whether this node is long clickable.
1910 *
1911 * @return True if the node is long clickable.
1912 */
1913 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001914 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001915 }
1916
1917 /**
1918 * Sets whether this node is long clickable.
1919 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001920 * <strong>Note:</strong> Cannot be called from an
1921 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001922 * This class is made immutable before being delivered to an AccessibilityService.
1923 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001924 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001925 * @param longClickable True if the node is long clickable.
1926 *
1927 * @throws IllegalStateException If called from an AccessibilityService.
1928 */
1929 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001930 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001931 }
1932
1933 /**
1934 * Gets whether this node is enabled.
1935 *
1936 * @return True if the node is enabled.
1937 */
1938 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001939 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001940 }
1941
1942 /**
1943 * Sets whether this node is enabled.
1944 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001945 * <strong>Note:</strong> Cannot be called from an
1946 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001947 * This class is made immutable before being delivered to an AccessibilityService.
1948 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001949 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001950 * @param enabled True if the node is enabled.
1951 *
1952 * @throws IllegalStateException If called from an AccessibilityService.
1953 */
1954 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001955 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001956 }
1957
1958 /**
1959 * Gets whether this node is a password.
1960 *
1961 * @return True if the node is a password.
1962 */
1963 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001964 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001965 }
1966
1967 /**
1968 * Sets whether this node is a password.
1969 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001970 * <strong>Note:</strong> Cannot be called from an
1971 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001972 * This class is made immutable before being delivered to an AccessibilityService.
1973 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001974 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001975 * @param password True if the node is a password.
1976 *
1977 * @throws IllegalStateException If called from an AccessibilityService.
1978 */
1979 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001980 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001981 }
1982
1983 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001984 * Gets if the node is scrollable.
1985 *
1986 * @return True if the node is scrollable, false otherwise.
1987 */
1988 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001989 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001990 }
1991
1992 /**
1993 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001994 * <p>
1995 * <strong>Note:</strong> Cannot be called from an
1996 * {@link android.accessibilityservice.AccessibilityService}.
1997 * This class is made immutable before being delivered to an AccessibilityService.
1998 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07001999 *
2000 * @param scrollable True if the node is scrollable, false otherwise.
2001 *
2002 * @throws IllegalStateException If called from an AccessibilityService.
2003 */
2004 public void setScrollable(boolean scrollable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08002005 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
2006 }
2007
2008 /**
2009 * Gets if the node is editable.
2010 *
2011 * @return True if the node is editable, false otherwise.
2012 */
2013 public boolean isEditable() {
2014 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
2015 }
2016
2017 /**
2018 * Sets whether this node is editable.
2019 * <p>
2020 * <strong>Note:</strong> Cannot be called from an
2021 * {@link android.accessibilityservice.AccessibilityService}.
2022 * This class is made immutable before being delivered to an AccessibilityService.
2023 * </p>
2024 *
2025 * @param editable True if the node is editable.
2026 *
2027 * @throws IllegalStateException If called from an AccessibilityService.
2028 */
2029 public void setEditable(boolean editable) {
2030 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07002031 }
2032
2033 /**
Phil Weaver1f222542016-01-08 11:49:32 -08002034 * Get the drawing order of the view corresponding it this node.
2035 * <p>
2036 * Drawing order is determined only within the node's parent, so this index is only relative
2037 * to its siblings.
2038 * <p>
2039 * In some cases, the drawing order is essentially simultaneous, so it is possible for two
2040 * siblings to return the same value. It is also possible that values will be skipped.
2041 *
2042 * @return The drawing position of the view corresponding to this node relative to its siblings.
2043 */
2044 public int getDrawingOrder() {
2045 return mDrawingOrderInParent;
2046 }
2047
2048 /**
2049 * Set the drawing order of the view corresponding it this node.
2050 *
2051 * <p>
2052 * <strong>Note:</strong> Cannot be called from an
2053 * {@link android.accessibilityservice.AccessibilityService}.
2054 * This class is made immutable before being delivered to an AccessibilityService.
2055 * </p>
2056 * @param drawingOrderInParent
2057 * @throws IllegalStateException If called from an AccessibilityService.
2058 */
2059 public void setDrawingOrder(int drawingOrderInParent) {
2060 enforceNotSealed();
2061 mDrawingOrderInParent = drawingOrderInParent;
2062 }
2063
2064 /**
Svetoslav3577a282013-06-06 14:09:10 -07002065 * Gets the collection info if the node is a collection. A collection
2066 * child is always a collection item.
2067 *
2068 * @return The collection info.
2069 */
2070 public CollectionInfo getCollectionInfo() {
2071 return mCollectionInfo;
2072 }
2073
2074 /**
2075 * Sets the collection info if the node is a collection. A collection
2076 * child is always a collection item.
2077 * <p>
2078 * <strong>Note:</strong> Cannot be called from an
2079 * {@link android.accessibilityservice.AccessibilityService}.
2080 * This class is made immutable before being delivered to an AccessibilityService.
2081 * </p>
2082 *
2083 * @param collectionInfo The collection info.
2084 */
2085 public void setCollectionInfo(CollectionInfo collectionInfo) {
2086 enforceNotSealed();
2087 mCollectionInfo = collectionInfo;
2088 }
2089
2090 /**
2091 * Gets the collection item info if the node is a collection item. A collection
2092 * item is always a child of a collection.
2093 *
2094 * @return The collection item info.
2095 */
2096 public CollectionItemInfo getCollectionItemInfo() {
2097 return mCollectionItemInfo;
2098 }
2099
2100 /**
2101 * Sets the collection item info if the node is a collection item. A collection
2102 * item is always a child of a collection.
2103 * <p>
2104 * <strong>Note:</strong> Cannot be called from an
2105 * {@link android.accessibilityservice.AccessibilityService}.
2106 * This class is made immutable before being delivered to an AccessibilityService.
2107 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07002108 */
2109 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
2110 enforceNotSealed();
2111 mCollectionItemInfo = collectionItemInfo;
2112 }
2113
2114 /**
2115 * Gets the range info if this node is a range.
2116 *
2117 * @return The range.
2118 */
2119 public RangeInfo getRangeInfo() {
2120 return mRangeInfo;
2121 }
2122
2123 /**
2124 * Sets the range info if this node is a range.
2125 * <p>
2126 * <strong>Note:</strong> Cannot be called from an
2127 * {@link android.accessibilityservice.AccessibilityService}.
2128 * This class is made immutable before being delivered to an AccessibilityService.
2129 * </p>
2130 *
2131 * @param rangeInfo The range info.
2132 */
2133 public void setRangeInfo(RangeInfo rangeInfo) {
2134 enforceNotSealed();
2135 mRangeInfo = rangeInfo;
2136 }
2137
2138 /**
2139 * Gets if the content of this node is invalid. For example,
2140 * a date is not well-formed.
2141 *
2142 * @return If the node content is invalid.
2143 */
2144 public boolean isContentInvalid() {
2145 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
2146 }
2147
2148 /**
2149 * Sets if the content of this node is invalid. For example,
2150 * a date is not well-formed.
2151 * <p>
2152 * <strong>Note:</strong> Cannot be called from an
2153 * {@link android.accessibilityservice.AccessibilityService}.
2154 * This class is made immutable before being delivered to an AccessibilityService.
2155 * </p>
2156 *
2157 * @param contentInvalid If the node content is invalid.
2158 */
2159 public void setContentInvalid(boolean contentInvalid) {
2160 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
2161 }
2162
2163 /**
Mady Mellore8608912015-06-05 09:02:55 -07002164 * Gets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002165 *
Mady Mellore8608912015-06-05 09:02:55 -07002166 * @return True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002167 */
Mady Mellore8608912015-06-05 09:02:55 -07002168 public boolean isContextClickable() {
2169 return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
Mady Mellore82067b2015-04-30 09:58:35 -07002170 }
2171
2172 /**
Mady Mellore8608912015-06-05 09:02:55 -07002173 * Sets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002174 * <p>
2175 * <strong>Note:</strong> Cannot be called from an
2176 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
2177 * before being delivered to an AccessibilityService.
2178 * </p>
2179 *
Mady Mellore8608912015-06-05 09:02:55 -07002180 * @param contextClickable True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002181 * @throws IllegalStateException If called from an AccessibilityService.
2182 */
Mady Mellore8608912015-06-05 09:02:55 -07002183 public void setContextClickable(boolean contextClickable) {
2184 setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
Mady Mellore82067b2015-04-30 09:58:35 -07002185 }
2186
2187 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002188 * Gets the node's live region mode.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002189 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002190 * A live region is a node that contains information that is important for
2191 * the user and when it changes the user should be notified. For example,
2192 * in a login screen with a TextView that displays an "incorrect password"
2193 * notification, that view should be marked as a live region with mode
2194 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002195 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002196 * It is the responsibility of the accessibility service to monitor
2197 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating
2198 * changes to live region nodes and their children.
Svetoslav3577a282013-06-06 14:09:10 -07002199 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002200 * @return The live region mode, or
2201 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2202 * live region.
2203 * @see android.view.View#getAccessibilityLiveRegion()
Svetoslav3577a282013-06-06 14:09:10 -07002204 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002205 public int getLiveRegion() {
2206 return mLiveRegion;
Svetoslav3577a282013-06-06 14:09:10 -07002207 }
2208
2209 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002210 * Sets the node's live region mode.
Svetoslav3577a282013-06-06 14:09:10 -07002211 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002212 * <strong>Note:</strong> Cannot be called from an
2213 * {@link android.accessibilityservice.AccessibilityService}. This class is
2214 * made immutable before being delivered to an AccessibilityService.
Svetoslav3577a282013-06-06 14:09:10 -07002215 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002216 * @param mode The live region mode, or
2217 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2218 * live region.
2219 * @see android.view.View#setAccessibilityLiveRegion(int)
Svetoslav3577a282013-06-06 14:09:10 -07002220 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002221 public void setLiveRegion(int mode) {
2222 enforceNotSealed();
2223 mLiveRegion = mode;
Svetoslav3577a282013-06-06 14:09:10 -07002224 }
2225
2226 /**
2227 * Gets if the node is a multi line editable text.
2228 *
2229 * @return True if the node is multi line.
2230 */
2231 public boolean isMultiLine() {
2232 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
2233 }
2234
2235 /**
2236 * Sets if the node is a multi line editable text.
2237 * <p>
2238 * <strong>Note:</strong> Cannot be called from an
2239 * {@link android.accessibilityservice.AccessibilityService}.
2240 * This class is made immutable before being delivered to an AccessibilityService.
2241 * </p>
2242 *
2243 * @param multiLine True if the node is multi line.
2244 */
2245 public void setMultiLine(boolean multiLine) {
Svetoslav3577a282013-06-06 14:09:10 -07002246 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
2247 }
2248
2249 /**
2250 * Gets if this node opens a popup or a dialog.
2251 *
2252 * @return If the the node opens a popup.
2253 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002254 public boolean canOpenPopup() {
Svetoslav3577a282013-06-06 14:09:10 -07002255 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
2256 }
2257
2258 /**
2259 * Sets if this node opens a popup or a dialog.
2260 * <p>
2261 * <strong>Note:</strong> Cannot be called from an
2262 * {@link android.accessibilityservice.AccessibilityService}.
2263 * This class is made immutable before being delivered to an AccessibilityService.
2264 * </p>
2265 *
2266 * @param opensPopup If the the node opens a popup.
2267 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002268 public void setCanOpenPopup(boolean opensPopup) {
Phil Weavere1951292017-08-18 17:56:04 +00002269 enforceNotSealed();
Svetoslav3577a282013-06-06 14:09:10 -07002270 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
2271 }
2272
2273 /**
Svetoslav3577a282013-06-06 14:09:10 -07002274 * Gets if the node can be dismissed.
2275 *
2276 * @return If the node can be dismissed.
2277 */
2278 public boolean isDismissable() {
2279 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
2280 }
2281
2282 /**
2283 * Sets if the node can be dismissed.
2284 * <p>
2285 * <strong>Note:</strong> Cannot be called from an
2286 * {@link android.accessibilityservice.AccessibilityService}.
2287 * This class is made immutable before being delivered to an AccessibilityService.
2288 * </p>
2289 *
2290 * @param dismissable If the node can be dismissed.
2291 */
2292 public void setDismissable(boolean dismissable) {
Svetoslav3577a282013-06-06 14:09:10 -07002293 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
2294 }
2295
2296 /**
Casey Burkhardt2d80ae42016-01-31 12:52:23 -08002297 * Returns whether the node originates from a view considered important for accessibility.
2298 *
2299 * @return {@code true} if the node originates from a view considered important for
2300 * accessibility, {@code false} otherwise
2301 *
2302 * @see View#isImportantForAccessibility()
2303 */
2304 public boolean isImportantForAccessibility() {
2305 return getBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE);
2306 }
2307
2308 /**
2309 * Sets whether the node is considered important for accessibility.
2310 * <p>
2311 * <strong>Note:</strong> Cannot be called from an
2312 * {@link android.accessibilityservice.AccessibilityService}.
2313 * This class is made immutable before being delivered to an AccessibilityService.
2314 * </p>
2315 *
2316 * @param important {@code true} if the node is considered important for accessibility,
2317 * {@code false} otherwise
2318 */
2319 public void setImportantForAccessibility(boolean important) {
2320 setBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE, important);
2321 }
2322
2323 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002324 * Returns whether the node's text represents a hint for the user to enter text. It should only
2325 * be {@code true} if the node has editable text.
2326 *
2327 * @return {@code true} if the text in the node represents a hint to the user, {@code false}
2328 * otherwise.
2329 */
2330 public boolean isShowingHintText() {
2331 return getBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT);
2332 }
2333
2334 /**
2335 * Sets whether the node's text represents a hint for the user to enter text. It should only
2336 * be {@code true} if the node has editable text.
2337 * <p>
2338 * <strong>Note:</strong> Cannot be called from an
2339 * {@link android.accessibilityservice.AccessibilityService}.
2340 * This class is made immutable before being delivered to an AccessibilityService.
2341 * </p>
2342 *
2343 * @param showingHintText {@code true} if the text in the node represents a hint to the user,
2344 * {@code false} otherwise.
2345 */
2346 public void setShowingHintText(boolean showingHintText) {
2347 setBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT, showingHintText);
2348 }
2349
2350 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002351 * Gets the package this node comes from.
2352 *
2353 * @return The package name.
2354 */
2355 public CharSequence getPackageName() {
2356 return mPackageName;
2357 }
2358
2359 /**
2360 * Sets the package this node comes from.
2361 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002362 * <strong>Note:</strong> Cannot be called from an
2363 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002364 * This class is made immutable before being delivered to an AccessibilityService.
2365 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002366 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002367 * @param packageName The package name.
2368 *
2369 * @throws IllegalStateException If called from an AccessibilityService.
2370 */
2371 public void setPackageName(CharSequence packageName) {
2372 enforceNotSealed();
2373 mPackageName = packageName;
2374 }
2375
2376 /**
2377 * Gets the class this node comes from.
2378 *
2379 * @return The class name.
2380 */
2381 public CharSequence getClassName() {
2382 return mClassName;
2383 }
2384
2385 /**
2386 * Sets the class this node comes from.
2387 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002388 * <strong>Note:</strong> Cannot be called from an
2389 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002390 * This class is made immutable before being delivered to an AccessibilityService.
2391 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002392 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002393 * @param className The class name.
2394 *
2395 * @throws IllegalStateException If called from an AccessibilityService.
2396 */
2397 public void setClassName(CharSequence className) {
2398 enforceNotSealed();
2399 mClassName = className;
2400 }
2401
2402 /**
2403 * Gets the text of this node.
Phil Weaver193520e2016-12-13 09:39:06 -08002404 * <p>
2405 * <strong>Note:</strong> If the text contains {@link ClickableSpan}s or {@link URLSpan}s,
2406 * these spans will have been replaced with ones whose {@link ClickableSpan#onClick(View)}
2407 * can be called from an {@link AccessibilityService}. When called from a service, the
2408 * {@link View} argument is ignored and the corresponding span will be found on the view that
2409 * this {@code AccessibilityNodeInfo} represents and called with that view as its argument.
2410 * <p>
2411 * This treatment of {@link ClickableSpan}s means that the text returned from this method may
2412 * different slightly one passed to {@link #setText(CharSequence)}, although they will be
2413 * equivalent according to {@link TextUtils#equals(CharSequence, CharSequence)}. The
2414 * {@link ClickableSpan#onClick(View)} of any spans, however, will generally not work outside
2415 * of an accessibility service.
2416 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002417 *
2418 * @return The text.
2419 */
2420 public CharSequence getText() {
Phil Weaver193520e2016-12-13 09:39:06 -08002421 // Attach this node to any spans that need it
2422 if (mText instanceof Spanned) {
2423 Spanned spanned = (Spanned) mText;
2424 AccessibilityClickableSpan[] clickableSpans =
2425 spanned.getSpans(0, mText.length(), AccessibilityClickableSpan.class);
2426 for (int i = 0; i < clickableSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002427 clickableSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002428 }
2429 AccessibilityURLSpan[] urlSpans =
2430 spanned.getSpans(0, mText.length(), AccessibilityURLSpan.class);
2431 for (int i = 0; i < urlSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002432 urlSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002433 }
2434 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002435 return mText;
2436 }
2437
2438 /**
Phil Weaver193520e2016-12-13 09:39:06 -08002439 * Get the text passed to setText before any changes to the spans.
2440 * @hide
2441 */
2442 public CharSequence getOriginalText() {
2443 return mOriginalText;
2444 }
2445
2446 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002447 * Sets the text of this node.
2448 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002449 * <strong>Note:</strong> Cannot be called from an
2450 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002451 * This class is made immutable before being delivered to an AccessibilityService.
2452 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002453 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002454 * @param text The text.
2455 *
2456 * @throws IllegalStateException If called from an AccessibilityService.
2457 */
2458 public void setText(CharSequence text) {
2459 enforceNotSealed();
Phil Weaver193520e2016-12-13 09:39:06 -08002460 mOriginalText = text;
2461 // Replace any ClickableSpans in mText with placeholders
2462 if (text instanceof Spanned) {
2463 ClickableSpan[] spans =
2464 ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
2465 if (spans.length > 0) {
Phil Weaver0ebe6bd2017-02-21 16:24:31 -08002466 Spannable spannable = new SpannableStringBuilder(text);
Phil Weaver193520e2016-12-13 09:39:06 -08002467 for (int i = 0; i < spans.length; i++) {
2468 ClickableSpan span = spans[i];
2469 if ((span instanceof AccessibilityClickableSpan)
2470 || (span instanceof AccessibilityURLSpan)) {
2471 // We've already done enough
2472 break;
2473 }
2474 int spanToReplaceStart = spannable.getSpanStart(span);
2475 int spanToReplaceEnd = spannable.getSpanEnd(span);
2476 int spanToReplaceFlags = spannable.getSpanFlags(span);
2477 spannable.removeSpan(span);
2478 ClickableSpan replacementSpan = (span instanceof URLSpan)
2479 ? new AccessibilityURLSpan((URLSpan) span)
2480 : new AccessibilityClickableSpan(span.getId());
2481 spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
2482 spanToReplaceFlags);
2483 }
2484 mText = spannable;
2485 return;
2486 }
2487 }
Phil Weaveref955ad2016-08-25 12:58:15 -07002488 mText = (text == null) ? null : text.subSequence(0, text.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002489 }
2490
2491 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002492 * Gets the hint text of this node. Only applies to nodes where text can be entered.
2493 *
2494 * @return The hint text.
2495 */
2496 public CharSequence getHintText() {
2497 return mHintText;
2498 }
2499
2500 /**
2501 * Sets the hint text of this node. Only applies to nodes where text can be entered.
2502 * <p>
2503 * <strong>Note:</strong> Cannot be called from an
2504 * {@link android.accessibilityservice.AccessibilityService}.
2505 * This class is made immutable before being delivered to an AccessibilityService.
2506 * </p>
2507 *
2508 * @param hintText The hint text for this mode.
2509 *
2510 * @throws IllegalStateException If called from an AccessibilityService.
2511 */
2512 public void setHintText(CharSequence hintText) {
2513 enforceNotSealed();
2514 mHintText = (hintText == null) ? null : hintText.subSequence(0, hintText.length());
2515 }
2516
2517 /**
Alan Viverettefccbff52014-07-07 15:06:14 -07002518 * Sets the error text of this node.
2519 * <p>
2520 * <strong>Note:</strong> Cannot be called from an
2521 * {@link android.accessibilityservice.AccessibilityService}.
2522 * This class is made immutable before being delivered to an AccessibilityService.
2523 * </p>
2524 *
2525 * @param error The error text.
2526 *
2527 * @throws IllegalStateException If called from an AccessibilityService.
2528 */
2529 public void setError(CharSequence error) {
2530 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002531 mError = (error == null) ? null : error.subSequence(0, error.length());
Alan Viverettefccbff52014-07-07 15:06:14 -07002532 }
2533
2534 /**
2535 * Gets the error text of this node.
2536 *
2537 * @return The error text.
2538 */
2539 public CharSequence getError() {
2540 return mError;
2541 }
2542
2543 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002544 * Gets the content description of this node.
2545 *
2546 * @return The content description.
2547 */
2548 public CharSequence getContentDescription() {
2549 return mContentDescription;
2550 }
2551
2552 /**
2553 * Sets the content description of this node.
2554 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002555 * <strong>Note:</strong> Cannot be called from an
2556 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002557 * This class is made immutable before being delivered to an AccessibilityService.
2558 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002559 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002560 * @param contentDescription The content description.
2561 *
2562 * @throws IllegalStateException If called from an AccessibilityService.
2563 */
2564 public void setContentDescription(CharSequence contentDescription) {
2565 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002566 mContentDescription = (contentDescription == null) ? null
2567 : contentDescription.subSequence(0, contentDescription.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002568 }
2569
2570 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002571 * Sets the view for which the view represented by this info serves as a
2572 * label for accessibility purposes.
2573 *
2574 * @param labeled The view for which this info serves as a label.
2575 */
2576 public void setLabelFor(View labeled) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002577 setLabelFor(labeled, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002578 }
2579
2580 /**
2581 * Sets the view for which the view represented by this info serves as a
2582 * label for accessibility purposes. If <code>virtualDescendantId</code>
2583 * is {@link View#NO_ID} the root is set as the labeled.
2584 * <p>
2585 * A virtual descendant is an imaginary View that is reported as a part of the view
2586 * hierarchy for accessibility purposes. This enables custom views that draw complex
2587 * content to report themselves as a tree of virtual views, thus conveying their
2588 * logical structure.
2589 * </p>
2590 * <p>
2591 * <strong>Note:</strong> Cannot be called from an
2592 * {@link android.accessibilityservice.AccessibilityService}.
2593 * This class is made immutable before being delivered to an AccessibilityService.
2594 * </p>
2595 *
2596 * @param root The root whose virtual descendant serves as a label.
2597 * @param virtualDescendantId The id of the virtual descendant.
2598 */
2599 public void setLabelFor(View root, int virtualDescendantId) {
2600 enforceNotSealed();
2601 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002602 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002603 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2604 }
2605
2606 /**
2607 * Gets the node info for which the view represented by this info serves as
2608 * a label for accessibility purposes.
2609 * <p>
2610 * <strong>Note:</strong> It is a client responsibility to recycle the
2611 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2612 * to avoid creating of multiple instances.
2613 * </p>
2614 *
2615 * @return The labeled info.
2616 */
2617 public AccessibilityNodeInfo getLabelFor() {
2618 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002619 return getNodeForAccessibilityId(mLabelForId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002620 }
2621
2622 /**
2623 * Sets the view which serves as the label of the view represented by
2624 * this info for accessibility purposes.
2625 *
2626 * @param label The view that labels this node's source.
2627 */
2628 public void setLabeledBy(View label) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002629 setLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002630 }
2631
2632 /**
2633 * Sets the view which serves as the label of the view represented by
2634 * this info for accessibility purposes. If <code>virtualDescendantId</code>
2635 * is {@link View#NO_ID} the root is set as the label.
2636 * <p>
2637 * A virtual descendant is an imaginary View that is reported as a part of the view
2638 * hierarchy for accessibility purposes. This enables custom views that draw complex
2639 * content to report themselves as a tree of virtual views, thus conveying their
2640 * logical structure.
2641 * </p>
2642 * <p>
2643 * <strong>Note:</strong> Cannot be called from an
2644 * {@link android.accessibilityservice.AccessibilityService}.
2645 * This class is made immutable before being delivered to an AccessibilityService.
2646 * </p>
2647 *
2648 * @param root The root whose virtual descendant labels this node's source.
2649 * @param virtualDescendantId The id of the virtual descendant.
2650 */
2651 public void setLabeledBy(View root, int virtualDescendantId) {
2652 enforceNotSealed();
2653 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002654 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002655 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2656 }
2657
2658 /**
2659 * Gets the node info which serves as the label of the view represented by
2660 * this info for accessibility purposes.
2661 * <p>
2662 * <strong>Note:</strong> It is a client responsibility to recycle the
2663 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2664 * to avoid creating of multiple instances.
2665 * </p>
2666 *
2667 * @return The label.
2668 */
2669 public AccessibilityNodeInfo getLabeledBy() {
2670 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002671 return getNodeForAccessibilityId(mLabeledById);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002672 }
2673
2674 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002675 * Sets the fully qualified resource name of the source view's id.
2676 *
2677 * <p>
2678 * <strong>Note:</strong> Cannot be called from an
2679 * {@link android.accessibilityservice.AccessibilityService}.
2680 * This class is made immutable before being delivered to an AccessibilityService.
2681 * </p>
2682 *
Svetoslav92826452013-02-05 14:57:42 -08002683 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002684 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002685 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002686 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08002687 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002688 }
2689
2690 /**
2691 * Gets the fully qualified resource name of the source view's id.
2692 *
2693 * <p>
2694 * <strong>Note:</strong> The primary usage of this API is for UI test automation
2695 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
2696 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08002697 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002698 * </p>
2699
2700 * @return The id resource name.
2701 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002702 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08002703 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002704 }
2705
2706 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002707 * Gets the text selection start or the cursor position.
2708 * <p>
2709 * If no text is selected, both this method and
2710 * {@link AccessibilityNodeInfo#getTextSelectionEnd()} return the same value:
2711 * the current location of the cursor.
2712 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002713 *
Phil Weaver40ded282016-01-25 15:49:02 -08002714 * @return The text selection start, the cursor location if there is no selection, or -1 if
2715 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002716 */
2717 public int getTextSelectionStart() {
2718 return mTextSelectionStart;
2719 }
2720
2721 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002722 * Gets the text selection end if text is selected.
2723 * <p>
2724 * If no text is selected, both this method and
2725 * {@link AccessibilityNodeInfo#getTextSelectionStart()} return the same value:
2726 * the current location of the cursor.
2727 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002728 *
Phil Weaver40ded282016-01-25 15:49:02 -08002729 * @return The text selection end, the cursor location if there is no selection, or -1 if
2730 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002731 */
2732 public int getTextSelectionEnd() {
2733 return mTextSelectionEnd;
2734 }
2735
2736 /**
2737 * Sets the text selection start and end.
2738 * <p>
2739 * <strong>Note:</strong> Cannot be called from an
2740 * {@link android.accessibilityservice.AccessibilityService}.
2741 * This class is made immutable before being delivered to an AccessibilityService.
2742 * </p>
2743 *
2744 * @param start The text selection start.
2745 * @param end The text selection end.
2746 *
2747 * @throws IllegalStateException If called from an AccessibilityService.
2748 */
2749 public void setTextSelection(int start, int end) {
2750 enforceNotSealed();
2751 mTextSelectionStart = start;
2752 mTextSelectionEnd = end;
2753 }
2754
2755 /**
Svetoslav6254f482013-06-04 17:22:14 -07002756 * Gets the input type of the source as defined by {@link InputType}.
2757 *
2758 * @return The input type.
2759 */
2760 public int getInputType() {
2761 return mInputType;
2762 }
2763
2764 /**
2765 * Sets the input type of the source as defined by {@link InputType}.
2766 * <p>
2767 * <strong>Note:</strong> Cannot be called from an
2768 * {@link android.accessibilityservice.AccessibilityService}.
2769 * This class is made immutable before being delivered to an
2770 * AccessibilityService.
2771 * </p>
2772 *
2773 * @param inputType The input type.
2774 *
2775 * @throws IllegalStateException If called from an AccessibilityService.
2776 */
2777 public void setInputType(int inputType) {
Alan Viverettedf39cb92013-08-19 12:28:04 -07002778 enforceNotSealed();
Svetoslav6254f482013-06-04 17:22:14 -07002779 mInputType = inputType;
2780 }
2781
2782 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002783 * Gets an optional bundle with extra data. The bundle
Svetoslav6254f482013-06-04 17:22:14 -07002784 * is lazily created and never <code>null</code>.
2785 * <p>
2786 * <strong>Note:</strong> It is recommended to use the package
2787 * name of your application as a prefix for the keys to avoid
2788 * collisions which may confuse an accessibility service if the
2789 * same key has different meaning when emitted from different
2790 * applications.
2791 * </p>
2792 *
2793 * @return The bundle.
2794 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002795 public Bundle getExtras() {
2796 if (mExtras == null) {
2797 mExtras = new Bundle();
Svetoslav6254f482013-06-04 17:22:14 -07002798 }
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002799 return mExtras;
Svetoslav6254f482013-06-04 17:22:14 -07002800 }
2801
2802 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08002803 * Check if a node has an extras bundle
2804 * @hide
2805 */
2806 public boolean hasExtras() {
2807 return mExtras != null;
2808 }
2809
2810 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002811 * Gets the value of a boolean property.
2812 *
2813 * @param property The property.
2814 * @return The value.
2815 */
2816 private boolean getBooleanProperty(int property) {
2817 return (mBooleanProperties & property) != 0;
2818 }
2819
2820 /**
2821 * Sets a boolean property.
2822 *
2823 * @param property The property.
2824 * @param value The value.
2825 *
2826 * @throws IllegalStateException If called from an AccessibilityService.
2827 */
2828 private void setBooleanProperty(int property, boolean value) {
2829 enforceNotSealed();
2830 if (value) {
2831 mBooleanProperties |= property;
2832 } else {
2833 mBooleanProperties &= ~property;
2834 }
2835 }
2836
2837 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002838 * Sets the unique id of the IAccessibilityServiceConnection over which
2839 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002840 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002841 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002842 *
2843 * @hide
2844 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002845 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002846 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002847 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002848 }
2849
2850 /**
Phil Weaver23161e72017-04-19 12:16:36 -07002851 * Get the connection ID.
2852 *
2853 * @return The connection id
2854 *
2855 * @hide
2856 */
2857 public int getConnectionId() {
2858 return mConnectionId;
2859 }
2860
2861 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002862 * {@inheritDoc}
2863 */
Alan Viverettef0aed092013-11-06 15:33:03 -08002864 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002865 public int describeContents() {
2866 return 0;
2867 }
2868
2869 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08002870 * Sets the id of the source node.
2871 *
2872 * @param sourceId The id.
2873 * @param windowId The window id.
2874 *
2875 * @hide
2876 */
2877 public void setSourceNodeId(long sourceId, int windowId) {
2878 enforceNotSealed();
2879 mSourceNodeId = sourceId;
2880 mWindowId = windowId;
2881 }
2882
2883 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08002884 * Gets the id of the source node.
2885 *
2886 * @return The id.
2887 *
2888 * @hide
2889 */
2890 public long getSourceNodeId() {
2891 return mSourceNodeId;
2892 }
2893
2894 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002895 * Sets if this instance is sealed.
2896 *
2897 * @param sealed Whether is sealed.
2898 *
2899 * @hide
2900 */
2901 public void setSealed(boolean sealed) {
2902 mSealed = sealed;
2903 }
2904
2905 /**
2906 * Gets if this instance is sealed.
2907 *
2908 * @return Whether is sealed.
2909 *
2910 * @hide
2911 */
2912 public boolean isSealed() {
2913 return mSealed;
2914 }
2915
2916 /**
2917 * Enforces that this instance is sealed.
2918 *
2919 * @throws IllegalStateException If this instance is not sealed.
2920 *
2921 * @hide
2922 */
2923 protected void enforceSealed() {
2924 if (!isSealed()) {
2925 throw new IllegalStateException("Cannot perform this "
2926 + "action on a not sealed instance.");
2927 }
2928 }
2929
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002930 private void enforceValidFocusDirection(int direction) {
2931 switch (direction) {
2932 case View.FOCUS_DOWN:
2933 case View.FOCUS_UP:
2934 case View.FOCUS_LEFT:
2935 case View.FOCUS_RIGHT:
2936 case View.FOCUS_FORWARD:
2937 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002938 return;
2939 default:
2940 throw new IllegalArgumentException("Unknown direction: " + direction);
2941 }
2942 }
2943
2944 private void enforceValidFocusType(int focusType) {
2945 switch (focusType) {
2946 case FOCUS_INPUT:
2947 case FOCUS_ACCESSIBILITY:
2948 return;
2949 default:
2950 throw new IllegalArgumentException("Unknown focus type: " + focusType);
2951 }
2952 }
2953
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002954 /**
2955 * Enforces that this instance is not sealed.
2956 *
2957 * @throws IllegalStateException If this instance is sealed.
2958 *
2959 * @hide
2960 */
2961 protected void enforceNotSealed() {
2962 if (isSealed()) {
2963 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09002964 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002965 }
2966 }
2967
2968 /**
2969 * Returns a cached instance if such is available otherwise a new one
2970 * and sets the source.
2971 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07002972 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002973 * @return An instance.
2974 *
2975 * @see #setSource(View)
2976 */
2977 public static AccessibilityNodeInfo obtain(View source) {
2978 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2979 info.setSource(source);
2980 return info;
2981 }
2982
2983 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002984 * Returns a cached instance if such is available otherwise a new one
2985 * and sets the source.
2986 *
2987 * @param root The root of the virtual subtree.
2988 * @param virtualDescendantId The id of the virtual descendant.
2989 * @return An instance.
2990 *
2991 * @see #setSource(View, int)
2992 */
2993 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
2994 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2995 info.setSource(root, virtualDescendantId);
2996 return info;
2997 }
2998
2999 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003000 * Returns a cached instance if such is available otherwise a new one.
3001 *
3002 * @return An instance.
3003 */
3004 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003005 AccessibilityNodeInfo info = sPool.acquire();
Phil Weaver62d20fa2016-09-15 11:05:55 -07003006 if (sNumInstancesInUse != null) {
3007 sNumInstancesInUse.incrementAndGet();
3008 }
Phil Weavere1951292017-08-18 17:56:04 +00003009 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003010 }
3011
3012 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003013 * Returns a cached instance if such is available or a new one is
3014 * create. The returned instance is initialized from the given
3015 * <code>info</code>.
3016 *
3017 * @param info The other info.
3018 * @return An instance.
3019 */
3020 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
3021 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
3022 infoClone.init(info);
3023 return infoClone;
3024 }
3025
3026 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003027 * Return an instance back to be reused.
3028 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003029 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003030 *
3031 * @throws IllegalStateException If the info is already recycled.
3032 */
3033 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003034 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003035 sPool.release(this);
Phil Weaver62d20fa2016-09-15 11:05:55 -07003036 if (sNumInstancesInUse != null) {
3037 sNumInstancesInUse.decrementAndGet();
3038 }
Phil Weaverb010b122016-08-17 17:47:48 -07003039 }
3040
3041 /**
Phil Weaver62d20fa2016-09-15 11:05:55 -07003042 * Specify a counter that will be incremented on obtain() and decremented on recycle()
Phil Weaverb010b122016-08-17 17:47:48 -07003043 *
3044 * @hide
3045 */
Phil Weaver62d20fa2016-09-15 11:05:55 -07003046 @TestApi
3047 public static void setNumInstancesInUseCounter(AtomicInteger counter) {
3048 sNumInstancesInUse = counter;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003049 }
3050
3051 /**
3052 * {@inheritDoc}
3053 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003054 * <strong>Note:</strong> After the instance is written to a parcel it
3055 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003056 * </p>
3057 */
Alan Viverettef0aed092013-11-06 15:33:03 -08003058 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003059 public void writeToParcel(Parcel parcel, int flags) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003060 // Write bit set of indices of fields with values differing from default
3061 long nonDefaultFields = 0;
3062 int fieldIndex = 0; // index of the current field
3063 if (isSealed() != DEFAULT.isSealed()) nonDefaultFields |= bitAt(fieldIndex);
3064 fieldIndex++;
3065 if (mSourceNodeId != DEFAULT.mSourceNodeId) nonDefaultFields |= bitAt(fieldIndex);
3066 fieldIndex++;
3067 if (mWindowId != DEFAULT.mWindowId) nonDefaultFields |= bitAt(fieldIndex);
3068 fieldIndex++;
3069 if (mParentNodeId != DEFAULT.mParentNodeId) nonDefaultFields |= bitAt(fieldIndex);
3070 fieldIndex++;
3071 if (mLabelForId != DEFAULT.mLabelForId) nonDefaultFields |= bitAt(fieldIndex);
3072 fieldIndex++;
3073 if (mLabeledById != DEFAULT.mLabeledById) nonDefaultFields |= bitAt(fieldIndex);
3074 fieldIndex++;
3075 if (mTraversalBefore != DEFAULT.mTraversalBefore) nonDefaultFields |= bitAt(fieldIndex);
3076 fieldIndex++;
3077 if (mTraversalAfter != DEFAULT.mTraversalAfter) nonDefaultFields |= bitAt(fieldIndex);
3078 fieldIndex++;
3079 if (mConnectionId != DEFAULT.mConnectionId) nonDefaultFields |= bitAt(fieldIndex);
3080 fieldIndex++;
3081 if (!Objects.equals(mChildNodeIds, DEFAULT.mChildNodeIds)) {
3082 nonDefaultFields |= bitAt(fieldIndex);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003083 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003084 fieldIndex++;
3085 if (!Objects.equals(mBoundsInParent, DEFAULT.mBoundsInParent)) {
3086 nonDefaultFields |= bitAt(fieldIndex);
3087 }
3088 fieldIndex++;
3089 if (!Objects.equals(mBoundsInScreen, DEFAULT.mBoundsInScreen)) {
3090 nonDefaultFields |= bitAt(fieldIndex);
3091 }
3092 fieldIndex++;
3093 if (!Objects.equals(mActions, DEFAULT.mActions)) nonDefaultFields |= bitAt(fieldIndex);
3094 fieldIndex++;
3095 if (mMaxTextLength != DEFAULT.mMaxTextLength) nonDefaultFields |= bitAt(fieldIndex);
3096 fieldIndex++;
3097 if (mMovementGranularities != DEFAULT.mMovementGranularities) {
3098 nonDefaultFields |= bitAt(fieldIndex);
3099 }
3100 fieldIndex++;
3101 if (mBooleanProperties != DEFAULT.mBooleanProperties) nonDefaultFields |= bitAt(fieldIndex);
3102 fieldIndex++;
3103 if (!Objects.equals(mPackageName, DEFAULT.mPackageName)) {
3104 nonDefaultFields |= bitAt(fieldIndex);
3105 }
3106 fieldIndex++;
3107 if (!Objects.equals(mClassName, DEFAULT.mClassName)) nonDefaultFields |= bitAt(fieldIndex);
3108 fieldIndex++;
3109 if (!Objects.equals(mText, DEFAULT.mText)) nonDefaultFields |= bitAt(fieldIndex);
3110 fieldIndex++;
3111 if (!Objects.equals(mHintText, DEFAULT.mHintText)) {
3112 nonDefaultFields |= bitAt(fieldIndex);
3113 }
3114 fieldIndex++;
3115 if (!Objects.equals(mError, DEFAULT.mError)) nonDefaultFields |= bitAt(fieldIndex);
3116 fieldIndex++;
3117 if (!Objects.equals(mContentDescription, DEFAULT.mContentDescription)) {
3118 nonDefaultFields |= bitAt(fieldIndex);
3119 }
3120 fieldIndex++;
3121 if (!Objects.equals(mViewIdResourceName, DEFAULT.mViewIdResourceName)) {
3122 nonDefaultFields |= bitAt(fieldIndex);
3123 }
3124 fieldIndex++;
3125 if (mTextSelectionStart != DEFAULT.mTextSelectionStart) {
3126 nonDefaultFields |= bitAt(fieldIndex);
3127 }
3128 fieldIndex++;
3129 if (mTextSelectionEnd != DEFAULT.mTextSelectionEnd) {
3130 nonDefaultFields |= bitAt(fieldIndex);
3131 }
3132 fieldIndex++;
3133 if (mInputType != DEFAULT.mInputType) nonDefaultFields |= bitAt(fieldIndex);
3134 fieldIndex++;
3135 if (mLiveRegion != DEFAULT.mLiveRegion) nonDefaultFields |= bitAt(fieldIndex);
3136 fieldIndex++;
3137 if (mDrawingOrderInParent != DEFAULT.mDrawingOrderInParent) {
3138 nonDefaultFields |= bitAt(fieldIndex);
3139 }
3140 fieldIndex++;
3141 if (!Objects.equals(mExtraDataKeys, DEFAULT.mExtraDataKeys)) {
3142 nonDefaultFields |= bitAt(fieldIndex);
3143 }
3144 fieldIndex++;
3145 if (!Objects.equals(mExtras, DEFAULT.mExtras)) nonDefaultFields |= bitAt(fieldIndex);
3146 fieldIndex++;
3147 if (!Objects.equals(mRangeInfo, DEFAULT.mRangeInfo)) nonDefaultFields |= bitAt(fieldIndex);
3148 fieldIndex++;
3149 if (!Objects.equals(mCollectionInfo, DEFAULT.mCollectionInfo)) {
3150 nonDefaultFields |= bitAt(fieldIndex);
3151 }
3152 fieldIndex++;
3153 if (!Objects.equals(mCollectionItemInfo, DEFAULT.mCollectionItemInfo)) {
3154 nonDefaultFields |= bitAt(fieldIndex);
3155 }
3156 int totalFields = fieldIndex;
3157 parcel.writeLong(nonDefaultFields);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003158
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003159 fieldIndex = 0;
3160 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(isSealed() ? 1 : 0);
3161 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mSourceNodeId);
3162 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mWindowId);
3163 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mParentNodeId);
3164 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabelForId);
3165 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabeledById);
3166 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalBefore);
3167 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalAfter);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003168
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003169 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003170
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003171 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3172 final LongArray childIds = mChildNodeIds;
3173 if (childIds == null) {
3174 parcel.writeInt(0);
3175 } else {
3176 final int childIdsSize = childIds.size();
3177 parcel.writeInt(childIdsSize);
3178 for (int i = 0; i < childIdsSize; i++) {
3179 parcel.writeLong(childIds.get(i));
Kristian Monsen74bc1942014-04-29 11:00:17 -07003180 }
3181 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003182 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003183
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003184 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3185 parcel.writeInt(mBoundsInParent.top);
3186 parcel.writeInt(mBoundsInParent.bottom);
3187 parcel.writeInt(mBoundsInParent.left);
3188 parcel.writeInt(mBoundsInParent.right);
3189 }
3190
3191 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3192 parcel.writeInt(mBoundsInScreen.top);
3193 parcel.writeInt(mBoundsInScreen.bottom);
3194 parcel.writeInt(mBoundsInScreen.left);
3195 parcel.writeInt(mBoundsInScreen.right);
3196 }
3197
3198 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3199 if (mActions != null && !mActions.isEmpty()) {
3200 final int actionCount = mActions.size();
3201
Eugene Susla554edd32017-05-24 16:49:59 -07003202 int nonStandardActionCount = 0;
3203 int defaultStandardActions = 0;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003204 for (int i = 0; i < actionCount; i++) {
3205 AccessibilityAction action = mActions.get(i);
Eugene Susla554edd32017-05-24 16:49:59 -07003206 if (isDefaultStandardAction(action)) {
3207 defaultStandardActions |= action.mSerializationFlag;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003208 } else {
Eugene Susla554edd32017-05-24 16:49:59 -07003209 nonStandardActionCount++;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003210 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003211 }
Eugene Susla554edd32017-05-24 16:49:59 -07003212 parcel.writeInt(defaultStandardActions);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003213
Eugene Susla554edd32017-05-24 16:49:59 -07003214 parcel.writeInt(nonStandardActionCount);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003215 for (int i = 0; i < actionCount; i++) {
3216 AccessibilityAction action = mActions.get(i);
Eugene Susla554edd32017-05-24 16:49:59 -07003217 if (!isDefaultStandardAction(action)) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003218 parcel.writeInt(action.getId());
3219 parcel.writeCharSequence(action.getLabel());
3220 }
3221 }
3222 } else {
3223 parcel.writeInt(0);
3224 parcel.writeInt(0);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003225 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003226 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003227
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003228 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMaxTextLength);
3229 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMovementGranularities);
3230 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mBooleanProperties);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003231
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003232 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPackageName);
3233 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mClassName);
3234 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mText);
3235 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mHintText);
3236 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mError);
3237 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3238 parcel.writeCharSequence(mContentDescription);
Phil Weaverc2e28932016-12-08 12:29:25 -08003239 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003240 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeString(mViewIdResourceName);
Svetoslav6254f482013-06-04 17:22:14 -07003241
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003242 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionStart);
3243 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionEnd);
3244 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mInputType);
3245 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mLiveRegion);
3246 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mDrawingOrderInParent);
Svetoslavbcc46a02013-02-06 11:56:00 -08003247
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003248 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeStringList(mExtraDataKeys);
3249
3250 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeBundle(mExtras);
3251
3252 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav3577a282013-06-06 14:09:10 -07003253 parcel.writeInt(mRangeInfo.getType());
3254 parcel.writeFloat(mRangeInfo.getMin());
3255 parcel.writeFloat(mRangeInfo.getMax());
3256 parcel.writeFloat(mRangeInfo.getCurrent());
Svetoslav3577a282013-06-06 14:09:10 -07003257 }
3258
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003259 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003260 parcel.writeInt(mCollectionInfo.getRowCount());
3261 parcel.writeInt(mCollectionInfo.getColumnCount());
Svetoslav3577a282013-06-06 14:09:10 -07003262 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003263 parcel.writeInt(mCollectionInfo.getSelectionMode());
Svetoslav3577a282013-06-06 14:09:10 -07003264 }
3265
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003266 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003267 parcel.writeInt(mCollectionItemInfo.getRowIndex());
3268 parcel.writeInt(mCollectionItemInfo.getRowSpan());
Alan Viverettefaeac962015-06-01 09:03:27 -07003269 parcel.writeInt(mCollectionItemInfo.getColumnIndex());
3270 parcel.writeInt(mCollectionItemInfo.getColumnSpan());
Svetoslav3577a282013-06-06 14:09:10 -07003271 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003272 parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003273 }
3274
3275 if (DEBUG) {
3276 fieldIndex--;
3277 if (totalFields != fieldIndex) {
3278 throw new IllegalStateException("Number of fields mismatch: " + totalFields
3279 + " vs " + fieldIndex);
3280 }
Svetoslav3577a282013-06-06 14:09:10 -07003281 }
3282
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003283 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003284 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003285 recycle();
3286 }
3287
3288 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003289 * Initializes this instance from another one.
3290 *
3291 * @param other The other instance.
3292 */
3293 private void init(AccessibilityNodeInfo other) {
3294 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003295 mSourceNodeId = other.mSourceNodeId;
3296 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07003297 mLabelForId = other.mLabelForId;
3298 mLabeledById = other.mLabeledById;
Svetoslav6c702902014-10-09 18:40:56 -07003299 mTraversalBefore = other.mTraversalBefore;
3300 mTraversalAfter = other.mTraversalAfter;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003301 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08003302 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003303 mBoundsInParent.set(other.mBoundsInParent);
3304 mBoundsInScreen.set(other.mBoundsInScreen);
3305 mPackageName = other.mPackageName;
3306 mClassName = other.mClassName;
3307 mText = other.mText;
Phil Weaver776afc22016-12-21 10:55:13 -08003308 mHintText = other.mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -07003309 mError = other.mError;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003310 mContentDescription = other.mContentDescription;
Svetoslav22431a32013-02-05 14:30:19 -08003311 mViewIdResourceName = other.mViewIdResourceName;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003312
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003313 if (mActions != null) mActions.clear();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003314 final ArrayList<AccessibilityAction> otherActions = other.mActions;
3315 if (otherActions != null && otherActions.size() > 0) {
3316 if (mActions == null) {
3317 mActions = new ArrayList(otherActions);
3318 } else {
Kristian Monsen74bc1942014-04-29 11:00:17 -07003319 mActions.addAll(other.mActions);
3320 }
3321 }
3322
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003323 mBooleanProperties = other.mBooleanProperties;
Alan Viverette029942f2014-08-12 14:55:56 -07003324 mMaxTextLength = other.mMaxTextLength;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003325 mMovementGranularities = other.mMovementGranularities;
Alan Viverettef0aed092013-11-06 15:33:03 -08003326
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003327
3328 if (mChildNodeIds != null) mChildNodeIds.clear();
Alan Viverettef0aed092013-11-06 15:33:03 -08003329 final LongArray otherChildNodeIds = other.mChildNodeIds;
3330 if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) {
3331 if (mChildNodeIds == null) {
3332 mChildNodeIds = otherChildNodeIds.clone();
3333 } else {
3334 mChildNodeIds.addAll(otherChildNodeIds);
3335 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003336 }
Alan Viverettef0aed092013-11-06 15:33:03 -08003337
Svetoslavbcc46a02013-02-06 11:56:00 -08003338 mTextSelectionStart = other.mTextSelectionStart;
3339 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07003340 mInputType = other.mInputType;
Alan Viverette77e9a282013-09-12 17:16:09 -07003341 mLiveRegion = other.mLiveRegion;
Phil Weaver1f222542016-01-08 11:49:32 -08003342 mDrawingOrderInParent = other.mDrawingOrderInParent;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003343
Phil Weaverc2e28932016-12-08 12:29:25 -08003344 mExtraDataKeys = other.mExtraDataKeys;
3345
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003346 mExtras = other.mExtras != null ? new Bundle(other.mExtras) : null;
3347
3348 if (mRangeInfo != null) mRangeInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003349 mRangeInfo = (other.mRangeInfo != null)
3350 ? RangeInfo.obtain(other.mRangeInfo) : null;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003351 if (mCollectionInfo != null) mCollectionInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003352 mCollectionInfo = (other.mCollectionInfo != null)
3353 ? CollectionInfo.obtain(other.mCollectionInfo) : null;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003354 if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003355 mCollectionItemInfo = (other.mCollectionItemInfo != null)
3356 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003357 }
3358
3359 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003360 * Creates a new instance from a {@link Parcel}.
3361 *
3362 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
3363 */
3364 private void initFromParcel(Parcel parcel) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003365 // Bit mask of non-default-valued field indices
3366 long nonDefaultFields = parcel.readLong();
3367 int fieldIndex = 0;
3368 final boolean sealed = isBitSet(nonDefaultFields, fieldIndex++)
3369 ? (parcel.readInt() == 1)
3370 : DEFAULT.mSealed;
3371 if (isBitSet(nonDefaultFields, fieldIndex++)) mSourceNodeId = parcel.readLong();
3372 if (isBitSet(nonDefaultFields, fieldIndex++)) mWindowId = parcel.readInt();
3373 if (isBitSet(nonDefaultFields, fieldIndex++)) mParentNodeId = parcel.readLong();
3374 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabelForId = parcel.readLong();
3375 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabeledById = parcel.readLong();
3376 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalBefore = parcel.readLong();
3377 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalAfter = parcel.readLong();
Svetoslav6c702902014-10-09 18:40:56 -07003378
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003379 if (isBitSet(nonDefaultFields, fieldIndex++)) mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003380
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003381 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3382 final int childrenSize = parcel.readInt();
3383 if (childrenSize <= 0) {
3384 mChildNodeIds = null;
3385 } else {
3386 mChildNodeIds = new LongArray(childrenSize);
3387 for (int i = 0; i < childrenSize; i++) {
3388 final long childId = parcel.readLong();
3389 mChildNodeIds.add(childId);
3390 }
Alan Viverettef0aed092013-11-06 15:33:03 -08003391 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003392 }
3393
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003394 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3395 mBoundsInParent.top = parcel.readInt();
3396 mBoundsInParent.bottom = parcel.readInt();
3397 mBoundsInParent.left = parcel.readInt();
3398 mBoundsInParent.right = parcel.readInt();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003399 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003400
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003401 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3402 mBoundsInScreen.top = parcel.readInt();
3403 mBoundsInScreen.bottom = parcel.readInt();
3404 mBoundsInScreen.left = parcel.readInt();
3405 mBoundsInScreen.right = parcel.readInt();
Phil Weaverc2e28932016-12-08 12:29:25 -08003406 }
3407
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003408 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Eugene Susla554edd32017-05-24 16:49:59 -07003409 final int standardActions = parcel.readInt();
3410 addStandardActions(standardActions);
3411 final int nonStandardActionCount = parcel.readInt();
3412 for (int i = 0; i < nonStandardActionCount; i++) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003413 final AccessibilityAction action = new AccessibilityAction(
3414 parcel.readInt(), parcel.readCharSequence());
3415 addActionUnchecked(action);
3416 }
Svetoslav6254f482013-06-04 17:22:14 -07003417 }
Svetoslav3577a282013-06-06 14:09:10 -07003418
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003419 if (isBitSet(nonDefaultFields, fieldIndex++)) mMaxTextLength = parcel.readInt();
3420 if (isBitSet(nonDefaultFields, fieldIndex++)) mMovementGranularities = parcel.readInt();
3421 if (isBitSet(nonDefaultFields, fieldIndex++)) mBooleanProperties = parcel.readInt();
Svetoslav3577a282013-06-06 14:09:10 -07003422
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003423 if (isBitSet(nonDefaultFields, fieldIndex++)) mPackageName = parcel.readCharSequence();
3424 if (isBitSet(nonDefaultFields, fieldIndex++)) mClassName = parcel.readCharSequence();
3425 if (isBitSet(nonDefaultFields, fieldIndex++)) mText = parcel.readCharSequence();
3426 if (isBitSet(nonDefaultFields, fieldIndex++)) mHintText = parcel.readCharSequence();
3427 if (isBitSet(nonDefaultFields, fieldIndex++)) mError = parcel.readCharSequence();
3428 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3429 mContentDescription = parcel.readCharSequence();
Svetoslav3577a282013-06-06 14:09:10 -07003430 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003431 if (isBitSet(nonDefaultFields, fieldIndex++)) mViewIdResourceName = parcel.readString();
Svetoslav3577a282013-06-06 14:09:10 -07003432
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003433 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionStart = parcel.readInt();
3434 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionEnd = parcel.readInt();
3435
3436 if (isBitSet(nonDefaultFields, fieldIndex++)) mInputType = parcel.readInt();
3437 if (isBitSet(nonDefaultFields, fieldIndex++)) mLiveRegion = parcel.readInt();
3438 if (isBitSet(nonDefaultFields, fieldIndex++)) mDrawingOrderInParent = parcel.readInt();
3439
3440 mExtraDataKeys = isBitSet(nonDefaultFields, fieldIndex++)
3441 ? parcel.createStringArrayList()
3442 : null;
3443
3444 mExtras = isBitSet(nonDefaultFields, fieldIndex++)
3445 ? parcel.readBundle()
3446 : null;
3447
3448 if (mRangeInfo != null) mRangeInfo.recycle();
3449 mRangeInfo = isBitSet(nonDefaultFields, fieldIndex++)
3450 ? RangeInfo.obtain(
3451 parcel.readInt(),
3452 parcel.readFloat(),
3453 parcel.readFloat(),
3454 parcel.readFloat())
3455 : null;
3456
3457 if (mCollectionInfo != null) mCollectionInfo.recycle();
3458 mCollectionInfo = isBitSet(nonDefaultFields, fieldIndex++)
3459 ? CollectionInfo.obtain(
3460 parcel.readInt(),
3461 parcel.readInt(),
3462 parcel.readInt() == 1,
3463 parcel.readInt())
3464 : null;
3465
3466 if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
3467 mCollectionItemInfo = isBitSet(nonDefaultFields, fieldIndex++)
3468 ? CollectionItemInfo.obtain(
3469 parcel.readInt(),
3470 parcel.readInt(),
3471 parcel.readInt(),
3472 parcel.readInt(),
3473 parcel.readInt() == 1,
3474 parcel.readInt() == 1)
3475 : null;
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -07003476
3477 mSealed = sealed;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003478 }
3479
3480 /**
3481 * Clears the state of this instance.
3482 */
3483 private void clear() {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003484 init(DEFAULT);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003485 }
3486
Eugene Susla554edd32017-05-24 16:49:59 -07003487 private static boolean isDefaultStandardAction(AccessibilityAction action) {
3488 return action.mSerializationFlag != -1 && TextUtils.isEmpty(action.getLabel());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003489 }
3490
3491 private static AccessibilityAction getActionSingleton(int actionId) {
3492 final int actions = AccessibilityAction.sStandardActions.size();
3493 for (int i = 0; i < actions; i++) {
3494 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3495 if (actionId == currentAction.getId()) {
3496 return currentAction;
3497 }
3498 }
3499
3500 return null;
3501 }
3502
Eugene Susla554edd32017-05-24 16:49:59 -07003503 private static AccessibilityAction getActionSingletonBySerializationFlag(int flag) {
3504 final int actions = AccessibilityAction.sStandardActions.size();
3505 for (int i = 0; i < actions; i++) {
3506 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3507 if (flag == currentAction.mSerializationFlag) {
3508 return currentAction;
3509 }
3510 }
3511
3512 return null;
3513 }
3514
3515 private void addStandardActions(int serializationIdMask) {
3516 int remainingIds = serializationIdMask;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003517 while (remainingIds > 0) {
3518 final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
3519 remainingIds &= ~id;
Eugene Susla554edd32017-05-24 16:49:59 -07003520 AccessibilityAction action = getActionSingletonBySerializationFlag(id);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003521 addAction(action);
3522 }
3523 }
3524
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003525 /**
3526 * Gets the human readable action symbolic name.
3527 *
3528 * @param action The action.
3529 * @return The symbolic name.
3530 */
3531 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003532 switch (action) {
3533 case ACTION_FOCUS:
3534 return "ACTION_FOCUS";
3535 case ACTION_CLEAR_FOCUS:
3536 return "ACTION_CLEAR_FOCUS";
3537 case ACTION_SELECT:
3538 return "ACTION_SELECT";
3539 case ACTION_CLEAR_SELECTION:
3540 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003541 case ACTION_CLICK:
3542 return "ACTION_CLICK";
3543 case ACTION_LONG_CLICK:
3544 return "ACTION_LONG_CLICK";
3545 case ACTION_ACCESSIBILITY_FOCUS:
3546 return "ACTION_ACCESSIBILITY_FOCUS";
3547 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
3548 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003549 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
3550 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
3551 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
3552 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003553 case ACTION_NEXT_HTML_ELEMENT:
3554 return "ACTION_NEXT_HTML_ELEMENT";
3555 case ACTION_PREVIOUS_HTML_ELEMENT:
3556 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07003557 case ACTION_SCROLL_FORWARD:
3558 return "ACTION_SCROLL_FORWARD";
3559 case ACTION_SCROLL_BACKWARD:
3560 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08003561 case ACTION_CUT:
3562 return "ACTION_CUT";
3563 case ACTION_COPY:
3564 return "ACTION_COPY";
3565 case ACTION_PASTE:
3566 return "ACTION_PASTE";
3567 case ACTION_SET_SELECTION:
3568 return "ACTION_SET_SELECTION";
Steven Dao103a577c2015-10-12 17:35:59 -07003569 case ACTION_EXPAND:
3570 return "ACTION_EXPAND";
3571 case ACTION_COLLAPSE:
3572 return "ACTION_COLLAPSE";
3573 case ACTION_DISMISS:
3574 return "ACTION_DISMISS";
3575 case ACTION_SET_TEXT:
3576 return "ACTION_SET_TEXT";
3577 case R.id.accessibilityActionShowOnScreen:
3578 return "ACTION_SHOW_ON_SCREEN";
3579 case R.id.accessibilityActionScrollToPosition:
3580 return "ACTION_SCROLL_TO_POSITION";
3581 case R.id.accessibilityActionScrollUp:
3582 return "ACTION_SCROLL_UP";
3583 case R.id.accessibilityActionScrollLeft:
3584 return "ACTION_SCROLL_LEFT";
3585 case R.id.accessibilityActionScrollDown:
3586 return "ACTION_SCROLL_DOWN";
3587 case R.id.accessibilityActionScrollRight:
3588 return "ACTION_SCROLL_RIGHT";
3589 case R.id.accessibilityActionSetProgress:
3590 return "ACTION_SET_PROGRESS";
3591 case R.id.accessibilityActionContextClick:
3592 return "ACTION_CONTEXT_CLICK";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003593 default:
Steven Dao103a577c2015-10-12 17:35:59 -07003594 return "ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003595 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003596 }
3597
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003598 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003599 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003600 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003601 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003602 * @return The symbolic name.
3603 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003604 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003605 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003606 case MOVEMENT_GRANULARITY_CHARACTER:
3607 return "MOVEMENT_GRANULARITY_CHARACTER";
3608 case MOVEMENT_GRANULARITY_WORD:
3609 return "MOVEMENT_GRANULARITY_WORD";
3610 case MOVEMENT_GRANULARITY_LINE:
3611 return "MOVEMENT_GRANULARITY_LINE";
3612 case MOVEMENT_GRANULARITY_PARAGRAPH:
3613 return "MOVEMENT_GRANULARITY_PARAGRAPH";
3614 case MOVEMENT_GRANULARITY_PAGE:
3615 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003616 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003617 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003618 }
3619 }
3620
Svetoslav Ganov02107852011-10-03 17:06:56 -07003621 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Phil Weaver23161e72017-04-19 12:16:36 -07003622 return ((mWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
3623 && (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
3624 && (mConnectionId != UNDEFINED_CONNECTION_ID));
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003625 }
3626
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003627 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003628 public boolean equals(Object object) {
3629 if (this == object) {
3630 return true;
3631 }
3632 if (object == null) {
3633 return false;
3634 }
3635 if (getClass() != object.getClass()) {
3636 return false;
3637 }
3638 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003639 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003640 return false;
3641 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07003642 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003643 return false;
3644 }
3645 return true;
3646 }
3647
3648 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003649 public int hashCode() {
3650 final int prime = 31;
3651 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003652 result = prime * result + getAccessibilityViewId(mSourceNodeId);
3653 result = prime * result + getVirtualDescendantId(mSourceNodeId);
3654 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003655 return result;
3656 }
3657
3658 @Override
3659 public String toString() {
3660 StringBuilder builder = new StringBuilder();
3661 builder.append(super.toString());
3662
3663 if (DEBUG) {
Svetoslav8e3feb12014-02-24 13:46:47 -08003664 builder.append("; sourceNodeId: " + mSourceNodeId);
Svetoslav Ganov02107852011-10-03 17:06:56 -07003665 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
3666 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
3667 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav6c702902014-10-09 18:40:56 -07003668 builder.append("; traversalBefore: ").append(mTraversalBefore);
3669 builder.append("; traversalAfter: ").append(mTraversalAfter);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003670
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003671 int granularities = mMovementGranularities;
3672 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003673 while (granularities != 0) {
3674 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
3675 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003676 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003677 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003678 builder.append(", ");
3679 }
3680 }
3681 builder.append("]");
3682
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003683 builder.append("; childAccessibilityIds: [");
Alan Viverettef0aed092013-11-06 15:33:03 -08003684 final LongArray childIds = mChildNodeIds;
3685 if (childIds != null) {
3686 for (int i = 0, count = childIds.size(); i < count; i++) {
3687 builder.append(childIds.get(i));
3688 if (i < count - 1) {
3689 builder.append(", ");
3690 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003691 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003692 }
3693 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003694 }
3695
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003696 builder.append("; boundsInParent: " + mBoundsInParent);
3697 builder.append("; boundsInScreen: " + mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003698
3699 builder.append("; packageName: ").append(mPackageName);
3700 builder.append("; className: ").append(mClassName);
3701 builder.append("; text: ").append(mText);
Alan Viverettefccbff52014-07-07 15:06:14 -07003702 builder.append("; error: ").append(mError);
Alan Viverette029942f2014-08-12 14:55:56 -07003703 builder.append("; maxTextLength: ").append(mMaxTextLength);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003704 builder.append("; contentDescription: ").append(mContentDescription);
Svetoslav22431a32013-02-05 14:30:19 -08003705 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003706
3707 builder.append("; checkable: ").append(isCheckable());
3708 builder.append("; checked: ").append(isChecked());
3709 builder.append("; focusable: ").append(isFocusable());
3710 builder.append("; focused: ").append(isFocused());
3711 builder.append("; selected: ").append(isSelected());
3712 builder.append("; clickable: ").append(isClickable());
3713 builder.append("; longClickable: ").append(isLongClickable());
Mady Mellore8608912015-06-05 09:02:55 -07003714 builder.append("; contextClickable: ").append(isContextClickable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003715 builder.append("; enabled: ").append(isEnabled());
3716 builder.append("; password: ").append(isPassword());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003717 builder.append("; scrollable: ").append(isScrollable());
Phil Weaver4d3eec412016-09-01 16:28:34 -07003718 builder.append("; importantForAccessibility: ").append(isImportantForAccessibility());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003719 builder.append("; actions: ").append(mActions);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003720
3721 return builder.toString();
3722 }
3723
Svetoslav6c702902014-10-09 18:40:56 -07003724 private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
3725 if (!canPerformRequestOverConnection(accessibilityId)) {
3726 return null;
3727 }
3728 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
3729 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
3730 mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
Phil Weaverc2e28932016-12-08 12:29:25 -08003731 | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null);
Svetoslav6c702902014-10-09 18:40:56 -07003732 }
3733
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003734 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07003735 * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
3736 * Each action has a unique id that is mandatory and optional data.
3737 * <p>
3738 * There are three categories of actions:
3739 * <ul>
3740 * <li><strong>Standard actions</strong> - These are actions that are reported and
3741 * handled by the standard UI widgets in the platform. For each standard action
3742 * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
Phil Weaver426361c2017-02-22 13:06:25 -08003743 * These actions will have {@code null} labels.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003744 * </li>
3745 * <li><strong>Custom actions action</strong> - These are actions that are reported
3746 * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
3747 * example, an application may define a custom action for clearing the user history.
3748 * </li>
3749 * <li><strong>Overriden standard actions</strong> - These are actions that override
3750 * standard actions to customize them. For example, an app may add a label to the
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003751 * standard {@link #ACTION_CLICK} action to announce that this action clears browsing history.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003752 * </ul>
3753 * </p>
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003754 * <p>
3755 * Actions are typically added to an {@link AccessibilityNodeInfo} by using
3756 * {@link AccessibilityNodeInfo#addAction(AccessibilityAction)} within
3757 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed
3758 * within {@link View#performAccessibilityAction(int, Bundle)}.
3759 * </p>
3760 * <p class="note">
3761 * <strong>Note:</strong> Views which support these actions should invoke
3762 * {@link View#setImportantForAccessibility(int)} with
3763 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService}
3764 * can discover the set of supported actions.
3765 * </p>
Kristian Monsen74bc1942014-04-29 11:00:17 -07003766 */
3767 public static final class AccessibilityAction {
3768
Eugene Susla554edd32017-05-24 16:49:59 -07003769 /** @hide */
3770 public static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
3771
Kristian Monsen74bc1942014-04-29 11:00:17 -07003772 /**
3773 * Action that gives input focus to the node.
3774 */
3775 public static final AccessibilityAction ACTION_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003776 new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003777
3778 /**
3779 * Action that clears input focus of the node.
3780 */
3781 public static final AccessibilityAction ACTION_CLEAR_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003782 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003783
3784 /**
3785 * Action that selects the node.
3786 */
3787 public static final AccessibilityAction ACTION_SELECT =
Eugene Susla554edd32017-05-24 16:49:59 -07003788 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SELECT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003789
3790 /**
3791 * Action that deselects the node.
3792 */
3793 public static final AccessibilityAction ACTION_CLEAR_SELECTION =
Eugene Susla554edd32017-05-24 16:49:59 -07003794 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003795
3796 /**
3797 * Action that clicks on the node info.
3798 */
3799 public static final AccessibilityAction ACTION_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07003800 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003801
3802 /**
3803 * Action that long clicks on the node.
3804 */
3805 public static final AccessibilityAction ACTION_LONG_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07003806 new AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003807
3808 /**
3809 * Action that gives accessibility focus to the node.
3810 */
3811 public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003812 new AccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003813
3814 /**
3815 * Action that clears accessibility focus of the node.
3816 */
3817 public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003818 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003819
3820 /**
3821 * Action that requests to go to the next entity in this node's text
3822 * at a given movement granularity. For example, move to the next character,
3823 * word, etc.
3824 * <p>
3825 * <strong>Arguments:</strong>
3826 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3827 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3828 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3829 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3830 * <strong>Example:</strong> Move to the previous character and do not extend selection.
3831 * <code><pre><p>
3832 * Bundle arguments = new Bundle();
3833 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3834 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3835 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3836 * false);
3837 * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(),
3838 * arguments);
3839 * </code></pre></p>
3840 * </p>
3841 *
3842 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3843 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3844 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3845 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3846 *
3847 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3848 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3849 * @see AccessibilityNodeInfo#getMovementGranularities()
3850 * AccessibilityNodeInfo.getMovementGranularities()
3851 *
3852 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3853 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3854 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3855 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3856 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3857 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3858 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3859 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3860 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3861 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3862 */
3863 public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY =
Eugene Susla554edd32017-05-24 16:49:59 -07003864 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003865
3866 /**
3867 * Action that requests to go to the previous entity in this node's text
3868 * at a given movement granularity. For example, move to the next character,
3869 * word, etc.
3870 * <p>
3871 * <strong>Arguments:</strong>
3872 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3873 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3874 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3875 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3876 * <strong>Example:</strong> Move to the next character and do not extend selection.
3877 * <code><pre><p>
3878 * Bundle arguments = new Bundle();
3879 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3880 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3881 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3882 * false);
3883 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(),
3884 * arguments);
3885 * </code></pre></p>
3886 * </p>
3887 *
3888 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3889 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3890 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3891 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3892 *
3893 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3894 * AccessibilityNodeInfo.setMovementGranularities(int)
3895 * @see AccessibilityNodeInfo#getMovementGranularities()
3896 * AccessibilityNodeInfo.getMovementGranularities()
3897 *
3898 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3899 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3900 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3901 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3902 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3903 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3904 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3905 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3906 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3907 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3908 */
3909 public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY =
3910 new AccessibilityAction(
Eugene Susla554edd32017-05-24 16:49:59 -07003911 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003912
3913 /**
3914 * Action to move to the next HTML element of a given type. For example, move
3915 * to the BUTTON, INPUT, TABLE, etc.
3916 * <p>
3917 * <strong>Arguments:</strong>
3918 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3919 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3920 * <strong>Example:</strong>
3921 * <code><pre><p>
3922 * Bundle arguments = new Bundle();
3923 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3924 * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments);
3925 * </code></pre></p>
3926 * </p>
3927 */
3928 public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT =
Eugene Susla554edd32017-05-24 16:49:59 -07003929 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003930
3931 /**
3932 * Action to move to the previous HTML element of a given type. For example, move
3933 * to the BUTTON, INPUT, TABLE, etc.
3934 * <p>
3935 * <strong>Arguments:</strong>
3936 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3937 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3938 * <strong>Example:</strong>
3939 * <code><pre><p>
3940 * Bundle arguments = new Bundle();
3941 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3942 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments);
3943 * </code></pre></p>
3944 * </p>
3945 */
3946 public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT =
Eugene Susla554edd32017-05-24 16:49:59 -07003947 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003948
3949 /**
3950 * Action to scroll the node content forward.
3951 */
3952 public static final AccessibilityAction ACTION_SCROLL_FORWARD =
Eugene Susla554edd32017-05-24 16:49:59 -07003953 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003954
3955 /**
3956 * Action to scroll the node content backward.
3957 */
3958 public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
Eugene Susla554edd32017-05-24 16:49:59 -07003959 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003960
3961 /**
3962 * Action to copy the current selection to the clipboard.
3963 */
3964 public static final AccessibilityAction ACTION_COPY =
Eugene Susla554edd32017-05-24 16:49:59 -07003965 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COPY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003966
3967 /**
3968 * Action to paste the current clipboard content.
3969 */
3970 public static final AccessibilityAction ACTION_PASTE =
Eugene Susla554edd32017-05-24 16:49:59 -07003971 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PASTE);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003972
3973 /**
3974 * Action to cut the current selection and place it to the clipboard.
3975 */
3976 public static final AccessibilityAction ACTION_CUT =
Eugene Susla554edd32017-05-24 16:49:59 -07003977 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CUT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003978
3979 /**
3980 * Action to set the selection. Performing this action with no arguments
3981 * clears the selection.
3982 * <p>
3983 * <strong>Arguments:</strong>
3984 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3985 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT},
3986 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3987 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br>
3988 * <strong>Example:</strong>
3989 * <code><pre><p>
3990 * Bundle arguments = new Bundle();
3991 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
3992 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
3993 * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments);
3994 * </code></pre></p>
3995 * </p>
3996 *
3997 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3998 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT
3999 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
4000 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT
4001 */
4002 public static final AccessibilityAction ACTION_SET_SELECTION =
Eugene Susla554edd32017-05-24 16:49:59 -07004003 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004004
4005 /**
4006 * Action to expand an expandable node.
4007 */
4008 public static final AccessibilityAction ACTION_EXPAND =
Eugene Susla554edd32017-05-24 16:49:59 -07004009 new AccessibilityAction(AccessibilityNodeInfo.ACTION_EXPAND);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004010
4011 /**
4012 * Action to collapse an expandable node.
4013 */
4014 public static final AccessibilityAction ACTION_COLLAPSE =
Eugene Susla554edd32017-05-24 16:49:59 -07004015 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004016
4017 /**
4018 * Action to dismiss a dismissable node.
4019 */
4020 public static final AccessibilityAction ACTION_DISMISS =
Eugene Susla554edd32017-05-24 16:49:59 -07004021 new AccessibilityAction(AccessibilityNodeInfo.ACTION_DISMISS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004022
4023 /**
4024 * Action that sets the text of the node. Performing the action without argument,
4025 * using <code> null</code> or empty {@link CharSequence} will clear the text. This
4026 * action will also put the cursor at the end of text.
4027 * <p>
4028 * <strong>Arguments:</strong>
4029 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
4030 * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
4031 * <strong>Example:</strong>
4032 * <code><pre><p>
4033 * Bundle arguments = new Bundle();
4034 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
4035 * "android");
4036 * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments);
4037 * </code></pre></p>
4038 */
4039 public static final AccessibilityAction ACTION_SET_TEXT =
Eugene Susla554edd32017-05-24 16:49:59 -07004040 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_TEXT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004041
Alan Viverette26c44ee2015-03-25 14:54:13 -07004042 /**
4043 * Action that requests the node make its bounding rectangle visible
4044 * on the screen, scrolling if necessary just enough.
4045 *
4046 * @see View#requestRectangleOnScreen(Rect)
4047 */
4048 public static final AccessibilityAction ACTION_SHOW_ON_SCREEN =
Eugene Susla554edd32017-05-24 16:49:59 -07004049 new AccessibilityAction(R.id.accessibilityActionShowOnScreen);
Alan Viverette26c44ee2015-03-25 14:54:13 -07004050
Alan Viverette23f44322015-04-06 16:04:56 -07004051 /**
4052 * Action that scrolls the node to make the specified collection
4053 * position visible on screen.
4054 * <p>
4055 * <strong>Arguments:</strong>
4056 * <ul>
4057 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
4058 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
4059 * <ul>
4060 *
4061 * @see AccessibilityNodeInfo#getCollectionInfo()
4062 */
4063 public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
Eugene Susla554edd32017-05-24 16:49:59 -07004064 new AccessibilityAction(R.id.accessibilityActionScrollToPosition);
Alan Viverette23f44322015-04-06 16:04:56 -07004065
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004066 /**
4067 * Action to scroll the node content up.
4068 */
4069 public static final AccessibilityAction ACTION_SCROLL_UP =
Eugene Susla554edd32017-05-24 16:49:59 -07004070 new AccessibilityAction(R.id.accessibilityActionScrollUp);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004071
4072 /**
4073 * Action to scroll the node content left.
4074 */
4075 public static final AccessibilityAction ACTION_SCROLL_LEFT =
Eugene Susla554edd32017-05-24 16:49:59 -07004076 new AccessibilityAction(R.id.accessibilityActionScrollLeft);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004077
4078 /**
4079 * Action to scroll the node content down.
4080 */
4081 public static final AccessibilityAction ACTION_SCROLL_DOWN =
Eugene Susla554edd32017-05-24 16:49:59 -07004082 new AccessibilityAction(R.id.accessibilityActionScrollDown);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004083
4084 /**
4085 * Action to scroll the node content right.
4086 */
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004087 public static final AccessibilityAction ACTION_SCROLL_RIGHT =
Eugene Susla554edd32017-05-24 16:49:59 -07004088 new AccessibilityAction(R.id.accessibilityActionScrollRight);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004089
Mady Mellord2744002015-04-30 16:17:16 -07004090 /**
Mady Mellore8608912015-06-05 09:02:55 -07004091 * Action that context clicks the node.
Mady Mellore82067b2015-04-30 09:58:35 -07004092 */
Mady Mellore8608912015-06-05 09:02:55 -07004093 public static final AccessibilityAction ACTION_CONTEXT_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07004094 new AccessibilityAction(R.id.accessibilityActionContextClick);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004095
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004096 /**
4097 * Action that sets progress between {@link RangeInfo#getMin() RangeInfo.getMin()} and
4098 * {@link RangeInfo#getMax() RangeInfo.getMax()}. It should use the same value type as
4099 * {@link RangeInfo#getType() RangeInfo.getType()}
4100 * <p>
4101 * <strong>Arguments:</strong>
4102 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_PROGRESS_VALUE}
4103 *
4104 * @see RangeInfo
4105 */
4106 public static final AccessibilityAction ACTION_SET_PROGRESS =
Eugene Susla554edd32017-05-24 16:49:59 -07004107 new AccessibilityAction(R.id.accessibilityActionSetProgress);
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004108
Phil Weaverf00cd142017-03-03 13:44:00 -08004109 /**
4110 * Action to move a window to a new location.
4111 * <p>
4112 * <strong>Arguments:</strong>
4113 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_X}
4114 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_Y}
4115 */
4116 public static final AccessibilityAction ACTION_MOVE_WINDOW =
Eugene Susla554edd32017-05-24 16:49:59 -07004117 new AccessibilityAction(R.id.accessibilityActionMoveWindow);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004118
4119 private final int mActionId;
4120 private final CharSequence mLabel;
4121
Eugene Susla554edd32017-05-24 16:49:59 -07004122 /** @hide */
4123 public int mSerializationFlag = -1;
4124
Kristian Monsen74bc1942014-04-29 11:00:17 -07004125 /**
4126 * Creates a new AccessibilityAction. For adding a standard action without a specific label,
4127 * use the static constants.
4128 *
4129 * You can also override the description for one the standard actions. Below is an example
4130 * how to override the standard click action by adding a custom label:
4131 * <pre>
4132 * AccessibilityAction action = new AccessibilityAction(
Phil Weaverc3791292016-09-12 11:06:49 -07004133 * AccessibilityAction.ACTION_CLICK.getId(), getLocalizedLabel());
Kristian Monsen74bc1942014-04-29 11:00:17 -07004134 * node.addAction(action);
4135 * </pre>
4136 *
4137 * @param actionId The id for this action. This should either be one of the
4138 * standard actions or a specific action for your app. In that case it is
4139 * required to use a resource identifier.
4140 * @param label The label for the new AccessibilityAction.
4141 */
4142 public AccessibilityAction(int actionId, @Nullable CharSequence label) {
Svetoslav5c4cd182014-05-21 14:53:16 -07004143 if ((actionId & ACTION_TYPE_MASK) == 0 && Integer.bitCount(actionId) != 1) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07004144 throw new IllegalArgumentException("Invalid standard action id");
4145 }
4146
Kristian Monsen74bc1942014-04-29 11:00:17 -07004147 mActionId = actionId;
4148 mLabel = label;
4149 }
4150
4151 /**
Eugene Susla554edd32017-05-24 16:49:59 -07004152 * Constructor for a {@link #sStandardActions standard} action
4153 */
4154 private AccessibilityAction(int standardActionId) {
4155 this(standardActionId, null);
4156
4157 mSerializationFlag = (int) bitAt(sStandardActions.size());
4158 sStandardActions.add(this);
4159 }
4160
4161 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07004162 * Gets the id for this action.
4163 *
4164 * @return The action id.
4165 */
4166 public int getId() {
4167 return mActionId;
4168 }
4169
4170 /**
4171 * Gets the label for this action. Its purpose is to describe the
4172 * action to user.
4173 *
4174 * @return The label.
4175 */
4176 public CharSequence getLabel() {
4177 return mLabel;
4178 }
4179
4180 @Override
4181 public int hashCode() {
4182 return mActionId;
4183 }
4184
4185 @Override
4186 public boolean equals(Object other) {
4187 if (other == null) {
4188 return false;
4189 }
4190
4191 if (other == this) {
4192 return true;
4193 }
4194
4195 if (getClass() != other.getClass()) {
4196 return false;
4197 }
4198
4199 return mActionId == ((AccessibilityAction)other).mActionId;
4200 }
4201
4202 @Override
4203 public String toString() {
4204 return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
4205 }
4206 }
4207
4208 /**
Svetoslav3577a282013-06-06 14:09:10 -07004209 * Class with information if a node is a range. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004210 * {@link RangeInfo#obtain(int, float, float, float)} to get an instance. Recycling is
4211 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav3577a282013-06-06 14:09:10 -07004212 */
4213 public static final class RangeInfo {
4214 private static final int MAX_POOL_SIZE = 10;
4215
4216 /** Range type: integer. */
4217 public static final int RANGE_TYPE_INT = 0;
4218 /** Range type: float. */
4219 public static final int RANGE_TYPE_FLOAT = 1;
4220 /** Range type: percent with values from zero to one.*/
4221 public static final int RANGE_TYPE_PERCENT = 2;
4222
4223 private static final SynchronizedPool<RangeInfo> sPool =
4224 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
4225
4226 private int mType;
4227 private float mMin;
4228 private float mMax;
4229 private float mCurrent;
4230
4231 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004232 * Obtains a pooled instance that is a clone of another one.
4233 *
4234 * @param other The instance to clone.
4235 *
4236 * @hide
4237 */
4238 public static RangeInfo obtain(RangeInfo other) {
4239 return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
4240 }
4241
4242 /**
Svetoslav3577a282013-06-06 14:09:10 -07004243 * Obtains a pooled instance.
4244 *
4245 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004246 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4247 * minimum.
4248 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4249 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004250 * @param current The current value.
4251 */
4252 public static RangeInfo obtain(int type, float min, float max, float current) {
4253 RangeInfo info = sPool.acquire();
Steven Dao24142812016-04-13 15:25:09 -07004254 if (info == null) {
4255 return new RangeInfo(type, min, max, current);
4256 }
4257
4258 info.mType = type;
4259 info.mMin = min;
4260 info.mMax = max;
4261 info.mCurrent = current;
4262 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004263 }
4264
4265 /**
4266 * Creates a new range.
4267 *
4268 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004269 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4270 * minimum.
4271 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4272 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004273 * @param current The current value.
4274 */
4275 private RangeInfo(int type, float min, float max, float current) {
4276 mType = type;
4277 mMin = min;
4278 mMax = max;
4279 mCurrent = current;
4280 }
4281
4282 /**
4283 * Gets the range type.
4284 *
4285 * @return The range type.
4286 *
4287 * @see #RANGE_TYPE_INT
4288 * @see #RANGE_TYPE_FLOAT
4289 * @see #RANGE_TYPE_PERCENT
4290 */
4291 public int getType() {
4292 return mType;
4293 }
4294
4295 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004296 * Gets the minimum value.
Svetoslav3577a282013-06-06 14:09:10 -07004297 *
Phil Weaver79e44192016-12-19 14:24:49 -08004298 * @return The minimum value, or {@code Float.NEGATIVE_INFINITY} if no minimum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004299 */
4300 public float getMin() {
4301 return mMin;
4302 }
4303
4304 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004305 * Gets the maximum value.
Svetoslav3577a282013-06-06 14:09:10 -07004306 *
Phil Weaver79e44192016-12-19 14:24:49 -08004307 * @return The maximum value, or {@code Float.POSITIVE_INFINITY} if no maximum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004308 */
4309 public float getMax() {
4310 return mMax;
4311 }
4312
4313 /**
4314 * Gets the current value.
4315 *
4316 * @return The current value.
4317 */
4318 public float getCurrent() {
4319 return mCurrent;
4320 }
4321
4322 /**
4323 * Recycles this instance.
4324 */
4325 void recycle() {
4326 clear();
4327 sPool.release(this);
4328 }
4329
4330 private void clear() {
4331 mType = 0;
4332 mMin = 0;
4333 mMax = 0;
4334 mCurrent = 0;
4335 }
4336 }
4337
4338 /**
4339 * Class with information if a node is a collection. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004340 * {@link CollectionInfo#obtain(int, int, boolean)} to get an instance. Recycling is
4341 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004342 * <p>
4343 * A collection of items has rows and columns and may be hierarchical.
4344 * For example, a horizontal list is a collection with one column, as
4345 * many rows as the list items, and is not hierarchical; A table is a
4346 * collection with several rows, several columns, and is not hierarchical;
4347 * A vertical tree is a hierarchical collection with one column and
4348 * as many rows as the first level children.
4349 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004350 */
4351 public static final class CollectionInfo {
Alan Viverette76769ae2014-02-12 16:38:10 -08004352 /** Selection mode where items are not selectable. */
4353 public static final int SELECTION_MODE_NONE = 0;
4354
4355 /** Selection mode where a single item may be selected. */
4356 public static final int SELECTION_MODE_SINGLE = 1;
4357
4358 /** Selection mode where multiple items may be selected. */
4359 public static final int SELECTION_MODE_MULTIPLE = 2;
4360
Svetoslav3577a282013-06-06 14:09:10 -07004361 private static final int MAX_POOL_SIZE = 20;
4362
4363 private static final SynchronizedPool<CollectionInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004364 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004365
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004366 private int mRowCount;
4367 private int mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004368 private boolean mHierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004369 private int mSelectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004370
4371 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004372 * Obtains a pooled instance that is a clone of another one.
4373 *
4374 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004375 * @hide
4376 */
4377 public static CollectionInfo obtain(CollectionInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004378 return CollectionInfo.obtain(other.mRowCount, other.mColumnCount, other.mHierarchical,
4379 other.mSelectionMode);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004380 }
4381
4382 /**
Svetoslav3577a282013-06-06 14:09:10 -07004383 * Obtains a pooled instance.
4384 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004385 * @param rowCount The number of rows.
4386 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004387 * @param hierarchical Whether the collection is hierarchical.
4388 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004389 public static CollectionInfo obtain(int rowCount, int columnCount,
4390 boolean hierarchical) {
4391 return obtain(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE);
4392 }
4393
4394 /**
4395 * Obtains a pooled instance.
4396 *
4397 * @param rowCount The number of rows.
4398 * @param columnCount The number of columns.
4399 * @param hierarchical Whether the collection is hierarchical.
4400 * @param selectionMode The collection's selection mode, one of:
4401 * <ul>
4402 * <li>{@link #SELECTION_MODE_NONE}
4403 * <li>{@link #SELECTION_MODE_SINGLE}
4404 * <li>{@link #SELECTION_MODE_MULTIPLE}
4405 * </ul>
4406 */
4407 public static CollectionInfo obtain(int rowCount, int columnCount,
4408 boolean hierarchical, int selectionMode) {
4409 final CollectionInfo info = sPool.acquire();
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004410 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004411 return new CollectionInfo(rowCount, columnCount, hierarchical, selectionMode);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004412 }
4413
4414 info.mRowCount = rowCount;
4415 info.mColumnCount = columnCount;
4416 info.mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004417 info.mSelectionMode = selectionMode;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004418 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004419 }
4420
4421 /**
4422 * Creates a new instance.
4423 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004424 * @param rowCount The number of rows.
4425 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004426 * @param hierarchical Whether the collection is hierarchical.
Alan Viverette76769ae2014-02-12 16:38:10 -08004427 * @param selectionMode The collection's selection mode.
Svetoslav3577a282013-06-06 14:09:10 -07004428 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004429 private CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
4430 int selectionMode) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004431 mRowCount = rowCount;
4432 mColumnCount = columnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004433 mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004434 mSelectionMode = selectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004435 }
4436
4437 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004438 * Gets the number of rows.
Svetoslav3577a282013-06-06 14:09:10 -07004439 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004440 * @return The row count.
Svetoslav3577a282013-06-06 14:09:10 -07004441 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004442 public int getRowCount() {
4443 return mRowCount;
Svetoslav3577a282013-06-06 14:09:10 -07004444 }
4445
4446 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004447 * Gets the number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004448 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004449 * @return The column count.
Svetoslav3577a282013-06-06 14:09:10 -07004450 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004451 public int getColumnCount() {
4452 return mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004453 }
4454
4455 /**
4456 * Gets if the collection is a hierarchically ordered.
4457 *
4458 * @return Whether the collection is hierarchical.
4459 */
4460 public boolean isHierarchical() {
4461 return mHierarchical;
4462 }
4463
4464 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004465 * Gets the collection's selection mode.
4466 *
4467 * @return The collection's selection mode, one of:
4468 * <ul>
4469 * <li>{@link #SELECTION_MODE_NONE}
4470 * <li>{@link #SELECTION_MODE_SINGLE}
4471 * <li>{@link #SELECTION_MODE_MULTIPLE}
4472 * </ul>
4473 */
4474 public int getSelectionMode() {
4475 return mSelectionMode;
4476 }
4477
4478 /**
Svetoslav3577a282013-06-06 14:09:10 -07004479 * Recycles this instance.
4480 */
4481 void recycle() {
4482 clear();
4483 sPool.release(this);
4484 }
4485
4486 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004487 mRowCount = 0;
4488 mColumnCount = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004489 mHierarchical = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004490 mSelectionMode = SELECTION_MODE_NONE;
Svetoslav3577a282013-06-06 14:09:10 -07004491 }
4492 }
4493
4494 /**
4495 * Class with information if a node is a collection item. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004496 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean)}
Phil Weaver764152b2016-07-19 11:32:27 -07004497 * to get an instance. Recycling is handled by the {@link AccessibilityNodeInfo} to which this
4498 * object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004499 * <p>
4500 * A collection item is contained in a collection, it starts at
4501 * a given row and column in the collection, and spans one or
4502 * more rows and columns. For example, a header of two related
4503 * table columns starts at the first row and the first column,
4504 * spans one row and two columns.
4505 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004506 */
4507 public static final class CollectionItemInfo {
4508 private static final int MAX_POOL_SIZE = 20;
4509
4510 private static final SynchronizedPool<CollectionItemInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004511 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004512
4513 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004514 * Obtains a pooled instance that is a clone of another one.
4515 *
4516 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004517 * @hide
4518 */
4519 public static CollectionItemInfo obtain(CollectionItemInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004520 return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan, other.mColumnIndex,
4521 other.mColumnSpan, other.mHeading, other.mSelected);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004522 }
4523
4524 /**
Svetoslav3577a282013-06-06 14:09:10 -07004525 * Obtains a pooled instance.
4526 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004527 * @param rowIndex The row index at which the item is located.
4528 * @param rowSpan The number of rows the item spans.
4529 * @param columnIndex The column index at which the item is located.
4530 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004531 * @param heading Whether the item is a heading.
4532 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004533 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4534 int columnIndex, int columnSpan, boolean heading) {
4535 return obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading, false);
4536 }
4537
4538 /**
4539 * Obtains a pooled instance.
4540 *
4541 * @param rowIndex The row index at which the item is located.
4542 * @param rowSpan The number of rows the item spans.
4543 * @param columnIndex The column index at which the item is located.
4544 * @param columnSpan The number of columns the item spans.
4545 * @param heading Whether the item is a heading.
4546 * @param selected Whether the item is selected.
4547 */
4548 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4549 int columnIndex, int columnSpan, boolean heading, boolean selected) {
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004550 final CollectionItemInfo info = sPool.acquire();
4551 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004552 return new CollectionItemInfo(
4553 rowIndex, rowSpan, columnIndex, columnSpan, heading, selected);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004554 }
4555
4556 info.mRowIndex = rowIndex;
4557 info.mRowSpan = rowSpan;
4558 info.mColumnIndex = columnIndex;
4559 info.mColumnSpan = columnSpan;
4560 info.mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004561 info.mSelected = selected;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004562 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004563 }
4564
4565 private boolean mHeading;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004566 private int mColumnIndex;
4567 private int mRowIndex;
4568 private int mColumnSpan;
4569 private int mRowSpan;
Alan Viverette76769ae2014-02-12 16:38:10 -08004570 private boolean mSelected;
Svetoslav3577a282013-06-06 14:09:10 -07004571
4572 /**
4573 * Creates a new instance.
4574 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004575 * @param rowIndex The row index at which the item is located.
4576 * @param rowSpan The number of rows the item spans.
4577 * @param columnIndex The column index at which the item is located.
4578 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004579 * @param heading Whether the item is a heading.
4580 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004581 private CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
4582 boolean heading, boolean selected) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004583 mRowIndex = rowIndex;
4584 mRowSpan = rowSpan;
4585 mColumnIndex = columnIndex;
4586 mColumnSpan = columnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004587 mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004588 mSelected = selected;
Svetoslav3577a282013-06-06 14:09:10 -07004589 }
4590
4591 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004592 * Gets the column index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004593 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004594 * @return The column index.
Svetoslav3577a282013-06-06 14:09:10 -07004595 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004596 public int getColumnIndex() {
4597 return mColumnIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004598 }
4599
4600 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004601 * Gets the row index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004602 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004603 * @return The row index.
Svetoslav3577a282013-06-06 14:09:10 -07004604 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004605 public int getRowIndex() {
4606 return mRowIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004607 }
4608
4609 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004610 * Gets the number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004611 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004612 * @return The column span.
Svetoslav3577a282013-06-06 14:09:10 -07004613 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004614 public int getColumnSpan() {
4615 return mColumnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004616 }
4617
4618 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004619 * Gets the number of rows the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004620 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004621 * @return The row span.
Svetoslav3577a282013-06-06 14:09:10 -07004622 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004623 public int getRowSpan() {
4624 return mRowSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004625 }
4626
4627 /**
4628 * Gets if the collection item is a heading. For example, section
4629 * heading, table header, etc.
4630 *
4631 * @return If the item is a heading.
4632 */
4633 public boolean isHeading() {
4634 return mHeading;
4635 }
4636
4637 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004638 * Gets if the collection item is selected.
4639 *
4640 * @return If the item is selected.
4641 */
4642 public boolean isSelected() {
4643 return mSelected;
4644 }
4645
4646 /**
Svetoslav3577a282013-06-06 14:09:10 -07004647 * Recycles this instance.
4648 */
4649 void recycle() {
4650 clear();
4651 sPool.release(this);
4652 }
4653
4654 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004655 mColumnIndex = 0;
4656 mColumnSpan = 0;
4657 mRowIndex = 0;
4658 mRowSpan = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004659 mHeading = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004660 mSelected = false;
Svetoslav3577a282013-06-06 14:09:10 -07004661 }
4662 }
4663
4664 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08004665 * @see android.os.Parcelable.Creator
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004666 */
4667 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
4668 new Parcelable.Creator<AccessibilityNodeInfo>() {
Alan Viverettef0aed092013-11-06 15:33:03 -08004669 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004670 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
4671 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
4672 info.initFromParcel(parcel);
4673 return info;
4674 }
4675
Alan Viverettef0aed092013-11-06 15:33:03 -08004676 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004677 public AccessibilityNodeInfo[] newArray(int size) {
4678 return new AccessibilityNodeInfo[size];
4679 }
4680 };
4681}