AccessibilityNodeInfoCompat.java revision 086e7db1ab6ef49b4b7974c471b70f81b2d13aef
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.view.accessibility;
18
19import android.graphics.Rect;
20import android.os.Build;
21import android.os.Bundle;
22import android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat;
23import android.support.v4.view.ViewCompat;
24import android.view.View;
25import android.view.accessibility.AccessibilityEvent;
26
27import java.util.ArrayList;
28import java.util.Collections;
29import java.util.List;
30
31/**
32 * Helper for accessing {@link android.view.accessibility.AccessibilityNodeInfo}
33 * introduced after API level 4 in a backwards compatible fashion.
34 */
35public class AccessibilityNodeInfoCompat {
36
37    static interface AccessibilityNodeInfoImpl {
38        public Object obtain();
39        public Object obtain(View source);
40        public Object obtain(Object info);
41        public Object obtain(View root, int virtualDescendantId);
42        public void setSource(Object info, View source);
43        public void setSource(Object info, View root, int virtualDescendantId);
44        public Object findFocus(Object info, int focus);
45        public Object focusSearch(Object info, int direction);
46        public int getWindowId(Object info);
47        public int getChildCount(Object info);
48        public Object getChild(Object info, int index);
49        public void addChild(Object info, View child);
50        public void addChild(Object info, View child, int virtualDescendantId);
51        public int getActions(Object info);
52        public void addAction(Object info, int action);
53        public boolean performAction(Object info, int action);
54        public boolean performAction(Object info, int action, Bundle arguments);
55        public void setMovementGranularities(Object info, int granularities);
56        public int getMovementGranularities(Object info);
57        public List<Object> findAccessibilityNodeInfosByText(Object info, String text);
58        public Object getParent(Object info);
59        public void setParent(Object info, View root, int virtualDescendantId);
60        public void setParent(Object info, View parent);
61        public void getBoundsInParent(Object info, Rect outBounds);
62        public void setBoundsInParent(Object info, Rect bounds);
63        public void getBoundsInScreen(Object info, Rect outBounds);
64        public void setBoundsInScreen(Object info, Rect bounds);
65        public boolean isCheckable(Object info);
66        public void setCheckable(Object info, boolean checkable);
67        public boolean isChecked(Object info);
68        public void setChecked(Object info, boolean checked);
69        public boolean isFocusable(Object info);
70        public void setFocusable(Object info, boolean focusable);
71        public boolean isFocused(Object info);
72        public void setFocused(Object info, boolean focused);
73        public boolean isVisibleToUser(Object info);
74        public void setVisibleToUser(Object info, boolean visibleToUser);
75        public boolean isAccessibilityFocused(Object info);
76        public void setAccessibilityFocused(Object info, boolean focused);
77        public boolean isSelected(Object info);
78        public void setSelected(Object info, boolean selected);
79        public boolean isClickable(Object info);
80        public void setClickable(Object info, boolean clickable);
81        public boolean isLongClickable(Object info);
82        public void setLongClickable(Object info, boolean longClickable);
83        public boolean isEnabled(Object info);
84        public void setEnabled(Object info, boolean enabled);
85        public boolean isPassword(Object info);
86        public void setPassword(Object info, boolean password);
87        public boolean isScrollable(Object info);
88        public void setScrollable(Object info, boolean scrollable);
89        public CharSequence getPackageName(Object info);
90        public void setPackageName(Object info, CharSequence packageName);
91        public CharSequence getClassName(Object info);
92        public void setClassName(Object info, CharSequence className);
93        public CharSequence getText(Object info);
94        public void setText(Object info, CharSequence text);
95        public CharSequence getContentDescription(Object info);
96        public void setContentDescription(Object info, CharSequence contentDescription);
97        public void recycle(Object info);
98        public String getViewIdResourceName(Object info);
99        public void setViewIdResourceName(Object info, String viewId);
100        public int getLiveRegion(Object info);
101        public void setLiveRegion(Object info, int mode);
102    }
103
104    static class AccessibilityNodeInfoStubImpl implements AccessibilityNodeInfoImpl {
105        @Override
106        public Object obtain() {
107            return null;
108        }
109
110        @Override
111        public Object obtain(View source) {
112            return null;
113        }
114
115        @Override
116        public Object obtain(View root, int virtualDescendantId) {
117            return null;
118        }
119
120        @Override
121        public Object obtain(Object info) {
122            return null;
123        }
124
125        @Override
126        public void addAction(Object info, int action) {
127
128        }
129
130        @Override
131        public void addChild(Object info, View child) {
132
133        }
134
135        @Override
136        public void addChild(Object info, View child, int virtualDescendantId) {
137
138        }
139
140        @Override
141        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
142            return Collections.emptyList();
143        }
144
145        @Override
146        public int getActions(Object info) {
147            return 0;
148        }
149
150        @Override
151        public void getBoundsInParent(Object info, Rect outBounds) {
152
153        }
154
155        @Override
156        public void getBoundsInScreen(Object info, Rect outBounds) {
157
158        }
159
160        @Override
161        public Object getChild(Object info, int index) {
162            return null;
163        }
164
165        @Override
166        public int getChildCount(Object info) {
167            return 0;
168        }
169
170        @Override
171        public CharSequence getClassName(Object info) {
172            return null;
173        }
174
175        @Override
176        public CharSequence getContentDescription(Object info) {
177            return null;
178        }
179
180        @Override
181        public CharSequence getPackageName(Object info) {
182            return null;
183        }
184
185        @Override
186        public Object getParent(Object info) {
187            return null;
188        }
189
190        @Override
191        public CharSequence getText(Object info) {
192            return null;
193        }
194
195        @Override
196        public int getWindowId(Object info) {
197            return 0;
198        }
199
200        @Override
201        public boolean isCheckable(Object info) {
202            return false;
203        }
204
205        @Override
206        public boolean isChecked(Object info) {
207            return false;
208        }
209
210        @Override
211        public boolean isClickable(Object info) {
212            return false;
213        }
214
215        @Override
216        public boolean isEnabled(Object info) {
217            return false;
218        }
219
220        @Override
221        public boolean isFocusable(Object info) {
222            return false;
223        }
224
225        @Override
226        public boolean isFocused(Object info) {
227            return false;
228        }
229
230        @Override
231        public boolean isVisibleToUser(Object info) {
232            return false;
233        }
234
235        @Override
236        public boolean isAccessibilityFocused(Object info) {
237            return false;
238        }
239
240        @Override
241        public boolean isLongClickable(Object info) {
242            return false;
243        }
244
245        @Override
246        public boolean isPassword(Object info) {
247            return false;
248        }
249
250        @Override
251        public boolean isScrollable(Object info) {
252            return false;
253        }
254
255        @Override
256        public boolean isSelected(Object info) {
257            return false;
258        }
259
260        @Override
261        public boolean performAction(Object info, int action) {
262            return false;
263        }
264
265        @Override
266        public boolean performAction(Object info, int action, Bundle arguments) {
267            return false;
268        }
269
270        @Override
271        public void setMovementGranularities(Object info, int granularities) {
272
273        }
274
275        @Override
276        public int getMovementGranularities(Object info) {
277            return 0;
278        }
279
280        @Override
281        public void setBoundsInParent(Object info, Rect bounds) {
282
283        }
284
285        @Override
286        public void setBoundsInScreen(Object info, Rect bounds) {
287
288        }
289
290        @Override
291        public void setCheckable(Object info, boolean checkable) {
292
293        }
294
295        @Override
296        public void setChecked(Object info, boolean checked) {
297
298        }
299
300        @Override
301        public void setClassName(Object info, CharSequence className) {
302
303        }
304
305        @Override
306        public void setClickable(Object info, boolean clickable) {
307
308        }
309
310        @Override
311        public void setContentDescription(Object info, CharSequence contentDescription) {
312
313        }
314
315        @Override
316        public void setEnabled(Object info, boolean enabled) {
317
318        }
319
320        @Override
321        public void setFocusable(Object info, boolean focusable) {
322
323        }
324
325        @Override
326        public void setFocused(Object info, boolean focused) {
327
328        }
329
330        @Override
331        public void setVisibleToUser(Object info, boolean visibleToUser) {
332
333        }
334
335        @Override
336        public void setAccessibilityFocused(Object info, boolean focused) {
337
338        }
339
340        @Override
341        public void setLongClickable(Object info, boolean longClickable) {
342
343        }
344
345        @Override
346        public void setPackageName(Object info, CharSequence packageName) {
347
348        }
349
350        @Override
351        public void setParent(Object info, View parent) {
352
353        }
354
355        @Override
356        public void setPassword(Object info, boolean password) {
357
358        }
359
360        @Override
361        public void setScrollable(Object info, boolean scrollable) {
362
363        }
364
365        @Override
366        public void setSelected(Object info, boolean selected) {
367
368        }
369
370        @Override
371        public void setSource(Object info, View source) {
372
373        }
374
375        @Override
376        public void setSource(Object info, View root, int virtualDescendantId) {
377
378        }
379
380        @Override
381        public Object findFocus(Object info, int focus) {
382            return null;
383        }
384
385        @Override
386        public Object focusSearch(Object info, int direction) {
387            return null;
388        }
389
390        @Override
391        public void setText(Object info, CharSequence text) {
392
393        }
394
395        @Override
396        public void recycle(Object info) {
397
398        }
399
400        @Override
401        public void setParent(Object info, View root, int virtualDescendantId) {
402
403        }
404
405        @Override
406        public String getViewIdResourceName(Object info) {
407            return null;
408        }
409
410        @Override
411        public void setViewIdResourceName(Object info, String viewId) {
412
413        }
414
415        @Override
416        public int getLiveRegion(Object info) {
417            return ViewCompat.ACCESSIBILITY_LIVE_REGION_NONE;
418        }
419
420        @Override
421        public void setLiveRegion(Object info, int mode) {
422            // No-op
423        }
424    }
425
426    static class AccessibilityNodeInfoIcsImpl extends AccessibilityNodeInfoStubImpl {
427        @Override
428        public Object obtain() {
429            return AccessibilityNodeInfoCompatIcs.obtain();
430        }
431
432        @Override
433        public Object obtain(View source) {
434            return AccessibilityNodeInfoCompatIcs.obtain(source);
435        }
436
437        @Override
438        public Object obtain(Object info) {
439            return AccessibilityNodeInfoCompatIcs.obtain(info);
440        }
441
442        @Override
443        public void addAction(Object info, int action) {
444            AccessibilityNodeInfoCompatIcs.addAction(info, action);
445        }
446
447        @Override
448        public void addChild(Object info, View child) {
449            AccessibilityNodeInfoCompatIcs.addChild(info, child);
450        }
451
452        @Override
453        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
454            return AccessibilityNodeInfoCompatIcs.findAccessibilityNodeInfosByText(info, text);
455        }
456
457        @Override
458        public int getActions(Object info) {
459            return AccessibilityNodeInfoCompatIcs.getActions(info);
460        }
461
462        @Override
463        public void getBoundsInParent(Object info, Rect outBounds) {
464            AccessibilityNodeInfoCompatIcs.getBoundsInParent(info, outBounds);
465        }
466
467        @Override
468        public void getBoundsInScreen(Object info, Rect outBounds) {
469            AccessibilityNodeInfoCompatIcs.getBoundsInScreen(info, outBounds);
470        }
471
472        @Override
473        public Object getChild(Object info, int index) {
474            return AccessibilityNodeInfoCompatIcs.getChild(info, index);
475        }
476
477        @Override
478        public int getChildCount(Object info) {
479            return AccessibilityNodeInfoCompatIcs.getChildCount(info);
480        }
481
482        @Override
483        public CharSequence getClassName(Object info) {
484            return AccessibilityNodeInfoCompatIcs.getClassName(info);
485        }
486
487        @Override
488        public CharSequence getContentDescription(Object info) {
489            return AccessibilityNodeInfoCompatIcs.getContentDescription(info);
490        }
491
492        @Override
493        public CharSequence getPackageName(Object info) {
494            return AccessibilityNodeInfoCompatIcs.getPackageName(info);
495        }
496
497        @Override
498        public Object getParent(Object info) {
499            return AccessibilityNodeInfoCompatIcs.getParent(info);
500        }
501
502        @Override
503        public CharSequence getText(Object info) {
504            return AccessibilityNodeInfoCompatIcs.getText(info);
505        }
506
507        @Override
508        public int getWindowId(Object info) {
509            return AccessibilityNodeInfoCompatIcs.getWindowId(info);
510        }
511
512        @Override
513        public boolean isCheckable(Object info) {
514            return AccessibilityNodeInfoCompatIcs.isCheckable(info);
515        }
516
517        @Override
518        public boolean isChecked(Object info) {
519            return AccessibilityNodeInfoCompatIcs.isChecked(info);
520        }
521
522        @Override
523        public boolean isClickable(Object info) {
524            return AccessibilityNodeInfoCompatIcs.isClickable(info);
525        }
526
527        @Override
528        public boolean isEnabled(Object info) {
529            return AccessibilityNodeInfoCompatIcs.isEnabled(info);
530        }
531
532        @Override
533        public boolean isFocusable(Object info) {
534            return AccessibilityNodeInfoCompatIcs.isFocusable(info);
535        }
536
537        @Override
538        public boolean isFocused(Object info) {
539            return AccessibilityNodeInfoCompatIcs.isFocused(info);
540        }
541
542        @Override
543        public boolean isLongClickable(Object info) {
544            return AccessibilityNodeInfoCompatIcs.isLongClickable(info);
545        }
546
547        @Override
548        public boolean isPassword(Object info) {
549            return AccessibilityNodeInfoCompatIcs.isPassword(info);
550        }
551
552        @Override
553        public boolean isScrollable(Object info) {
554            return AccessibilityNodeInfoCompatIcs.isScrollable(info);
555        }
556
557        @Override
558        public boolean isSelected(Object info) {
559            return AccessibilityNodeInfoCompatIcs.isSelected(info);
560        }
561
562        @Override
563        public boolean performAction(Object info, int action) {
564            return AccessibilityNodeInfoCompatIcs.performAction(info, action);
565        }
566
567        @Override
568        public void setBoundsInParent(Object info, Rect bounds) {
569            AccessibilityNodeInfoCompatIcs.setBoundsInParent(info, bounds);
570        }
571
572        @Override
573        public void setBoundsInScreen(Object info, Rect bounds) {
574            AccessibilityNodeInfoCompatIcs.setBoundsInScreen(info, bounds);
575        }
576
577        @Override
578        public void setCheckable(Object info, boolean checkable) {
579            AccessibilityNodeInfoCompatIcs.setCheckable(info, checkable);
580        }
581
582        @Override
583        public void setChecked(Object info, boolean checked) {
584            AccessibilityNodeInfoCompatIcs.setChecked(info, checked);
585        }
586
587        @Override
588        public void setClassName(Object info, CharSequence className) {
589            AccessibilityNodeInfoCompatIcs.setClassName(info, className);
590        }
591
592        @Override
593        public void setClickable(Object info, boolean clickable) {
594            AccessibilityNodeInfoCompatIcs.setClickable(info, clickable);
595        }
596
597        @Override
598        public void setContentDescription(Object info, CharSequence contentDescription) {
599            AccessibilityNodeInfoCompatIcs.setContentDescription(info, contentDescription);
600        }
601
602        @Override
603        public void setEnabled(Object info, boolean enabled) {
604            AccessibilityNodeInfoCompatIcs.setEnabled(info, enabled);
605        }
606
607        @Override
608        public void setFocusable(Object info, boolean focusable) {
609            AccessibilityNodeInfoCompatIcs.setFocusable(info, focusable);
610        }
611
612        @Override
613        public void setFocused(Object info, boolean focused) {
614            AccessibilityNodeInfoCompatIcs.setFocused(info, focused);
615        }
616
617        @Override
618        public void setLongClickable(Object info, boolean longClickable) {
619            AccessibilityNodeInfoCompatIcs.setLongClickable(info, longClickable);
620        }
621
622        @Override
623        public void setPackageName(Object info, CharSequence packageName) {
624            AccessibilityNodeInfoCompatIcs.setPackageName(info, packageName);
625        }
626
627        @Override
628        public void setParent(Object info, View parent) {
629            AccessibilityNodeInfoCompatIcs.setParent(info, parent);
630        }
631
632        @Override
633        public void setPassword(Object info, boolean password) {
634            AccessibilityNodeInfoCompatIcs.setPassword(info, password);
635        }
636
637        @Override
638        public void setScrollable(Object info, boolean scrollable) {
639            AccessibilityNodeInfoCompatIcs.setScrollable(info, scrollable);
640        }
641
642        @Override
643        public void setSelected(Object info, boolean selected) {
644            AccessibilityNodeInfoCompatIcs.setSelected(info, selected);
645        }
646
647        @Override
648        public void setSource(Object info, View source) {
649            AccessibilityNodeInfoCompatIcs.setSource(info, source);
650        }
651
652        @Override
653        public void setText(Object info, CharSequence text) {
654            AccessibilityNodeInfoCompatIcs.setText(info, text);
655        }
656
657        @Override
658        public void recycle(Object info) {
659            AccessibilityNodeInfoCompatIcs.recycle(info);
660        }
661    }
662
663    static class AccessibilityNodeInfoJellybeanImpl extends AccessibilityNodeInfoIcsImpl {
664        @Override
665        public Object obtain(View root, int virtualDescendantId) {
666            return AccessibilityNodeInfoCompatJellyBean.obtain(root, virtualDescendantId);
667        }
668
669        @Override
670        public Object findFocus(Object info, int focus) {
671            return AccessibilityNodeInfoCompatJellyBean.findFocus(info, focus);
672        }
673
674        @Override
675        public Object focusSearch(Object info, int direction) {
676            return AccessibilityNodeInfoCompatJellyBean.focusSearch(info, direction);
677        }
678
679        @Override
680        public void addChild(Object info, View child, int virtualDescendantId) {
681            AccessibilityNodeInfoCompatJellyBean.addChild(info, child, virtualDescendantId);
682        }
683
684        @Override
685        public void setSource(Object info, View root, int virtualDescendantId) {
686            AccessibilityNodeInfoCompatJellyBean.setSource(info, root, virtualDescendantId);
687        }
688
689        @Override
690        public boolean isVisibleToUser(Object info) {
691            return AccessibilityNodeInfoCompatJellyBean.isVisibleToUser(info);
692        }
693
694        @Override
695        public void setVisibleToUser(Object info, boolean visibleToUser) {
696            AccessibilityNodeInfoCompatJellyBean.setVisibleToUser(info, visibleToUser);
697        }
698
699        @Override
700        public boolean isAccessibilityFocused(Object info) {
701            return AccessibilityNodeInfoCompatJellyBean.isAccessibilityFocused(info);
702        }
703
704        @Override
705        public void setAccessibilityFocused(Object info, boolean focused) {
706            AccessibilityNodeInfoCompatJellyBean.setAccesibilityFocused(info, focused);
707        }
708
709        @Override
710        public boolean performAction(Object info, int action, Bundle arguments) {
711            return AccessibilityNodeInfoCompatJellyBean.performAction(info, action, arguments);
712        }
713
714        @Override
715        public void setMovementGranularities(Object info, int granularities) {
716            AccessibilityNodeInfoCompatJellyBean.setMovementGranularities(info, granularities);
717        }
718
719        @Override
720        public int getMovementGranularities(Object info) {
721            return AccessibilityNodeInfoCompatJellyBean.getMovementGranularities(info);
722        }
723
724        @Override
725        public void setParent(Object info, View root, int virtualDescendantId) {
726            AccessibilityNodeInfoCompatJellyBean.setParent(info, root, virtualDescendantId);
727        }
728    }
729
730    static class AccessibilityNodeInfoJellybeanMr2Impl extends AccessibilityNodeInfoJellybeanImpl {
731
732        @Override
733        public String getViewIdResourceName(Object info) {
734            return AccessibilityNodeInfoCompatJellybeanMr2.getViewIdResourceName(info);
735        }
736
737        @Override
738        public void setViewIdResourceName(Object info, String viewId) {
739            AccessibilityNodeInfoCompatJellybeanMr2.setViewIdResourceName(info, viewId);
740        }
741    }
742
743    static class AccessibilityNodeInfoKitKatImpl extends AccessibilityNodeInfoJellybeanMr2Impl {
744        @Override
745        public int getLiveRegion(Object info) {
746            return AccessibilityNodeInfoCompatKitKat.getLiveRegion(info);
747        }
748
749        @Override
750        public void setLiveRegion(Object info, int mode) {
751            AccessibilityNodeInfoCompatKitKat.setLiveRegion(info, mode);
752        }
753    }
754
755    static {
756        if (Build.VERSION.SDK_INT >= 19) { // KitKat
757            IMPL = new AccessibilityNodeInfoKitKatImpl();
758        } else if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
759            IMPL = new AccessibilityNodeInfoJellybeanMr2Impl();
760        } else if (Build.VERSION.SDK_INT >= 16) { // JellyBean
761            IMPL = new AccessibilityNodeInfoJellybeanImpl();
762        } else if (Build.VERSION.SDK_INT >= 14) { // ICS
763            IMPL = new AccessibilityNodeInfoIcsImpl();
764        } else {
765            IMPL = new AccessibilityNodeInfoStubImpl();
766        }
767    }
768
769    private static final AccessibilityNodeInfoImpl IMPL;
770
771    private final Object mInfo;
772
773    // Actions introduced in IceCreamSandwich
774
775    /**
776     * Action that focuses the node.
777     */
778    public static final int ACTION_FOCUS = 0x00000001;
779
780    /**
781     * Action that unfocuses the node.
782     */
783    public static final int ACTION_CLEAR_FOCUS = 0x00000002;
784
785    /**
786     * Action that selects the node.
787     */
788    public static final int ACTION_SELECT = 0x00000004;
789
790    /**
791     * Action that unselects the node.
792     */
793    public static final int ACTION_CLEAR_SELECTION = 0x00000008;
794
795    /**
796     * Action that clicks on the node info.
797     */
798    public static final int ACTION_CLICK = 0x00000010;
799
800    /**
801     * Action that long clicks on the node.
802     */
803    public static final int ACTION_LONG_CLICK = 0x00000020;
804
805    // Actions introduced in JellyBean
806
807    /**
808     * Action that gives accessibility focus to the node.
809     */
810    public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
811
812    /**
813     * Action that clears accessibility focus of the node.
814     */
815    public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
816
817    /**
818     * Action that requests to go to the next entity in this node's text
819     * at a given movement granularity. For example, move to the next character,
820     * word, etc.
821     * <p>
822     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
823     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
824     * <strong>Example:</strong> Move to the previous character and do not extend selection.
825     * <code><pre><p>
826     *   Bundle arguments = new Bundle();
827     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
828     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
829     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
830     *           false);
831     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
832     * </code></pre></p>
833     * </p>
834     *
835     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
836     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
837     *
838     * @see #setMovementGranularities(int)
839     * @see #getMovementGranularities()
840     *
841     * @see #MOVEMENT_GRANULARITY_CHARACTER
842     * @see #MOVEMENT_GRANULARITY_WORD
843     * @see #MOVEMENT_GRANULARITY_LINE
844     * @see #MOVEMENT_GRANULARITY_PARAGRAPH
845     * @see #MOVEMENT_GRANULARITY_PAGE
846     */
847    public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
848
849    /**
850     * Action that requests to go to the previous entity in this node's text
851     * at a given movement granularity. For example, move to the next character,
852     * word, etc.
853     * <p>
854     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
855     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
856     * <strong>Example:</strong> Move to the next character and do not extend selection.
857     * <code><pre><p>
858     *   Bundle arguments = new Bundle();
859     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
860     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
861     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
862     *           false);
863     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
864     *           arguments);
865     * </code></pre></p>
866     * </p>
867     *
868     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
869     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
870     *
871     * @see #setMovementGranularities(int)
872     * @see #getMovementGranularities()
873     *
874     * @see #MOVEMENT_GRANULARITY_CHARACTER
875     * @see #MOVEMENT_GRANULARITY_WORD
876     * @see #MOVEMENT_GRANULARITY_LINE
877     * @see #MOVEMENT_GRANULARITY_PARAGRAPH
878     * @see #MOVEMENT_GRANULARITY_PAGE
879     */
880    public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
881
882    /**
883     * Action to move to the next HTML element of a given type. For example, move
884     * to the BUTTON, INPUT, TABLE, etc.
885     * <p>
886     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
887     * <strong>Example:</strong>
888     * <code><pre><p>
889     *   Bundle arguments = new Bundle();
890     *   arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
891     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
892     * </code></pre></p>
893     * </p>
894     */
895    public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
896
897    /**
898     * Action to move to the previous HTML element of a given type. For example, move
899     * to the BUTTON, INPUT, TABLE, etc.
900     * <p>
901     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
902     * <strong>Example:</strong>
903     * <code><pre><p>
904     *   Bundle arguments = new Bundle();
905     *   arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
906     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
907     * </code></pre></p>
908     * </p>
909     */
910    public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
911
912    /**
913     * Action to scroll the node content forward.
914     */
915    public static final int ACTION_SCROLL_FORWARD = 0x00001000;
916
917    /**
918     * Action to scroll the node content backward.
919     */
920    public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
921
922    // Actions introduced in JellyBeanMr2
923
924    /**
925     * Action to copy the current selection to the clipboard.
926     */
927    public static final int ACTION_COPY = 0x00004000;
928
929    /**
930     * Action to paste the current clipboard content.
931     */
932    public static final int ACTION_PASTE = 0x00008000;
933
934    /**
935     * Action to cut the current selection and place it to the clipboard.
936     */
937    public static final int ACTION_CUT = 0x00010000;
938
939    /**
940     * Action to set the selection. Performing this action with no arguments
941     * clears the selection.
942     * <p>
943     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SELECTION_START_INT},
944     * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
945     * <strong>Example:</strong>
946     * <code><pre><p>
947     *   Bundle arguments = new Bundle();
948     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
949     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
950     *   info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
951     * </code></pre></p>
952     * </p>
953     *
954     * @see #ACTION_ARGUMENT_SELECTION_START_INT
955     * @see #ACTION_ARGUMENT_SELECTION_END_INT
956     */
957    public static final int ACTION_SET_SELECTION = 0x00020000;
958
959    // Action arguments
960
961    /**
962     * Argument for which movement granularity to be used when traversing the node text.
963     * <p>
964     * <strong>Type:</strong> int<br>
965     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
966     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
967     * </p>
968     */
969    public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
970        "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
971
972    /**
973     * Argument for which HTML element to get moving to the next/previous HTML element.
974     * <p>
975     * <strong>Type:</strong> String<br>
976     * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
977     *         {@link #ACTION_PREVIOUS_HTML_ELEMENT}
978     * </p>
979     */
980    public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
981        "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
982
983    /**
984     * Argument for whether when moving at granularity to extend the selection
985     * or to move it otherwise.
986     * <p>
987     * <strong>Type:</strong> boolean<br>
988     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
989     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
990     * </p>
991     *
992     * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
993     * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
994     */
995    public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
996            "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
997
998    /**
999     * Argument for specifying the selection start.
1000     * <p>
1001     * <strong>Type:</strong> int<br>
1002     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
1003     * </p>
1004     *
1005     * @see #ACTION_SET_SELECTION
1006     */
1007    public static final String ACTION_ARGUMENT_SELECTION_START_INT =
1008            "ACTION_ARGUMENT_SELECTION_START_INT";
1009
1010    /**
1011     * Argument for specifying the selection end.
1012     * <p>
1013     * <strong>Type:</strong> int<br>
1014     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
1015     * </p>
1016     *
1017     * @see #ACTION_SET_SELECTION
1018     */
1019    public static final String ACTION_ARGUMENT_SELECTION_END_INT =
1020            "ACTION_ARGUMENT_SELECTION_END_INT";
1021
1022    // Focus types
1023
1024    /**
1025     * The input focus.
1026     */
1027    public static final int FOCUS_INPUT = 1;
1028
1029    /**
1030     * The accessibility focus.
1031     */
1032    public static final int FOCUS_ACCESSIBILITY = 2;
1033
1034    // Movement granularities
1035
1036    /**
1037     * Movement granularity bit for traversing the text of a node by character.
1038     */
1039    public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
1040
1041    /**
1042     * Movement granularity bit for traversing the text of a node by word.
1043     */
1044    public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
1045
1046    /**
1047     * Movement granularity bit for traversing the text of a node by line.
1048     */
1049    public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
1050
1051    /**
1052     * Movement granularity bit for traversing the text of a node by paragraph.
1053     */
1054    public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
1055
1056    /**
1057     * Movement granularity bit for traversing the text of a node by page.
1058     */
1059    public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
1060
1061    /**
1062     * Creates a wrapper for info implementation.
1063     *
1064     * @param object The info to wrap.
1065     * @return A wrapper for if the object is not null, null otherwise.
1066     */
1067    static AccessibilityNodeInfoCompat wrapNonNullInstance(Object object) {
1068        if (object != null) {
1069            return new AccessibilityNodeInfoCompat(object);
1070        }
1071        return null;
1072    }
1073
1074    /**
1075     * Creates a new instance wrapping an
1076     * {@link android.view.accessibility.AccessibilityNodeInfo}.
1077     *
1078     * @param info The info.
1079     */
1080    public AccessibilityNodeInfoCompat(Object info) {
1081        mInfo = info;
1082    }
1083
1084    /**
1085     * @return The wrapped {@link android.view.accessibility.AccessibilityNodeInfo}.
1086     */
1087    public Object getInfo() {
1088        return mInfo;
1089    }
1090
1091    /**
1092     * Returns a cached instance if such is available otherwise a new one and
1093     * sets the source.
1094     *
1095     * @return An instance.
1096     * @see #setSource(View)
1097     */
1098    public static AccessibilityNodeInfoCompat obtain(View source) {
1099        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain(source));
1100    }
1101
1102    /**
1103     * Returns a cached instance if such is available otherwise a new one
1104     * and sets the source.
1105     *
1106     * @param root The root of the virtual subtree.
1107     * @param virtualDescendantId The id of the virtual descendant.
1108     * @return An instance.
1109     *
1110     * @see #setSource(View, int)
1111     */
1112    public static AccessibilityNodeInfoCompat obtain(View root, int virtualDescendantId) {
1113        return AccessibilityNodeInfoCompat.wrapNonNullInstance(
1114                IMPL.obtain(root, virtualDescendantId));
1115    }
1116
1117    /**
1118     * Returns a cached instance if such is available otherwise a new one.
1119     *
1120     * @return An instance.
1121     */
1122    public static AccessibilityNodeInfoCompat obtain() {
1123        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain());
1124    }
1125
1126    /**
1127     * Returns a cached instance if such is available or a new one is create.
1128     * The returned instance is initialized from the given <code>info</code>.
1129     *
1130     * @param info The other info.
1131     * @return An instance.
1132     */
1133    public static AccessibilityNodeInfoCompat obtain(AccessibilityNodeInfoCompat info) {
1134        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain(info.mInfo));
1135    }
1136
1137    /**
1138     * Sets the source.
1139     *
1140     * @param source The info source.
1141     */
1142    public void setSource(View source) {
1143        IMPL.setSource(mInfo, source);
1144    }
1145
1146    /**
1147     * Sets the source to be a virtual descendant of the given <code>root</code>.
1148     * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
1149     * is set as the source.
1150     * <p>
1151     * A virtual descendant is an imaginary View that is reported as a part of the view
1152     * hierarchy for accessibility purposes. This enables custom views that draw complex
1153     * content to report themselves as a tree of virtual views, thus conveying their
1154     * logical structure.
1155     * </p>
1156     * <p>
1157     *   <strong>Note:</strong> Cannot be called from an
1158     *   {@link android.accessibilityservice.AccessibilityService}.
1159     *   This class is made immutable before being delivered to an AccessibilityService.
1160     * </p>
1161     *
1162     * @param root The root of the virtual subtree.
1163     * @param virtualDescendantId The id of the virtual descendant.
1164     */
1165    public void setSource(View root, int virtualDescendantId) {
1166        IMPL.setSource(mInfo, root, virtualDescendantId);
1167    }
1168
1169    /**
1170     * Find the view that has the specified focus type. The search starts from
1171     * the view represented by this node info.
1172     *
1173     * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
1174     *         {@link #FOCUS_ACCESSIBILITY}.
1175     * @return The node info of the focused view or null.
1176     *
1177     * @see #FOCUS_INPUT
1178     * @see #FOCUS_ACCESSIBILITY
1179     */
1180    public AccessibilityNodeInfoCompat findFocus(int focus) {
1181        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.findFocus(mInfo, focus));
1182    }
1183
1184    /**
1185     * Searches for the nearest view in the specified direction that can take
1186     * input focus.
1187     *
1188     * @param direction The direction. Can be one of:
1189     *     {@link View#FOCUS_DOWN},
1190     *     {@link View#FOCUS_UP},
1191     *     {@link View#FOCUS_LEFT},
1192     *     {@link View#FOCUS_RIGHT},
1193     *     {@link View#FOCUS_FORWARD},
1194     *     {@link View#FOCUS_BACKWARD}.
1195     *
1196     * @return The node info for the view that can take accessibility focus.
1197     */
1198    public AccessibilityNodeInfoCompat focusSearch(int direction) {
1199        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.focusSearch(mInfo, direction));
1200    }
1201
1202    /**
1203     * Gets the id of the window from which the info comes from.
1204     *
1205     * @return The window id.
1206     */
1207    public int getWindowId() {
1208        return IMPL.getWindowId(mInfo);
1209    }
1210
1211    /**
1212     * Gets the number of children.
1213     *
1214     * @return The child count.
1215     */
1216    public int getChildCount() {
1217        return IMPL.getChildCount(mInfo);
1218    }
1219
1220    /**
1221     * Get the child at given index.
1222     * <p>
1223     * <strong>Note:</strong> It is a client responsibility to recycle the
1224     * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} to
1225     * avoid creating of multiple instances.
1226     * </p>
1227     *
1228     * @param index The child index.
1229     * @return The child node.
1230     * @throws IllegalStateException If called outside of an
1231     *             AccessibilityService.
1232     */
1233    public AccessibilityNodeInfoCompat getChild(int index) {
1234        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getChild(mInfo, index));
1235    }
1236
1237    /**
1238     * Adds a child.
1239     * <p>
1240     * <strong>Note:</strong> Cannot be called from an
1241     * {@link android.accessibilityservice.AccessibilityService}. This class is
1242     * made immutable before being delivered to an AccessibilityService.
1243     * </p>
1244     *
1245     * @param child The child.
1246     * @throws IllegalStateException If called from an AccessibilityService.
1247     */
1248    public void addChild(View child) {
1249        IMPL.addChild(mInfo, child);
1250    }
1251
1252    /**
1253     * Adds a virtual child which is a descendant of the given <code>root</code>.
1254     * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
1255     * is added as a child.
1256     * <p>
1257     * A virtual descendant is an imaginary View that is reported as a part of the view
1258     * hierarchy for accessibility purposes. This enables custom views that draw complex
1259     * content to report them selves as a tree of virtual views, thus conveying their
1260     * logical structure.
1261     * </p>
1262     *
1263     * @param root The root of the virtual subtree.
1264     * @param virtualDescendantId The id of the virtual child.
1265     */
1266    public void addChild(View root, int virtualDescendantId) {
1267        IMPL.addChild(mInfo, root, virtualDescendantId);
1268    }
1269
1270    /**
1271     * Gets the actions that can be performed on the node.
1272     *
1273     * @return The bit mask of with actions.
1274     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_FOCUS
1275     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
1276     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_SELECT
1277     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
1278     */
1279    public int getActions() {
1280        return IMPL.getActions(mInfo);
1281    }
1282
1283    /**
1284     * Adds an action that can be performed on the node.
1285     * <p>
1286     * <strong>Note:</strong> Cannot be called from an
1287     * {@link android.accessibilityservice.AccessibilityService}. This class is
1288     * made immutable before being delivered to an AccessibilityService.
1289     * </p>
1290     *
1291     * @param action The action.
1292     * @throws IllegalStateException If called from an AccessibilityService.
1293     */
1294    public void addAction(int action) {
1295        IMPL.addAction(mInfo, action);
1296    }
1297
1298    /**
1299     * Performs an action on the node.
1300     * <p>
1301     * <strong>Note:</strong> An action can be performed only if the request is
1302     * made from an {@link android.accessibilityservice.AccessibilityService}.
1303     * </p>
1304     *
1305     * @param action The action to perform.
1306     * @return True if the action was performed.
1307     * @throws IllegalStateException If called outside of an
1308     *             AccessibilityService.
1309     */
1310    public boolean performAction(int action) {
1311        return IMPL.performAction(mInfo, action);
1312    }
1313
1314    /**
1315     * Performs an action on the node.
1316     * <p>
1317     *   <strong>Note:</strong> An action can be performed only if the request is made
1318     *   from an {@link android.accessibilityservice.AccessibilityService}.
1319     * </p>
1320     *
1321     * @param action The action to perform.
1322     * @param arguments A bundle with additional arguments.
1323     * @return True if the action was performed.
1324     *
1325     * @throws IllegalStateException If called outside of an AccessibilityService.
1326     */
1327    public boolean performAction(int action, Bundle arguments) {
1328        return IMPL.performAction(mInfo, action, arguments);
1329    }
1330
1331    /**
1332     * Sets the movement granularities for traversing the text of this node.
1333     * <p>
1334     *   <strong>Note:</strong> Cannot be called from an
1335     *   {@link android.accessibilityservice.AccessibilityService}.
1336     *   This class is made immutable before being delivered to an AccessibilityService.
1337     * </p>
1338     *
1339     * @param granularities The bit mask with granularities.
1340     *
1341     * @throws IllegalStateException If called from an AccessibilityService.
1342     */
1343    public void setMovementGranularities(int granularities) {
1344        IMPL.setMovementGranularities(mInfo, granularities);
1345    }
1346
1347    /**
1348     * Gets the movement granularities for traversing the text of this node.
1349     *
1350     * @return The bit mask with granularities.
1351     */
1352    public int getMovementGranularities() {
1353        return IMPL.getMovementGranularities(mInfo);
1354    }
1355
1356    /**
1357     * Finds {@link android.view.accessibility.AccessibilityNodeInfo}s by text. The match
1358     * is case insensitive containment. The search is relative to this info i.e. this
1359     * info is the root of the traversed tree.
1360     * <p>
1361     * <strong>Note:</strong> It is a client responsibility to recycle the
1362     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
1363     * to avoid creating of multiple instances.
1364     * </p>
1365     *
1366     * @param text The searched text.
1367     * @return A list of node info.
1368     */
1369    public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text) {
1370        List<AccessibilityNodeInfoCompat> result = new ArrayList<AccessibilityNodeInfoCompat>();
1371        List<Object> infos = IMPL.findAccessibilityNodeInfosByText(mInfo, text);
1372        final int infoCount = infos.size();
1373        for (int i = 0; i < infoCount; i++) {
1374            Object info = infos.get(i);
1375            result.add(new AccessibilityNodeInfoCompat(info));
1376        }
1377        return result;
1378    }
1379
1380    /**
1381     * Gets the parent.
1382     * <p>
1383     * <strong>Note:</strong> It is a client responsibility to recycle the
1384     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
1385     * to avoid creating of multiple instances.
1386     * </p>
1387     *
1388     * @return The parent.
1389     */
1390    public AccessibilityNodeInfoCompat getParent() {
1391        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getParent(mInfo));
1392    }
1393
1394    /**
1395     * Sets the parent.
1396     * <p>
1397     * <strong>Note:</strong> Cannot be called from an
1398     * {@link android.accessibilityservice.AccessibilityService}. This class is
1399     * made immutable before being delivered to an AccessibilityService.
1400     * </p>
1401     *
1402     * @param parent The parent.
1403     * @throws IllegalStateException If called from an AccessibilityService.
1404     */
1405    public void setParent(View parent) {
1406        IMPL.setParent(mInfo, parent);
1407    }
1408
1409    /**
1410     * Sets the parent to be a virtual descendant of the given <code>root</code>.
1411     * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1412     * is set as the parent.
1413     * <p>
1414     * A virtual descendant is an imaginary View that is reported as a part of the view
1415     * hierarchy for accessibility purposes. This enables custom views that draw complex
1416     * content to report them selves as a tree of virtual views, thus conveying their
1417     * logical structure.
1418     * </p>
1419     * <p>
1420     *   <strong>Note:</strong> Cannot be called from an
1421     *   {@link android.accessibilityservice.AccessibilityService}.
1422     *   This class is made immutable before being delivered to an AccessibilityService.
1423     * </p>
1424     *
1425     * @param root The root of the virtual subtree.
1426     * @param virtualDescendantId The id of the virtual descendant.
1427     */
1428    public void setParent(View root, int virtualDescendantId) {
1429        IMPL.setParent(mInfo, root, virtualDescendantId);
1430    }
1431
1432    /**
1433     * Gets the node bounds in parent coordinates.
1434     *
1435     * @param outBounds The output node bounds.
1436     */
1437    public void getBoundsInParent(Rect outBounds) {
1438        IMPL.getBoundsInParent(mInfo, outBounds);
1439    }
1440
1441    /**
1442     * Sets the node bounds in parent coordinates.
1443     * <p>
1444     * <strong>Note:</strong> Cannot be called from an
1445     * {@link android.accessibilityservice.AccessibilityService}. This class is
1446     * made immutable before being delivered to an AccessibilityService.
1447     * </p>
1448     *
1449     * @param bounds The node bounds.
1450     *@throws IllegalStateException If called from an AccessibilityService.
1451     */
1452    public void setBoundsInParent(Rect bounds) {
1453        IMPL.setBoundsInParent(mInfo, bounds);
1454    }
1455
1456    /**
1457     * Gets the node bounds in screen coordinates.
1458     *
1459     * @param outBounds The output node bounds.
1460     */
1461    public void getBoundsInScreen(Rect outBounds) {
1462        IMPL.getBoundsInScreen(mInfo, outBounds);
1463    }
1464
1465    /**
1466     * Sets the node bounds in screen coordinates.
1467     * <p>
1468     * <strong>Note:</strong> Cannot be called from an
1469     * {@link android.accessibilityservice.AccessibilityService}. This class is
1470     * made immutable before being delivered to an AccessibilityService.
1471     * </p>
1472     *
1473     * @param bounds The node bounds.
1474     * @throws IllegalStateException If called from an AccessibilityService.
1475     */
1476    public void setBoundsInScreen(Rect bounds) {
1477        IMPL.setBoundsInScreen(mInfo, bounds);
1478    }
1479
1480    /**
1481     * Gets whether this node is checkable.
1482     *
1483     * @return True if the node is checkable.
1484     */
1485    public boolean isCheckable() {
1486        return IMPL.isCheckable(mInfo);
1487    }
1488
1489    /**
1490     * Sets whether this node is checkable.
1491     * <p>
1492     * <strong>Note:</strong> Cannot be called from an
1493     * {@link android.accessibilityservice.AccessibilityService}. This class is
1494     * made immutable before being delivered to an AccessibilityService.
1495     * </p>
1496     *
1497     * @param checkable True if the node is checkable.
1498     * @throws IllegalStateException If called from an AccessibilityService.
1499     */
1500    public void setCheckable(boolean checkable) {
1501        IMPL.setCheckable(mInfo, checkable);
1502    }
1503
1504    /**
1505     * Gets whether this node is checked.
1506     *
1507     * @return True if the node is checked.
1508     */
1509    public boolean isChecked() {
1510        return IMPL.isChecked(mInfo);
1511    }
1512
1513    /**
1514     * Sets whether this node is checked.
1515     * <p>
1516     * <strong>Note:</strong> Cannot be called from an
1517     * {@link android.accessibilityservice.AccessibilityService}. This class is
1518     * made immutable before being delivered to an AccessibilityService.
1519     * </p>
1520     *
1521     * @param checked True if the node is checked.
1522     * @throws IllegalStateException If called from an AccessibilityService.
1523     */
1524    public void setChecked(boolean checked) {
1525        IMPL.setChecked(mInfo, checked);
1526    }
1527
1528    /**
1529     * Gets whether this node is focusable.
1530     *
1531     * @return True if the node is focusable.
1532     */
1533    public boolean isFocusable() {
1534        return IMPL.isFocusable(mInfo);
1535    }
1536
1537    /**
1538     * Sets whether this node is focusable.
1539     * <p>
1540     * <strong>Note:</strong> Cannot be called from an
1541     * {@link android.accessibilityservice.AccessibilityService}. This class is
1542     * made immutable before being delivered to an AccessibilityService.
1543     * </p>
1544     *
1545     * @param focusable True if the node is focusable.
1546     * @throws IllegalStateException If called from an AccessibilityService.
1547     */
1548    public void setFocusable(boolean focusable) {
1549        IMPL.setFocusable(mInfo, focusable);
1550    }
1551
1552    /**
1553     * Gets whether this node is focused.
1554     *
1555     * @return True if the node is focused.
1556     */
1557    public boolean isFocused() {
1558        return IMPL.isFocused(mInfo);
1559    }
1560
1561    /**
1562     * Sets whether this node is focused.
1563     * <p>
1564     * <strong>Note:</strong> Cannot be called from an
1565     * {@link android.accessibilityservice.AccessibilityService}. This class is
1566     * made immutable before being delivered to an AccessibilityService.
1567     * </p>
1568     *
1569     * @param focused True if the node is focused.
1570     * @throws IllegalStateException If called from an AccessibilityService.
1571     */
1572    public void setFocused(boolean focused) {
1573        IMPL.setFocused(mInfo, focused);
1574    }
1575
1576    /**
1577     * Sets whether this node is visible to the user.
1578     *
1579     * @return Whether the node is visible to the user.
1580     */
1581    public boolean isVisibleToUser() {
1582        return IMPL.isVisibleToUser(mInfo);
1583    }
1584
1585    /**
1586     * Sets whether this node is visible to the user.
1587     * <p>
1588     *   <strong>Note:</strong> Cannot be called from an
1589     *   {@link android.accessibilityservice.AccessibilityService}.
1590     *   This class is made immutable before being delivered to an AccessibilityService.
1591     * </p>
1592     *
1593     * @param visibleToUser Whether the node is visible to the user.
1594     *
1595     * @throws IllegalStateException If called from an AccessibilityService.
1596     */
1597    public void setVisibleToUser(boolean visibleToUser) {
1598        IMPL.setVisibleToUser(mInfo, visibleToUser);
1599    }
1600
1601    /**
1602     * Gets whether this node is accessibility focused.
1603     *
1604     * @return True if the node is accessibility focused.
1605     */
1606    public boolean isAccessibilityFocused() {
1607        return IMPL.isAccessibilityFocused(mInfo);
1608    }
1609
1610    /**
1611     * Sets whether this node is accessibility focused.
1612     * <p>
1613     *   <strong>Note:</strong> Cannot be called from an
1614     *   {@link android.accessibilityservice.AccessibilityService}.
1615     *   This class is made immutable before being delivered to an AccessibilityService.
1616     * </p>
1617     *
1618     * @param focused True if the node is accessibility focused.
1619     *
1620     * @throws IllegalStateException If called from an AccessibilityService.
1621     */
1622    public void setAccessibilityFocused(boolean focused) {
1623        IMPL.setAccessibilityFocused(mInfo, focused);
1624    }
1625
1626    /**
1627     * Gets whether this node is selected.
1628     *
1629     * @return True if the node is selected.
1630     */
1631    public boolean isSelected() {
1632        return IMPL.isSelected(mInfo);
1633    }
1634
1635    /**
1636     * Sets whether this node is selected.
1637     * <p>
1638     * <strong>Note:</strong> Cannot be called from an
1639     * {@link android.accessibilityservice.AccessibilityService}. This class is
1640     * made immutable before being delivered to an AccessibilityService.
1641     * </p>
1642     *
1643     * @param selected True if the node is selected.
1644     * @throws IllegalStateException If called from an AccessibilityService.
1645     */
1646    public void setSelected(boolean selected) {
1647        IMPL.setSelected(mInfo, selected);
1648    }
1649
1650    /**
1651     * Gets whether this node is clickable.
1652     *
1653     * @return True if the node is clickable.
1654     */
1655    public boolean isClickable() {
1656        return IMPL.isClickable(mInfo);
1657    }
1658
1659    /**
1660     * Sets whether this node is clickable.
1661     * <p>
1662     * <strong>Note:</strong> Cannot be called from an
1663     * {@link android.accessibilityservice.AccessibilityService}. This class is
1664     * made immutable before being delivered to an AccessibilityService.
1665     * </p>
1666     *
1667     * @param clickable True if the node is clickable.
1668     * @throws IllegalStateException If called from an AccessibilityService.
1669     */
1670    public void setClickable(boolean clickable) {
1671        IMPL.setClickable(mInfo, clickable);
1672    }
1673
1674    /**
1675     * Gets whether this node is long clickable.
1676     *
1677     * @return True if the node is long clickable.
1678     */
1679    public boolean isLongClickable() {
1680        return IMPL.isLongClickable(mInfo);
1681    }
1682
1683    /**
1684     * Sets whether this node is long clickable.
1685     * <p>
1686     * <strong>Note:</strong> Cannot be called from an
1687     * {@link android.accessibilityservice.AccessibilityService}. This class is
1688     * made immutable before being delivered to an AccessibilityService.
1689     * </p>
1690     *
1691     * @param longClickable True if the node is long clickable.
1692     * @throws IllegalStateException If called from an AccessibilityService.
1693     */
1694    public void setLongClickable(boolean longClickable) {
1695        IMPL.setLongClickable(mInfo, longClickable);
1696    }
1697
1698    /**
1699     * Gets whether this node is enabled.
1700     *
1701     * @return True if the node is enabled.
1702     */
1703    public boolean isEnabled() {
1704        return IMPL.isEnabled(mInfo);
1705    }
1706
1707    /**
1708     * Sets whether this node is enabled.
1709     * <p>
1710     * <strong>Note:</strong> Cannot be called from an
1711     * {@link android.accessibilityservice.AccessibilityService}. This class is
1712     * made immutable before being delivered to an AccessibilityService.
1713     * </p>
1714     *
1715     * @param enabled True if the node is enabled.
1716     * @throws IllegalStateException If called from an AccessibilityService.
1717     */
1718    public void setEnabled(boolean enabled) {
1719        IMPL.setEnabled(mInfo, enabled);
1720    }
1721
1722    /**
1723     * Gets whether this node is a password.
1724     *
1725     * @return True if the node is a password.
1726     */
1727    public boolean isPassword() {
1728        return IMPL.isPassword(mInfo);
1729    }
1730
1731    /**
1732     * Sets whether this node is a password.
1733     * <p>
1734     * <strong>Note:</strong> Cannot be called from an
1735     * {@link android.accessibilityservice.AccessibilityService}. This class is
1736     * made immutable before being delivered to an AccessibilityService.
1737     * </p>
1738     *
1739     * @param password True if the node is a password.
1740     * @throws IllegalStateException If called from an AccessibilityService.
1741     */
1742    public void setPassword(boolean password) {
1743        IMPL.setPassword(mInfo, password);
1744    }
1745
1746    /**
1747     * Gets if the node is scrollable.
1748     *
1749     * @return True if the node is scrollable, false otherwise.
1750     */
1751    public boolean isScrollable() {
1752        return IMPL.isScrollable(mInfo);
1753    }
1754
1755    /**
1756     * Sets if the node is scrollable.
1757     * <p>
1758     * <strong>Note:</strong> Cannot be called from an
1759     * {@link android.accessibilityservice.AccessibilityService}. This class is
1760     * made immutable before being delivered to an AccessibilityService.
1761     * </p>
1762     *
1763     * @param scrollable True if the node is scrollable, false otherwise.
1764     * @throws IllegalStateException If called from an AccessibilityService.
1765     */
1766    public void setScrollable(boolean scrollable) {
1767        IMPL.setScrollable(mInfo, scrollable);
1768    }
1769
1770    /**
1771     * Gets the package this node comes from.
1772     *
1773     * @return The package name.
1774     */
1775    public CharSequence getPackageName() {
1776        return IMPL.getPackageName(mInfo);
1777    }
1778
1779    /**
1780     * Sets the package this node comes from.
1781     * <p>
1782     * <strong>Note:</strong> Cannot be called from an
1783     * {@link android.accessibilityservice.AccessibilityService}. This class is
1784     * made immutable before being delivered to an AccessibilityService.
1785     * </p>
1786     *
1787     * @param packageName The package name.
1788     * @throws IllegalStateException If called from an AccessibilityService.
1789     */
1790    public void setPackageName(CharSequence packageName) {
1791        IMPL.setPackageName(mInfo, packageName);
1792    }
1793
1794    /**
1795     * Gets the class this node comes from.
1796     *
1797     * @return The class name.
1798     */
1799    public CharSequence getClassName() {
1800        return IMPL.getClassName(mInfo);
1801    }
1802
1803    /**
1804     * Sets the class this node comes from.
1805     * <p>
1806     * <strong>Note:</strong> Cannot be called from an
1807     * {@link android.accessibilityservice.AccessibilityService}. This class is
1808     * made immutable before being delivered to an AccessibilityService.
1809     * </p>
1810     *
1811     * @param className The class name.
1812     * @throws IllegalStateException If called from an AccessibilityService.
1813     */
1814    public void setClassName(CharSequence className) {
1815        IMPL.setClassName(mInfo, className);
1816    }
1817
1818    /**
1819     * Gets the text of this node.
1820     *
1821     * @return The text.
1822     */
1823    public CharSequence getText() {
1824        return IMPL.getText(mInfo);
1825    }
1826
1827    /**
1828     * Sets the text of this node.
1829     * <p>
1830     * <strong>Note:</strong> Cannot be called from an
1831     * {@link android.accessibilityservice.AccessibilityService}. This class is
1832     * made immutable before being delivered to an AccessibilityService.
1833     * </p>
1834     *
1835     * @param text The text.
1836     * @throws IllegalStateException If called from an AccessibilityService.
1837     */
1838    public void setText(CharSequence text) {
1839        IMPL.setText(mInfo, text);
1840    }
1841
1842    /**
1843     * Gets the content description of this node.
1844     *
1845     * @return The content description.
1846     */
1847    public CharSequence getContentDescription() {
1848        return IMPL.getContentDescription(mInfo);
1849    }
1850
1851    /**
1852     * Sets the content description of this node.
1853     * <p>
1854     * <strong>Note:</strong> Cannot be called from an
1855     * {@link android.accessibilityservice.AccessibilityService}. This class is
1856     * made immutable before being delivered to an AccessibilityService.
1857     * </p>
1858     *
1859     * @param contentDescription The content description.
1860     * @throws IllegalStateException If called from an AccessibilityService.
1861     */
1862    public void setContentDescription(CharSequence contentDescription) {
1863        IMPL.setContentDescription(mInfo, contentDescription);
1864    }
1865
1866    /**
1867     * Return an instance back to be reused.
1868     * <p>
1869     * <strong>Note:</strong> You must not touch the object after calling this function.
1870     *
1871     * @throws IllegalStateException If the info is already recycled.
1872     */
1873    public void recycle() {
1874        IMPL.recycle(mInfo);
1875    }
1876
1877    /**
1878     * Sets the fully qualified resource name of the source view's id.
1879     *
1880     * <p>
1881     *   <strong>Note:</strong> Cannot be called from an
1882     *   {@link android.accessibilityservice.AccessibilityService}.
1883     *   This class is made immutable before being delivered to an AccessibilityService.
1884     * </p>
1885     *
1886     * @param viewId The id resource name.
1887     */
1888    public void setViewIdResourceName(String viewId) {
1889        IMPL.setViewIdResourceName(mInfo, viewId);
1890    }
1891
1892    /**
1893     * Gets the fully qualified resource name of the source view's id.
1894     *
1895     * <p>
1896     *   <strong>Note:</strong> The primary usage of this API is for UI test automation
1897     *   and in order to report the source view id of an {@link AccessibilityNodeInfoCompat}
1898     *   the client has to set the {@link AccessibilityServiceInfoCompat#FLAG_REPORT_VIEW_IDS}
1899     *   flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
1900     * </p>
1901     *
1902     * @return The id resource name.
1903     */
1904    public String getViewIdResourceName() {
1905        return IMPL.getViewIdResourceName(mInfo);
1906    }
1907
1908    /**
1909     * Gets the node's live region mode.
1910     * <p>
1911     * A live region is a node that contains information that is important for
1912     * the user and when it changes the user should be notified. For example,
1913     * in a login screen with a TextView that displays an "incorrect password"
1914     * notification, that view should be marked as a live region with mode
1915     * {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_POLITE}.
1916     * <p>
1917     * It is the responsibility of the accessibility service to monitor
1918     * {@link AccessibilityEventCompat#TYPE_WINDOW_CONTENT_CHANGED} events
1919     * indicating changes to live region nodes and their children.
1920     *
1921     * @return The live region mode, or
1922     *         {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is
1923     *         not a live region.
1924     * @see ViewCompat#getAccessibilityLiveRegion(View)
1925     */
1926    public int getLiveRegion() {
1927        return IMPL.getLiveRegion(mInfo);
1928    }
1929
1930    /**
1931     * Sets the node's live region mode.
1932     * <p>
1933     * <strong>Note:</strong> Cannot be called from an
1934     * {@link android.accessibilityservice.AccessibilityService}. This class is
1935     * made immutable before being delivered to an AccessibilityService.
1936     *
1937     * @param mode The live region mode, or
1938     *        {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is
1939     *        not a live region.
1940     * @see ViewCompat#setAccessibilityLiveRegion(View, int)
1941     */
1942    public void setLiveRegion(int mode) {
1943        IMPL.setLiveRegion(mInfo, mode);
1944    }
1945
1946    @Override
1947    public int hashCode() {
1948        return (mInfo == null) ? 0 : mInfo.hashCode();
1949    }
1950
1951    @Override
1952    public boolean equals(Object obj) {
1953        if (this == obj) {
1954            return true;
1955        }
1956        if (obj == null) {
1957            return false;
1958        }
1959        if (getClass() != obj.getClass()) {
1960            return false;
1961        }
1962        AccessibilityNodeInfoCompat other = (AccessibilityNodeInfoCompat) obj;
1963        if (mInfo == null) {
1964            if (other.mInfo != null) {
1965                return false;
1966            }
1967        } else if (!mInfo.equals(other.mInfo)) {
1968            return false;
1969        }
1970        return true;
1971    }
1972
1973    @Override
1974    public String toString() {
1975        StringBuilder builder = new StringBuilder();
1976        builder.append(super.toString());
1977
1978        Rect bounds = new Rect();
1979
1980        getBoundsInParent(bounds);
1981        builder.append("; boundsInParent: " + bounds);
1982
1983        getBoundsInScreen(bounds);
1984        builder.append("; boundsInScreen: " + bounds);
1985
1986        builder.append("; packageName: ").append(getPackageName());
1987        builder.append("; className: ").append(getClassName());
1988        builder.append("; text: ").append(getText());
1989        builder.append("; contentDescription: ").append(getContentDescription());
1990        builder.append("; viewId: ").append(getViewIdResourceName());
1991
1992        builder.append("; checkable: ").append(isCheckable());
1993        builder.append("; checked: ").append(isChecked());
1994        builder.append("; focusable: ").append(isFocusable());
1995        builder.append("; focused: ").append(isFocused());
1996        builder.append("; selected: ").append(isSelected());
1997        builder.append("; clickable: ").append(isClickable());
1998        builder.append("; longClickable: ").append(isLongClickable());
1999        builder.append("; enabled: ").append(isEnabled());
2000        builder.append("; password: ").append(isPassword());
2001        builder.append("; scrollable: " + isScrollable());
2002
2003        builder.append("; [");
2004        for (int actionBits = getActions(); actionBits != 0;) {
2005            final int action = 1 << Integer.numberOfTrailingZeros(actionBits);
2006            actionBits &= ~action;
2007            builder.append(getActionSymbolicName(action));
2008            if (actionBits != 0) {
2009                builder.append(", ");
2010            }
2011        }
2012        builder.append("]");
2013
2014        return builder.toString();
2015    }
2016
2017    private static String getActionSymbolicName(int action) {
2018        switch (action) {
2019            case ACTION_FOCUS:
2020                return "ACTION_FOCUS";
2021            case ACTION_CLEAR_FOCUS:
2022                return "ACTION_CLEAR_FOCUS";
2023            case ACTION_SELECT:
2024                return "ACTION_SELECT";
2025            case ACTION_CLEAR_SELECTION:
2026                return "ACTION_CLEAR_SELECTION";
2027            case ACTION_CLICK:
2028                return "ACTION_CLICK";
2029            case ACTION_LONG_CLICK:
2030                return "ACTION_LONG_CLICK";
2031            case ACTION_ACCESSIBILITY_FOCUS:
2032                return "ACTION_ACCESSIBILITY_FOCUS";
2033            case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
2034                return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
2035            case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
2036                return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
2037            case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
2038                return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
2039            case ACTION_NEXT_HTML_ELEMENT:
2040                return "ACTION_NEXT_HTML_ELEMENT";
2041            case ACTION_PREVIOUS_HTML_ELEMENT:
2042                return "ACTION_PREVIOUS_HTML_ELEMENT";
2043            case ACTION_SCROLL_FORWARD:
2044                return "ACTION_SCROLL_FORWARD";
2045            case ACTION_SCROLL_BACKWARD:
2046                return "ACTION_SCROLL_BACKWARD";
2047            case ACTION_CUT:
2048                return "ACTION_CUT";
2049            case ACTION_COPY:
2050                return "ACTION_COPY";
2051            case ACTION_PASTE:
2052                return "ACTION_PASTE";
2053            case ACTION_SET_SELECTION:
2054                return "ACTION_SET_SELECTION";
2055            default:
2056                return"ACTION_UNKNOWN";
2057        }
2058    }
2059}
2060