blob: 5148d92a827997dfa2f895e4c7b2e59e5d18fa76 [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
Phil Weaverc2e28932016-12-08 12:29:25 -080019import static java.util.Collections.EMPTY_LIST;
20
Casey Burkhardt7ef48be2016-01-31 11:51:09 -080021import android.accessibilityservice.AccessibilityService;
Svetoslav Ganov80943d82013-01-02 10:25:37 -080022import android.accessibilityservice.AccessibilityServiceInfo;
Kristian Monsen74bc1942014-04-29 11:00:17 -070023import android.annotation.Nullable;
Phil Weaver62d20fa2016-09-15 11:05:55 -070024import android.annotation.TestApi;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070025import android.graphics.Rect;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070026import android.os.Bundle;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070027import android.os.Parcel;
28import android.os.Parcelable;
Svetoslav6254f482013-06-04 17:22:14 -070029import android.text.InputType;
Phil Weaver193520e2016-12-13 09:39:06 -080030import android.text.Spannable;
Phil Weaver0ebe6bd2017-02-21 16:24:31 -080031import android.text.SpannableStringBuilder;
Phil Weaver193520e2016-12-13 09:39:06 -080032import android.text.Spanned;
Kristian Monsen74bc1942014-04-29 11:00:17 -070033import android.text.TextUtils;
Phil Weaver193520e2016-12-13 09:39:06 -080034import android.text.style.AccessibilityClickableSpan;
35import android.text.style.AccessibilityURLSpan;
36import android.text.style.ClickableSpan;
37import android.text.style.URLSpan;
Kristian Monsen74bc1942014-04-29 11:00:17 -070038import android.util.ArraySet;
Alan Viverettef0aed092013-11-06 15:33:03 -080039import android.util.LongArray;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -080040import android.util.Pools.SynchronizedPool;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070041import android.view.View;
42
Alan Viverette26c44ee2015-03-25 14:54:13 -070043import com.android.internal.R;
44
Kristian Monsen74bc1942014-04-29 11:00:17 -070045import java.util.ArrayList;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070046import java.util.Collections;
47import java.util.List;
Phil Weaverb010b122016-08-17 17:47:48 -070048import java.util.concurrent.atomic.AtomicInteger;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070049
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070050/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070051 * This class represents a node of the window content as well as actions that
52 * can be requested from its source. From the point of view of an
Phil Weaver40ded282016-01-25 15:49:02 -080053 * {@link android.accessibilityservice.AccessibilityService} a window's content is
54 * presented as a tree of accessibility node infos, which may or may not map one-to-one
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070055 * to the view hierarchy. In other words, a custom view is free to report itself as
56 * a tree of accessibility node info.
57 * </p>
58 * <p>
59 * Once an accessibility node info is delivered to an accessibility service it is
60 * made immutable and calling a state mutation method generates an error.
61 * </p>
62 * <p>
63 * Please refer to {@link android.accessibilityservice.AccessibilityService} for
64 * details about how to obtain a handle to window content as a tree of accessibility
Phil Weaver40ded282016-01-25 15:49:02 -080065 * node info as well as details about the security model.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070066 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080067 * <div class="special reference">
68 * <h3>Developer Guides</h3>
69 * <p>For more information about making applications accessible, read the
70 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
71 * developer guide.</p>
72 * </div>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070073 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070074 * @see android.accessibilityservice.AccessibilityService
75 * @see AccessibilityEvent
76 * @see AccessibilityManager
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070077 */
78public class AccessibilityNodeInfo implements Parcelable {
79
80 private static final boolean DEBUG = false;
81
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080082 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080083 public static final int UNDEFINED_CONNECTION_ID = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080084
85 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080086 public static final int UNDEFINED_SELECTION_INDEX = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080087
Phil Weaverf00cd142017-03-03 13:44:00 -080088 /* Special IDs for node source IDs */
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080089 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080090 public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE;
91
92 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -080093 public static final int ROOT_ITEM_ID = Integer.MAX_VALUE - 1;
Svetoslav8e3feb12014-02-24 13:46:47 -080094
95 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -080096 public static final long UNDEFINED_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -080097
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -080098 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -080099 public static final long ROOT_NODE_ID = makeNodeId(ROOT_ITEM_ID,
100 AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav1e0d4af2014-04-10 17:41:29 -0700101
102 /** @hide */
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800103 public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
104
105 /** @hide */
106 public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
107
108 /** @hide */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700109 public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004;
110
111 /** @hide */
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800112 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008;
113
114 /** @hide */
115 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800116
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700117 // Actions.
118
119 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700120 * Action that gives input focus to the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700121 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700122 public static final int ACTION_FOCUS = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700123
124 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700125 * Action that clears input focus of the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700126 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700127 public static final int ACTION_CLEAR_FOCUS = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700128
129 /**
130 * Action that selects the node.
131 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700132 public static final int ACTION_SELECT = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700133
134 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -0700135 * Action that deselects the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700136 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700137 public static final int ACTION_CLEAR_SELECTION = 0x00000008;
138
139 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700140 * Action that clicks on the node info.
Maxim Bogatov219b41d2015-05-01 14:00:24 -0700141 *
142 * See {@link AccessibilityAction#ACTION_CLICK}
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700143 */
144 public static final int ACTION_CLICK = 0x00000010;
145
146 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700147 * Action that long clicks on the node.
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700148 */
149 public static final int ACTION_LONG_CLICK = 0x00000020;
150
151 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700152 * Action that gives accessibility focus to the node.
153 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700154 public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700155
156 /**
157 * Action that clears accessibility focus of the node.
158 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700159 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700160
161 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700162 * Action that requests to go to the next entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700163 * at a given movement granularity. For example, move to the next character,
164 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700165 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800166 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
167 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
168 * <strong>Example:</strong> Move to the previous character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700169 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700170 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700171 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
172 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800173 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
174 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700175 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700176 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700177 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700178 *
Svetoslav7c512842013-01-30 23:02:08 -0800179 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
180 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
181 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700182 * @see #setMovementGranularities(int)
183 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700184 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700185 * @see #MOVEMENT_GRANULARITY_CHARACTER
186 * @see #MOVEMENT_GRANULARITY_WORD
187 * @see #MOVEMENT_GRANULARITY_LINE
188 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
189 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700190 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700191 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700192
193 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700194 * Action that requests to go to the previous entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700195 * at a given movement granularity. For example, move to the next character,
196 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700197 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800198 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
199 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
200 * <strong>Example:</strong> Move to the next character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700201 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700202 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700203 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
204 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800205 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
206 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700207 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
208 * arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700209 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700210 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700211 *
Svetoslav7c512842013-01-30 23:02:08 -0800212 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
213 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
214 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700215 * @see #setMovementGranularities(int)
216 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700217 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700218 * @see #MOVEMENT_GRANULARITY_CHARACTER
219 * @see #MOVEMENT_GRANULARITY_WORD
220 * @see #MOVEMENT_GRANULARITY_LINE
221 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
222 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700223 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700224 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700225
226 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700227 * Action to move to the next HTML element of a given type. For example, move
228 * to the BUTTON, INPUT, TABLE, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700229 * <p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700230 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
231 * <strong>Example:</strong>
232 * <code><pre><p>
233 * Bundle arguments = new Bundle();
234 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
235 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
236 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700237 * </p>
238 */
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700239 public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
240
241 /**
242 * Action to move to the previous HTML element of a given type. For example, move
243 * to the BUTTON, INPUT, TABLE, etc.
244 * <p>
245 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
246 * <strong>Example:</strong>
247 * <code><pre><p>
248 * Bundle arguments = new Bundle();
249 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
250 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
251 * </code></pre></p>
252 * </p>
253 */
254 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
255
256 /**
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700257 * Action to scroll the node content forward.
258 */
259 public static final int ACTION_SCROLL_FORWARD = 0x00001000;
260
261 /**
262 * Action to scroll the node content backward.
263 */
264 public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
265
266 /**
Svetoslav7c512842013-01-30 23:02:08 -0800267 * Action to copy the current selection to the clipboard.
268 */
269 public static final int ACTION_COPY = 0x00004000;
270
271 /**
272 * Action to paste the current clipboard content.
273 */
274 public static final int ACTION_PASTE = 0x00008000;
275
276 /**
277 * Action to cut the current selection and place it to the clipboard.
278 */
279 public static final int ACTION_CUT = 0x00010000;
280
281 /**
282 * Action to set the selection. Performing this action with no arguments
283 * clears the selection.
284 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700285 * <strong>Arguments:</strong>
286 * {@link #ACTION_ARGUMENT_SELECTION_START_INT},
Svetoslav7c512842013-01-30 23:02:08 -0800287 * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
288 * <strong>Example:</strong>
289 * <code><pre><p>
290 * Bundle arguments = new Bundle();
291 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
292 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
293 * info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
294 * </code></pre></p>
295 * </p>
296 *
297 * @see #ACTION_ARGUMENT_SELECTION_START_INT
298 * @see #ACTION_ARGUMENT_SELECTION_END_INT
299 */
300 public static final int ACTION_SET_SELECTION = 0x00020000;
301
302 /**
Svetoslav3577a282013-06-06 14:09:10 -0700303 * Action to expand an expandable node.
304 */
305 public static final int ACTION_EXPAND = 0x00040000;
306
307 /**
308 * Action to collapse an expandable node.
309 */
310 public static final int ACTION_COLLAPSE = 0x00080000;
311
312 /**
313 * Action to dismiss a dismissable node.
314 */
315 public static final int ACTION_DISMISS = 0x00100000;
316
Guang Zhu4cd353c2014-02-12 19:54:30 -0800317 /**
318 * Action that sets the text of the node. Performing the action without argument, using <code>
319 * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
320 * cursor at the end of text.
321 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700322 * <strong>Arguments:</strong>
323 * {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800324 * <strong>Example:</strong>
325 * <code><pre><p>
326 * Bundle arguments = new Bundle();
327 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
328 * "android");
329 * info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
330 * </code></pre></p>
331 */
332 public static final int ACTION_SET_TEXT = 0x00200000;
333
Kristian Monsen74bc1942014-04-29 11:00:17 -0700334 private static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
335
336 /**
337 * Mask to see if the value is larger than the largest ACTION_ constant
338 */
339 private static final int ACTION_TYPE_MASK = 0xFF000000;
340
Svetoslav3577a282013-06-06 14:09:10 -0700341 // Action arguments
342
343 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700344 * Argument for which movement granularity to be used when traversing the node text.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700345 * <p>
346 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700347 * <strong>Actions:</strong>
348 * <ul>
349 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
350 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
351 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700352 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800353 *
Alan Viverette23f44322015-04-06 16:04:56 -0700354 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
355 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700356 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700357 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
Svetoslav7c512842013-01-30 23:02:08 -0800358 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700359
360 /**
361 * Argument for which HTML element to get moving to the next/previous HTML element.
362 * <p>
363 * <strong>Type:</strong> String<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700364 * <strong>Actions:</strong>
365 * <ul>
366 * <li>{@link AccessibilityAction#ACTION_NEXT_HTML_ELEMENT}</li>
367 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT}</li>
368 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700369 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800370 *
Alan Viverette23f44322015-04-06 16:04:56 -0700371 * @see AccessibilityAction#ACTION_NEXT_HTML_ELEMENT
372 * @see AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700373 */
374 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
Svetoslav7c512842013-01-30 23:02:08 -0800375 "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
376
377 /**
378 * Argument for whether when moving at granularity to extend the selection
379 * or to move it otherwise.
380 * <p>
381 * <strong>Type:</strong> boolean<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700382 * <strong>Actions:</strong>
383 * <ul>
384 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
385 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
386 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800387 *
Alan Viverette23f44322015-04-06 16:04:56 -0700388 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
389 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav7c512842013-01-30 23:02:08 -0800390 */
391 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
392 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
393
394 /**
395 * Argument for specifying the selection start.
396 * <p>
397 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700398 * <strong>Actions:</strong>
399 * <ul>
400 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
401 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800402 *
Alan Viverette23f44322015-04-06 16:04:56 -0700403 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800404 */
405 public static final String ACTION_ARGUMENT_SELECTION_START_INT =
406 "ACTION_ARGUMENT_SELECTION_START_INT";
407
408 /**
409 * Argument for specifying the selection end.
410 * <p>
411 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700412 * <strong>Actions:</strong>
413 * <ul>
414 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
415 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800416 *
Alan Viverette23f44322015-04-06 16:04:56 -0700417 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800418 */
419 public static final String ACTION_ARGUMENT_SELECTION_END_INT =
420 "ACTION_ARGUMENT_SELECTION_END_INT";
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700421
Guang Zhu4cd353c2014-02-12 19:54:30 -0800422 /**
Alan Viverette23f44322015-04-06 16:04:56 -0700423 * Argument for specifying the text content to set.
Guang Zhu4cd353c2014-02-12 19:54:30 -0800424 * <p>
425 * <strong>Type:</strong> CharSequence<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700426 * <strong>Actions:</strong>
427 * <ul>
428 * <li>{@link AccessibilityAction#ACTION_SET_TEXT}</li>
429 * </ul>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800430 *
Alan Viverette23f44322015-04-06 16:04:56 -0700431 * @see AccessibilityAction#ACTION_SET_TEXT
Guang Zhu4cd353c2014-02-12 19:54:30 -0800432 */
433 public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
434 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
435
Alan Viverette23f44322015-04-06 16:04:56 -0700436 /**
437 * Argument for specifying the collection row to make visible on screen.
438 * <p>
439 * <strong>Type:</strong> int<br>
440 * <strong>Actions:</strong>
441 * <ul>
442 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
443 * </ul>
444 *
445 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
446 */
447 public static final String ACTION_ARGUMENT_ROW_INT =
448 "android.view.accessibility.action.ARGUMENT_ROW_INT";
449
450 /**
451 * Argument for specifying the collection column to make visible on screen.
452 * <p>
453 * <strong>Type:</strong> int<br>
454 * <strong>Actions:</strong>
455 * <ul>
456 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
457 * </ul>
458 *
459 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
460 */
461 public static final String ACTION_ARGUMENT_COLUMN_INT =
462 "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
463
Maxim Bogatov32e59d52015-04-30 16:57:33 -0700464 /**
465 * Argument for specifying the progress value to set.
466 * <p>
467 * <strong>Type:</strong> float<br>
468 * <strong>Actions:</strong>
469 * <ul>
470 * <li>{@link AccessibilityAction#ACTION_SET_PROGRESS}</li>
471 * </ul>
472 *
473 * @see AccessibilityAction#ACTION_SET_PROGRESS
474 */
475 public static final String ACTION_ARGUMENT_PROGRESS_VALUE =
476 "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
477
Phil Weaver193520e2016-12-13 09:39:06 -0800478 /**
Phil Weaverf00cd142017-03-03 13:44:00 -0800479 * Argument for specifying the x coordinate to which to move a window.
480 * <p>
481 * <strong>Type:</strong> int<br>
482 * <strong>Actions:</strong>
483 * <ul>
484 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
485 * </ul>
486 *
487 * @see AccessibilityAction#ACTION_MOVE_WINDOW
488 */
489 public static final String ACTION_ARGUMENT_MOVE_WINDOW_X =
Phil Weaverbe2922f2017-04-28 14:58:35 -0700490 "ACTION_ARGUMENT_MOVE_WINDOW_X";
Phil Weaverf00cd142017-03-03 13:44:00 -0800491
492 /**
493 * Argument for specifying the y coordinate to which to move a window.
494 * <p>
495 * <strong>Type:</strong> int<br>
496 * <strong>Actions:</strong>
497 * <ul>
498 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
499 * </ul>
500 *
501 * @see AccessibilityAction#ACTION_MOVE_WINDOW
502 */
503 public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y =
Phil Weaverbe2922f2017-04-28 14:58:35 -0700504 "ACTION_ARGUMENT_MOVE_WINDOW_Y";
Phil Weaverf00cd142017-03-03 13:44:00 -0800505
506 /**
Phil Weaver193520e2016-12-13 09:39:06 -0800507 * Argument to pass the {@link AccessibilityClickableSpan}.
508 * For use with R.id.accessibilityActionClickOnClickableSpan
509 * @hide
510 */
511 public static final String ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN =
512 "android.view.accessibility.action.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN";
513
Svetoslav3577a282013-06-06 14:09:10 -0700514 // Focus types
515
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700516 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700517 * The input focus.
518 */
519 public static final int FOCUS_INPUT = 1;
520
521 /**
522 * The accessibility focus.
523 */
524 public static final int FOCUS_ACCESSIBILITY = 2;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700525
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700526 // Movement granularities
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700527
528 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700529 * Movement granularity bit for traversing the text of a node by character.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700530 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700531 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
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 word.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700535 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700536 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
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 line.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700540 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700541 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
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 paragraph.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700545 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700546 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
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 page.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700550 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700551 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700552
Phil Weaverc2e28932016-12-08 12:29:25 -0800553 /**
554 * Key used to request and locate extra data for text character location. This key requests that
555 * an array of {@link android.graphics.RectF}s be added to the extras. This request is made with
556 * {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by this request are two
557 * integers: {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and
558 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index must be valid
559 * inside the CharSequence returned by {@link #getText()}, and the length must be positive.
560 * <p>
561 * The data can be retrieved from the {@code Bundle} returned by {@link #getExtras()} using this
562 * string as a key for {@link Bundle#getParcelableArray(String)}. The
563 * {@link android.graphics.RectF} will be null for characters that either do not exist or are
564 * off the screen.
565 *
566 * {@see #refreshWithExtraData(String, Bundle)}
567 */
568 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY =
569 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
570
571 /**
572 * Integer argument specifying the start index of the requested text location data. Must be
573 * valid inside the CharSequence returned by {@link #getText()}.
574 *
575 * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
576 */
577 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX =
578 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
579
580 /**
581 * Integer argument specifying the end index of the requested text location data. Must be
582 * positive.
583 *
584 * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
585 */
586 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH =
587 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
588
589 /** @hide */
590 public static final String EXTRA_DATA_REQUESTED_KEY =
591 "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested";
592
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700593 // Boolean attributes.
594
Svetoslavbcc46a02013-02-06 11:56:00 -0800595 private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700596
Svetoslavbcc46a02013-02-06 11:56:00 -0800597 private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700598
Svetoslavbcc46a02013-02-06 11:56:00 -0800599 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700600
Svetoslavbcc46a02013-02-06 11:56:00 -0800601 private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700602
Svetoslavbcc46a02013-02-06 11:56:00 -0800603 private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700604
Svetoslavbcc46a02013-02-06 11:56:00 -0800605 private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700606
Svetoslavbcc46a02013-02-06 11:56:00 -0800607 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700608
Svetoslavbcc46a02013-02-06 11:56:00 -0800609 private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700610
Svetoslavbcc46a02013-02-06 11:56:00 -0800611 private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700612
Svetoslavbcc46a02013-02-06 11:56:00 -0800613 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
Svetoslav Ganova0156172011-06-26 17:55:44 -0700614
Svetoslavbcc46a02013-02-06 11:56:00 -0800615 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700616
Svetoslavbcc46a02013-02-06 11:56:00 -0800617 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
618
619 private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -0700620
Alan Viverette77e9a282013-09-12 17:16:09 -0700621 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
Svetoslav3577a282013-06-06 14:09:10 -0700622
Alan Viverette77e9a282013-09-12 17:16:09 -0700623 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
Svetoslav3577a282013-06-06 14:09:10 -0700624
Alan Viverette77e9a282013-09-12 17:16:09 -0700625 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
Svetoslav3577a282013-06-06 14:09:10 -0700626
Alan Viverette77e9a282013-09-12 17:16:09 -0700627 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
Svetoslav3577a282013-06-06 14:09:10 -0700628
Mady Mellore8608912015-06-05 09:02:55 -0700629 private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
Mady Mellore82067b2015-04-30 09:58:35 -0700630
Casey Burkhardt2d80ae42016-01-31 12:52:23 -0800631 private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
632
Phil Weaver776afc22016-12-21 10:55:13 -0800633 private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
634
Svetoslav Ganov02107852011-10-03 17:06:56 -0700635 /**
636 * Bits that provide the id of a virtual descendant of a view.
637 */
638 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
639
640 /**
641 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
642 * virtual descendant of a view. Such a descendant does not exist in the view
643 * hierarchy and is only reported via the accessibility APIs.
644 */
645 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
646
Phil Weaver62d20fa2016-09-15 11:05:55 -0700647 private static AtomicInteger sNumInstancesInUse;
Phil Weaverb010b122016-08-17 17:47:48 -0700648
Svetoslav Ganov02107852011-10-03 17:06:56 -0700649 /**
650 * Gets the accessibility view id which identifies a View in the view three.
651 *
652 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
653 * @return The accessibility view id part of the node id.
654 *
655 * @hide
656 */
657 public static int getAccessibilityViewId(long accessibilityNodeId) {
658 return (int) accessibilityNodeId;
659 }
660
661 /**
662 * Gets the virtual descendant id which identifies an imaginary view in a
663 * containing View.
664 *
665 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
666 * @return The virtual view id part of the node id.
667 *
668 * @hide
669 */
670 public static int getVirtualDescendantId(long accessibilityNodeId) {
671 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
672 >> VIRTUAL_DESCENDANT_ID_SHIFT);
673 }
674
675 /**
676 * Makes a node id by shifting the <code>virtualDescendantId</code>
677 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
678 * the bitwise or with the <code>accessibilityViewId</code>.
679 *
680 * @param accessibilityViewId A View accessibility id.
681 * @param virtualDescendantId A virtual descendant id.
682 * @return The node id.
683 *
684 * @hide
685 */
686 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
687 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
688 }
689
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700690 // Housekeeping.
691 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800692 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -0700693 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800694
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700695 private boolean mSealed;
696
697 // Data.
Phil Weaver23161e72017-04-19 12:16:36 -0700698 private int mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Phil Weaverf00cd142017-03-03 13:44:00 -0800699 private long mSourceNodeId = UNDEFINED_NODE_ID;
700 private long mParentNodeId = UNDEFINED_NODE_ID;
701 private long mLabelForId = UNDEFINED_NODE_ID;
702 private long mLabeledById = UNDEFINED_NODE_ID;
703 private long mTraversalBefore = UNDEFINED_NODE_ID;
704 private long mTraversalAfter = UNDEFINED_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800705
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700706 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700707 private final Rect mBoundsInParent = new Rect();
708 private final Rect mBoundsInScreen = new Rect();
Phil Weaver1f222542016-01-08 11:49:32 -0800709 private int mDrawingOrderInParent;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700710
711 private CharSequence mPackageName;
712 private CharSequence mClassName;
Phil Weaver193520e2016-12-13 09:39:06 -0800713 // Hidden, unparceled value used to hold the original value passed to setText
714 private CharSequence mOriginalText;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700715 private CharSequence mText;
Phil Weaver776afc22016-12-21 10:55:13 -0800716 private CharSequence mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -0700717 private CharSequence mError;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700718 private CharSequence mContentDescription;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700719 private String mViewIdResourceName;
Phil Weaverc2e28932016-12-08 12:29:25 -0800720 private ArrayList<String> mExtraDataKeys;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700721
Alan Viverettef0aed092013-11-06 15:33:03 -0800722 private LongArray mChildNodeIds;
Kristian Monsen74bc1942014-04-29 11:00:17 -0700723 private ArrayList<AccessibilityAction> mActions;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700724
Alan Viverette029942f2014-08-12 14:55:56 -0700725 private int mMaxTextLength = -1;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700726 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700727
Svetoslav8e3feb12014-02-24 13:46:47 -0800728 private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
729 private int mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
Svetoslav6254f482013-06-04 17:22:14 -0700730 private int mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -0700731 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav6254f482013-06-04 17:22:14 -0700732
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -0700733 private Bundle mExtras;
Svetoslavbcc46a02013-02-06 11:56:00 -0800734
Svetoslav8e3feb12014-02-24 13:46:47 -0800735 private int mConnectionId = UNDEFINED_CONNECTION_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700736
Svetoslav3577a282013-06-06 14:09:10 -0700737 private RangeInfo mRangeInfo;
738 private CollectionInfo mCollectionInfo;
739 private CollectionItemInfo mCollectionItemInfo;
740
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700741 /**
742 * Hide constructor from clients.
743 */
744 private AccessibilityNodeInfo() {
745 /* do nothing */
746 }
747
748 /**
749 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700750 * <p>
751 * <strong>Note:</strong> Cannot be called from an
752 * {@link android.accessibilityservice.AccessibilityService}.
753 * This class is made immutable before being delivered to an AccessibilityService.
754 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700755 *
756 * @param source The info source.
757 */
758 public void setSource(View source) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800759 setSource(source, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700760 }
761
762 /**
763 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700764 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700765 * is set as the source.
766 * <p>
767 * A virtual descendant is an imaginary View that is reported as a part of the view
768 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700769 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700770 * logical structure.
771 * </p>
772 * <p>
773 * <strong>Note:</strong> Cannot be called from an
774 * {@link android.accessibilityservice.AccessibilityService}.
775 * This class is made immutable before being delivered to an AccessibilityService.
776 * </p>
777 *
778 * @param root The root of the virtual subtree.
779 * @param virtualDescendantId The id of the virtual descendant.
780 */
781 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700782 enforceNotSealed();
Svetoslav8e3feb12014-02-24 13:46:47 -0800783 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700784 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -0800785 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700786 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700787 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700788
Svetoslav Ganov42138042012-03-20 11:51:39 -0700789 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700790 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700791 * the view represented by this node info.
792 *
793 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
794 * {@link #FOCUS_ACCESSIBILITY}.
795 * @return The node info of the focused view or null.
796 *
797 * @see #FOCUS_INPUT
798 * @see #FOCUS_ACCESSIBILITY
799 */
800 public AccessibilityNodeInfo findFocus(int focus) {
801 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700802 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700803 if (!canPerformRequestOverConnection(mSourceNodeId)) {
804 return null;
805 }
806 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
807 mSourceNodeId, focus);
808 }
809
810 /**
811 * Searches for the nearest view in the specified direction that can take
812 * the input focus.
813 *
814 * @param direction The direction. Can be one of:
815 * {@link View#FOCUS_DOWN},
816 * {@link View#FOCUS_UP},
817 * {@link View#FOCUS_LEFT},
818 * {@link View#FOCUS_RIGHT},
819 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700820 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700821 *
822 * @return The node info for the view that can take accessibility focus.
823 */
824 public AccessibilityNodeInfo focusSearch(int direction) {
825 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700826 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700827 if (!canPerformRequestOverConnection(mSourceNodeId)) {
828 return null;
829 }
830 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
831 mSourceNodeId, direction);
832 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700833
834 /**
835 * Gets the id of the window from which the info comes from.
836 *
837 * @return The window id.
838 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700839 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700840 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700841 }
842
843 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800844 * Refreshes this info with the latest state of the view it represents.
845 * <p>
846 * <strong>Note:</strong> If this method returns false this info is obsolete
847 * since it represents a view that is no longer in the view tree and should
848 * be recycled.
849 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700850 *
851 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800852 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700853 *
854 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800855 */
Phil Weaverc2e28932016-12-08 12:29:25 -0800856 public boolean refresh(Bundle arguments, boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800857 enforceSealed();
858 if (!canPerformRequestOverConnection(mSourceNodeId)) {
859 return false;
860 }
861 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
862 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Phil Weaverc2e28932016-12-08 12:29:25 -0800863 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0, arguments);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800864 if (refreshedInfo == null) {
865 return false;
866 }
867 init(refreshedInfo);
868 refreshedInfo.recycle();
869 return true;
870 }
871
872 /**
Svetoslav6254f482013-06-04 17:22:14 -0700873 * Refreshes this info with the latest state of the view it represents.
Phil Weaverc2e28932016-12-08 12:29:25 -0800874 *
875 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
876 * by this node is no longer in the view tree (and thus this node is obsolete and should be
877 * recycled).
Svetoslav6254f482013-06-04 17:22:14 -0700878 */
879 public boolean refresh() {
Phil Weaverc2e28932016-12-08 12:29:25 -0800880 return refresh(null, true);
881 }
882
883 /**
884 * Refreshes this info with the latest state of the view it represents, and request new
885 * data be added by the View.
886 *
887 * @param extraDataKey A bitmask of the extra data requested. Data that must be requested
888 * with this mechanism is generally expensive to retrieve, so should only be
889 * requested when needed. See
890 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
891 * {@link #getAvailableExtraData()}.
892 * @param args A bundle of arguments for the request. These depend on the particular request.
893 *
894 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
895 * by this node is no longer in the view tree (and thus this node is obsolete and should be
896 * recycled).
897 */
898 public boolean refreshWithExtraData(String extraDataKey, Bundle args) {
899 args.putString(EXTRA_DATA_REQUESTED_KEY, extraDataKey);
900 return refresh(args, true);
Svetoslav6254f482013-06-04 17:22:14 -0700901 }
902
903 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800904 * Returns the array containing the IDs of this node's children.
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800905 *
906 * @hide
907 */
Alan Viverettef0aed092013-11-06 15:33:03 -0800908 public LongArray getChildNodeIds() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800909 return mChildNodeIds;
910 }
911
912 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800913 * Returns the id of the child at the specified index.
914 *
915 * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt;=
916 * getChildCount()
917 * @hide
918 */
919 public long getChildId(int index) {
920 if (mChildNodeIds == null) {
921 throw new IndexOutOfBoundsException();
922 }
923 return mChildNodeIds.get(index);
924 }
925
926 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700927 * Gets the number of children.
928 *
929 * @return The child count.
930 */
931 public int getChildCount() {
Alan Viverettef0aed092013-11-06 15:33:03 -0800932 return mChildNodeIds == null ? 0 : mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700933 }
934
935 /**
936 * Get the child at given index.
937 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700938 * <strong>Note:</strong> It is a client responsibility to recycle the
939 * received info by calling {@link AccessibilityNodeInfo#recycle()}
940 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700941 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700942 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700943 * @param index The child index.
944 * @return The child node.
945 *
946 * @throws IllegalStateException If called outside of an AccessibilityService.
947 *
948 */
949 public AccessibilityNodeInfo getChild(int index) {
950 enforceSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -0800951 if (mChildNodeIds == null) {
952 return null;
953 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700954 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700955 return null;
956 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800957 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700958 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800959 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Phil Weaverc2e28932016-12-08 12:29:25 -0800960 childId, false, FLAG_PREFETCH_DESCENDANTS, null);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700961 }
962
963 /**
964 * Adds a child.
965 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700966 * <strong>Note:</strong> Cannot be called from an
967 * {@link android.accessibilityservice.AccessibilityService}.
968 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700969 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700970 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700971 * @param child The child.
972 *
973 * @throws IllegalStateException If called from an AccessibilityService.
974 */
975 public void addChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800976 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, true);
Alan Viverettef0aed092013-11-06 15:33:03 -0800977 }
978
979 /**
980 * Unchecked version of {@link #addChild(View)} that does not verify
981 * uniqueness. For framework use only.
982 *
983 * @hide
984 */
985 public void addChildUnchecked(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800986 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, false);
Alan Viverettef0aed092013-11-06 15:33:03 -0800987 }
988
989 /**
990 * Removes a child. If the child was not previously added to the node,
991 * calling this method has no effect.
992 * <p>
993 * <strong>Note:</strong> Cannot be called from an
994 * {@link android.accessibilityservice.AccessibilityService}.
995 * This class is made immutable before being delivered to an AccessibilityService.
996 * </p>
997 *
998 * @param child The child.
999 * @return true if the child was present
1000 *
1001 * @throws IllegalStateException If called from an AccessibilityService.
1002 */
1003 public boolean removeChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001004 return removeChild(child, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001005 }
1006
1007 /**
1008 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -07001009 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -07001010 * is added as a child.
1011 * <p>
1012 * A virtual descendant is an imaginary View that is reported as a part of the view
1013 * hierarchy for accessibility purposes. This enables custom views that draw complex
1014 * content to report them selves as a tree of virtual views, thus conveying their
1015 * logical structure.
1016 * </p>
1017 *
1018 * @param root The root of the virtual subtree.
1019 * @param virtualDescendantId The id of the virtual child.
1020 */
1021 public void addChild(View root, int virtualDescendantId) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001022 addChildInternal(root, virtualDescendantId, true);
1023 }
1024
1025 private void addChildInternal(View root, int virtualDescendantId, boolean checked) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001026 enforceNotSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -08001027 if (mChildNodeIds == null) {
1028 mChildNodeIds = new LongArray();
1029 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07001030 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001031 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001032 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Alan Viverettef0aed092013-11-06 15:33:03 -08001033 // If we're checking uniqueness and the ID already exists, abort.
1034 if (checked && mChildNodeIds.indexOf(childNodeId) >= 0) {
1035 return;
1036 }
1037 mChildNodeIds.add(childNodeId);
1038 }
1039
1040 /**
1041 * Removes a virtual child which is a descendant of the given
1042 * <code>root</code>. If the child was not previously added to the node,
1043 * calling this method has no effect.
1044 *
1045 * @param root The root of the virtual subtree.
1046 * @param virtualDescendantId The id of the virtual child.
1047 * @return true if the child was present
1048 * @see #addChild(View, int)
1049 */
1050 public boolean removeChild(View root, int virtualDescendantId) {
1051 enforceNotSealed();
1052 final LongArray childIds = mChildNodeIds;
1053 if (childIds == null) {
1054 return false;
1055 }
1056 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001057 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Alan Viverettef0aed092013-11-06 15:33:03 -08001058 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1059 final int index = childIds.indexOf(childNodeId);
1060 if (index < 0) {
1061 return false;
1062 }
1063 childIds.remove(index);
1064 return true;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001065 }
1066
1067 /**
1068 * Gets the actions that can be performed on the node.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001069 */
1070 public List<AccessibilityAction> getActionList() {
1071 if (mActions == null) {
1072 return Collections.emptyList();
1073 }
1074
1075 return mActions;
1076 }
1077
1078 /**
1079 * Gets the actions that can be performed on the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001080 *
1081 * @return The bit mask of with actions.
1082 *
1083 * @see AccessibilityNodeInfo#ACTION_FOCUS
1084 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
1085 * @see AccessibilityNodeInfo#ACTION_SELECT
1086 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07001087 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
1088 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
1089 * @see AccessibilityNodeInfo#ACTION_CLICK
1090 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
1091 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1092 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1093 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
1094 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
1095 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
1096 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Kristian Monsen74bc1942014-04-29 11:00:17 -07001097 *
1098 * @deprecated Use {@link #getActionList()}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001099 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001100 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001101 public int getActions() {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001102 int returnValue = 0;
1103
1104 if (mActions == null) {
1105 return returnValue;
1106 }
1107
1108 final int actionSize = mActions.size();
1109 for (int i = 0; i < actionSize; i++) {
1110 int actionId = mActions.get(i).getId();
1111 if (actionId <= LAST_LEGACY_STANDARD_ACTION) {
1112 returnValue |= actionId;
1113 }
1114 }
1115
1116 return returnValue;
1117 }
1118
1119 /**
1120 * Adds an action that can be performed on the node.
1121 * <p>
1122 * To add a standard action use the static constants on {@link AccessibilityAction}.
1123 * To add a custom action create a new {@link AccessibilityAction} by passing in a
1124 * resource id from your application as the action id and an optional label that
1125 * describes the action. To override one of the standard actions use as the action
1126 * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that
1127 * describes the action.
1128 * </p>
1129 * <p>
1130 * <strong>Note:</strong> Cannot be called from an
1131 * {@link android.accessibilityservice.AccessibilityService}.
1132 * This class is made immutable before being delivered to an AccessibilityService.
1133 * </p>
1134 *
1135 * @param action The action.
1136 *
1137 * @throws IllegalStateException If called from an AccessibilityService.
1138 */
1139 public void addAction(AccessibilityAction action) {
1140 enforceNotSealed();
1141
Alan Viverettec921f272015-05-14 12:26:49 -07001142 addActionUnchecked(action);
1143 }
1144
1145 private void addActionUnchecked(AccessibilityAction action) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001146 if (action == null) {
1147 return;
1148 }
1149
1150 if (mActions == null) {
Alan Viverette23f44322015-04-06 16:04:56 -07001151 mActions = new ArrayList<>();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001152 }
1153
1154 mActions.remove(action);
1155 mActions.add(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001156 }
1157
1158 /**
1159 * Adds an action that can be performed on the node.
1160 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001161 * <strong>Note:</strong> Cannot be called from an
1162 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001163 * This class is made immutable before being delivered to an AccessibilityService.
1164 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001165 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001166 * @param action The action.
1167 *
1168 * @throws IllegalStateException If called from an AccessibilityService.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001169 * @throws IllegalArgumentException If the argument is not one of the standard actions.
1170 *
1171 * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)}
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001172 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001173 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001174 public void addAction(int action) {
1175 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001176
Kristian Monsen8d5f3fa2014-05-20 13:16:19 -07001177 if ((action & ACTION_TYPE_MASK) != 0) {
1178 throw new IllegalArgumentException("Action is not a combination of the standard " +
1179 "actions: " + action);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001180 }
1181
Kristian Monsen8d5f3fa2014-05-20 13:16:19 -07001182 addLegacyStandardActions(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001183 }
1184
1185 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08001186 * Removes an action that can be performed on the node. If the action was
1187 * not already added to the node, calling this method has no effect.
1188 * <p>
1189 * <strong>Note:</strong> Cannot be called from an
1190 * {@link android.accessibilityservice.AccessibilityService}.
1191 * This class is made immutable before being delivered to an AccessibilityService.
1192 * </p>
1193 *
Kristian Monsen74bc1942014-04-29 11:00:17 -07001194 * @param action The action to be removed.
1195 *
1196 * @throws IllegalStateException If called from an AccessibilityService.
1197 * @deprecated Use {@link #removeAction(AccessibilityAction)}
1198 */
1199 @Deprecated
1200 public void removeAction(int action) {
1201 enforceNotSealed();
1202
1203 removeAction(getActionSingleton(action));
1204 }
1205
1206 /**
1207 * Removes an action that can be performed on the node. If the action was
1208 * not already added to the node, calling this method has no effect.
1209 * <p>
1210 * <strong>Note:</strong> Cannot be called from an
1211 * {@link android.accessibilityservice.AccessibilityService}.
1212 * This class is made immutable before being delivered to an AccessibilityService.
1213 * </p>
1214 *
1215 * @param action The action to be removed.
1216 * @return The action removed from the list of actions.
Alan Viverettef0aed092013-11-06 15:33:03 -08001217 *
1218 * @throws IllegalStateException If called from an AccessibilityService.
1219 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001220 public boolean removeAction(AccessibilityAction action) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001221 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001222
1223 if (mActions == null || action == null) {
1224 return false;
1225 }
1226
1227 return mActions.remove(action);
Alan Viverettef0aed092013-11-06 15:33:03 -08001228 }
1229
1230 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08001231 * Removes all actions.
1232 *
1233 * @hide
1234 */
1235 public void removeAllActions() {
1236 if (mActions != null) {
1237 mActions.clear();
1238 }
1239 }
1240
1241 /**
Svetoslav6c702902014-10-09 18:40:56 -07001242 * Gets the node before which this one is visited during traversal. A screen-reader
1243 * must visit the content of this node before the content of the one it precedes.
1244 *
1245 * @return The succeeding node if such or <code>null</code>.
1246 *
1247 * @see #setTraversalBefore(android.view.View)
1248 * @see #setTraversalBefore(android.view.View, int)
1249 */
1250 public AccessibilityNodeInfo getTraversalBefore() {
1251 enforceSealed();
1252 return getNodeForAccessibilityId(mTraversalBefore);
1253 }
1254
1255 /**
1256 * Sets the view before whose node this one should be visited during traversal. A
1257 * screen-reader must visit the content of this node before the content of the one
1258 * it precedes.
1259 * <p>
1260 * <strong>Note:</strong> Cannot be called from an
1261 * {@link android.accessibilityservice.AccessibilityService}.
1262 * This class is made immutable before being delivered to an AccessibilityService.
1263 * </p>
1264 *
1265 * @param view The view providing the preceding node.
1266 *
1267 * @see #getTraversalBefore()
1268 */
1269 public void setTraversalBefore(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001270 setTraversalBefore(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001271 }
1272
1273 /**
1274 * Sets the node before which this one is visited during traversal. A screen-reader
1275 * must visit the content of this node before the content of the one it precedes.
1276 * The successor is a virtual descendant of the given <code>root</code>. If
1277 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
1278 * as the successor.
1279 * <p>
1280 * A virtual descendant is an imaginary View that is reported as a part of the view
1281 * hierarchy for accessibility purposes. This enables custom views that draw complex
1282 * content to report them selves as a tree of virtual views, thus conveying their
1283 * logical structure.
1284 * </p>
1285 * <p>
1286 * <strong>Note:</strong> Cannot be called from an
1287 * {@link android.accessibilityservice.AccessibilityService}.
1288 * This class is made immutable before being delivered to an AccessibilityService.
1289 * </p>
1290 *
1291 * @param root The root of the virtual subtree.
1292 * @param virtualDescendantId The id of the virtual descendant.
1293 */
1294 public void setTraversalBefore(View root, int virtualDescendantId) {
1295 enforceNotSealed();
1296 final int rootAccessibilityViewId = (root != null)
1297 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1298 mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1299 }
1300
1301 /**
1302 * Gets the node after which this one is visited in accessibility traversal.
1303 * A screen-reader must visit the content of the other node before the content
1304 * of this one.
1305 *
1306 * @return The succeeding node if such or <code>null</code>.
1307 *
1308 * @see #setTraversalAfter(android.view.View)
1309 * @see #setTraversalAfter(android.view.View, int)
1310 */
1311 public AccessibilityNodeInfo getTraversalAfter() {
1312 enforceSealed();
1313 return getNodeForAccessibilityId(mTraversalAfter);
1314 }
1315
1316 /**
1317 * Sets the view whose node is visited after this one in accessibility traversal.
1318 * A screen-reader must visit the content of the other node before the content
1319 * of this one.
1320 * <p>
1321 * <strong>Note:</strong> Cannot be called from an
1322 * {@link android.accessibilityservice.AccessibilityService}.
1323 * This class is made immutable before being delivered to an AccessibilityService.
1324 * </p>
1325 *
1326 * @param view The previous view.
1327 *
1328 * @see #getTraversalAfter()
1329 */
1330 public void setTraversalAfter(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001331 setTraversalAfter(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001332 }
1333
1334 /**
1335 * Sets the node after which this one is visited in accessibility traversal.
1336 * A screen-reader must visit the content of the other node before the content
1337 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
1338 * the root is set as the predecessor.
1339 * <p>
1340 * A virtual descendant is an imaginary View that is reported as a part of the view
1341 * hierarchy for accessibility purposes. This enables custom views that draw complex
1342 * content to report them selves as a tree of virtual views, thus conveying their
1343 * logical structure.
1344 * </p>
1345 * <p>
1346 * <strong>Note:</strong> Cannot be called from an
1347 * {@link android.accessibilityservice.AccessibilityService}.
1348 * This class is made immutable before being delivered to an AccessibilityService.
1349 * </p>
1350 *
1351 * @param root The root of the virtual subtree.
1352 * @param virtualDescendantId The id of the virtual descendant.
1353 */
1354 public void setTraversalAfter(View root, int virtualDescendantId) {
1355 enforceNotSealed();
1356 final int rootAccessibilityViewId = (root != null)
1357 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1358 mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1359 }
1360
1361 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08001362 * Get the extra data available for this node.
1363 * <p>
1364 * Some data that is useful for some accessibility services is expensive to compute, and would
1365 * place undue overhead on apps to compute all the time. That data can be requested with
1366 * {@link #refreshWithExtraData(String, Bundle)}.
1367 *
1368 * @return An unmodifiable list of keys corresponding to extra data that can be requested.
1369 * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
1370 */
1371 public List<String> getAvailableExtraData() {
1372 if (mExtraDataKeys != null) {
1373 return Collections.unmodifiableList(mExtraDataKeys);
1374 } else {
1375 return EMPTY_LIST;
1376 }
1377 }
1378
1379 /**
1380 * Set the extra data available for this node.
1381 * <p>
1382 * <strong>Note:</strong> When a {@code View} passes in a non-empty list, it promises that
1383 * it will populate the node's extras with corresponding pieces of information in
1384 * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)}.
1385 * <p>
1386 * <strong>Note:</strong> Cannot be called from an
1387 * {@link android.accessibilityservice.AccessibilityService}.
1388 * This class is made immutable before being delivered to an AccessibilityService.
1389 *
1390 * @param extraDataKeys A list of types of extra data that are available.
1391 * @see #getAvailableExtraData()
1392 *
1393 * @throws IllegalStateException If called from an AccessibilityService.
1394 */
1395 public void setAvailableExtraData(List<String> extraDataKeys) {
1396 enforceNotSealed();
1397 mExtraDataKeys = new ArrayList<>(extraDataKeys);
1398 }
1399
1400 /**
Alan Viverette029942f2014-08-12 14:55:56 -07001401 * Sets the maximum text length, or -1 for no limit.
1402 * <p>
1403 * Typically used to indicate that an editable text field has a limit on
1404 * the number of characters entered.
1405 * <p>
1406 * <strong>Note:</strong> Cannot be called from an
1407 * {@link android.accessibilityservice.AccessibilityService}.
1408 * This class is made immutable before being delivered to an AccessibilityService.
1409 *
1410 * @param max The maximum text length.
1411 * @see #getMaxTextLength()
1412 *
1413 * @throws IllegalStateException If called from an AccessibilityService.
1414 */
1415 public void setMaxTextLength(int max) {
1416 enforceNotSealed();
1417 mMaxTextLength = max;
1418 }
1419
1420 /**
1421 * Returns the maximum text length for this node.
1422 *
1423 * @return The maximum text length, or -1 for no limit.
1424 * @see #setMaxTextLength(int)
1425 */
1426 public int getMaxTextLength() {
1427 return mMaxTextLength;
1428 }
1429
1430 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001431 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001432 * <p>
1433 * <strong>Note:</strong> Cannot be called from an
1434 * {@link android.accessibilityservice.AccessibilityService}.
1435 * This class is made immutable before being delivered to an AccessibilityService.
1436 * </p>
1437 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001438 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001439 *
1440 * @throws IllegalStateException If called from an AccessibilityService.
1441 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001442 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001443 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001444 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001445 }
1446
1447 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001448 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001449 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001450 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001451 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001452 public int getMovementGranularities() {
1453 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001454 }
1455
1456 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001457 * Performs an action on the node.
1458 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001459 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001460 * from an {@link android.accessibilityservice.AccessibilityService}.
1461 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001462 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001463 * @param action The action to perform.
1464 * @return True if the action was performed.
1465 *
1466 * @throws IllegalStateException If called outside of an AccessibilityService.
1467 */
1468 public boolean performAction(int action) {
1469 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001470 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001471 return false;
1472 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001473 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001474 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1475 action, null);
1476 }
1477
1478 /**
1479 * Performs an action on the node.
1480 * <p>
1481 * <strong>Note:</strong> An action can be performed only if the request is made
1482 * from an {@link android.accessibilityservice.AccessibilityService}.
1483 * </p>
1484 *
1485 * @param action The action to perform.
1486 * @param arguments A bundle with additional arguments.
1487 * @return True if the action was performed.
1488 *
1489 * @throws IllegalStateException If called outside of an AccessibilityService.
1490 */
1491 public boolean performAction(int action, Bundle arguments) {
1492 enforceSealed();
1493 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1494 return false;
1495 }
1496 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1497 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1498 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001499 }
1500
1501 /**
1502 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001503 * insensitive containment. The search is relative to this info i.e.
1504 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07001505 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001506 * <p>
1507 * <strong>Note:</strong> It is a client responsibility to recycle the
1508 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1509 * to avoid creating of multiple instances.
1510 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001511 *
1512 * @param text The searched text.
1513 * @return A list of node info.
1514 */
1515 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
1516 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001517 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001518 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001519 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001520 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -08001521 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
1522 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001523 }
1524
1525 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001526 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
1527 * name where a fully qualified id is of the from "package:id/id_resource_name".
1528 * For example, if the target application's package is "foo.bar" and the id
1529 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
1530 *
1531 * <p>
1532 * <strong>Note:</strong> It is a client responsibility to recycle the
1533 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1534 * to avoid creating of multiple instances.
1535 * </p>
1536 * <p>
1537 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1538 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
1539 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001540 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001541 * </p>
1542 *
1543 * @param viewId The fully qualified resource name of the view id to find.
1544 * @return A list of node info.
1545 */
1546 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
1547 enforceSealed();
1548 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1549 return Collections.emptyList();
1550 }
1551 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1552 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
1553 viewId);
1554 }
1555
1556 /**
Svetoslav8e3feb12014-02-24 13:46:47 -08001557 * Gets the window to which this node belongs.
1558 *
1559 * @return The window.
1560 *
1561 * @see android.accessibilityservice.AccessibilityService#getWindows()
1562 */
1563 public AccessibilityWindowInfo getWindow() {
1564 enforceSealed();
1565 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1566 return null;
1567 }
1568 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1569 return client.getWindow(mConnectionId, mWindowId);
1570 }
1571
1572 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001573 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001574 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001575 * <strong>Note:</strong> It is a client responsibility to recycle the
1576 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1577 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001578 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001579 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001580 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001581 */
1582 public AccessibilityNodeInfo getParent() {
1583 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07001584 return getNodeForAccessibilityId(mParentNodeId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08001585 }
1586
1587 /**
1588 * @return The parent node id.
1589 *
1590 * @hide
1591 */
1592 public long getParentNodeId() {
1593 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001594 }
1595
1596 /**
1597 * Sets the parent.
1598 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001599 * <strong>Note:</strong> Cannot be called from an
1600 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001601 * This class is made immutable before being delivered to an AccessibilityService.
1602 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001603 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001604 * @param parent The parent.
1605 *
1606 * @throws IllegalStateException If called from an AccessibilityService.
1607 */
1608 public void setParent(View parent) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001609 setParent(parent, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001610 }
1611
1612 /**
1613 * Sets the parent to be a virtual descendant of the given <code>root</code>.
1614 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1615 * is set as the parent.
1616 * <p>
1617 * A virtual descendant is an imaginary View that is reported as a part of the view
1618 * hierarchy for accessibility purposes. This enables custom views that draw complex
1619 * content to report them selves as a tree of virtual views, thus conveying their
1620 * logical structure.
1621 * </p>
1622 * <p>
1623 * <strong>Note:</strong> Cannot be called from an
1624 * {@link android.accessibilityservice.AccessibilityService}.
1625 * This class is made immutable before being delivered to an AccessibilityService.
1626 * </p>
1627 *
1628 * @param root The root of the virtual subtree.
1629 * @param virtualDescendantId The id of the virtual descendant.
1630 */
1631 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001632 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001633 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001634 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001635 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001636 }
1637
1638 /**
1639 * Gets the node bounds in parent coordinates.
1640 *
1641 * @param outBounds The output node bounds.
1642 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001643 public void getBoundsInParent(Rect outBounds) {
1644 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
1645 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001646 }
1647
1648 /**
1649 * Sets the node bounds in parent coordinates.
1650 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001651 * <strong>Note:</strong> Cannot be called from an
1652 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001653 * This class is made immutable before being delivered to an AccessibilityService.
1654 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001655 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001656 * @param bounds The node bounds.
1657 *
1658 * @throws IllegalStateException If called from an AccessibilityService.
1659 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001660 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001661 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001662 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1663 }
1664
1665 /**
1666 * Gets the node bounds in screen coordinates.
1667 *
1668 * @param outBounds The output node bounds.
1669 */
1670 public void getBoundsInScreen(Rect outBounds) {
1671 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1672 mBoundsInScreen.right, mBoundsInScreen.bottom);
1673 }
1674
1675 /**
Alan Viverettea7ea65e2015-05-15 11:30:21 -07001676 * Returns the actual rect containing the node bounds in screen coordinates.
1677 *
1678 * @hide Not safe to expose outside the framework.
1679 */
1680 public Rect getBoundsInScreen() {
1681 return mBoundsInScreen;
1682 }
1683
1684 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001685 * Sets the node bounds in screen coordinates.
1686 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001687 * <strong>Note:</strong> Cannot be called from an
1688 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001689 * This class is made immutable before being delivered to an AccessibilityService.
1690 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001691 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001692 * @param bounds The node bounds.
1693 *
1694 * @throws IllegalStateException If called from an AccessibilityService.
1695 */
1696 public void setBoundsInScreen(Rect bounds) {
1697 enforceNotSealed();
1698 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001699 }
1700
1701 /**
1702 * Gets whether this node is checkable.
1703 *
1704 * @return True if the node is checkable.
1705 */
1706 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001707 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001708 }
1709
1710 /**
1711 * Sets whether this node is checkable.
1712 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001713 * <strong>Note:</strong> Cannot be called from an
1714 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001715 * This class is made immutable before being delivered to an AccessibilityService.
1716 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001717 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001718 * @param checkable True if the node is checkable.
1719 *
1720 * @throws IllegalStateException If called from an AccessibilityService.
1721 */
1722 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001723 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001724 }
1725
1726 /**
1727 * Gets whether this node is checked.
1728 *
1729 * @return True if the node is checked.
1730 */
1731 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001732 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001733 }
1734
1735 /**
1736 * Sets whether this node is checked.
1737 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001738 * <strong>Note:</strong> Cannot be called from an
1739 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001740 * This class is made immutable before being delivered to an AccessibilityService.
1741 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001742 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001743 * @param checked True if the node is checked.
1744 *
1745 * @throws IllegalStateException If called from an AccessibilityService.
1746 */
1747 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001748 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001749 }
1750
1751 /**
1752 * Gets whether this node is focusable.
1753 *
1754 * @return True if the node is focusable.
1755 */
1756 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001757 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001758 }
1759
1760 /**
1761 * Sets whether this node is focusable.
1762 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001763 * <strong>Note:</strong> Cannot be called from an
1764 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001765 * This class is made immutable before being delivered to an AccessibilityService.
1766 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001767 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001768 * @param focusable True if the node is focusable.
1769 *
1770 * @throws IllegalStateException If called from an AccessibilityService.
1771 */
1772 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001773 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001774 }
1775
1776 /**
1777 * Gets whether this node is focused.
1778 *
1779 * @return True if the node is focused.
1780 */
1781 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001782 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001783 }
1784
1785 /**
1786 * Sets whether this node is focused.
1787 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001788 * <strong>Note:</strong> Cannot be called from an
1789 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001790 * This class is made immutable before being delivered to an AccessibilityService.
1791 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001792 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001793 * @param focused True if the node is focused.
1794 *
1795 * @throws IllegalStateException If called from an AccessibilityService.
1796 */
1797 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001798 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001799 }
1800
1801 /**
Alan Viverette1579edc2015-04-01 13:23:06 -07001802 * Gets whether this node is visible to the user.
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001803 *
1804 * @return Whether the node is visible to the user.
1805 */
1806 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001807 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001808 }
1809
1810 /**
1811 * Sets whether this node is visible to the user.
1812 * <p>
1813 * <strong>Note:</strong> Cannot be called from an
1814 * {@link android.accessibilityservice.AccessibilityService}.
1815 * This class is made immutable before being delivered to an AccessibilityService.
1816 * </p>
1817 *
1818 * @param visibleToUser Whether the node is visible to the user.
1819 *
1820 * @throws IllegalStateException If called from an AccessibilityService.
1821 */
1822 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001823 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001824 }
1825
1826 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001827 * Gets whether this node is accessibility focused.
1828 *
1829 * @return True if the node is accessibility focused.
1830 */
1831 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001832 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001833 }
1834
1835 /**
1836 * Sets whether this node is accessibility focused.
1837 * <p>
1838 * <strong>Note:</strong> Cannot be called from an
1839 * {@link android.accessibilityservice.AccessibilityService}.
1840 * This class is made immutable before being delivered to an AccessibilityService.
1841 * </p>
1842 *
1843 * @param focused True if the node is accessibility focused.
1844 *
1845 * @throws IllegalStateException If called from an AccessibilityService.
1846 */
1847 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001848 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001849 }
1850
1851 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001852 * Gets whether this node is selected.
1853 *
1854 * @return True if the node is selected.
1855 */
1856 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001857 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001858 }
1859
1860 /**
1861 * Sets whether this node is selected.
1862 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001863 * <strong>Note:</strong> Cannot be called from an
1864 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001865 * This class is made immutable before being delivered to an AccessibilityService.
1866 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001867 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001868 * @param selected True if the node is selected.
1869 *
1870 * @throws IllegalStateException If called from an AccessibilityService.
1871 */
1872 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001873 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001874 }
1875
1876 /**
1877 * Gets whether this node is clickable.
1878 *
1879 * @return True if the node is clickable.
1880 */
1881 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001882 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001883 }
1884
1885 /**
1886 * Sets whether this node is clickable.
1887 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001888 * <strong>Note:</strong> Cannot be called from an
1889 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001890 * This class is made immutable before being delivered to an AccessibilityService.
1891 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001892 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001893 * @param clickable True if the node is clickable.
1894 *
1895 * @throws IllegalStateException If called from an AccessibilityService.
1896 */
1897 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001898 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001899 }
1900
1901 /**
1902 * Gets whether this node is long clickable.
1903 *
1904 * @return True if the node is long clickable.
1905 */
1906 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001907 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001908 }
1909
1910 /**
1911 * Sets whether this node is long clickable.
1912 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001913 * <strong>Note:</strong> Cannot be called from an
1914 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001915 * This class is made immutable before being delivered to an AccessibilityService.
1916 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001917 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001918 * @param longClickable True if the node is long clickable.
1919 *
1920 * @throws IllegalStateException If called from an AccessibilityService.
1921 */
1922 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001923 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001924 }
1925
1926 /**
1927 * Gets whether this node is enabled.
1928 *
1929 * @return True if the node is enabled.
1930 */
1931 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001932 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001933 }
1934
1935 /**
1936 * Sets whether this node is enabled.
1937 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001938 * <strong>Note:</strong> Cannot be called from an
1939 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001940 * This class is made immutable before being delivered to an AccessibilityService.
1941 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001942 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001943 * @param enabled True if the node is enabled.
1944 *
1945 * @throws IllegalStateException If called from an AccessibilityService.
1946 */
1947 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001948 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001949 }
1950
1951 /**
1952 * Gets whether this node is a password.
1953 *
1954 * @return True if the node is a password.
1955 */
1956 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001957 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001958 }
1959
1960 /**
1961 * Sets whether this node is a password.
1962 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001963 * <strong>Note:</strong> Cannot be called from an
1964 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001965 * This class is made immutable before being delivered to an AccessibilityService.
1966 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001967 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001968 * @param password True if the node is a password.
1969 *
1970 * @throws IllegalStateException If called from an AccessibilityService.
1971 */
1972 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001973 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001974 }
1975
1976 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001977 * Gets if the node is scrollable.
1978 *
1979 * @return True if the node is scrollable, false otherwise.
1980 */
1981 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001982 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001983 }
1984
1985 /**
1986 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001987 * <p>
1988 * <strong>Note:</strong> Cannot be called from an
1989 * {@link android.accessibilityservice.AccessibilityService}.
1990 * This class is made immutable before being delivered to an AccessibilityService.
1991 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07001992 *
1993 * @param scrollable True if the node is scrollable, false otherwise.
1994 *
1995 * @throws IllegalStateException If called from an AccessibilityService.
1996 */
1997 public void setScrollable(boolean scrollable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001998 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
1999 }
2000
2001 /**
2002 * Gets if the node is editable.
2003 *
2004 * @return True if the node is editable, false otherwise.
2005 */
2006 public boolean isEditable() {
2007 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
2008 }
2009
2010 /**
2011 * Sets whether this node is editable.
2012 * <p>
2013 * <strong>Note:</strong> Cannot be called from an
2014 * {@link android.accessibilityservice.AccessibilityService}.
2015 * This class is made immutable before being delivered to an AccessibilityService.
2016 * </p>
2017 *
2018 * @param editable True if the node is editable.
2019 *
2020 * @throws IllegalStateException If called from an AccessibilityService.
2021 */
2022 public void setEditable(boolean editable) {
2023 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07002024 }
2025
2026 /**
Phil Weaver1f222542016-01-08 11:49:32 -08002027 * Get the drawing order of the view corresponding it this node.
2028 * <p>
2029 * Drawing order is determined only within the node's parent, so this index is only relative
2030 * to its siblings.
2031 * <p>
2032 * In some cases, the drawing order is essentially simultaneous, so it is possible for two
2033 * siblings to return the same value. It is also possible that values will be skipped.
2034 *
2035 * @return The drawing position of the view corresponding to this node relative to its siblings.
2036 */
2037 public int getDrawingOrder() {
2038 return mDrawingOrderInParent;
2039 }
2040
2041 /**
2042 * Set the drawing order of the view corresponding it this node.
2043 *
2044 * <p>
2045 * <strong>Note:</strong> Cannot be called from an
2046 * {@link android.accessibilityservice.AccessibilityService}.
2047 * This class is made immutable before being delivered to an AccessibilityService.
2048 * </p>
2049 * @param drawingOrderInParent
2050 * @throws IllegalStateException If called from an AccessibilityService.
2051 */
2052 public void setDrawingOrder(int drawingOrderInParent) {
2053 enforceNotSealed();
2054 mDrawingOrderInParent = drawingOrderInParent;
2055 }
2056
2057 /**
Svetoslav3577a282013-06-06 14:09:10 -07002058 * Gets the collection info if the node is a collection. A collection
2059 * child is always a collection item.
2060 *
2061 * @return The collection info.
2062 */
2063 public CollectionInfo getCollectionInfo() {
2064 return mCollectionInfo;
2065 }
2066
2067 /**
2068 * Sets the collection info if the node is a collection. A collection
2069 * child is always a collection item.
2070 * <p>
2071 * <strong>Note:</strong> Cannot be called from an
2072 * {@link android.accessibilityservice.AccessibilityService}.
2073 * This class is made immutable before being delivered to an AccessibilityService.
2074 * </p>
2075 *
2076 * @param collectionInfo The collection info.
2077 */
2078 public void setCollectionInfo(CollectionInfo collectionInfo) {
2079 enforceNotSealed();
2080 mCollectionInfo = collectionInfo;
2081 }
2082
2083 /**
2084 * Gets the collection item info if the node is a collection item. A collection
2085 * item is always a child of a collection.
2086 *
2087 * @return The collection item info.
2088 */
2089 public CollectionItemInfo getCollectionItemInfo() {
2090 return mCollectionItemInfo;
2091 }
2092
2093 /**
2094 * Sets the collection item info if the node is a collection item. A collection
2095 * item is always a child of a collection.
2096 * <p>
2097 * <strong>Note:</strong> Cannot be called from an
2098 * {@link android.accessibilityservice.AccessibilityService}.
2099 * This class is made immutable before being delivered to an AccessibilityService.
2100 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07002101 */
2102 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
2103 enforceNotSealed();
2104 mCollectionItemInfo = collectionItemInfo;
2105 }
2106
2107 /**
2108 * Gets the range info if this node is a range.
2109 *
2110 * @return The range.
2111 */
2112 public RangeInfo getRangeInfo() {
2113 return mRangeInfo;
2114 }
2115
2116 /**
2117 * Sets the range info if this node is a range.
2118 * <p>
2119 * <strong>Note:</strong> Cannot be called from an
2120 * {@link android.accessibilityservice.AccessibilityService}.
2121 * This class is made immutable before being delivered to an AccessibilityService.
2122 * </p>
2123 *
2124 * @param rangeInfo The range info.
2125 */
2126 public void setRangeInfo(RangeInfo rangeInfo) {
2127 enforceNotSealed();
2128 mRangeInfo = rangeInfo;
2129 }
2130
2131 /**
2132 * Gets if the content of this node is invalid. For example,
2133 * a date is not well-formed.
2134 *
2135 * @return If the node content is invalid.
2136 */
2137 public boolean isContentInvalid() {
2138 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
2139 }
2140
2141 /**
2142 * Sets if the content of this node is invalid. For example,
2143 * a date is not well-formed.
2144 * <p>
2145 * <strong>Note:</strong> Cannot be called from an
2146 * {@link android.accessibilityservice.AccessibilityService}.
2147 * This class is made immutable before being delivered to an AccessibilityService.
2148 * </p>
2149 *
2150 * @param contentInvalid If the node content is invalid.
2151 */
2152 public void setContentInvalid(boolean contentInvalid) {
2153 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
2154 }
2155
2156 /**
Mady Mellore8608912015-06-05 09:02:55 -07002157 * Gets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002158 *
Mady Mellore8608912015-06-05 09:02:55 -07002159 * @return True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002160 */
Mady Mellore8608912015-06-05 09:02:55 -07002161 public boolean isContextClickable() {
2162 return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
Mady Mellore82067b2015-04-30 09:58:35 -07002163 }
2164
2165 /**
Mady Mellore8608912015-06-05 09:02:55 -07002166 * Sets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002167 * <p>
2168 * <strong>Note:</strong> Cannot be called from an
2169 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
2170 * before being delivered to an AccessibilityService.
2171 * </p>
2172 *
Mady Mellore8608912015-06-05 09:02:55 -07002173 * @param contextClickable True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002174 * @throws IllegalStateException If called from an AccessibilityService.
2175 */
Mady Mellore8608912015-06-05 09:02:55 -07002176 public void setContextClickable(boolean contextClickable) {
2177 setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
Mady Mellore82067b2015-04-30 09:58:35 -07002178 }
2179
2180 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002181 * Gets the node's live region mode.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002182 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002183 * A live region is a node that contains information that is important for
2184 * the user and when it changes the user should be notified. For example,
2185 * in a login screen with a TextView that displays an "incorrect password"
2186 * notification, that view should be marked as a live region with mode
2187 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002188 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002189 * It is the responsibility of the accessibility service to monitor
2190 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating
2191 * changes to live region nodes and their children.
Svetoslav3577a282013-06-06 14:09:10 -07002192 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002193 * @return The live region mode, or
2194 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2195 * live region.
2196 * @see android.view.View#getAccessibilityLiveRegion()
Svetoslav3577a282013-06-06 14:09:10 -07002197 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002198 public int getLiveRegion() {
2199 return mLiveRegion;
Svetoslav3577a282013-06-06 14:09:10 -07002200 }
2201
2202 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002203 * Sets the node's live region mode.
Svetoslav3577a282013-06-06 14:09:10 -07002204 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002205 * <strong>Note:</strong> Cannot be called from an
2206 * {@link android.accessibilityservice.AccessibilityService}. This class is
2207 * made immutable before being delivered to an AccessibilityService.
Svetoslav3577a282013-06-06 14:09:10 -07002208 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002209 * @param mode The live region mode, or
2210 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2211 * live region.
2212 * @see android.view.View#setAccessibilityLiveRegion(int)
Svetoslav3577a282013-06-06 14:09:10 -07002213 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002214 public void setLiveRegion(int mode) {
2215 enforceNotSealed();
2216 mLiveRegion = mode;
Svetoslav3577a282013-06-06 14:09:10 -07002217 }
2218
2219 /**
2220 * Gets if the node is a multi line editable text.
2221 *
2222 * @return True if the node is multi line.
2223 */
2224 public boolean isMultiLine() {
2225 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
2226 }
2227
2228 /**
2229 * Sets if the node is a multi line editable text.
2230 * <p>
2231 * <strong>Note:</strong> Cannot be called from an
2232 * {@link android.accessibilityservice.AccessibilityService}.
2233 * This class is made immutable before being delivered to an AccessibilityService.
2234 * </p>
2235 *
2236 * @param multiLine True if the node is multi line.
2237 */
2238 public void setMultiLine(boolean multiLine) {
Svetoslav3577a282013-06-06 14:09:10 -07002239 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
2240 }
2241
2242 /**
2243 * Gets if this node opens a popup or a dialog.
2244 *
2245 * @return If the the node opens a popup.
2246 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002247 public boolean canOpenPopup() {
Svetoslav3577a282013-06-06 14:09:10 -07002248 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
2249 }
2250
2251 /**
2252 * Sets if this node opens a popup or a dialog.
2253 * <p>
2254 * <strong>Note:</strong> Cannot be called from an
2255 * {@link android.accessibilityservice.AccessibilityService}.
2256 * This class is made immutable before being delivered to an AccessibilityService.
2257 * </p>
2258 *
2259 * @param opensPopup If the the node opens a popup.
2260 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002261 public void setCanOpenPopup(boolean opensPopup) {
2262 enforceNotSealed();
Svetoslav3577a282013-06-06 14:09:10 -07002263 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
2264 }
2265
2266 /**
Svetoslav3577a282013-06-06 14:09:10 -07002267 * Gets if the node can be dismissed.
2268 *
2269 * @return If the node can be dismissed.
2270 */
2271 public boolean isDismissable() {
2272 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
2273 }
2274
2275 /**
2276 * Sets if the node can be dismissed.
2277 * <p>
2278 * <strong>Note:</strong> Cannot be called from an
2279 * {@link android.accessibilityservice.AccessibilityService}.
2280 * This class is made immutable before being delivered to an AccessibilityService.
2281 * </p>
2282 *
2283 * @param dismissable If the node can be dismissed.
2284 */
2285 public void setDismissable(boolean dismissable) {
Svetoslav3577a282013-06-06 14:09:10 -07002286 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
2287 }
2288
2289 /**
Casey Burkhardt2d80ae42016-01-31 12:52:23 -08002290 * Returns whether the node originates from a view considered important for accessibility.
2291 *
2292 * @return {@code true} if the node originates from a view considered important for
2293 * accessibility, {@code false} otherwise
2294 *
2295 * @see View#isImportantForAccessibility()
2296 */
2297 public boolean isImportantForAccessibility() {
2298 return getBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE);
2299 }
2300
2301 /**
2302 * Sets whether the node is considered important for accessibility.
2303 * <p>
2304 * <strong>Note:</strong> Cannot be called from an
2305 * {@link android.accessibilityservice.AccessibilityService}.
2306 * This class is made immutable before being delivered to an AccessibilityService.
2307 * </p>
2308 *
2309 * @param important {@code true} if the node is considered important for accessibility,
2310 * {@code false} otherwise
2311 */
2312 public void setImportantForAccessibility(boolean important) {
2313 setBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE, important);
2314 }
2315
2316 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002317 * Returns whether the node's text represents a hint for the user to enter text. It should only
2318 * be {@code true} if the node has editable text.
2319 *
2320 * @return {@code true} if the text in the node represents a hint to the user, {@code false}
2321 * otherwise.
2322 */
2323 public boolean isShowingHintText() {
2324 return getBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT);
2325 }
2326
2327 /**
2328 * Sets whether the node's text represents a hint for the user to enter text. It should only
2329 * be {@code true} if the node has editable text.
2330 * <p>
2331 * <strong>Note:</strong> Cannot be called from an
2332 * {@link android.accessibilityservice.AccessibilityService}.
2333 * This class is made immutable before being delivered to an AccessibilityService.
2334 * </p>
2335 *
2336 * @param showingHintText {@code true} if the text in the node represents a hint to the user,
2337 * {@code false} otherwise.
2338 */
2339 public void setShowingHintText(boolean showingHintText) {
2340 setBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT, showingHintText);
2341 }
2342
2343 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002344 * Gets the package this node comes from.
2345 *
2346 * @return The package name.
2347 */
2348 public CharSequence getPackageName() {
2349 return mPackageName;
2350 }
2351
2352 /**
2353 * Sets the package this node comes from.
2354 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002355 * <strong>Note:</strong> Cannot be called from an
2356 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002357 * This class is made immutable before being delivered to an AccessibilityService.
2358 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002359 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002360 * @param packageName The package name.
2361 *
2362 * @throws IllegalStateException If called from an AccessibilityService.
2363 */
2364 public void setPackageName(CharSequence packageName) {
2365 enforceNotSealed();
2366 mPackageName = packageName;
2367 }
2368
2369 /**
2370 * Gets the class this node comes from.
2371 *
2372 * @return The class name.
2373 */
2374 public CharSequence getClassName() {
2375 return mClassName;
2376 }
2377
2378 /**
2379 * Sets the class this node comes from.
2380 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002381 * <strong>Note:</strong> Cannot be called from an
2382 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002383 * This class is made immutable before being delivered to an AccessibilityService.
2384 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002385 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002386 * @param className The class name.
2387 *
2388 * @throws IllegalStateException If called from an AccessibilityService.
2389 */
2390 public void setClassName(CharSequence className) {
2391 enforceNotSealed();
2392 mClassName = className;
2393 }
2394
2395 /**
2396 * Gets the text of this node.
Phil Weaver193520e2016-12-13 09:39:06 -08002397 * <p>
2398 * <strong>Note:</strong> If the text contains {@link ClickableSpan}s or {@link URLSpan}s,
2399 * these spans will have been replaced with ones whose {@link ClickableSpan#onClick(View)}
2400 * can be called from an {@link AccessibilityService}. When called from a service, the
2401 * {@link View} argument is ignored and the corresponding span will be found on the view that
2402 * this {@code AccessibilityNodeInfo} represents and called with that view as its argument.
2403 * <p>
2404 * This treatment of {@link ClickableSpan}s means that the text returned from this method may
2405 * different slightly one passed to {@link #setText(CharSequence)}, although they will be
2406 * equivalent according to {@link TextUtils#equals(CharSequence, CharSequence)}. The
2407 * {@link ClickableSpan#onClick(View)} of any spans, however, will generally not work outside
2408 * of an accessibility service.
2409 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002410 *
2411 * @return The text.
2412 */
2413 public CharSequence getText() {
Phil Weaver193520e2016-12-13 09:39:06 -08002414 // Attach this node to any spans that need it
2415 if (mText instanceof Spanned) {
2416 Spanned spanned = (Spanned) mText;
2417 AccessibilityClickableSpan[] clickableSpans =
2418 spanned.getSpans(0, mText.length(), AccessibilityClickableSpan.class);
2419 for (int i = 0; i < clickableSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002420 clickableSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002421 }
2422 AccessibilityURLSpan[] urlSpans =
2423 spanned.getSpans(0, mText.length(), AccessibilityURLSpan.class);
2424 for (int i = 0; i < urlSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002425 urlSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002426 }
2427 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002428 return mText;
2429 }
2430
2431 /**
Phil Weaver193520e2016-12-13 09:39:06 -08002432 * Get the text passed to setText before any changes to the spans.
2433 * @hide
2434 */
2435 public CharSequence getOriginalText() {
2436 return mOriginalText;
2437 }
2438
2439 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002440 * Sets the text of this node.
2441 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002442 * <strong>Note:</strong> Cannot be called from an
2443 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002444 * This class is made immutable before being delivered to an AccessibilityService.
2445 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002446 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002447 * @param text The text.
2448 *
2449 * @throws IllegalStateException If called from an AccessibilityService.
2450 */
2451 public void setText(CharSequence text) {
2452 enforceNotSealed();
Phil Weaver193520e2016-12-13 09:39:06 -08002453 mOriginalText = text;
2454 // Replace any ClickableSpans in mText with placeholders
2455 if (text instanceof Spanned) {
2456 ClickableSpan[] spans =
2457 ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
2458 if (spans.length > 0) {
Phil Weaver0ebe6bd2017-02-21 16:24:31 -08002459 Spannable spannable = new SpannableStringBuilder(text);
Phil Weaver193520e2016-12-13 09:39:06 -08002460 for (int i = 0; i < spans.length; i++) {
2461 ClickableSpan span = spans[i];
2462 if ((span instanceof AccessibilityClickableSpan)
2463 || (span instanceof AccessibilityURLSpan)) {
2464 // We've already done enough
2465 break;
2466 }
2467 int spanToReplaceStart = spannable.getSpanStart(span);
2468 int spanToReplaceEnd = spannable.getSpanEnd(span);
2469 int spanToReplaceFlags = spannable.getSpanFlags(span);
2470 spannable.removeSpan(span);
2471 ClickableSpan replacementSpan = (span instanceof URLSpan)
2472 ? new AccessibilityURLSpan((URLSpan) span)
2473 : new AccessibilityClickableSpan(span.getId());
2474 spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
2475 spanToReplaceFlags);
2476 }
2477 mText = spannable;
2478 return;
2479 }
2480 }
Phil Weaveref955ad2016-08-25 12:58:15 -07002481 mText = (text == null) ? null : text.subSequence(0, text.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002482 }
2483
2484 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002485 * Gets the hint text of this node. Only applies to nodes where text can be entered.
2486 *
2487 * @return The hint text.
2488 */
2489 public CharSequence getHintText() {
2490 return mHintText;
2491 }
2492
2493 /**
2494 * Sets the hint text of this node. Only applies to nodes where text can be entered.
2495 * <p>
2496 * <strong>Note:</strong> Cannot be called from an
2497 * {@link android.accessibilityservice.AccessibilityService}.
2498 * This class is made immutable before being delivered to an AccessibilityService.
2499 * </p>
2500 *
2501 * @param hintText The hint text for this mode.
2502 *
2503 * @throws IllegalStateException If called from an AccessibilityService.
2504 */
2505 public void setHintText(CharSequence hintText) {
2506 enforceNotSealed();
2507 mHintText = (hintText == null) ? null : hintText.subSequence(0, hintText.length());
2508 }
2509
2510 /**
Alan Viverettefccbff52014-07-07 15:06:14 -07002511 * Sets the error text of this node.
2512 * <p>
2513 * <strong>Note:</strong> Cannot be called from an
2514 * {@link android.accessibilityservice.AccessibilityService}.
2515 * This class is made immutable before being delivered to an AccessibilityService.
2516 * </p>
2517 *
2518 * @param error The error text.
2519 *
2520 * @throws IllegalStateException If called from an AccessibilityService.
2521 */
2522 public void setError(CharSequence error) {
2523 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002524 mError = (error == null) ? null : error.subSequence(0, error.length());
Alan Viverettefccbff52014-07-07 15:06:14 -07002525 }
2526
2527 /**
2528 * Gets the error text of this node.
2529 *
2530 * @return The error text.
2531 */
2532 public CharSequence getError() {
2533 return mError;
2534 }
2535
2536 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002537 * Gets the content description of this node.
2538 *
2539 * @return The content description.
2540 */
2541 public CharSequence getContentDescription() {
2542 return mContentDescription;
2543 }
2544
2545 /**
2546 * Sets the content description of this node.
2547 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002548 * <strong>Note:</strong> Cannot be called from an
2549 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002550 * This class is made immutable before being delivered to an AccessibilityService.
2551 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002552 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002553 * @param contentDescription The content description.
2554 *
2555 * @throws IllegalStateException If called from an AccessibilityService.
2556 */
2557 public void setContentDescription(CharSequence contentDescription) {
2558 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002559 mContentDescription = (contentDescription == null) ? null
2560 : contentDescription.subSequence(0, contentDescription.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002561 }
2562
2563 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002564 * Sets the view for which the view represented by this info serves as a
2565 * label for accessibility purposes.
2566 *
2567 * @param labeled The view for which this info serves as a label.
2568 */
2569 public void setLabelFor(View labeled) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002570 setLabelFor(labeled, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002571 }
2572
2573 /**
2574 * Sets the view for which the view represented by this info serves as a
2575 * label for accessibility purposes. If <code>virtualDescendantId</code>
2576 * is {@link View#NO_ID} the root is set as the labeled.
2577 * <p>
2578 * A virtual descendant is an imaginary View that is reported as a part of the view
2579 * hierarchy for accessibility purposes. This enables custom views that draw complex
2580 * content to report themselves as a tree of virtual views, thus conveying their
2581 * logical structure.
2582 * </p>
2583 * <p>
2584 * <strong>Note:</strong> Cannot be called from an
2585 * {@link android.accessibilityservice.AccessibilityService}.
2586 * This class is made immutable before being delivered to an AccessibilityService.
2587 * </p>
2588 *
2589 * @param root The root whose virtual descendant serves as a label.
2590 * @param virtualDescendantId The id of the virtual descendant.
2591 */
2592 public void setLabelFor(View root, int virtualDescendantId) {
2593 enforceNotSealed();
2594 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002595 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002596 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2597 }
2598
2599 /**
2600 * Gets the node info for which the view represented by this info serves as
2601 * a label for accessibility purposes.
2602 * <p>
2603 * <strong>Note:</strong> It is a client responsibility to recycle the
2604 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2605 * to avoid creating of multiple instances.
2606 * </p>
2607 *
2608 * @return The labeled info.
2609 */
2610 public AccessibilityNodeInfo getLabelFor() {
2611 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002612 return getNodeForAccessibilityId(mLabelForId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002613 }
2614
2615 /**
2616 * Sets the view which serves as the label of the view represented by
2617 * this info for accessibility purposes.
2618 *
2619 * @param label The view that labels this node's source.
2620 */
2621 public void setLabeledBy(View label) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002622 setLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002623 }
2624
2625 /**
2626 * Sets the view which serves as the label of the view represented by
2627 * this info for accessibility purposes. If <code>virtualDescendantId</code>
2628 * is {@link View#NO_ID} the root is set as the label.
2629 * <p>
2630 * A virtual descendant is an imaginary View that is reported as a part of the view
2631 * hierarchy for accessibility purposes. This enables custom views that draw complex
2632 * content to report themselves as a tree of virtual views, thus conveying their
2633 * logical structure.
2634 * </p>
2635 * <p>
2636 * <strong>Note:</strong> Cannot be called from an
2637 * {@link android.accessibilityservice.AccessibilityService}.
2638 * This class is made immutable before being delivered to an AccessibilityService.
2639 * </p>
2640 *
2641 * @param root The root whose virtual descendant labels this node's source.
2642 * @param virtualDescendantId The id of the virtual descendant.
2643 */
2644 public void setLabeledBy(View root, int virtualDescendantId) {
2645 enforceNotSealed();
2646 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002647 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002648 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2649 }
2650
2651 /**
2652 * Gets the node info which serves as the label of the view represented by
2653 * this info for accessibility purposes.
2654 * <p>
2655 * <strong>Note:</strong> It is a client responsibility to recycle the
2656 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2657 * to avoid creating of multiple instances.
2658 * </p>
2659 *
2660 * @return The label.
2661 */
2662 public AccessibilityNodeInfo getLabeledBy() {
2663 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002664 return getNodeForAccessibilityId(mLabeledById);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002665 }
2666
2667 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002668 * Sets the fully qualified resource name of the source view's id.
2669 *
2670 * <p>
2671 * <strong>Note:</strong> Cannot be called from an
2672 * {@link android.accessibilityservice.AccessibilityService}.
2673 * This class is made immutable before being delivered to an AccessibilityService.
2674 * </p>
2675 *
Svetoslav92826452013-02-05 14:57:42 -08002676 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002677 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002678 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002679 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08002680 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002681 }
2682
2683 /**
2684 * Gets the fully qualified resource name of the source view's id.
2685 *
2686 * <p>
2687 * <strong>Note:</strong> The primary usage of this API is for UI test automation
2688 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
2689 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08002690 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002691 * </p>
2692
2693 * @return The id resource name.
2694 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002695 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08002696 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002697 }
2698
2699 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002700 * Gets the text selection start or the cursor position.
2701 * <p>
2702 * If no text is selected, both this method and
2703 * {@link AccessibilityNodeInfo#getTextSelectionEnd()} return the same value:
2704 * the current location of the cursor.
2705 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002706 *
Phil Weaver40ded282016-01-25 15:49:02 -08002707 * @return The text selection start, the cursor location if there is no selection, or -1 if
2708 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002709 */
2710 public int getTextSelectionStart() {
2711 return mTextSelectionStart;
2712 }
2713
2714 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002715 * Gets the text selection end if text is selected.
2716 * <p>
2717 * If no text is selected, both this method and
2718 * {@link AccessibilityNodeInfo#getTextSelectionStart()} return the same value:
2719 * the current location of the cursor.
2720 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002721 *
Phil Weaver40ded282016-01-25 15:49:02 -08002722 * @return The text selection end, the cursor location if there is no selection, or -1 if
2723 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002724 */
2725 public int getTextSelectionEnd() {
2726 return mTextSelectionEnd;
2727 }
2728
2729 /**
2730 * Sets the text selection start and end.
2731 * <p>
2732 * <strong>Note:</strong> Cannot be called from an
2733 * {@link android.accessibilityservice.AccessibilityService}.
2734 * This class is made immutable before being delivered to an AccessibilityService.
2735 * </p>
2736 *
2737 * @param start The text selection start.
2738 * @param end The text selection end.
2739 *
2740 * @throws IllegalStateException If called from an AccessibilityService.
2741 */
2742 public void setTextSelection(int start, int end) {
2743 enforceNotSealed();
2744 mTextSelectionStart = start;
2745 mTextSelectionEnd = end;
2746 }
2747
2748 /**
Svetoslav6254f482013-06-04 17:22:14 -07002749 * Gets the input type of the source as defined by {@link InputType}.
2750 *
2751 * @return The input type.
2752 */
2753 public int getInputType() {
2754 return mInputType;
2755 }
2756
2757 /**
2758 * Sets the input type of the source as defined by {@link InputType}.
2759 * <p>
2760 * <strong>Note:</strong> Cannot be called from an
2761 * {@link android.accessibilityservice.AccessibilityService}.
2762 * This class is made immutable before being delivered to an
2763 * AccessibilityService.
2764 * </p>
2765 *
2766 * @param inputType The input type.
2767 *
2768 * @throws IllegalStateException If called from an AccessibilityService.
2769 */
2770 public void setInputType(int inputType) {
Alan Viverettedf39cb92013-08-19 12:28:04 -07002771 enforceNotSealed();
Svetoslav6254f482013-06-04 17:22:14 -07002772 mInputType = inputType;
2773 }
2774
2775 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002776 * Gets an optional bundle with extra data. The bundle
Svetoslav6254f482013-06-04 17:22:14 -07002777 * is lazily created and never <code>null</code>.
2778 * <p>
2779 * <strong>Note:</strong> It is recommended to use the package
2780 * name of your application as a prefix for the keys to avoid
2781 * collisions which may confuse an accessibility service if the
2782 * same key has different meaning when emitted from different
2783 * applications.
2784 * </p>
2785 *
2786 * @return The bundle.
2787 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002788 public Bundle getExtras() {
2789 if (mExtras == null) {
2790 mExtras = new Bundle();
Svetoslav6254f482013-06-04 17:22:14 -07002791 }
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002792 return mExtras;
Svetoslav6254f482013-06-04 17:22:14 -07002793 }
2794
2795 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08002796 * Check if a node has an extras bundle
2797 * @hide
2798 */
2799 public boolean hasExtras() {
2800 return mExtras != null;
2801 }
2802
2803 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002804 * Gets the value of a boolean property.
2805 *
2806 * @param property The property.
2807 * @return The value.
2808 */
2809 private boolean getBooleanProperty(int property) {
2810 return (mBooleanProperties & property) != 0;
2811 }
2812
2813 /**
2814 * Sets a boolean property.
2815 *
2816 * @param property The property.
2817 * @param value The value.
2818 *
2819 * @throws IllegalStateException If called from an AccessibilityService.
2820 */
2821 private void setBooleanProperty(int property, boolean value) {
2822 enforceNotSealed();
2823 if (value) {
2824 mBooleanProperties |= property;
2825 } else {
2826 mBooleanProperties &= ~property;
2827 }
2828 }
2829
2830 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002831 * Sets the unique id of the IAccessibilityServiceConnection over which
2832 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002833 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002834 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002835 *
2836 * @hide
2837 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002838 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002839 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002840 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002841 }
2842
2843 /**
Phil Weaver23161e72017-04-19 12:16:36 -07002844 * Get the connection ID.
2845 *
2846 * @return The connection id
2847 *
2848 * @hide
2849 */
2850 public int getConnectionId() {
2851 return mConnectionId;
2852 }
2853
2854 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002855 * {@inheritDoc}
2856 */
Alan Viverettef0aed092013-11-06 15:33:03 -08002857 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002858 public int describeContents() {
2859 return 0;
2860 }
2861
2862 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08002863 * Sets the id of the source node.
2864 *
2865 * @param sourceId The id.
2866 * @param windowId The window id.
2867 *
2868 * @hide
2869 */
2870 public void setSourceNodeId(long sourceId, int windowId) {
2871 enforceNotSealed();
2872 mSourceNodeId = sourceId;
2873 mWindowId = windowId;
2874 }
2875
2876 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08002877 * Gets the id of the source node.
2878 *
2879 * @return The id.
2880 *
2881 * @hide
2882 */
2883 public long getSourceNodeId() {
2884 return mSourceNodeId;
2885 }
2886
2887 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002888 * Sets if this instance is sealed.
2889 *
2890 * @param sealed Whether is sealed.
2891 *
2892 * @hide
2893 */
2894 public void setSealed(boolean sealed) {
2895 mSealed = sealed;
2896 }
2897
2898 /**
2899 * Gets if this instance is sealed.
2900 *
2901 * @return Whether is sealed.
2902 *
2903 * @hide
2904 */
2905 public boolean isSealed() {
2906 return mSealed;
2907 }
2908
2909 /**
2910 * Enforces that this instance is sealed.
2911 *
2912 * @throws IllegalStateException If this instance is not sealed.
2913 *
2914 * @hide
2915 */
2916 protected void enforceSealed() {
2917 if (!isSealed()) {
2918 throw new IllegalStateException("Cannot perform this "
2919 + "action on a not sealed instance.");
2920 }
2921 }
2922
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002923 private void enforceValidFocusDirection(int direction) {
2924 switch (direction) {
2925 case View.FOCUS_DOWN:
2926 case View.FOCUS_UP:
2927 case View.FOCUS_LEFT:
2928 case View.FOCUS_RIGHT:
2929 case View.FOCUS_FORWARD:
2930 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002931 return;
2932 default:
2933 throw new IllegalArgumentException("Unknown direction: " + direction);
2934 }
2935 }
2936
2937 private void enforceValidFocusType(int focusType) {
2938 switch (focusType) {
2939 case FOCUS_INPUT:
2940 case FOCUS_ACCESSIBILITY:
2941 return;
2942 default:
2943 throw new IllegalArgumentException("Unknown focus type: " + focusType);
2944 }
2945 }
2946
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002947 /**
2948 * Enforces that this instance is not sealed.
2949 *
2950 * @throws IllegalStateException If this instance is sealed.
2951 *
2952 * @hide
2953 */
2954 protected void enforceNotSealed() {
2955 if (isSealed()) {
2956 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09002957 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002958 }
2959 }
2960
2961 /**
2962 * Returns a cached instance if such is available otherwise a new one
2963 * and sets the source.
2964 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07002965 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002966 * @return An instance.
2967 *
2968 * @see #setSource(View)
2969 */
2970 public static AccessibilityNodeInfo obtain(View source) {
2971 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2972 info.setSource(source);
2973 return info;
2974 }
2975
2976 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002977 * Returns a cached instance if such is available otherwise a new one
2978 * and sets the source.
2979 *
2980 * @param root The root of the virtual subtree.
2981 * @param virtualDescendantId The id of the virtual descendant.
2982 * @return An instance.
2983 *
2984 * @see #setSource(View, int)
2985 */
2986 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
2987 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2988 info.setSource(root, virtualDescendantId);
2989 return info;
2990 }
2991
2992 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002993 * Returns a cached instance if such is available otherwise a new one.
2994 *
2995 * @return An instance.
2996 */
2997 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08002998 AccessibilityNodeInfo info = sPool.acquire();
Phil Weaver62d20fa2016-09-15 11:05:55 -07002999 if (sNumInstancesInUse != null) {
3000 sNumInstancesInUse.incrementAndGet();
3001 }
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003002 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003003 }
3004
3005 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003006 * Returns a cached instance if such is available or a new one is
3007 * create. The returned instance is initialized from the given
3008 * <code>info</code>.
3009 *
3010 * @param info The other info.
3011 * @return An instance.
3012 */
3013 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
3014 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
3015 infoClone.init(info);
3016 return infoClone;
3017 }
3018
3019 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003020 * Return an instance back to be reused.
3021 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003022 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003023 *
3024 * @throws IllegalStateException If the info is already recycled.
3025 */
3026 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003027 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003028 sPool.release(this);
Phil Weaver62d20fa2016-09-15 11:05:55 -07003029 if (sNumInstancesInUse != null) {
3030 sNumInstancesInUse.decrementAndGet();
3031 }
Phil Weaverb010b122016-08-17 17:47:48 -07003032 }
3033
3034 /**
Phil Weaver62d20fa2016-09-15 11:05:55 -07003035 * Specify a counter that will be incremented on obtain() and decremented on recycle()
Phil Weaverb010b122016-08-17 17:47:48 -07003036 *
3037 * @hide
3038 */
Phil Weaver62d20fa2016-09-15 11:05:55 -07003039 @TestApi
3040 public static void setNumInstancesInUseCounter(AtomicInteger counter) {
3041 sNumInstancesInUse = counter;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003042 }
3043
3044 /**
3045 * {@inheritDoc}
3046 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003047 * <strong>Note:</strong> After the instance is written to a parcel it
3048 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003049 * </p>
3050 */
Alan Viverettef0aed092013-11-06 15:33:03 -08003051 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003052 public void writeToParcel(Parcel parcel, int flags) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003053 parcel.writeInt(isSealed() ? 1 : 0);
Svetoslav Ganov02107852011-10-03 17:06:56 -07003054 parcel.writeLong(mSourceNodeId);
3055 parcel.writeInt(mWindowId);
3056 parcel.writeLong(mParentNodeId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07003057 parcel.writeLong(mLabelForId);
3058 parcel.writeLong(mLabeledById);
Svetoslav6c702902014-10-09 18:40:56 -07003059 parcel.writeLong(mTraversalBefore);
3060 parcel.writeLong(mTraversalAfter);
3061
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08003062 parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003063
Alan Viverettef0aed092013-11-06 15:33:03 -08003064 final LongArray childIds = mChildNodeIds;
3065 if (childIds == null) {
3066 parcel.writeInt(0);
3067 } else {
3068 final int childIdsSize = childIds.size();
3069 parcel.writeInt(childIdsSize);
3070 for (int i = 0; i < childIdsSize; i++) {
3071 parcel.writeLong(childIds.get(i));
3072 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003073 }
3074
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003075 parcel.writeInt(mBoundsInParent.top);
3076 parcel.writeInt(mBoundsInParent.bottom);
3077 parcel.writeInt(mBoundsInParent.left);
3078 parcel.writeInt(mBoundsInParent.right);
3079
3080 parcel.writeInt(mBoundsInScreen.top);
3081 parcel.writeInt(mBoundsInScreen.bottom);
3082 parcel.writeInt(mBoundsInScreen.left);
3083 parcel.writeInt(mBoundsInScreen.right);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003084
Kristian Monsen74bc1942014-04-29 11:00:17 -07003085 if (mActions != null && !mActions.isEmpty()) {
3086 final int actionCount = mActions.size();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003087
Phil Weaver487d8692017-04-06 17:40:51 -07003088 int nonLegacyActionCount = 0;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003089 int defaultLegacyStandardActions = 0;
3090 for (int i = 0; i < actionCount; i++) {
3091 AccessibilityAction action = mActions.get(i);
3092 if (isDefaultLegacyStandardAction(action)) {
3093 defaultLegacyStandardActions |= action.getId();
Phil Weaver487d8692017-04-06 17:40:51 -07003094 } else {
3095 nonLegacyActionCount++;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003096 }
3097 }
3098 parcel.writeInt(defaultLegacyStandardActions);
Phil Weaver487d8692017-04-06 17:40:51 -07003099 parcel.writeInt(nonLegacyActionCount);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003100
3101 for (int i = 0; i < actionCount; i++) {
3102 AccessibilityAction action = mActions.get(i);
3103 if (!isDefaultLegacyStandardAction(action)) {
3104 parcel.writeInt(action.getId());
3105 parcel.writeCharSequence(action.getLabel());
3106 }
3107 }
3108 } else {
3109 parcel.writeInt(0);
Phil Weaver487d8692017-04-06 17:40:51 -07003110 parcel.writeInt(0);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003111 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003112
Alan Viverette029942f2014-08-12 14:55:56 -07003113 parcel.writeInt(mMaxTextLength);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003114 parcel.writeInt(mMovementGranularities);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003115 parcel.writeInt(mBooleanProperties);
3116
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003117 parcel.writeCharSequence(mPackageName);
3118 parcel.writeCharSequence(mClassName);
3119 parcel.writeCharSequence(mText);
Phil Weaver776afc22016-12-21 10:55:13 -08003120 parcel.writeCharSequence(mHintText);
Alan Viverettefccbff52014-07-07 15:06:14 -07003121 parcel.writeCharSequence(mError);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003122 parcel.writeCharSequence(mContentDescription);
Svetoslav9fa1ee52013-04-22 12:43:03 -07003123 parcel.writeString(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003124
Svetoslavbcc46a02013-02-06 11:56:00 -08003125 parcel.writeInt(mTextSelectionStart);
3126 parcel.writeInt(mTextSelectionEnd);
Svetoslav6254f482013-06-04 17:22:14 -07003127 parcel.writeInt(mInputType);
Alan Viverette77e9a282013-09-12 17:16:09 -07003128 parcel.writeInt(mLiveRegion);
Phil Weaver1f222542016-01-08 11:49:32 -08003129 parcel.writeInt(mDrawingOrderInParent);
Phil Weaverc2e28932016-12-08 12:29:25 -08003130 if (mExtraDataKeys != null) {
3131 parcel.writeInt(1);
3132 parcel.writeStringList(mExtraDataKeys);
3133 } else {
3134 parcel.writeInt(0);
3135 }
Svetoslav6254f482013-06-04 17:22:14 -07003136
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003137 if (mExtras != null) {
Svetoslav6254f482013-06-04 17:22:14 -07003138 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003139 parcel.writeBundle(mExtras);
Svetoslav6254f482013-06-04 17:22:14 -07003140 } else {
3141 parcel.writeInt(0);
3142 }
Svetoslavbcc46a02013-02-06 11:56:00 -08003143
Svetoslav3577a282013-06-06 14:09:10 -07003144 if (mRangeInfo != null) {
3145 parcel.writeInt(1);
3146 parcel.writeInt(mRangeInfo.getType());
3147 parcel.writeFloat(mRangeInfo.getMin());
3148 parcel.writeFloat(mRangeInfo.getMax());
3149 parcel.writeFloat(mRangeInfo.getCurrent());
3150 } else {
3151 parcel.writeInt(0);
3152 }
3153
3154 if (mCollectionInfo != null) {
3155 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003156 parcel.writeInt(mCollectionInfo.getRowCount());
3157 parcel.writeInt(mCollectionInfo.getColumnCount());
Svetoslav3577a282013-06-06 14:09:10 -07003158 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003159 parcel.writeInt(mCollectionInfo.getSelectionMode());
Svetoslav3577a282013-06-06 14:09:10 -07003160 } else {
3161 parcel.writeInt(0);
3162 }
3163
3164 if (mCollectionItemInfo != null) {
3165 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003166 parcel.writeInt(mCollectionItemInfo.getRowIndex());
3167 parcel.writeInt(mCollectionItemInfo.getRowSpan());
Alan Viverettefaeac962015-06-01 09:03:27 -07003168 parcel.writeInt(mCollectionItemInfo.getColumnIndex());
3169 parcel.writeInt(mCollectionItemInfo.getColumnSpan());
Svetoslav3577a282013-06-06 14:09:10 -07003170 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003171 parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
Svetoslav3577a282013-06-06 14:09:10 -07003172 } else {
3173 parcel.writeInt(0);
3174 }
3175
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003176 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003177 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003178 recycle();
3179 }
3180
3181 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003182 * Initializes this instance from another one.
3183 *
3184 * @param other The other instance.
3185 */
3186 private void init(AccessibilityNodeInfo other) {
3187 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003188 mSourceNodeId = other.mSourceNodeId;
3189 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07003190 mLabelForId = other.mLabelForId;
3191 mLabeledById = other.mLabeledById;
Svetoslav6c702902014-10-09 18:40:56 -07003192 mTraversalBefore = other.mTraversalBefore;
3193 mTraversalAfter = other.mTraversalAfter;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003194 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08003195 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003196 mBoundsInParent.set(other.mBoundsInParent);
3197 mBoundsInScreen.set(other.mBoundsInScreen);
3198 mPackageName = other.mPackageName;
3199 mClassName = other.mClassName;
3200 mText = other.mText;
Phil Weaver776afc22016-12-21 10:55:13 -08003201 mHintText = other.mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -07003202 mError = other.mError;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003203 mContentDescription = other.mContentDescription;
Svetoslav22431a32013-02-05 14:30:19 -08003204 mViewIdResourceName = other.mViewIdResourceName;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003205
3206 final ArrayList<AccessibilityAction> otherActions = other.mActions;
3207 if (otherActions != null && otherActions.size() > 0) {
3208 if (mActions == null) {
3209 mActions = new ArrayList(otherActions);
3210 } else {
3211 mActions.clear();
3212 mActions.addAll(other.mActions);
3213 }
3214 }
3215
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003216 mBooleanProperties = other.mBooleanProperties;
Alan Viverette029942f2014-08-12 14:55:56 -07003217 mMaxTextLength = other.mMaxTextLength;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003218 mMovementGranularities = other.mMovementGranularities;
Alan Viverettef0aed092013-11-06 15:33:03 -08003219
3220 final LongArray otherChildNodeIds = other.mChildNodeIds;
3221 if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) {
3222 if (mChildNodeIds == null) {
3223 mChildNodeIds = otherChildNodeIds.clone();
3224 } else {
Svetoslav8e3feb12014-02-24 13:46:47 -08003225 mChildNodeIds.clear();
Alan Viverettef0aed092013-11-06 15:33:03 -08003226 mChildNodeIds.addAll(otherChildNodeIds);
3227 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003228 }
Alan Viverettef0aed092013-11-06 15:33:03 -08003229
Svetoslavbcc46a02013-02-06 11:56:00 -08003230 mTextSelectionStart = other.mTextSelectionStart;
3231 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07003232 mInputType = other.mInputType;
Alan Viverette77e9a282013-09-12 17:16:09 -07003233 mLiveRegion = other.mLiveRegion;
Phil Weaver1f222542016-01-08 11:49:32 -08003234 mDrawingOrderInParent = other.mDrawingOrderInParent;
Phil Weaverc2e28932016-12-08 12:29:25 -08003235 mExtraDataKeys = other.mExtraDataKeys;
3236
Jeff Sharkey297017d2016-03-29 16:37:14 -06003237 if (other.mExtras != null) {
3238 mExtras = new Bundle(other.mExtras);
3239 } else {
3240 mExtras = null;
Svetoslav6254f482013-06-04 17:22:14 -07003241 }
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003242 mRangeInfo = (other.mRangeInfo != null)
3243 ? RangeInfo.obtain(other.mRangeInfo) : null;
3244 mCollectionInfo = (other.mCollectionInfo != null)
3245 ? CollectionInfo.obtain(other.mCollectionInfo) : null;
3246 mCollectionItemInfo = (other.mCollectionItemInfo != null)
3247 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003248 }
3249
3250 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003251 * Creates a new instance from a {@link Parcel}.
3252 *
3253 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
3254 */
3255 private void initFromParcel(Parcel parcel) {
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -07003256 final boolean sealed = (parcel.readInt() == 1);
Svetoslav Ganov02107852011-10-03 17:06:56 -07003257 mSourceNodeId = parcel.readLong();
3258 mWindowId = parcel.readInt();
3259 mParentNodeId = parcel.readLong();
Svetoslav Ganov33aef982012-09-13 12:49:03 -07003260 mLabelForId = parcel.readLong();
3261 mLabeledById = parcel.readLong();
Svetoslav6c702902014-10-09 18:40:56 -07003262 mTraversalBefore = parcel.readLong();
3263 mTraversalAfter = parcel.readLong();
3264
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08003265 mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003266
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003267 final int childrenSize = parcel.readInt();
Alan Viverettef0aed092013-11-06 15:33:03 -08003268 if (childrenSize <= 0) {
3269 mChildNodeIds = null;
3270 } else {
3271 mChildNodeIds = new LongArray(childrenSize);
3272 for (int i = 0; i < childrenSize; i++) {
3273 final long childId = parcel.readLong();
3274 mChildNodeIds.add(childId);
3275 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003276 }
3277
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003278 mBoundsInParent.top = parcel.readInt();
3279 mBoundsInParent.bottom = parcel.readInt();
3280 mBoundsInParent.left = parcel.readInt();
3281 mBoundsInParent.right = parcel.readInt();
3282
3283 mBoundsInScreen.top = parcel.readInt();
3284 mBoundsInScreen.bottom = parcel.readInt();
3285 mBoundsInScreen.left = parcel.readInt();
3286 mBoundsInScreen.right = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003287
Phil Weaver487d8692017-04-06 17:40:51 -07003288 final int legacyStandardActions = parcel.readInt();
3289 addLegacyStandardActions(legacyStandardActions);
3290 final int nonLegacyActionCount = parcel.readInt();
3291 for (int i = 0; i < nonLegacyActionCount; i++) {
3292 final AccessibilityAction action = new AccessibilityAction(
3293 parcel.readInt(), parcel.readCharSequence());
3294 addActionUnchecked(action);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003295 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003296
Alan Viverette029942f2014-08-12 14:55:56 -07003297 mMaxTextLength = parcel.readInt();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003298 mMovementGranularities = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003299 mBooleanProperties = parcel.readInt();
3300
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003301 mPackageName = parcel.readCharSequence();
3302 mClassName = parcel.readCharSequence();
3303 mText = parcel.readCharSequence();
Phil Weaver776afc22016-12-21 10:55:13 -08003304 mHintText = parcel.readCharSequence();
Alan Viverettefccbff52014-07-07 15:06:14 -07003305 mError = parcel.readCharSequence();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003306 mContentDescription = parcel.readCharSequence();
Svetoslav9fa1ee52013-04-22 12:43:03 -07003307 mViewIdResourceName = parcel.readString();
Svetoslavbcc46a02013-02-06 11:56:00 -08003308
3309 mTextSelectionStart = parcel.readInt();
3310 mTextSelectionEnd = parcel.readInt();
Svetoslav3577a282013-06-06 14:09:10 -07003311
Svetoslav6254f482013-06-04 17:22:14 -07003312 mInputType = parcel.readInt();
Alan Viverette77e9a282013-09-12 17:16:09 -07003313 mLiveRegion = parcel.readInt();
Phil Weaver1f222542016-01-08 11:49:32 -08003314 mDrawingOrderInParent = parcel.readInt();
Svetoslav6254f482013-06-04 17:22:14 -07003315
3316 if (parcel.readInt() == 1) {
Phil Weaverc2e28932016-12-08 12:29:25 -08003317 mExtraDataKeys = parcel.createStringArrayList();
3318 } else {
3319 mExtraDataKeys = null;
3320 }
3321
3322 if (parcel.readInt() == 1) {
Jeff Sharkey297017d2016-03-29 16:37:14 -06003323 mExtras = parcel.readBundle();
3324 } else {
3325 mExtras = null;
Svetoslav6254f482013-06-04 17:22:14 -07003326 }
Svetoslav3577a282013-06-06 14:09:10 -07003327
3328 if (parcel.readInt() == 1) {
3329 mRangeInfo = RangeInfo.obtain(
3330 parcel.readInt(),
3331 parcel.readFloat(),
3332 parcel.readFloat(),
3333 parcel.readFloat());
3334 }
3335
3336 if (parcel.readInt() == 1) {
3337 mCollectionInfo = CollectionInfo.obtain(
3338 parcel.readInt(),
3339 parcel.readInt(),
Alan Viverette76769ae2014-02-12 16:38:10 -08003340 parcel.readInt() == 1,
3341 parcel.readInt());
Svetoslav3577a282013-06-06 14:09:10 -07003342 }
3343
3344 if (parcel.readInt() == 1) {
3345 mCollectionItemInfo = CollectionItemInfo.obtain(
3346 parcel.readInt(),
3347 parcel.readInt(),
3348 parcel.readInt(),
3349 parcel.readInt(),
Alan Viverette76769ae2014-02-12 16:38:10 -08003350 parcel.readInt() == 1,
Svetoslav3577a282013-06-06 14:09:10 -07003351 parcel.readInt() == 1);
3352 }
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -07003353
3354 mSealed = sealed;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003355 }
3356
3357 /**
3358 * Clears the state of this instance.
3359 */
3360 private void clear() {
3361 mSealed = false;
Phil Weaverf00cd142017-03-03 13:44:00 -08003362 mSourceNodeId = UNDEFINED_NODE_ID;
3363 mParentNodeId = UNDEFINED_NODE_ID;
3364 mLabelForId = UNDEFINED_NODE_ID;
3365 mLabeledById = UNDEFINED_NODE_ID;
3366 mTraversalBefore = UNDEFINED_NODE_ID;
3367 mTraversalAfter = UNDEFINED_NODE_ID;
Phil Weaver23161e72017-04-19 12:16:36 -07003368 mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Svetoslav8e3feb12014-02-24 13:46:47 -08003369 mConnectionId = UNDEFINED_CONNECTION_ID;
Alan Viverette029942f2014-08-12 14:55:56 -07003370 mMaxTextLength = -1;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003371 mMovementGranularities = 0;
Alan Viverettef0aed092013-11-06 15:33:03 -08003372 if (mChildNodeIds != null) {
3373 mChildNodeIds.clear();
3374 }
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003375 mBoundsInParent.set(0, 0, 0, 0);
3376 mBoundsInScreen.set(0, 0, 0, 0);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003377 mBooleanProperties = 0;
Phil Weaver1f222542016-01-08 11:49:32 -08003378 mDrawingOrderInParent = 0;
Phil Weaver9b83ffb2017-02-10 10:10:01 -08003379 mExtraDataKeys = null;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003380 mPackageName = null;
3381 mClassName = null;
3382 mText = null;
Phil Weaver776afc22016-12-21 10:55:13 -08003383 mHintText = null;
Alan Viverettefccbff52014-07-07 15:06:14 -07003384 mError = null;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003385 mContentDescription = null;
Svetoslav22431a32013-02-05 14:30:19 -08003386 mViewIdResourceName = null;
Phil Weaverf00cd142017-03-03 13:44:00 -08003387 removeAllActions();
Svetoslav8e3feb12014-02-24 13:46:47 -08003388 mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
3389 mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
Svetoslav6254f482013-06-04 17:22:14 -07003390 mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -07003391 mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Jeff Sharkey297017d2016-03-29 16:37:14 -06003392 mExtras = null;
Svetoslav3577a282013-06-06 14:09:10 -07003393 if (mRangeInfo != null) {
3394 mRangeInfo.recycle();
3395 mRangeInfo = null;
3396 }
3397 if (mCollectionInfo != null) {
3398 mCollectionInfo.recycle();
3399 mCollectionInfo = null;
3400 }
3401 if (mCollectionItemInfo != null) {
3402 mCollectionItemInfo.recycle();
3403 mCollectionItemInfo = null;
3404 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003405 }
3406
Kristian Monsen74bc1942014-04-29 11:00:17 -07003407 private static boolean isDefaultLegacyStandardAction(AccessibilityAction action) {
3408 return (action.getId() <= LAST_LEGACY_STANDARD_ACTION
3409 && TextUtils.isEmpty(action.getLabel()));
3410 }
3411
3412 private static AccessibilityAction getActionSingleton(int actionId) {
3413 final int actions = AccessibilityAction.sStandardActions.size();
3414 for (int i = 0; i < actions; i++) {
3415 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3416 if (actionId == currentAction.getId()) {
3417 return currentAction;
3418 }
3419 }
3420
3421 return null;
3422 }
3423
3424 private void addLegacyStandardActions(int actionMask) {
3425 int remainingIds = actionMask;
3426 while (remainingIds > 0) {
3427 final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
3428 remainingIds &= ~id;
3429 AccessibilityAction action = getActionSingleton(id);
3430 addAction(action);
3431 }
3432 }
3433
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003434 /**
3435 * Gets the human readable action symbolic name.
3436 *
3437 * @param action The action.
3438 * @return The symbolic name.
3439 */
3440 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003441 switch (action) {
3442 case ACTION_FOCUS:
3443 return "ACTION_FOCUS";
3444 case ACTION_CLEAR_FOCUS:
3445 return "ACTION_CLEAR_FOCUS";
3446 case ACTION_SELECT:
3447 return "ACTION_SELECT";
3448 case ACTION_CLEAR_SELECTION:
3449 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003450 case ACTION_CLICK:
3451 return "ACTION_CLICK";
3452 case ACTION_LONG_CLICK:
3453 return "ACTION_LONG_CLICK";
3454 case ACTION_ACCESSIBILITY_FOCUS:
3455 return "ACTION_ACCESSIBILITY_FOCUS";
3456 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
3457 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003458 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
3459 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
3460 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
3461 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003462 case ACTION_NEXT_HTML_ELEMENT:
3463 return "ACTION_NEXT_HTML_ELEMENT";
3464 case ACTION_PREVIOUS_HTML_ELEMENT:
3465 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07003466 case ACTION_SCROLL_FORWARD:
3467 return "ACTION_SCROLL_FORWARD";
3468 case ACTION_SCROLL_BACKWARD:
3469 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08003470 case ACTION_CUT:
3471 return "ACTION_CUT";
3472 case ACTION_COPY:
3473 return "ACTION_COPY";
3474 case ACTION_PASTE:
3475 return "ACTION_PASTE";
3476 case ACTION_SET_SELECTION:
3477 return "ACTION_SET_SELECTION";
Steven Dao103a577c2015-10-12 17:35:59 -07003478 case ACTION_EXPAND:
3479 return "ACTION_EXPAND";
3480 case ACTION_COLLAPSE:
3481 return "ACTION_COLLAPSE";
3482 case ACTION_DISMISS:
3483 return "ACTION_DISMISS";
3484 case ACTION_SET_TEXT:
3485 return "ACTION_SET_TEXT";
3486 case R.id.accessibilityActionShowOnScreen:
3487 return "ACTION_SHOW_ON_SCREEN";
3488 case R.id.accessibilityActionScrollToPosition:
3489 return "ACTION_SCROLL_TO_POSITION";
3490 case R.id.accessibilityActionScrollUp:
3491 return "ACTION_SCROLL_UP";
3492 case R.id.accessibilityActionScrollLeft:
3493 return "ACTION_SCROLL_LEFT";
3494 case R.id.accessibilityActionScrollDown:
3495 return "ACTION_SCROLL_DOWN";
3496 case R.id.accessibilityActionScrollRight:
3497 return "ACTION_SCROLL_RIGHT";
3498 case R.id.accessibilityActionSetProgress:
3499 return "ACTION_SET_PROGRESS";
3500 case R.id.accessibilityActionContextClick:
3501 return "ACTION_CONTEXT_CLICK";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003502 default:
Steven Dao103a577c2015-10-12 17:35:59 -07003503 return "ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003504 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003505 }
3506
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003507 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003508 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003509 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003510 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003511 * @return The symbolic name.
3512 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003513 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003514 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003515 case MOVEMENT_GRANULARITY_CHARACTER:
3516 return "MOVEMENT_GRANULARITY_CHARACTER";
3517 case MOVEMENT_GRANULARITY_WORD:
3518 return "MOVEMENT_GRANULARITY_WORD";
3519 case MOVEMENT_GRANULARITY_LINE:
3520 return "MOVEMENT_GRANULARITY_LINE";
3521 case MOVEMENT_GRANULARITY_PARAGRAPH:
3522 return "MOVEMENT_GRANULARITY_PARAGRAPH";
3523 case MOVEMENT_GRANULARITY_PAGE:
3524 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003525 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003526 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003527 }
3528 }
3529
Svetoslav Ganov02107852011-10-03 17:06:56 -07003530 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Phil Weaver23161e72017-04-19 12:16:36 -07003531 return ((mWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
3532 && (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
3533 && (mConnectionId != UNDEFINED_CONNECTION_ID));
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003534 }
3535
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003536 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003537 public boolean equals(Object object) {
3538 if (this == object) {
3539 return true;
3540 }
3541 if (object == null) {
3542 return false;
3543 }
3544 if (getClass() != object.getClass()) {
3545 return false;
3546 }
3547 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003548 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003549 return false;
3550 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07003551 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003552 return false;
3553 }
3554 return true;
3555 }
3556
3557 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003558 public int hashCode() {
3559 final int prime = 31;
3560 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003561 result = prime * result + getAccessibilityViewId(mSourceNodeId);
3562 result = prime * result + getVirtualDescendantId(mSourceNodeId);
3563 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003564 return result;
3565 }
3566
3567 @Override
3568 public String toString() {
3569 StringBuilder builder = new StringBuilder();
3570 builder.append(super.toString());
3571
3572 if (DEBUG) {
Svetoslav8e3feb12014-02-24 13:46:47 -08003573 builder.append("; sourceNodeId: " + mSourceNodeId);
Svetoslav Ganov02107852011-10-03 17:06:56 -07003574 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
3575 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
3576 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav6c702902014-10-09 18:40:56 -07003577 builder.append("; traversalBefore: ").append(mTraversalBefore);
3578 builder.append("; traversalAfter: ").append(mTraversalAfter);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003579
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003580 int granularities = mMovementGranularities;
3581 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003582 while (granularities != 0) {
3583 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
3584 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003585 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003586 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003587 builder.append(", ");
3588 }
3589 }
3590 builder.append("]");
3591
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003592 builder.append("; childAccessibilityIds: [");
Alan Viverettef0aed092013-11-06 15:33:03 -08003593 final LongArray childIds = mChildNodeIds;
3594 if (childIds != null) {
3595 for (int i = 0, count = childIds.size(); i < count; i++) {
3596 builder.append(childIds.get(i));
3597 if (i < count - 1) {
3598 builder.append(", ");
3599 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003600 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003601 }
3602 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003603 }
3604
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003605 builder.append("; boundsInParent: " + mBoundsInParent);
3606 builder.append("; boundsInScreen: " + mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003607
3608 builder.append("; packageName: ").append(mPackageName);
3609 builder.append("; className: ").append(mClassName);
3610 builder.append("; text: ").append(mText);
Alan Viverettefccbff52014-07-07 15:06:14 -07003611 builder.append("; error: ").append(mError);
Alan Viverette029942f2014-08-12 14:55:56 -07003612 builder.append("; maxTextLength: ").append(mMaxTextLength);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003613 builder.append("; contentDescription: ").append(mContentDescription);
Svetoslav22431a32013-02-05 14:30:19 -08003614 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003615
3616 builder.append("; checkable: ").append(isCheckable());
3617 builder.append("; checked: ").append(isChecked());
3618 builder.append("; focusable: ").append(isFocusable());
3619 builder.append("; focused: ").append(isFocused());
3620 builder.append("; selected: ").append(isSelected());
3621 builder.append("; clickable: ").append(isClickable());
3622 builder.append("; longClickable: ").append(isLongClickable());
Mady Mellore8608912015-06-05 09:02:55 -07003623 builder.append("; contextClickable: ").append(isContextClickable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003624 builder.append("; enabled: ").append(isEnabled());
3625 builder.append("; password: ").append(isPassword());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003626 builder.append("; scrollable: ").append(isScrollable());
Phil Weaver4d3eec412016-09-01 16:28:34 -07003627 builder.append("; importantForAccessibility: ").append(isImportantForAccessibility());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003628 builder.append("; actions: ").append(mActions);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003629
3630 return builder.toString();
3631 }
3632
Svetoslav6c702902014-10-09 18:40:56 -07003633 private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
3634 if (!canPerformRequestOverConnection(accessibilityId)) {
3635 return null;
3636 }
3637 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
3638 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
3639 mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
Phil Weaverc2e28932016-12-08 12:29:25 -08003640 | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null);
Svetoslav6c702902014-10-09 18:40:56 -07003641 }
3642
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003643 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07003644 * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
3645 * Each action has a unique id that is mandatory and optional data.
3646 * <p>
3647 * There are three categories of actions:
3648 * <ul>
3649 * <li><strong>Standard actions</strong> - These are actions that are reported and
3650 * handled by the standard UI widgets in the platform. For each standard action
3651 * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
Phil Weaver426361c2017-02-22 13:06:25 -08003652 * These actions will have {@code null} labels.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003653 * </li>
3654 * <li><strong>Custom actions action</strong> - These are actions that are reported
3655 * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
3656 * example, an application may define a custom action for clearing the user history.
3657 * </li>
3658 * <li><strong>Overriden standard actions</strong> - These are actions that override
3659 * standard actions to customize them. For example, an app may add a label to the
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003660 * standard {@link #ACTION_CLICK} action to announce that this action clears browsing history.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003661 * </ul>
3662 * </p>
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003663 * <p>
3664 * Actions are typically added to an {@link AccessibilityNodeInfo} by using
3665 * {@link AccessibilityNodeInfo#addAction(AccessibilityAction)} within
3666 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed
3667 * within {@link View#performAccessibilityAction(int, Bundle)}.
3668 * </p>
3669 * <p class="note">
3670 * <strong>Note:</strong> Views which support these actions should invoke
3671 * {@link View#setImportantForAccessibility(int)} with
3672 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService}
3673 * can discover the set of supported actions.
3674 * </p>
Kristian Monsen74bc1942014-04-29 11:00:17 -07003675 */
3676 public static final class AccessibilityAction {
3677
3678 /**
3679 * Action that gives input focus to the node.
3680 */
3681 public static final AccessibilityAction ACTION_FOCUS =
3682 new AccessibilityAction(
3683 AccessibilityNodeInfo.ACTION_FOCUS, null);
3684
3685 /**
3686 * Action that clears input focus of the node.
3687 */
3688 public static final AccessibilityAction ACTION_CLEAR_FOCUS =
3689 new AccessibilityAction(
3690 AccessibilityNodeInfo.ACTION_CLEAR_FOCUS, null);
3691
3692 /**
3693 * Action that selects the node.
3694 */
3695 public static final AccessibilityAction ACTION_SELECT =
3696 new AccessibilityAction(
3697 AccessibilityNodeInfo.ACTION_SELECT, null);
3698
3699 /**
3700 * Action that deselects the node.
3701 */
3702 public static final AccessibilityAction ACTION_CLEAR_SELECTION =
3703 new AccessibilityAction(
3704 AccessibilityNodeInfo.ACTION_CLEAR_SELECTION, null);
3705
3706 /**
3707 * Action that clicks on the node info.
3708 */
3709 public static final AccessibilityAction ACTION_CLICK =
3710 new AccessibilityAction(
3711 AccessibilityNodeInfo.ACTION_CLICK, null);
3712
3713 /**
3714 * Action that long clicks on the node.
3715 */
3716 public static final AccessibilityAction ACTION_LONG_CLICK =
3717 new AccessibilityAction(
3718 AccessibilityNodeInfo.ACTION_LONG_CLICK, null);
3719
3720 /**
3721 * Action that gives accessibility focus to the node.
3722 */
3723 public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS =
3724 new AccessibilityAction(
3725 AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
3726
3727 /**
3728 * Action that clears accessibility focus of the node.
3729 */
3730 public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS =
3731 new AccessibilityAction(
3732 AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
3733
3734 /**
3735 * Action that requests to go to the next entity in this node's text
3736 * at a given movement granularity. For example, move to the next character,
3737 * word, etc.
3738 * <p>
3739 * <strong>Arguments:</strong>
3740 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3741 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3742 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3743 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3744 * <strong>Example:</strong> Move to the previous character and do not extend selection.
3745 * <code><pre><p>
3746 * Bundle arguments = new Bundle();
3747 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3748 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3749 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3750 * false);
3751 * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(),
3752 * arguments);
3753 * </code></pre></p>
3754 * </p>
3755 *
3756 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3757 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3758 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3759 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3760 *
3761 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3762 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3763 * @see AccessibilityNodeInfo#getMovementGranularities()
3764 * AccessibilityNodeInfo.getMovementGranularities()
3765 *
3766 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3767 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3768 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3769 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3770 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3771 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3772 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3773 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3774 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3775 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3776 */
3777 public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY =
3778 new AccessibilityAction(
3779 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, null);
3780
3781 /**
3782 * Action that requests to go to the previous entity in this node's text
3783 * at a given movement granularity. For example, move to the next character,
3784 * word, etc.
3785 * <p>
3786 * <strong>Arguments:</strong>
3787 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3788 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3789 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3790 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3791 * <strong>Example:</strong> Move to the next character and do not extend selection.
3792 * <code><pre><p>
3793 * Bundle arguments = new Bundle();
3794 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3795 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3796 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3797 * false);
3798 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(),
3799 * arguments);
3800 * </code></pre></p>
3801 * </p>
3802 *
3803 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3804 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3805 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3806 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3807 *
3808 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3809 * AccessibilityNodeInfo.setMovementGranularities(int)
3810 * @see AccessibilityNodeInfo#getMovementGranularities()
3811 * AccessibilityNodeInfo.getMovementGranularities()
3812 *
3813 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3814 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3815 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3816 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3817 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3818 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3819 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3820 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3821 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3822 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3823 */
3824 public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY =
3825 new AccessibilityAction(
3826 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, null);
3827
3828 /**
3829 * Action to move to the next HTML element of a given type. For example, move
3830 * to the BUTTON, INPUT, TABLE, etc.
3831 * <p>
3832 * <strong>Arguments:</strong>
3833 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3834 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3835 * <strong>Example:</strong>
3836 * <code><pre><p>
3837 * Bundle arguments = new Bundle();
3838 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3839 * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments);
3840 * </code></pre></p>
3841 * </p>
3842 */
3843 public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT =
3844 new AccessibilityAction(
3845 AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, null);
3846
3847 /**
3848 * Action to move to the previous HTML element of a given type. For example, move
3849 * to the BUTTON, INPUT, TABLE, etc.
3850 * <p>
3851 * <strong>Arguments:</strong>
3852 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3853 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3854 * <strong>Example:</strong>
3855 * <code><pre><p>
3856 * Bundle arguments = new Bundle();
3857 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3858 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments);
3859 * </code></pre></p>
3860 * </p>
3861 */
3862 public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT =
3863 new AccessibilityAction(
3864 AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, null);
3865
3866 /**
3867 * Action to scroll the node content forward.
3868 */
3869 public static final AccessibilityAction ACTION_SCROLL_FORWARD =
3870 new AccessibilityAction(
3871 AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, null);
3872
3873 /**
3874 * Action to scroll the node content backward.
3875 */
3876 public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
3877 new AccessibilityAction(
3878 AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, null);
3879
3880 /**
3881 * Action to copy the current selection to the clipboard.
3882 */
3883 public static final AccessibilityAction ACTION_COPY =
3884 new AccessibilityAction(
3885 AccessibilityNodeInfo.ACTION_COPY, null);
3886
3887 /**
3888 * Action to paste the current clipboard content.
3889 */
3890 public static final AccessibilityAction ACTION_PASTE =
3891 new AccessibilityAction(
3892 AccessibilityNodeInfo.ACTION_PASTE, null);
3893
3894 /**
3895 * Action to cut the current selection and place it to the clipboard.
3896 */
3897 public static final AccessibilityAction ACTION_CUT =
3898 new AccessibilityAction(
3899 AccessibilityNodeInfo.ACTION_CUT, null);
3900
3901 /**
3902 * Action to set the selection. Performing this action with no arguments
3903 * clears the selection.
3904 * <p>
3905 * <strong>Arguments:</strong>
3906 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3907 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT},
3908 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3909 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br>
3910 * <strong>Example:</strong>
3911 * <code><pre><p>
3912 * Bundle arguments = new Bundle();
3913 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
3914 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
3915 * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments);
3916 * </code></pre></p>
3917 * </p>
3918 *
3919 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3920 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT
3921 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3922 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT
3923 */
3924 public static final AccessibilityAction ACTION_SET_SELECTION =
3925 new AccessibilityAction(
3926 AccessibilityNodeInfo.ACTION_SET_SELECTION, null);
3927
3928 /**
3929 * Action to expand an expandable node.
3930 */
3931 public static final AccessibilityAction ACTION_EXPAND =
3932 new AccessibilityAction(
3933 AccessibilityNodeInfo.ACTION_EXPAND, null);
3934
3935 /**
3936 * Action to collapse an expandable node.
3937 */
3938 public static final AccessibilityAction ACTION_COLLAPSE =
3939 new AccessibilityAction(
3940 AccessibilityNodeInfo.ACTION_COLLAPSE, null);
3941
3942 /**
3943 * Action to dismiss a dismissable node.
3944 */
3945 public static final AccessibilityAction ACTION_DISMISS =
3946 new AccessibilityAction(
3947 AccessibilityNodeInfo.ACTION_DISMISS, null);
3948
3949 /**
3950 * Action that sets the text of the node. Performing the action without argument,
3951 * using <code> null</code> or empty {@link CharSequence} will clear the text. This
3952 * action will also put the cursor at the end of text.
3953 * <p>
3954 * <strong>Arguments:</strong>
3955 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
3956 * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
3957 * <strong>Example:</strong>
3958 * <code><pre><p>
3959 * Bundle arguments = new Bundle();
3960 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
3961 * "android");
3962 * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments);
3963 * </code></pre></p>
3964 */
3965 public static final AccessibilityAction ACTION_SET_TEXT =
3966 new AccessibilityAction(
3967 AccessibilityNodeInfo.ACTION_SET_TEXT, null);
3968
Alan Viverette26c44ee2015-03-25 14:54:13 -07003969 /**
3970 * Action that requests the node make its bounding rectangle visible
3971 * on the screen, scrolling if necessary just enough.
3972 *
3973 * @see View#requestRectangleOnScreen(Rect)
3974 */
3975 public static final AccessibilityAction ACTION_SHOW_ON_SCREEN =
Alan Viverette23f44322015-04-06 16:04:56 -07003976 new AccessibilityAction(R.id.accessibilityActionShowOnScreen, null);
Alan Viverette26c44ee2015-03-25 14:54:13 -07003977
Alan Viverette23f44322015-04-06 16:04:56 -07003978 /**
3979 * Action that scrolls the node to make the specified collection
3980 * position visible on screen.
3981 * <p>
3982 * <strong>Arguments:</strong>
3983 * <ul>
3984 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
3985 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
3986 * <ul>
3987 *
3988 * @see AccessibilityNodeInfo#getCollectionInfo()
3989 */
3990 public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
3991 new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null);
3992
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07003993 /**
3994 * Action to scroll the node content up.
3995 */
3996 public static final AccessibilityAction ACTION_SCROLL_UP =
3997 new AccessibilityAction(R.id.accessibilityActionScrollUp, null);
3998
3999 /**
4000 * Action to scroll the node content left.
4001 */
4002 public static final AccessibilityAction ACTION_SCROLL_LEFT =
4003 new AccessibilityAction(R.id.accessibilityActionScrollLeft, null);
4004
4005 /**
4006 * Action to scroll the node content down.
4007 */
4008 public static final AccessibilityAction ACTION_SCROLL_DOWN =
4009 new AccessibilityAction(R.id.accessibilityActionScrollDown, null);
4010
4011 /**
4012 * Action to scroll the node content right.
4013 */
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004014 public static final AccessibilityAction ACTION_SCROLL_RIGHT =
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004015 new AccessibilityAction(R.id.accessibilityActionScrollRight, null);
4016
Mady Mellord2744002015-04-30 16:17:16 -07004017 /**
Mady Mellore8608912015-06-05 09:02:55 -07004018 * Action that context clicks the node.
Mady Mellore82067b2015-04-30 09:58:35 -07004019 */
Mady Mellore8608912015-06-05 09:02:55 -07004020 public static final AccessibilityAction ACTION_CONTEXT_CLICK =
4021 new AccessibilityAction(R.id.accessibilityActionContextClick, null);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004022
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004023 /**
4024 * Action that sets progress between {@link RangeInfo#getMin() RangeInfo.getMin()} and
4025 * {@link RangeInfo#getMax() RangeInfo.getMax()}. It should use the same value type as
4026 * {@link RangeInfo#getType() RangeInfo.getType()}
4027 * <p>
4028 * <strong>Arguments:</strong>
4029 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_PROGRESS_VALUE}
4030 *
4031 * @see RangeInfo
4032 */
4033 public static final AccessibilityAction ACTION_SET_PROGRESS =
4034 new AccessibilityAction(R.id.accessibilityActionSetProgress, null);
4035
Phil Weaverf00cd142017-03-03 13:44:00 -08004036 /**
4037 * Action to move a window to a new location.
4038 * <p>
4039 * <strong>Arguments:</strong>
4040 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_X}
4041 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_Y}
4042 */
4043 public static final AccessibilityAction ACTION_MOVE_WINDOW =
4044 new AccessibilityAction(R.id.accessibilityActionMoveWindow, null);
4045
Alan Viverette23f44322015-04-06 16:04:56 -07004046 private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
Kristian Monsen74bc1942014-04-29 11:00:17 -07004047 static {
4048 sStandardActions.add(ACTION_FOCUS);
4049 sStandardActions.add(ACTION_CLEAR_FOCUS);
4050 sStandardActions.add(ACTION_SELECT);
4051 sStandardActions.add(ACTION_CLEAR_SELECTION);
4052 sStandardActions.add(ACTION_CLICK);
4053 sStandardActions.add(ACTION_LONG_CLICK);
4054 sStandardActions.add(ACTION_ACCESSIBILITY_FOCUS);
4055 sStandardActions.add(ACTION_CLEAR_ACCESSIBILITY_FOCUS);
4056 sStandardActions.add(ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
4057 sStandardActions.add(ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
4058 sStandardActions.add(ACTION_NEXT_HTML_ELEMENT);
4059 sStandardActions.add(ACTION_PREVIOUS_HTML_ELEMENT);
4060 sStandardActions.add(ACTION_SCROLL_FORWARD);
4061 sStandardActions.add(ACTION_SCROLL_BACKWARD);
4062 sStandardActions.add(ACTION_COPY);
4063 sStandardActions.add(ACTION_PASTE);
4064 sStandardActions.add(ACTION_CUT);
4065 sStandardActions.add(ACTION_SET_SELECTION);
4066 sStandardActions.add(ACTION_EXPAND);
4067 sStandardActions.add(ACTION_COLLAPSE);
4068 sStandardActions.add(ACTION_DISMISS);
4069 sStandardActions.add(ACTION_SET_TEXT);
Alan Viverette26c44ee2015-03-25 14:54:13 -07004070 sStandardActions.add(ACTION_SHOW_ON_SCREEN);
Alan Viverette23f44322015-04-06 16:04:56 -07004071 sStandardActions.add(ACTION_SCROLL_TO_POSITION);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004072 sStandardActions.add(ACTION_SCROLL_UP);
4073 sStandardActions.add(ACTION_SCROLL_LEFT);
4074 sStandardActions.add(ACTION_SCROLL_DOWN);
4075 sStandardActions.add(ACTION_SCROLL_RIGHT);
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004076 sStandardActions.add(ACTION_SET_PROGRESS);
Mady Mellore8608912015-06-05 09:02:55 -07004077 sStandardActions.add(ACTION_CONTEXT_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004078 }
4079
4080 private final int mActionId;
4081 private final CharSequence mLabel;
4082
4083 /**
4084 * Creates a new AccessibilityAction. For adding a standard action without a specific label,
4085 * use the static constants.
4086 *
4087 * You can also override the description for one the standard actions. Below is an example
4088 * how to override the standard click action by adding a custom label:
4089 * <pre>
4090 * AccessibilityAction action = new AccessibilityAction(
Phil Weaverc3791292016-09-12 11:06:49 -07004091 * AccessibilityAction.ACTION_CLICK.getId(), getLocalizedLabel());
Kristian Monsen74bc1942014-04-29 11:00:17 -07004092 * node.addAction(action);
4093 * </pre>
4094 *
4095 * @param actionId The id for this action. This should either be one of the
4096 * standard actions or a specific action for your app. In that case it is
4097 * required to use a resource identifier.
4098 * @param label The label for the new AccessibilityAction.
4099 */
4100 public AccessibilityAction(int actionId, @Nullable CharSequence label) {
Svetoslav5c4cd182014-05-21 14:53:16 -07004101 if ((actionId & ACTION_TYPE_MASK) == 0 && Integer.bitCount(actionId) != 1) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07004102 throw new IllegalArgumentException("Invalid standard action id");
4103 }
4104
Kristian Monsen74bc1942014-04-29 11:00:17 -07004105 mActionId = actionId;
4106 mLabel = label;
4107 }
4108
4109 /**
4110 * Gets the id for this action.
4111 *
4112 * @return The action id.
4113 */
4114 public int getId() {
4115 return mActionId;
4116 }
4117
4118 /**
4119 * Gets the label for this action. Its purpose is to describe the
4120 * action to user.
4121 *
4122 * @return The label.
4123 */
4124 public CharSequence getLabel() {
4125 return mLabel;
4126 }
4127
4128 @Override
4129 public int hashCode() {
4130 return mActionId;
4131 }
4132
4133 @Override
4134 public boolean equals(Object other) {
4135 if (other == null) {
4136 return false;
4137 }
4138
4139 if (other == this) {
4140 return true;
4141 }
4142
4143 if (getClass() != other.getClass()) {
4144 return false;
4145 }
4146
4147 return mActionId == ((AccessibilityAction)other).mActionId;
4148 }
4149
4150 @Override
4151 public String toString() {
4152 return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
4153 }
4154 }
4155
4156 /**
Svetoslav3577a282013-06-06 14:09:10 -07004157 * Class with information if a node is a range. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004158 * {@link RangeInfo#obtain(int, float, float, float)} to get an instance. Recycling is
4159 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav3577a282013-06-06 14:09:10 -07004160 */
4161 public static final class RangeInfo {
4162 private static final int MAX_POOL_SIZE = 10;
4163
4164 /** Range type: integer. */
4165 public static final int RANGE_TYPE_INT = 0;
4166 /** Range type: float. */
4167 public static final int RANGE_TYPE_FLOAT = 1;
4168 /** Range type: percent with values from zero to one.*/
4169 public static final int RANGE_TYPE_PERCENT = 2;
4170
4171 private static final SynchronizedPool<RangeInfo> sPool =
4172 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
4173
4174 private int mType;
4175 private float mMin;
4176 private float mMax;
4177 private float mCurrent;
4178
4179 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004180 * Obtains a pooled instance that is a clone of another one.
4181 *
4182 * @param other The instance to clone.
4183 *
4184 * @hide
4185 */
4186 public static RangeInfo obtain(RangeInfo other) {
4187 return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
4188 }
4189
4190 /**
Svetoslav3577a282013-06-06 14:09:10 -07004191 * Obtains a pooled instance.
4192 *
4193 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004194 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4195 * minimum.
4196 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4197 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004198 * @param current The current value.
4199 */
4200 public static RangeInfo obtain(int type, float min, float max, float current) {
4201 RangeInfo info = sPool.acquire();
Steven Dao24142812016-04-13 15:25:09 -07004202 if (info == null) {
4203 return new RangeInfo(type, min, max, current);
4204 }
4205
4206 info.mType = type;
4207 info.mMin = min;
4208 info.mMax = max;
4209 info.mCurrent = current;
4210 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004211 }
4212
4213 /**
4214 * Creates a new range.
4215 *
4216 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004217 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4218 * minimum.
4219 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4220 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004221 * @param current The current value.
4222 */
4223 private RangeInfo(int type, float min, float max, float current) {
4224 mType = type;
4225 mMin = min;
4226 mMax = max;
4227 mCurrent = current;
4228 }
4229
4230 /**
4231 * Gets the range type.
4232 *
4233 * @return The range type.
4234 *
4235 * @see #RANGE_TYPE_INT
4236 * @see #RANGE_TYPE_FLOAT
4237 * @see #RANGE_TYPE_PERCENT
4238 */
4239 public int getType() {
4240 return mType;
4241 }
4242
4243 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004244 * Gets the minimum value.
Svetoslav3577a282013-06-06 14:09:10 -07004245 *
Phil Weaver79e44192016-12-19 14:24:49 -08004246 * @return The minimum value, or {@code Float.NEGATIVE_INFINITY} if no minimum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004247 */
4248 public float getMin() {
4249 return mMin;
4250 }
4251
4252 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004253 * Gets the maximum value.
Svetoslav3577a282013-06-06 14:09:10 -07004254 *
Phil Weaver79e44192016-12-19 14:24:49 -08004255 * @return The maximum value, or {@code Float.POSITIVE_INFINITY} if no maximum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004256 */
4257 public float getMax() {
4258 return mMax;
4259 }
4260
4261 /**
4262 * Gets the current value.
4263 *
4264 * @return The current value.
4265 */
4266 public float getCurrent() {
4267 return mCurrent;
4268 }
4269
4270 /**
4271 * Recycles this instance.
4272 */
4273 void recycle() {
4274 clear();
4275 sPool.release(this);
4276 }
4277
4278 private void clear() {
4279 mType = 0;
4280 mMin = 0;
4281 mMax = 0;
4282 mCurrent = 0;
4283 }
4284 }
4285
4286 /**
4287 * Class with information if a node is a collection. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004288 * {@link CollectionInfo#obtain(int, int, boolean)} to get an instance. Recycling is
4289 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004290 * <p>
4291 * A collection of items has rows and columns and may be hierarchical.
4292 * For example, a horizontal list is a collection with one column, as
4293 * many rows as the list items, and is not hierarchical; A table is a
4294 * collection with several rows, several columns, and is not hierarchical;
4295 * A vertical tree is a hierarchical collection with one column and
4296 * as many rows as the first level children.
4297 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004298 */
4299 public static final class CollectionInfo {
Alan Viverette76769ae2014-02-12 16:38:10 -08004300 /** Selection mode where items are not selectable. */
4301 public static final int SELECTION_MODE_NONE = 0;
4302
4303 /** Selection mode where a single item may be selected. */
4304 public static final int SELECTION_MODE_SINGLE = 1;
4305
4306 /** Selection mode where multiple items may be selected. */
4307 public static final int SELECTION_MODE_MULTIPLE = 2;
4308
Svetoslav3577a282013-06-06 14:09:10 -07004309 private static final int MAX_POOL_SIZE = 20;
4310
4311 private static final SynchronizedPool<CollectionInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004312 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004313
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004314 private int mRowCount;
4315 private int mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004316 private boolean mHierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004317 private int mSelectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004318
4319 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004320 * Obtains a pooled instance that is a clone of another one.
4321 *
4322 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004323 * @hide
4324 */
4325 public static CollectionInfo obtain(CollectionInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004326 return CollectionInfo.obtain(other.mRowCount, other.mColumnCount, other.mHierarchical,
4327 other.mSelectionMode);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004328 }
4329
4330 /**
Svetoslav3577a282013-06-06 14:09:10 -07004331 * Obtains a pooled instance.
4332 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004333 * @param rowCount The number of rows.
4334 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004335 * @param hierarchical Whether the collection is hierarchical.
4336 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004337 public static CollectionInfo obtain(int rowCount, int columnCount,
4338 boolean hierarchical) {
4339 return obtain(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE);
4340 }
4341
4342 /**
4343 * Obtains a pooled instance.
4344 *
4345 * @param rowCount The number of rows.
4346 * @param columnCount The number of columns.
4347 * @param hierarchical Whether the collection is hierarchical.
4348 * @param selectionMode The collection's selection mode, one of:
4349 * <ul>
4350 * <li>{@link #SELECTION_MODE_NONE}
4351 * <li>{@link #SELECTION_MODE_SINGLE}
4352 * <li>{@link #SELECTION_MODE_MULTIPLE}
4353 * </ul>
4354 */
4355 public static CollectionInfo obtain(int rowCount, int columnCount,
4356 boolean hierarchical, int selectionMode) {
4357 final CollectionInfo info = sPool.acquire();
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004358 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004359 return new CollectionInfo(rowCount, columnCount, hierarchical, selectionMode);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004360 }
4361
4362 info.mRowCount = rowCount;
4363 info.mColumnCount = columnCount;
4364 info.mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004365 info.mSelectionMode = selectionMode;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004366 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004367 }
4368
4369 /**
4370 * Creates a new instance.
4371 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004372 * @param rowCount The number of rows.
4373 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004374 * @param hierarchical Whether the collection is hierarchical.
Alan Viverette76769ae2014-02-12 16:38:10 -08004375 * @param selectionMode The collection's selection mode.
Svetoslav3577a282013-06-06 14:09:10 -07004376 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004377 private CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
4378 int selectionMode) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004379 mRowCount = rowCount;
4380 mColumnCount = columnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004381 mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004382 mSelectionMode = selectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004383 }
4384
4385 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004386 * Gets the number of rows.
Svetoslav3577a282013-06-06 14:09:10 -07004387 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004388 * @return The row count.
Svetoslav3577a282013-06-06 14:09:10 -07004389 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004390 public int getRowCount() {
4391 return mRowCount;
Svetoslav3577a282013-06-06 14:09:10 -07004392 }
4393
4394 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004395 * Gets the number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004396 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004397 * @return The column count.
Svetoslav3577a282013-06-06 14:09:10 -07004398 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004399 public int getColumnCount() {
4400 return mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004401 }
4402
4403 /**
4404 * Gets if the collection is a hierarchically ordered.
4405 *
4406 * @return Whether the collection is hierarchical.
4407 */
4408 public boolean isHierarchical() {
4409 return mHierarchical;
4410 }
4411
4412 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004413 * Gets the collection's selection mode.
4414 *
4415 * @return The collection's selection mode, one of:
4416 * <ul>
4417 * <li>{@link #SELECTION_MODE_NONE}
4418 * <li>{@link #SELECTION_MODE_SINGLE}
4419 * <li>{@link #SELECTION_MODE_MULTIPLE}
4420 * </ul>
4421 */
4422 public int getSelectionMode() {
4423 return mSelectionMode;
4424 }
4425
4426 /**
Svetoslav3577a282013-06-06 14:09:10 -07004427 * Recycles this instance.
4428 */
4429 void recycle() {
4430 clear();
4431 sPool.release(this);
4432 }
4433
4434 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004435 mRowCount = 0;
4436 mColumnCount = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004437 mHierarchical = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004438 mSelectionMode = SELECTION_MODE_NONE;
Svetoslav3577a282013-06-06 14:09:10 -07004439 }
4440 }
4441
4442 /**
4443 * Class with information if a node is a collection item. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004444 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean)}
Phil Weaver764152b2016-07-19 11:32:27 -07004445 * to get an instance. Recycling is handled by the {@link AccessibilityNodeInfo} to which this
4446 * object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004447 * <p>
4448 * A collection item is contained in a collection, it starts at
4449 * a given row and column in the collection, and spans one or
4450 * more rows and columns. For example, a header of two related
4451 * table columns starts at the first row and the first column,
4452 * spans one row and two columns.
4453 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004454 */
4455 public static final class CollectionItemInfo {
4456 private static final int MAX_POOL_SIZE = 20;
4457
4458 private static final SynchronizedPool<CollectionItemInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004459 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004460
4461 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004462 * Obtains a pooled instance that is a clone of another one.
4463 *
4464 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004465 * @hide
4466 */
4467 public static CollectionItemInfo obtain(CollectionItemInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004468 return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan, other.mColumnIndex,
4469 other.mColumnSpan, other.mHeading, other.mSelected);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004470 }
4471
4472 /**
Svetoslav3577a282013-06-06 14:09:10 -07004473 * Obtains a pooled instance.
4474 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004475 * @param rowIndex The row index at which the item is located.
4476 * @param rowSpan The number of rows the item spans.
4477 * @param columnIndex The column index at which the item is located.
4478 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004479 * @param heading Whether the item is a heading.
4480 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004481 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4482 int columnIndex, int columnSpan, boolean heading) {
4483 return obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading, false);
4484 }
4485
4486 /**
4487 * Obtains a pooled instance.
4488 *
4489 * @param rowIndex The row index at which the item is located.
4490 * @param rowSpan The number of rows the item spans.
4491 * @param columnIndex The column index at which the item is located.
4492 * @param columnSpan The number of columns the item spans.
4493 * @param heading Whether the item is a heading.
4494 * @param selected Whether the item is selected.
4495 */
4496 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4497 int columnIndex, int columnSpan, boolean heading, boolean selected) {
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004498 final CollectionItemInfo info = sPool.acquire();
4499 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004500 return new CollectionItemInfo(
4501 rowIndex, rowSpan, columnIndex, columnSpan, heading, selected);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004502 }
4503
4504 info.mRowIndex = rowIndex;
4505 info.mRowSpan = rowSpan;
4506 info.mColumnIndex = columnIndex;
4507 info.mColumnSpan = columnSpan;
4508 info.mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004509 info.mSelected = selected;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004510 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004511 }
4512
4513 private boolean mHeading;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004514 private int mColumnIndex;
4515 private int mRowIndex;
4516 private int mColumnSpan;
4517 private int mRowSpan;
Alan Viverette76769ae2014-02-12 16:38:10 -08004518 private boolean mSelected;
Svetoslav3577a282013-06-06 14:09:10 -07004519
4520 /**
4521 * Creates a new instance.
4522 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004523 * @param rowIndex The row index at which the item is located.
4524 * @param rowSpan The number of rows the item spans.
4525 * @param columnIndex The column index at which the item is located.
4526 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004527 * @param heading Whether the item is a heading.
4528 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004529 private CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
4530 boolean heading, boolean selected) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004531 mRowIndex = rowIndex;
4532 mRowSpan = rowSpan;
4533 mColumnIndex = columnIndex;
4534 mColumnSpan = columnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004535 mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004536 mSelected = selected;
Svetoslav3577a282013-06-06 14:09:10 -07004537 }
4538
4539 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004540 * Gets the column index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004541 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004542 * @return The column index.
Svetoslav3577a282013-06-06 14:09:10 -07004543 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004544 public int getColumnIndex() {
4545 return mColumnIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004546 }
4547
4548 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004549 * Gets the row index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004550 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004551 * @return The row index.
Svetoslav3577a282013-06-06 14:09:10 -07004552 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004553 public int getRowIndex() {
4554 return mRowIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004555 }
4556
4557 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004558 * Gets the number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004559 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004560 * @return The column span.
Svetoslav3577a282013-06-06 14:09:10 -07004561 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004562 public int getColumnSpan() {
4563 return mColumnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004564 }
4565
4566 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004567 * Gets the number of rows the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004568 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004569 * @return The row span.
Svetoslav3577a282013-06-06 14:09:10 -07004570 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004571 public int getRowSpan() {
4572 return mRowSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004573 }
4574
4575 /**
4576 * Gets if the collection item is a heading. For example, section
4577 * heading, table header, etc.
4578 *
4579 * @return If the item is a heading.
4580 */
4581 public boolean isHeading() {
4582 return mHeading;
4583 }
4584
4585 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004586 * Gets if the collection item is selected.
4587 *
4588 * @return If the item is selected.
4589 */
4590 public boolean isSelected() {
4591 return mSelected;
4592 }
4593
4594 /**
Svetoslav3577a282013-06-06 14:09:10 -07004595 * Recycles this instance.
4596 */
4597 void recycle() {
4598 clear();
4599 sPool.release(this);
4600 }
4601
4602 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004603 mColumnIndex = 0;
4604 mColumnSpan = 0;
4605 mRowIndex = 0;
4606 mRowSpan = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004607 mHeading = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004608 mSelected = false;
Svetoslav3577a282013-06-06 14:09:10 -07004609 }
4610 }
4611
4612 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08004613 * @see android.os.Parcelable.Creator
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004614 */
4615 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
4616 new Parcelable.Creator<AccessibilityNodeInfo>() {
Alan Viverettef0aed092013-11-06 15:33:03 -08004617 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004618 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
4619 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
4620 info.initFromParcel(parcel);
4621 return info;
4622 }
4623
Alan Viverettef0aed092013-11-06 15:33:03 -08004624 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004625 public AccessibilityNodeInfo[] newArray(int size) {
4626 return new AccessibilityNodeInfo[size];
4627 }
4628 };
4629}