blob: 02b6185032505a94de6673b2bca63dbab0c1d189 [file] [log] [blame]
Svetoslav Ganov736c2752011-04-22 18:30:36 -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 Weaver651fe9f2017-05-24 16:43:46 -070019import android.annotation.Nullable;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070020import android.os.Parcelable;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070021import android.view.View;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070022
23import java.util.ArrayList;
24import java.util.List;
25
26/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070027 * Represents a record in an {@link AccessibilityEvent} and contains information
28 * about state change of its source {@link android.view.View}. When a view fires
29 * an accessibility event it requests from its parent to dispatch the
30 * constructed event. The parent may optionally append a record for itself
31 * for providing more context to
32 * {@link android.accessibilityservice.AccessibilityService}s. Hence,
33 * accessibility services can facilitate additional accessibility records
34 * to enhance feedback.
35 * </p>
36 * <p>
37 * Once the accessibility event containing a record is dispatched the record is
38 * made immutable and calling a state mutation method generates an error.
39 * </p>
40 * <p>
41 * <strong>Note:</strong> Not all properties are applicable to all accessibility
42 * event types. For detailed information please refer to {@link AccessibilityEvent}.
43 * </p>
Svetoslav Ganov736c2752011-04-22 18:30:36 -070044 *
Joe Fernandeze1302ed2012-02-06 14:30:15 -080045 * <div class="special reference">
46 * <h3>Developer Guides</h3>
47 * <p>For more information about creating and processing AccessibilityRecords, read the
48 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
49 * developer guide.</p>
50 * </div>
51 *
Svetoslav Ganov736c2752011-04-22 18:30:36 -070052 * @see AccessibilityEvent
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070053 * @see AccessibilityManager
54 * @see android.accessibilityservice.AccessibilityService
55 * @see AccessibilityNodeInfo
Svetoslav Ganov736c2752011-04-22 18:30:36 -070056 */
57public class AccessibilityRecord {
58
Svetoslav Ganov47b779b2011-07-17 11:07:53 -070059 private static final int UNDEFINED = -1;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070060
61 private static final int PROPERTY_CHECKED = 0x00000001;
62 private static final int PROPERTY_ENABLED = 0x00000002;
63 private static final int PROPERTY_PASSWORD = 0x00000004;
64 private static final int PROPERTY_FULL_SCREEN = 0x00000080;
Svetoslav Ganova0156172011-06-26 17:55:44 -070065 private static final int PROPERTY_SCROLLABLE = 0x00000100;
Svetoslav Ganov42138042012-03-20 11:51:39 -070066 private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070067
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -080068 private static final int GET_SOURCE_PREFETCH_FLAGS =
69 AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS
70 | AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
71 | AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS;
72
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070073 // Housekeeping
Svetoslav Ganov736c2752011-04-22 18:30:36 -070074 private static final int MAX_POOL_SIZE = 10;
Svetoslav Ganov887e1a12011-04-29 15:09:28 -070075 private static final Object sPoolLock = new Object();
Svetoslav Ganov736c2752011-04-22 18:30:36 -070076 private static AccessibilityRecord sPool;
77 private static int sPoolSize;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070078 private AccessibilityRecord mNext;
79 private boolean mIsInPool;
80
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070081 boolean mSealed;
Svetoslav8e3feb12014-02-24 13:46:47 -080082 int mBooleanProperties = 0;
Svetoslav Ganov47b779b2011-07-17 11:07:53 -070083 int mCurrentItemIndex = UNDEFINED;
84 int mItemCount = UNDEFINED;
85 int mFromIndex = UNDEFINED;
86 int mToIndex = UNDEFINED;
87 int mScrollX = UNDEFINED;
88 int mScrollY = UNDEFINED;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -070089 int mMaxScrollX = UNDEFINED;
90 int mMaxScrollY = UNDEFINED;
Svetoslav Ganova0156172011-06-26 17:55:44 -070091
Svetoslav Ganov47b779b2011-07-17 11:07:53 -070092 int mAddedCount= UNDEFINED;
93 int mRemovedCount = UNDEFINED;
Phil Weaver651fe9f2017-05-24 16:43:46 -070094 long mSourceNodeId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
Phil Weaverf00cd142017-03-03 13:44:00 -080095 int mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070096
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070097 CharSequence mClassName;
98 CharSequence mContentDescription;
99 CharSequence mBeforeText;
100 Parcelable mParcelableData;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700101
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700102 final List<CharSequence> mText = new ArrayList<CharSequence>();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800103
104 int mConnectionId = UNDEFINED;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700105
106 /*
107 * Hide constructor.
108 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700109 AccessibilityRecord() {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700110 }
111
112 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700113 * Sets the event source.
114 *
115 * @param source The source.
116 *
117 * @throws IllegalStateException If called from an AccessibilityService.
118 */
119 public void setSource(View source) {
Phil Weaverb37bfe92017-05-30 16:23:10 -0700120 setSource(source, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700121 }
122
123 /**
124 * Sets the source to be a virtual descendant of the given <code>root</code>.
125 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
126 * is set as the source.
127 * <p>
128 * A virtual descendant is an imaginary View that is reported as a part of the view
129 * hierarchy for accessibility purposes. This enables custom views that draw complex
130 * content to report them selves as a tree of virtual views, thus conveying their
131 * logical structure.
132 * </p>
133 *
134 * @param root The root of the virtual subtree.
135 * @param virtualDescendantId The id of the virtual descendant.
136 */
Phil Weaver651fe9f2017-05-24 16:43:46 -0700137 public void setSource(@Nullable View root, int virtualDescendantId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700138 enforceNotSealed();
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -0700139 boolean important = true;
Phil Weaver651fe9f2017-05-24 16:43:46 -0700140 int rootViewId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
Phil Weaverf00cd142017-03-03 13:44:00 -0800141 mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -0700142 if (root != null) {
Phil Weaver651fe9f2017-05-24 16:43:46 -0700143 important = root.isImportantForAccessibility();
144 rootViewId = root.getAccessibilityViewId();
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -0700145 mSourceWindowId = root.getAccessibilityWindowId();
Svetoslav Ganov52a62372012-05-02 14:19:37 -0700146 }
Svetoslav Ganov42138042012-03-20 11:51:39 -0700147 setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
Phil Weaver651fe9f2017-05-24 16:43:46 -0700148 mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700149 }
150
151 /**
Phil Weaver651fe9f2017-05-24 16:43:46 -0700152 * Set the source node ID directly
Phil Weaverf00cd142017-03-03 13:44:00 -0800153 *
Phil Weaver651fe9f2017-05-24 16:43:46 -0700154 * @param sourceNodeId The source node Id
Phil Weaverf00cd142017-03-03 13:44:00 -0800155 * @hide
156 */
Phil Weaver651fe9f2017-05-24 16:43:46 -0700157 public void setSourceNodeId(long sourceNodeId) {
158 mSourceNodeId = sourceNodeId;
Phil Weaverf00cd142017-03-03 13:44:00 -0800159 }
160
161 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700162 * Gets the {@link AccessibilityNodeInfo} of the event source.
163 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700164 * <strong>Note:</strong> It is a client responsibility to recycle the received info
165 * by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
166 * to avoid creating of multiple instances.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700167 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700168 * @return The info of the source.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700169 */
170 public AccessibilityNodeInfo getSource() {
171 enforceSealed();
Phil Weaver651fe9f2017-05-24 16:43:46 -0700172 if ((mConnectionId == UNDEFINED)
173 || (mSourceWindowId == AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
174 || (AccessibilityNodeInfo.getAccessibilityViewId(mSourceNodeId)
175 == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)) {
176 return null;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700177 }
Phil Weaver651fe9f2017-05-24 16:43:46 -0700178 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
179 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
180 mSourceNodeId, false, GET_SOURCE_PREFETCH_FLAGS, null);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700181 }
182
183 /**
Svetoslav Ganovfc9c4cd2012-11-02 11:49:22 -0700184 * Sets the window id.
185 *
186 * @param windowId The window id.
187 *
188 * @hide
189 */
190 public void setWindowId(int windowId) {
191 mSourceWindowId = windowId;
192 }
193
194 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700195 * Gets the id of the window from which the event comes from.
196 *
197 * @return The window id.
198 */
199 public int getWindowId() {
200 return mSourceWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700201 }
202
203 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700204 * Gets if the source is checked.
205 *
206 * @return True if the view is checked, false otherwise.
207 */
208 public boolean isChecked() {
209 return getBooleanProperty(PROPERTY_CHECKED);
210 }
211
212 /**
213 * Sets if the source is checked.
214 *
215 * @param isChecked True if the view is checked, false otherwise.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700216 *
217 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700218 */
219 public void setChecked(boolean isChecked) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700220 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700221 setBooleanProperty(PROPERTY_CHECKED, isChecked);
222 }
223
224 /**
225 * Gets if the source is enabled.
226 *
227 * @return True if the view is enabled, false otherwise.
228 */
229 public boolean isEnabled() {
230 return getBooleanProperty(PROPERTY_ENABLED);
231 }
232
233 /**
234 * Sets if the source is enabled.
235 *
236 * @param isEnabled True if the view is enabled, false otherwise.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700237 *
238 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700239 */
240 public void setEnabled(boolean isEnabled) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700241 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700242 setBooleanProperty(PROPERTY_ENABLED, isEnabled);
243 }
244
245 /**
246 * Gets if the source is a password field.
247 *
248 * @return True if the view is a password field, false otherwise.
249 */
250 public boolean isPassword() {
251 return getBooleanProperty(PROPERTY_PASSWORD);
252 }
253
254 /**
255 * Sets if the source is a password field.
256 *
257 * @param isPassword True if the view is a password field, false otherwise.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700258 *
259 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700260 */
261 public void setPassword(boolean isPassword) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700262 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700263 setBooleanProperty(PROPERTY_PASSWORD, isPassword);
264 }
265
266 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700267 * Gets if the source is taking the entire screen.
268 *
269 * @return True if the source is full screen, false otherwise.
270 */
271 public boolean isFullScreen() {
272 return getBooleanProperty(PROPERTY_FULL_SCREEN);
273 }
274
275 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700276 * Sets if the source is taking the entire screen.
277 *
278 * @param isFullScreen True if the source is full screen, false otherwise.
279 *
280 * @throws IllegalStateException If called from an AccessibilityService.
281 */
282 public void setFullScreen(boolean isFullScreen) {
283 enforceNotSealed();
284 setBooleanProperty(PROPERTY_FULL_SCREEN, isFullScreen);
285 }
286
287 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700288 * Gets if the source is scrollable.
289 *
290 * @return True if the source is scrollable, false otherwise.
291 */
292 public boolean isScrollable() {
293 return getBooleanProperty(PROPERTY_SCROLLABLE);
294 }
295
296 /**
297 * Sets if the source is scrollable.
298 *
299 * @param scrollable True if the source is scrollable, false otherwise.
300 *
301 * @throws IllegalStateException If called from an AccessibilityService.
302 */
303 public void setScrollable(boolean scrollable) {
304 enforceNotSealed();
305 setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
306 }
307
308 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700309 * Gets if the source is important for accessibility.
310 *
311 * <strong>Note:</strong> Used only internally to determine whether
312 * to deliver the event to a given accessibility service since some
313 * services may want to regard all views for accessibility while others
314 * may want to regard only the important views for accessibility.
315 *
316 * @return True if the source is important for accessibility,
317 * false otherwise.
318 *
319 * @hide
320 */
321 public boolean isImportantForAccessibility() {
322 return getBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY);
323 }
324
325 /**
Phil Weaver0a8caa12017-08-09 11:28:41 -0700326 * Sets if the source is important for accessibility.
327 *
328 * @param importantForAccessibility True if the source is important for accessibility,
329 * false otherwise.
330 *
331 * @throws IllegalStateException If called from an AccessibilityService.
332 * @hide
333 */
334 public void setImportantForAccessibility(boolean importantForAccessibility) {
335 enforceNotSealed();
336 setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, importantForAccessibility);
337 }
338
339 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700340 * Gets the number of items that can be visited.
341 *
342 * @return The number of items.
343 */
344 public int getItemCount() {
345 return mItemCount;
346 }
347
348 /**
349 * Sets the number of items that can be visited.
350 *
351 * @param itemCount The number of items.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700352 *
353 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700354 */
355 public void setItemCount(int itemCount) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700356 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700357 mItemCount = itemCount;
358 }
359
360 /**
361 * Gets the index of the source in the list of items the can be visited.
362 *
363 * @return The current item index.
364 */
365 public int getCurrentItemIndex() {
366 return mCurrentItemIndex;
367 }
368
369 /**
370 * Sets the index of the source in the list of items that can be visited.
371 *
372 * @param currentItemIndex The current item index.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700373 *
374 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700375 */
376 public void setCurrentItemIndex(int currentItemIndex) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700377 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700378 mCurrentItemIndex = currentItemIndex;
379 }
380
381 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700382 * Gets the index of the first character of the changed sequence,
383 * or the beginning of a text selection or the index of the first
384 * visible item when scrolling.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700385 *
Svetoslav Ganova0156172011-06-26 17:55:44 -0700386 * @return The index of the first character or selection
387 * start or the first visible item.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700388 */
389 public int getFromIndex() {
390 return mFromIndex;
391 }
392
393 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700394 * Sets the index of the first character of the changed sequence
395 * or the beginning of a text selection or the index of the first
396 * visible item when scrolling.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700397 *
Svetoslav Ganova0156172011-06-26 17:55:44 -0700398 * @param fromIndex The index of the first character or selection
399 * start or the first visible item.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700400 *
401 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700402 */
403 public void setFromIndex(int fromIndex) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700404 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700405 mFromIndex = fromIndex;
406 }
407
408 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700409 * Gets the index of text selection end or the index of the last
410 * visible item when scrolling.
411 *
412 * @return The index of selection end or last item index.
413 */
414 public int getToIndex() {
415 return mToIndex;
416 }
417
418 /**
419 * Sets the index of text selection end or the index of the last
420 * visible item when scrolling.
421 *
422 * @param toIndex The index of selection end or last item index.
423 */
424 public void setToIndex(int toIndex) {
425 enforceNotSealed();
426 mToIndex = toIndex;
427 }
428
429 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700430 * Gets the scroll offset of the source left edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700431 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700432 * @return The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700433 */
434 public int getScrollX() {
435 return mScrollX;
436 }
437
438 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700439 * Sets the scroll offset of the source left edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700440 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700441 * @param scrollX The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700442 */
443 public void setScrollX(int scrollX) {
444 enforceNotSealed();
445 mScrollX = scrollX;
446 }
447
448 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700449 * Gets the scroll offset of the source top edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700450 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700451 * @return The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700452 */
453 public int getScrollY() {
454 return mScrollY;
455 }
456
457 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700458 * Sets the scroll offset of the source top edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700459 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700460 * @param scrollY The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700461 */
462 public void setScrollY(int scrollY) {
463 enforceNotSealed();
464 mScrollY = scrollY;
465 }
466
467 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700468 * Gets the max scroll offset of the source left edge in pixels.
469 *
470 * @return The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700471 */
472 public int getMaxScrollX() {
473 return mMaxScrollX;
474 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700475
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700476 /**
477 * Sets the max scroll offset of the source left edge in pixels.
478 *
479 * @param maxScrollX The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700480 */
481 public void setMaxScrollX(int maxScrollX) {
482 enforceNotSealed();
483 mMaxScrollX = maxScrollX;
484 }
485
486 /**
487 * Gets the max scroll offset of the source top edge in pixels.
488 *
489 * @return The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700490 */
491 public int getMaxScrollY() {
492 return mMaxScrollY;
493 }
494
495 /**
496 * Sets the max scroll offset of the source top edge in pixels.
497 *
498 * @param maxScrollY The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700499 */
500 public void setMaxScrollY(int maxScrollY) {
501 enforceNotSealed();
502 mMaxScrollY = maxScrollY;
503 }
504
505 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700506 * Gets the number of added characters.
507 *
508 * @return The number of added characters.
509 */
510 public int getAddedCount() {
511 return mAddedCount;
512 }
513
514 /**
515 * Sets the number of added characters.
516 *
517 * @param addedCount The number of added characters.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700518 *
519 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700520 */
521 public void setAddedCount(int addedCount) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700522 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700523 mAddedCount = addedCount;
524 }
525
526 /**
527 * Gets the number of removed characters.
528 *
529 * @return The number of removed characters.
530 */
531 public int getRemovedCount() {
532 return mRemovedCount;
533 }
534
535 /**
536 * Sets the number of removed characters.
537 *
538 * @param removedCount The number of removed characters.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700539 *
540 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700541 */
542 public void setRemovedCount(int removedCount) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700543 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700544 mRemovedCount = removedCount;
545 }
546
547 /**
548 * Gets the class name of the source.
549 *
550 * @return The class name.
551 */
552 public CharSequence getClassName() {
553 return mClassName;
554 }
555
556 /**
557 * Sets the class name of the source.
558 *
559 * @param className The lass name.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700560 *
561 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700562 */
563 public void setClassName(CharSequence className) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700564 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700565 mClassName = className;
566 }
567
568 /**
569 * Gets the text of the event. The index in the list represents the priority
570 * of the text. Specifically, the lower the index the higher the priority.
571 *
572 * @return The text.
573 */
574 public List<CharSequence> getText() {
575 return mText;
576 }
577
578 /**
579 * Sets the text before a change.
580 *
581 * @return The text before the change.
582 */
583 public CharSequence getBeforeText() {
584 return mBeforeText;
585 }
586
587 /**
588 * Sets the text before a change.
589 *
590 * @param beforeText The text before the change.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700591 *
592 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700593 */
594 public void setBeforeText(CharSequence beforeText) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700595 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -0700596 mBeforeText = (beforeText == null) ? null
597 : beforeText.subSequence(0, beforeText.length());
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700598 }
599
600 /**
601 * Gets the description of the source.
602 *
603 * @return The description.
604 */
605 public CharSequence getContentDescription() {
606 return mContentDescription;
607 }
608
609 /**
610 * Sets the description of the source.
611 *
612 * @param contentDescription The description.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700613 *
614 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700615 */
616 public void setContentDescription(CharSequence contentDescription) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700617 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -0700618 mContentDescription = (contentDescription == null) ? null
619 : contentDescription.subSequence(0, contentDescription.length());
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700620 }
621
622 /**
623 * Gets the {@link Parcelable} data.
624 *
625 * @return The parcelable data.
626 */
627 public Parcelable getParcelableData() {
628 return mParcelableData;
629 }
630
631 /**
632 * Sets the {@link Parcelable} data of the event.
633 *
634 * @param parcelableData The parcelable data.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700635 *
636 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700637 */
638 public void setParcelableData(Parcelable parcelableData) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700639 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700640 mParcelableData = parcelableData;
641 }
642
643 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800644 * Gets the id of the source node.
645 *
646 * @return The id.
647 *
648 * @hide
649 */
650 public long getSourceNodeId() {
Phil Weaver651fe9f2017-05-24 16:43:46 -0700651 return mSourceNodeId;
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800652 }
653
654 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800655 * Sets the unique id of the IAccessibilityServiceConnection over which
656 * this instance can send requests to the system.
657 *
658 * @param connectionId The connection id.
659 *
660 * @hide
661 */
662 public void setConnectionId(int connectionId) {
663 enforceNotSealed();
664 mConnectionId = connectionId;
665 }
666
667 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700668 * Sets if this instance is sealed.
669 *
670 * @param sealed Whether is sealed.
671 *
672 * @hide
673 */
674 public void setSealed(boolean sealed) {
675 mSealed = sealed;
676 }
677
678 /**
679 * Gets if this instance is sealed.
680 *
681 * @return Whether is sealed.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700682 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700683 boolean isSealed() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700684 return mSealed;
685 }
686
687 /**
688 * Enforces that this instance is sealed.
689 *
690 * @throws IllegalStateException If this instance is not sealed.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700691 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700692 void enforceSealed() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700693 if (!isSealed()) {
694 throw new IllegalStateException("Cannot perform this "
695 + "action on a not sealed instance.");
696 }
697 }
698
699 /**
700 * Enforces that this instance is not sealed.
701 *
702 * @throws IllegalStateException If this instance is sealed.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700703 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700704 void enforceNotSealed() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700705 if (isSealed()) {
706 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +0900707 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700708 }
709 }
710
711 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700712 * Gets the value of a boolean property.
713 *
714 * @param property The property.
715 * @return The value.
716 */
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700717 private boolean getBooleanProperty(int property) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700718 return (mBooleanProperties & property) == property;
719 }
720
721 /**
722 * Sets a boolean property.
723 *
724 * @param property The property.
725 * @param value The value.
726 */
727 private void setBooleanProperty(int property, boolean value) {
728 if (value) {
729 mBooleanProperties |= property;
730 } else {
731 mBooleanProperties &= ~property;
732 }
733 }
734
735 /**
736 * Returns a cached instance if such is available or a new one is
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700737 * instantiated. The instance is initialized with data from the
738 * given record.
739 *
740 * @return An instance.
741 */
742 public static AccessibilityRecord obtain(AccessibilityRecord record) {
743 AccessibilityRecord clone = AccessibilityRecord.obtain();
744 clone.init(record);
745 return clone;
746 }
747
748 /**
749 * Returns a cached instance if such is available or a new one is
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700750 * instantiated.
751 *
752 * @return An instance.
753 */
Svetoslav Ganovd36a6992011-05-18 20:50:03 -0700754 public static AccessibilityRecord obtain() {
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700755 synchronized (sPoolLock) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700756 if (sPool != null) {
757 AccessibilityRecord record = sPool;
758 sPool = sPool.mNext;
759 sPoolSize--;
760 record.mNext = null;
761 record.mIsInPool = false;
762 return record;
763 }
764 return new AccessibilityRecord();
765 }
766 }
767
768 /**
769 * Return an instance back to be reused.
770 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700771 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700772 *
773 * @throws IllegalStateException If the record is already recycled.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700774 */
775 public void recycle() {
776 if (mIsInPool) {
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700777 throw new IllegalStateException("Record already recycled!");
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700778 }
779 clear();
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700780 synchronized (sPoolLock) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700781 if (sPoolSize <= MAX_POOL_SIZE) {
782 mNext = sPool;
783 sPool = this;
784 mIsInPool = true;
785 sPoolSize++;
786 }
787 }
788 }
789
790 /**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700791 * Initialize this record from another one.
792 *
793 * @param record The to initialize from.
794 */
795 void init(AccessibilityRecord record) {
796 mSealed = record.mSealed;
797 mBooleanProperties = record.mBooleanProperties;
798 mCurrentItemIndex = record.mCurrentItemIndex;
799 mItemCount = record.mItemCount;
800 mFromIndex = record.mFromIndex;
801 mToIndex = record.mToIndex;
802 mScrollX = record.mScrollX;
803 mScrollY = record.mScrollY;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700804 mMaxScrollX = record.mMaxScrollX;
805 mMaxScrollY = record.mMaxScrollY;
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700806 mAddedCount = record.mAddedCount;
807 mRemovedCount = record.mRemovedCount;
808 mClassName = record.mClassName;
809 mContentDescription = record.mContentDescription;
810 mBeforeText = record.mBeforeText;
811 mParcelableData = record.mParcelableData;
812 mText.addAll(record.mText);
813 mSourceWindowId = record.mSourceWindowId;
Phil Weaver651fe9f2017-05-24 16:43:46 -0700814 mSourceNodeId = record.mSourceNodeId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800815 mConnectionId = record.mConnectionId;
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700816 }
817
818 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700819 * Clears the state of this instance.
820 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700821 void clear() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700822 mSealed = false;
Svetoslav8e3feb12014-02-24 13:46:47 -0800823 mBooleanProperties = 0;
Svetoslav Ganov47b779b2011-07-17 11:07:53 -0700824 mCurrentItemIndex = UNDEFINED;
825 mItemCount = UNDEFINED;
826 mFromIndex = UNDEFINED;
827 mToIndex = UNDEFINED;
828 mScrollX = UNDEFINED;
829 mScrollY = UNDEFINED;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700830 mMaxScrollX = UNDEFINED;
831 mMaxScrollY = UNDEFINED;
Svetoslav Ganov47b779b2011-07-17 11:07:53 -0700832 mAddedCount = UNDEFINED;
833 mRemovedCount = UNDEFINED;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700834 mClassName = null;
835 mContentDescription = null;
836 mBeforeText = null;
837 mParcelableData = null;
838 mText.clear();
Phil Weaver651fe9f2017-05-24 16:43:46 -0700839 mSourceNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
840 mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800841 mConnectionId = UNDEFINED;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700842 }
843
844 @Override
845 public String toString() {
846 StringBuilder builder = new StringBuilder();
847 builder.append(" [ ClassName: " + mClassName);
848 builder.append("; Text: " + mText);
849 builder.append("; ContentDescription: " + mContentDescription);
850 builder.append("; ItemCount: " + mItemCount);
851 builder.append("; CurrentItemIndex: " + mCurrentItemIndex);
852 builder.append("; IsEnabled: " + getBooleanProperty(PROPERTY_ENABLED));
853 builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
854 builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
855 builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
Svetoslav Ganova0156172011-06-26 17:55:44 -0700856 builder.append("; Scrollable: " + getBooleanProperty(PROPERTY_SCROLLABLE));
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700857 builder.append("; BeforeText: " + mBeforeText);
858 builder.append("; FromIndex: " + mFromIndex);
Svetoslav Ganova0156172011-06-26 17:55:44 -0700859 builder.append("; ToIndex: " + mToIndex);
860 builder.append("; ScrollX: " + mScrollX);
861 builder.append("; ScrollY: " + mScrollY);
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700862 builder.append("; MaxScrollX: " + mMaxScrollX);
863 builder.append("; MaxScrollY: " + mMaxScrollY);
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700864 builder.append("; AddedCount: " + mAddedCount);
865 builder.append("; RemovedCount: " + mRemovedCount);
866 builder.append("; ParcelableData: " + mParcelableData);
867 builder.append(" ]");
868 return builder.toString();
869 }
870}