AccessibilityNodeInfoCompat.java revision cd85b06ae9fe64f4fc360b97a9af8896c193c403
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;
25
26import java.util.ArrayList;
27import java.util.Collections;
28import java.util.List;
29
30/**
31 * Helper for accessing {@link android.view.accessibility.AccessibilityNodeInfo}
32 * introduced after API level 4 in a backwards compatible fashion.
33 */
34public class AccessibilityNodeInfoCompat {
35
36    public static class AccessibilityActionCompat {
37        private final Object mAction;
38
39        /**
40         * Creates a new instance.
41         *
42         * @param actionId The action id.
43         * @param label The action label.
44         */
45        public AccessibilityActionCompat(int actionId, CharSequence label) {
46            this(IMPL.newAccessibilityAction(actionId, label));
47        }
48
49        private AccessibilityActionCompat(Object action) {
50            mAction = action;
51        }
52
53        /**
54         * Gets the id for this action.
55         *
56         * @return The action id.
57         */
58        public int getId() {
59            return IMPL.getAccessibilityActionId(mAction);
60        }
61
62        /**
63         * Gets the label for this action. Its purpose is to describe the
64         * action to user.
65         *
66         * @return The label.
67         */
68        public CharSequence getLabel() {
69            return IMPL.getAccessibilityActionLabel(mAction);
70        }
71    }
72
73    public static class CollectionInfoCompat {
74        /** Selection mode where items are not selectable. */
75        public static final int SELECTION_MODE_NONE = 0;
76
77        /** Selection mode where a single item may be selected. */
78        public static final int SELECTION_MODE_SINGLE = 1;
79
80        /** Selection mode where multiple items may be selected. */
81        public static final int SELECTION_MODE_MULTIPLE = 2;
82
83        final Object mInfo;
84
85        /**
86         * Returns a cached instance if such is available otherwise a new one.
87         *
88         * @return An instance.
89         */
90        public static CollectionInfoCompat obtain(int rowCount, int columnCount,
91                boolean hierarchical, int selectionMode) {
92            return new CollectionInfoCompat(IMPL.obtainCollectionInfo(rowCount, columnCount,
93                    hierarchical, selectionMode));
94        }
95
96        private CollectionInfoCompat(Object info) {
97            mInfo = info;
98        }
99
100        public int getColumnCount() {
101            return IMPL.getCollectionInfoColumnCount(mInfo);
102        }
103
104        public int getRowCount() {
105            return IMPL.getCollectionInfoRowCount(mInfo);
106        }
107
108        public boolean isHierarchical() {
109            return IMPL.isCollectionInfoHierarchical(mInfo);
110        }
111    }
112
113    public static class CollectionItemInfoCompat {
114
115        private final Object mInfo;
116
117        /**
118         * Returns a cached instance if such is available otherwise a new one.
119         *
120         * @return An instance.
121         */
122        public static CollectionItemInfoCompat obtain(int rowIndex, int rowSpan,
123                int columnIndex, int columnSpan, boolean heading, boolean selected) {
124            return new CollectionItemInfoCompat(IMPL.obtainCollectionItemInfo(rowIndex, rowSpan,
125                    columnIndex, columnSpan, heading, selected));
126        }
127
128        private CollectionItemInfoCompat(Object info) {
129            mInfo = info;
130        }
131
132        public int getColumnIndex() {
133            return IMPL.getCollectionItemColumnIndex(mInfo);
134        }
135
136        public int getColumnSpan() {
137            return IMPL.getCollectionItemColumnSpan(mInfo);
138        }
139
140        public int getRowIndex() {
141            return IMPL.getCollectionItemRowIndex(mInfo);
142        }
143
144        public int getRowSpan() {
145            return IMPL.getCollectionItemRowSpan(mInfo);
146        }
147
148        public boolean isHeading() {
149            return IMPL.isCollectionItemHeading(mInfo);
150        }
151
152        public boolean isSelected() {
153            return IMPL.isCollectionItemSelected(mInfo);
154        }
155    }
156
157    public static class RangeInfoCompat {
158        /** Range type: integer. */
159        public static final int RANGE_TYPE_INT = 0;
160        /** Range type: float. */
161        public static final int RANGE_TYPE_FLOAT = 1;
162        /** Range type: percent with values from zero to one.*/
163        public static final int RANGE_TYPE_PERCENT = 2;
164
165        private final Object mInfo;
166
167        private RangeInfoCompat(Object info) {
168            mInfo = info;
169        }
170
171        public float getCurrent() {
172            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getCurrent(mInfo);
173        }
174
175        public float getMax() {
176            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getMax(mInfo);
177        }
178
179        public float getMin() {
180            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getMin(mInfo);
181        }
182
183        public int getType() {
184            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getType(mInfo);
185        }
186    }
187
188    static interface AccessibilityNodeInfoImpl {
189        public Object newAccessibilityAction(int actionId, CharSequence label);
190        public Object obtain();
191        public Object obtain(View source);
192        public Object obtain(Object info);
193        public Object obtain(View root, int virtualDescendantId);
194        public void setSource(Object info, View source);
195        public void setSource(Object info, View root, int virtualDescendantId);
196        public Object findFocus(Object info, int focus);
197        public Object focusSearch(Object info, int direction);
198        public int getWindowId(Object info);
199        public int getChildCount(Object info);
200        public Object getChild(Object info, int index);
201        public void addChild(Object info, View child);
202        public void addChild(Object info, View child, int virtualDescendantId);
203        public int getActions(Object info);
204        public void addAction(Object info, int action);
205        public void addAction(Object info, Object action);
206        public int getAccessibilityActionId(Object action);
207        public CharSequence getAccessibilityActionLabel(Object action);
208        public boolean performAction(Object info, int action);
209        public boolean performAction(Object info, int action, Bundle arguments);
210        public void setMovementGranularities(Object info, int granularities);
211        public int getMovementGranularities(Object info);
212        public List<Object> findAccessibilityNodeInfosByText(Object info, String text);
213        public Object getParent(Object info);
214        public void setParent(Object info, View root, int virtualDescendantId);
215        public void setParent(Object info, View parent);
216        public void getBoundsInParent(Object info, Rect outBounds);
217        public void setBoundsInParent(Object info, Rect bounds);
218        public void getBoundsInScreen(Object info, Rect outBounds);
219        public void setBoundsInScreen(Object info, Rect bounds);
220        public boolean isCheckable(Object info);
221        public void setCheckable(Object info, boolean checkable);
222        public boolean isChecked(Object info);
223        public void setChecked(Object info, boolean checked);
224        public boolean isFocusable(Object info);
225        public void setFocusable(Object info, boolean focusable);
226        public boolean isFocused(Object info);
227        public void setFocused(Object info, boolean focused);
228        public boolean isVisibleToUser(Object info);
229        public void setVisibleToUser(Object info, boolean visibleToUser);
230        public boolean isAccessibilityFocused(Object info);
231        public void setAccessibilityFocused(Object info, boolean focused);
232        public boolean isSelected(Object info);
233        public void setSelected(Object info, boolean selected);
234        public boolean isClickable(Object info);
235        public void setClickable(Object info, boolean clickable);
236        public boolean isLongClickable(Object info);
237        public void setLongClickable(Object info, boolean longClickable);
238        public boolean isEnabled(Object info);
239        public void setEnabled(Object info, boolean enabled);
240        public boolean isPassword(Object info);
241        public void setPassword(Object info, boolean password);
242        public boolean isScrollable(Object info);
243        public void setScrollable(Object info, boolean scrollable);
244        public CharSequence getPackageName(Object info);
245        public void setPackageName(Object info, CharSequence packageName);
246        public CharSequence getClassName(Object info);
247        public void setClassName(Object info, CharSequence className);
248        public CharSequence getText(Object info);
249        public void setText(Object info, CharSequence text);
250        public CharSequence getContentDescription(Object info);
251        public void setContentDescription(Object info, CharSequence contentDescription);
252        public void recycle(Object info);
253        public String getViewIdResourceName(Object info);
254        public void setViewIdResourceName(Object info, String viewId);
255        public int getLiveRegion(Object info);
256        public void setLiveRegion(Object info, int mode);
257        public Object getCollectionInfo(Object info);
258        public void setCollectionInfo(Object info, Object collectionInfo);
259        public Object getCollectionItemInfo(Object info);
260        public void setCollectionItemInfo(Object info, Object collectionItemInfo);
261        public Object getRangeInfo(Object info);
262        public List<Object> getActionList(Object info);
263        public Object obtainCollectionInfo(int rowCount, int columnCount, boolean hierarchical,
264                int selectionMode);
265        public int getCollectionInfoColumnCount(Object info);
266        public int getCollectionInfoRowCount(Object info);
267        public boolean isCollectionInfoHierarchical(Object info);
268        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
269                int columnSpan, boolean heading, boolean selected);
270        public int getCollectionItemColumnIndex(Object info);
271        public int getCollectionItemColumnSpan(Object info);
272        public int getCollectionItemRowIndex(Object info);
273        public int getCollectionItemRowSpan(Object info);
274        public boolean isCollectionItemHeading(Object info);
275        public boolean isCollectionItemSelected(Object info);
276    }
277
278    static class AccessibilityNodeInfoStubImpl implements AccessibilityNodeInfoImpl {
279        @Override
280        public Object newAccessibilityAction(int actionId, CharSequence label) {
281            return null;
282        }
283
284        @Override
285        public Object obtain() {
286            return null;
287        }
288
289        @Override
290        public Object obtain(View source) {
291            return null;
292        }
293
294        @Override
295        public Object obtain(View root, int virtualDescendantId) {
296            return null;
297        }
298
299        @Override
300        public Object obtain(Object info) {
301            return null;
302        }
303
304        @Override
305        public void addAction(Object info, int action) {
306
307        }
308
309        @Override
310        public void addAction(Object info, Object action) {
311
312        }
313
314        @Override
315        public int getAccessibilityActionId(Object action) {
316            return 0;
317        }
318
319        @Override
320        public CharSequence getAccessibilityActionLabel(Object action) {
321            return null;
322        }
323
324        @Override
325        public void addChild(Object info, View child) {
326
327        }
328
329        @Override
330        public void addChild(Object info, View child, int virtualDescendantId) {
331
332        }
333
334        @Override
335        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
336            return Collections.emptyList();
337        }
338
339        @Override
340        public int getActions(Object info) {
341            return 0;
342        }
343
344        @Override
345        public void getBoundsInParent(Object info, Rect outBounds) {
346
347        }
348
349        @Override
350        public void getBoundsInScreen(Object info, Rect outBounds) {
351
352        }
353
354        @Override
355        public Object getChild(Object info, int index) {
356            return null;
357        }
358
359        @Override
360        public int getChildCount(Object info) {
361            return 0;
362        }
363
364        @Override
365        public CharSequence getClassName(Object info) {
366            return null;
367        }
368
369        @Override
370        public CharSequence getContentDescription(Object info) {
371            return null;
372        }
373
374        @Override
375        public CharSequence getPackageName(Object info) {
376            return null;
377        }
378
379        @Override
380        public Object getParent(Object info) {
381            return null;
382        }
383
384        @Override
385        public CharSequence getText(Object info) {
386            return null;
387        }
388
389        @Override
390        public int getWindowId(Object info) {
391            return 0;
392        }
393
394        @Override
395        public boolean isCheckable(Object info) {
396            return false;
397        }
398
399        @Override
400        public boolean isChecked(Object info) {
401            return false;
402        }
403
404        @Override
405        public boolean isClickable(Object info) {
406            return false;
407        }
408
409        @Override
410        public boolean isEnabled(Object info) {
411            return false;
412        }
413
414        @Override
415        public boolean isFocusable(Object info) {
416            return false;
417        }
418
419        @Override
420        public boolean isFocused(Object info) {
421            return false;
422        }
423
424        @Override
425        public boolean isVisibleToUser(Object info) {
426            return false;
427        }
428
429        @Override
430        public boolean isAccessibilityFocused(Object info) {
431            return false;
432        }
433
434        @Override
435        public boolean isLongClickable(Object info) {
436            return false;
437        }
438
439        @Override
440        public boolean isPassword(Object info) {
441            return false;
442        }
443
444        @Override
445        public boolean isScrollable(Object info) {
446            return false;
447        }
448
449        @Override
450        public boolean isSelected(Object info) {
451            return false;
452        }
453
454        @Override
455        public boolean performAction(Object info, int action) {
456            return false;
457        }
458
459        @Override
460        public boolean performAction(Object info, int action, Bundle arguments) {
461            return false;
462        }
463
464        @Override
465        public void setMovementGranularities(Object info, int granularities) {
466
467        }
468
469        @Override
470        public int getMovementGranularities(Object info) {
471            return 0;
472        }
473
474        @Override
475        public void setBoundsInParent(Object info, Rect bounds) {
476
477        }
478
479        @Override
480        public void setBoundsInScreen(Object info, Rect bounds) {
481
482        }
483
484        @Override
485        public void setCheckable(Object info, boolean checkable) {
486
487        }
488
489        @Override
490        public void setChecked(Object info, boolean checked) {
491
492        }
493
494        @Override
495        public void setClassName(Object info, CharSequence className) {
496
497        }
498
499        @Override
500        public void setClickable(Object info, boolean clickable) {
501
502        }
503
504        @Override
505        public void setContentDescription(Object info, CharSequence contentDescription) {
506
507        }
508
509        @Override
510        public void setEnabled(Object info, boolean enabled) {
511
512        }
513
514        @Override
515        public void setFocusable(Object info, boolean focusable) {
516
517        }
518
519        @Override
520        public void setFocused(Object info, boolean focused) {
521
522        }
523
524        @Override
525        public void setVisibleToUser(Object info, boolean visibleToUser) {
526
527        }
528
529        @Override
530        public void setAccessibilityFocused(Object info, boolean focused) {
531
532        }
533
534        @Override
535        public void setLongClickable(Object info, boolean longClickable) {
536
537        }
538
539        @Override
540        public void setPackageName(Object info, CharSequence packageName) {
541
542        }
543
544        @Override
545        public void setParent(Object info, View parent) {
546
547        }
548
549        @Override
550        public void setPassword(Object info, boolean password) {
551
552        }
553
554        @Override
555        public void setScrollable(Object info, boolean scrollable) {
556
557        }
558
559        @Override
560        public void setSelected(Object info, boolean selected) {
561
562        }
563
564        @Override
565        public void setSource(Object info, View source) {
566
567        }
568
569        @Override
570        public void setSource(Object info, View root, int virtualDescendantId) {
571
572        }
573
574        @Override
575        public Object findFocus(Object info, int focus) {
576            return null;
577        }
578
579        @Override
580        public Object focusSearch(Object info, int direction) {
581            return null;
582        }
583
584        @Override
585        public void setText(Object info, CharSequence text) {
586
587        }
588
589        @Override
590        public void recycle(Object info) {
591
592        }
593
594        @Override
595        public void setParent(Object info, View root, int virtualDescendantId) {
596
597        }
598
599        @Override
600        public String getViewIdResourceName(Object info) {
601            return null;
602        }
603
604        @Override
605        public void setViewIdResourceName(Object info, String viewId) {
606
607        }
608
609        @Override
610        public int getLiveRegion(Object info) {
611            return ViewCompat.ACCESSIBILITY_LIVE_REGION_NONE;
612        }
613
614        @Override
615        public void setLiveRegion(Object info, int mode) {
616            // No-op
617        }
618
619        @Override
620        public Object getCollectionInfo(Object info) {
621            return null;
622        }
623
624        @Override
625        public void setCollectionInfo(Object info, Object collectionInfo) {
626        }
627
628        @Override
629        public Object getCollectionItemInfo(Object info) {
630            return null;
631        }
632
633        @Override
634        public void setCollectionItemInfo(Object info, Object collectionItemInfo) {
635        }
636
637        @Override
638        public Object getRangeInfo(Object info) {
639            return null;
640        }
641
642        @Override
643        public List<Object> getActionList(Object info) {
644            return null;
645        }
646
647        @Override
648        public Object obtainCollectionInfo(int rowCount, int columnCount, boolean hierarchical,
649                int selectionMode) {
650            return null;
651        }
652
653        @Override
654        public int getCollectionInfoColumnCount(Object info) {
655            return 0;
656        }
657
658        @Override
659        public int getCollectionInfoRowCount(Object info) {
660            return 0;
661        }
662
663        @Override
664        public boolean isCollectionInfoHierarchical(Object info) {
665            return false;
666        }
667
668        @Override
669        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
670                int columnSpan, boolean heading, boolean selected) {
671            return null;
672        }
673
674        @Override
675        public int getCollectionItemColumnIndex(Object info) {
676            return 0;
677        }
678
679        @Override
680        public int getCollectionItemColumnSpan(Object info) {
681            return 0;
682        }
683
684        @Override
685        public int getCollectionItemRowIndex(Object info) {
686            return 0;
687        }
688
689        @Override
690        public int getCollectionItemRowSpan(Object info) {
691            return 0;
692        }
693
694        @Override
695        public boolean isCollectionItemHeading(Object info) {
696            return false;
697        }
698
699        @Override
700        public boolean isCollectionItemSelected(Object info) {
701            return false;
702        }
703    }
704
705    static class AccessibilityNodeInfoIcsImpl extends AccessibilityNodeInfoStubImpl {
706        @Override
707        public Object obtain() {
708            return AccessibilityNodeInfoCompatIcs.obtain();
709        }
710
711        @Override
712        public Object obtain(View source) {
713            return AccessibilityNodeInfoCompatIcs.obtain(source);
714        }
715
716        @Override
717        public Object obtain(Object info) {
718            return AccessibilityNodeInfoCompatIcs.obtain(info);
719        }
720
721        @Override
722        public void addAction(Object info, int action) {
723            AccessibilityNodeInfoCompatIcs.addAction(info, action);
724        }
725
726        @Override
727        public void addChild(Object info, View child) {
728            AccessibilityNodeInfoCompatIcs.addChild(info, child);
729        }
730
731        @Override
732        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
733            return AccessibilityNodeInfoCompatIcs.findAccessibilityNodeInfosByText(info, text);
734        }
735
736        @Override
737        public int getActions(Object info) {
738            return AccessibilityNodeInfoCompatIcs.getActions(info);
739        }
740
741        @Override
742        public void getBoundsInParent(Object info, Rect outBounds) {
743            AccessibilityNodeInfoCompatIcs.getBoundsInParent(info, outBounds);
744        }
745
746        @Override
747        public void getBoundsInScreen(Object info, Rect outBounds) {
748            AccessibilityNodeInfoCompatIcs.getBoundsInScreen(info, outBounds);
749        }
750
751        @Override
752        public Object getChild(Object info, int index) {
753            return AccessibilityNodeInfoCompatIcs.getChild(info, index);
754        }
755
756        @Override
757        public int getChildCount(Object info) {
758            return AccessibilityNodeInfoCompatIcs.getChildCount(info);
759        }
760
761        @Override
762        public CharSequence getClassName(Object info) {
763            return AccessibilityNodeInfoCompatIcs.getClassName(info);
764        }
765
766        @Override
767        public CharSequence getContentDescription(Object info) {
768            return AccessibilityNodeInfoCompatIcs.getContentDescription(info);
769        }
770
771        @Override
772        public CharSequence getPackageName(Object info) {
773            return AccessibilityNodeInfoCompatIcs.getPackageName(info);
774        }
775
776        @Override
777        public Object getParent(Object info) {
778            return AccessibilityNodeInfoCompatIcs.getParent(info);
779        }
780
781        @Override
782        public CharSequence getText(Object info) {
783            return AccessibilityNodeInfoCompatIcs.getText(info);
784        }
785
786        @Override
787        public int getWindowId(Object info) {
788            return AccessibilityNodeInfoCompatIcs.getWindowId(info);
789        }
790
791        @Override
792        public boolean isCheckable(Object info) {
793            return AccessibilityNodeInfoCompatIcs.isCheckable(info);
794        }
795
796        @Override
797        public boolean isChecked(Object info) {
798            return AccessibilityNodeInfoCompatIcs.isChecked(info);
799        }
800
801        @Override
802        public boolean isClickable(Object info) {
803            return AccessibilityNodeInfoCompatIcs.isClickable(info);
804        }
805
806        @Override
807        public boolean isEnabled(Object info) {
808            return AccessibilityNodeInfoCompatIcs.isEnabled(info);
809        }
810
811        @Override
812        public boolean isFocusable(Object info) {
813            return AccessibilityNodeInfoCompatIcs.isFocusable(info);
814        }
815
816        @Override
817        public boolean isFocused(Object info) {
818            return AccessibilityNodeInfoCompatIcs.isFocused(info);
819        }
820
821        @Override
822        public boolean isLongClickable(Object info) {
823            return AccessibilityNodeInfoCompatIcs.isLongClickable(info);
824        }
825
826        @Override
827        public boolean isPassword(Object info) {
828            return AccessibilityNodeInfoCompatIcs.isPassword(info);
829        }
830
831        @Override
832        public boolean isScrollable(Object info) {
833            return AccessibilityNodeInfoCompatIcs.isScrollable(info);
834        }
835
836        @Override
837        public boolean isSelected(Object info) {
838            return AccessibilityNodeInfoCompatIcs.isSelected(info);
839        }
840
841        @Override
842        public boolean performAction(Object info, int action) {
843            return AccessibilityNodeInfoCompatIcs.performAction(info, action);
844        }
845
846        @Override
847        public void setBoundsInParent(Object info, Rect bounds) {
848            AccessibilityNodeInfoCompatIcs.setBoundsInParent(info, bounds);
849        }
850
851        @Override
852        public void setBoundsInScreen(Object info, Rect bounds) {
853            AccessibilityNodeInfoCompatIcs.setBoundsInScreen(info, bounds);
854        }
855
856        @Override
857        public void setCheckable(Object info, boolean checkable) {
858            AccessibilityNodeInfoCompatIcs.setCheckable(info, checkable);
859        }
860
861        @Override
862        public void setChecked(Object info, boolean checked) {
863            AccessibilityNodeInfoCompatIcs.setChecked(info, checked);
864        }
865
866        @Override
867        public void setClassName(Object info, CharSequence className) {
868            AccessibilityNodeInfoCompatIcs.setClassName(info, className);
869        }
870
871        @Override
872        public void setClickable(Object info, boolean clickable) {
873            AccessibilityNodeInfoCompatIcs.setClickable(info, clickable);
874        }
875
876        @Override
877        public void setContentDescription(Object info, CharSequence contentDescription) {
878            AccessibilityNodeInfoCompatIcs.setContentDescription(info, contentDescription);
879        }
880
881        @Override
882        public void setEnabled(Object info, boolean enabled) {
883            AccessibilityNodeInfoCompatIcs.setEnabled(info, enabled);
884        }
885
886        @Override
887        public void setFocusable(Object info, boolean focusable) {
888            AccessibilityNodeInfoCompatIcs.setFocusable(info, focusable);
889        }
890
891        @Override
892        public void setFocused(Object info, boolean focused) {
893            AccessibilityNodeInfoCompatIcs.setFocused(info, focused);
894        }
895
896        @Override
897        public void setLongClickable(Object info, boolean longClickable) {
898            AccessibilityNodeInfoCompatIcs.setLongClickable(info, longClickable);
899        }
900
901        @Override
902        public void setPackageName(Object info, CharSequence packageName) {
903            AccessibilityNodeInfoCompatIcs.setPackageName(info, packageName);
904        }
905
906        @Override
907        public void setParent(Object info, View parent) {
908            AccessibilityNodeInfoCompatIcs.setParent(info, parent);
909        }
910
911        @Override
912        public void setPassword(Object info, boolean password) {
913            AccessibilityNodeInfoCompatIcs.setPassword(info, password);
914        }
915
916        @Override
917        public void setScrollable(Object info, boolean scrollable) {
918            AccessibilityNodeInfoCompatIcs.setScrollable(info, scrollable);
919        }
920
921        @Override
922        public void setSelected(Object info, boolean selected) {
923            AccessibilityNodeInfoCompatIcs.setSelected(info, selected);
924        }
925
926        @Override
927        public void setSource(Object info, View source) {
928            AccessibilityNodeInfoCompatIcs.setSource(info, source);
929        }
930
931        @Override
932        public void setText(Object info, CharSequence text) {
933            AccessibilityNodeInfoCompatIcs.setText(info, text);
934        }
935
936        @Override
937        public void recycle(Object info) {
938            AccessibilityNodeInfoCompatIcs.recycle(info);
939        }
940    }
941
942    static class AccessibilityNodeInfoJellybeanImpl extends AccessibilityNodeInfoIcsImpl {
943        @Override
944        public Object obtain(View root, int virtualDescendantId) {
945            return AccessibilityNodeInfoCompatJellyBean.obtain(root, virtualDescendantId);
946        }
947
948        @Override
949        public Object findFocus(Object info, int focus) {
950            return AccessibilityNodeInfoCompatJellyBean.findFocus(info, focus);
951        }
952
953        @Override
954        public Object focusSearch(Object info, int direction) {
955            return AccessibilityNodeInfoCompatJellyBean.focusSearch(info, direction);
956        }
957
958        @Override
959        public void addChild(Object info, View child, int virtualDescendantId) {
960            AccessibilityNodeInfoCompatJellyBean.addChild(info, child, virtualDescendantId);
961        }
962
963        @Override
964        public void setSource(Object info, View root, int virtualDescendantId) {
965            AccessibilityNodeInfoCompatJellyBean.setSource(info, root, virtualDescendantId);
966        }
967
968        @Override
969        public boolean isVisibleToUser(Object info) {
970            return AccessibilityNodeInfoCompatJellyBean.isVisibleToUser(info);
971        }
972
973        @Override
974        public void setVisibleToUser(Object info, boolean visibleToUser) {
975            AccessibilityNodeInfoCompatJellyBean.setVisibleToUser(info, visibleToUser);
976        }
977
978        @Override
979        public boolean isAccessibilityFocused(Object info) {
980            return AccessibilityNodeInfoCompatJellyBean.isAccessibilityFocused(info);
981        }
982
983        @Override
984        public void setAccessibilityFocused(Object info, boolean focused) {
985            AccessibilityNodeInfoCompatJellyBean.setAccesibilityFocused(info, focused);
986        }
987
988        @Override
989        public boolean performAction(Object info, int action, Bundle arguments) {
990            return AccessibilityNodeInfoCompatJellyBean.performAction(info, action, arguments);
991        }
992
993        @Override
994        public void setMovementGranularities(Object info, int granularities) {
995            AccessibilityNodeInfoCompatJellyBean.setMovementGranularities(info, granularities);
996        }
997
998        @Override
999        public int getMovementGranularities(Object info) {
1000            return AccessibilityNodeInfoCompatJellyBean.getMovementGranularities(info);
1001        }
1002
1003        @Override
1004        public void setParent(Object info, View root, int virtualDescendantId) {
1005            AccessibilityNodeInfoCompatJellyBean.setParent(info, root, virtualDescendantId);
1006        }
1007    }
1008
1009    static class AccessibilityNodeInfoJellybeanMr2Impl extends AccessibilityNodeInfoJellybeanImpl {
1010
1011        @Override
1012        public String getViewIdResourceName(Object info) {
1013            return AccessibilityNodeInfoCompatJellybeanMr2.getViewIdResourceName(info);
1014        }
1015
1016        @Override
1017        public void setViewIdResourceName(Object info, String viewId) {
1018            AccessibilityNodeInfoCompatJellybeanMr2.setViewIdResourceName(info, viewId);
1019        }
1020    }
1021
1022    static class AccessibilityNodeInfoKitKatImpl extends AccessibilityNodeInfoJellybeanMr2Impl {
1023        @Override
1024        public int getLiveRegion(Object info) {
1025            return AccessibilityNodeInfoCompatKitKat.getLiveRegion(info);
1026        }
1027
1028        @Override
1029        public void setLiveRegion(Object info, int mode) {
1030            AccessibilityNodeInfoCompatKitKat.setLiveRegion(info, mode);
1031        }
1032
1033        @Override
1034        public Object getCollectionInfo(Object info) {
1035            return AccessibilityNodeInfoCompatKitKat.getCollectionInfo(info);
1036        }
1037
1038        @Override
1039        public void setCollectionInfo(Object info, Object collectionInfo) {
1040            AccessibilityNodeInfoCompatKitKat.setCollectionInfo(info, collectionInfo);
1041        }
1042
1043        @Override
1044        public Object obtainCollectionInfo(int rowCount, int columnCount,
1045                boolean hierarchical, int selectionMode) {
1046            return AccessibilityNodeInfoCompatKitKat.obtainCollectionInfo(rowCount, columnCount,
1047                    hierarchical, selectionMode);
1048        }
1049
1050        @Override
1051        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
1052                int columnSpan, boolean heading, boolean selected) {
1053            return AccessibilityNodeInfoCompatKitKat
1054                    .obtainCollectionItemInfo(rowIndex, rowSpan, columnIndex, columnSpan, heading);
1055        }
1056
1057        @Override
1058        public int getCollectionInfoColumnCount(Object info) {
1059            return AccessibilityNodeInfoCompatKitKat.CollectionInfo.getColumnCount(info);
1060        }
1061
1062        @Override
1063        public int getCollectionInfoRowCount(Object info) {
1064            return AccessibilityNodeInfoCompatKitKat.CollectionInfo.getRowCount(info);
1065        }
1066
1067        @Override
1068        public boolean isCollectionInfoHierarchical(Object info) {
1069            return AccessibilityNodeInfoCompatKitKat.CollectionInfo.isHierarchical(info);
1070        }
1071
1072        @Override
1073        public Object getCollectionItemInfo(Object info) {
1074            return AccessibilityNodeInfoCompatKitKat.getCollectionItemInfo(info);
1075        }
1076
1077        @Override
1078        public Object getRangeInfo(Object info) {
1079            return AccessibilityNodeInfoCompatKitKat.getRangeInfo(info);
1080        }
1081
1082        @Override
1083        public int getCollectionItemColumnIndex(Object info) {
1084            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getColumnIndex(info);
1085        }
1086
1087        @Override
1088        public int getCollectionItemColumnSpan(Object info) {
1089            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getColumnSpan(info);
1090        }
1091
1092        @Override
1093        public int getCollectionItemRowIndex(Object info) {
1094            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getRowIndex(info);
1095        }
1096
1097        @Override
1098        public int getCollectionItemRowSpan(Object info) {
1099            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getRowSpan(info);
1100        }
1101
1102        @Override
1103        public boolean isCollectionItemHeading(Object info) {
1104            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.isHeading(info);
1105        }
1106
1107        @Override
1108        public void setCollectionItemInfo(Object info, Object collectionItemInfo) {
1109            AccessibilityNodeInfoCompatKitKat.setCollectionItemInfo(info, collectionItemInfo);
1110        }
1111    }
1112
1113    static class AccessibilityNodeInfoApi21Impl extends AccessibilityNodeInfoKitKatImpl {
1114        @Override
1115        public Object newAccessibilityAction(int actionId, CharSequence label) {
1116            return AccessibilityNodeInfoCompatApi21.newAccessibilityAction(actionId, label);
1117        }
1118
1119        @Override
1120        public List<Object> getActionList(Object info) {
1121            return AccessibilityNodeInfoCompatApi21.getActionList(info);
1122        }
1123
1124        @Override
1125        public Object obtainCollectionInfo(int rowCount, int columnCount, boolean hierarchical,
1126                int selectionMode) {
1127            return AccessibilityNodeInfoCompatApi21.obtainCollectionInfo(rowCount, columnCount,
1128                    hierarchical, selectionMode);
1129        }
1130
1131        @Override
1132        public void addAction(Object info, Object action) {
1133            AccessibilityNodeInfoCompatApi21.addAction(info, action);
1134        }
1135
1136        @Override
1137        public int getAccessibilityActionId(Object action) {
1138            return AccessibilityNodeInfoCompatApi21.getAccessibilityActionId(action);
1139        }
1140
1141        @Override
1142        public CharSequence getAccessibilityActionLabel(Object action) {
1143            return AccessibilityNodeInfoCompatApi21.getAccessibilityActionLabel(action);
1144        }
1145
1146        @Override
1147        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
1148                int columnSpan, boolean heading, boolean selected) {
1149            return AccessibilityNodeInfoCompatApi21.obtainCollectionItemInfo(rowIndex, rowSpan,
1150                    columnIndex, columnSpan, heading, selected);
1151        }
1152
1153        @Override
1154        public boolean isCollectionItemSelected(Object info) {
1155            return AccessibilityNodeInfoCompatApi21.CollectionItemInfo.isSelected(info);
1156        }
1157    }
1158
1159    static {
1160        if (Build.VERSION.SDK_INT >= 21) {
1161            IMPL = new AccessibilityNodeInfoApi21Impl();
1162        } else if (Build.VERSION.SDK_INT >= 19) { // KitKat
1163            IMPL = new AccessibilityNodeInfoKitKatImpl();
1164        } else if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
1165            IMPL = new AccessibilityNodeInfoJellybeanMr2Impl();
1166        } else if (Build.VERSION.SDK_INT >= 16) { // JellyBean
1167            IMPL = new AccessibilityNodeInfoJellybeanImpl();
1168        } else if (Build.VERSION.SDK_INT >= 14) { // ICS
1169            IMPL = new AccessibilityNodeInfoIcsImpl();
1170        } else {
1171            IMPL = new AccessibilityNodeInfoStubImpl();
1172        }
1173    }
1174
1175    private static final AccessibilityNodeInfoImpl IMPL;
1176
1177    private final Object mInfo;
1178
1179    // Actions introduced in IceCreamSandwich
1180
1181    /**
1182     * Action that focuses the node.
1183     */
1184    public static final int ACTION_FOCUS = 0x00000001;
1185
1186    /**
1187     * Action that unfocuses the node.
1188     */
1189    public static final int ACTION_CLEAR_FOCUS = 0x00000002;
1190
1191    /**
1192     * Action that selects the node.
1193     */
1194    public static final int ACTION_SELECT = 0x00000004;
1195
1196    /**
1197     * Action that unselects the node.
1198     */
1199    public static final int ACTION_CLEAR_SELECTION = 0x00000008;
1200
1201    /**
1202     * Action that clicks on the node info.
1203     */
1204    public static final int ACTION_CLICK = 0x00000010;
1205
1206    /**
1207     * Action that long clicks on the node.
1208     */
1209    public static final int ACTION_LONG_CLICK = 0x00000020;
1210
1211    // Actions introduced in JellyBean
1212
1213    /**
1214     * Action that gives accessibility focus to the node.
1215     */
1216    public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
1217
1218    /**
1219     * Action that clears accessibility focus of the node.
1220     */
1221    public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
1222
1223    /**
1224     * Action that requests to go to the next entity in this node's text
1225     * at a given movement granularity. For example, move to the next character,
1226     * word, etc.
1227     * <p>
1228     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
1229     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
1230     * <strong>Example:</strong> Move to the previous character and do not extend selection.
1231     * <code><pre><p>
1232     *   Bundle arguments = new Bundle();
1233     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
1234     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1235     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
1236     *           false);
1237     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1238     * </code></pre></p>
1239     * </p>
1240     *
1241     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
1242     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
1243     *
1244     * @see #setMovementGranularities(int)
1245     * @see #getMovementGranularities()
1246     *
1247     * @see #MOVEMENT_GRANULARITY_CHARACTER
1248     * @see #MOVEMENT_GRANULARITY_WORD
1249     * @see #MOVEMENT_GRANULARITY_LINE
1250     * @see #MOVEMENT_GRANULARITY_PARAGRAPH
1251     * @see #MOVEMENT_GRANULARITY_PAGE
1252     */
1253    public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
1254
1255    /**
1256     * Action that requests to go to the previous entity in this node's text
1257     * at a given movement granularity. For example, move to the next character,
1258     * word, etc.
1259     * <p>
1260     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
1261     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
1262     * <strong>Example:</strong> Move to the next character and do not extend selection.
1263     * <code><pre><p>
1264     *   Bundle arguments = new Bundle();
1265     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
1266     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1267     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
1268     *           false);
1269     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
1270     *           arguments);
1271     * </code></pre></p>
1272     * </p>
1273     *
1274     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
1275     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
1276     *
1277     * @see #setMovementGranularities(int)
1278     * @see #getMovementGranularities()
1279     *
1280     * @see #MOVEMENT_GRANULARITY_CHARACTER
1281     * @see #MOVEMENT_GRANULARITY_WORD
1282     * @see #MOVEMENT_GRANULARITY_LINE
1283     * @see #MOVEMENT_GRANULARITY_PARAGRAPH
1284     * @see #MOVEMENT_GRANULARITY_PAGE
1285     */
1286    public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
1287
1288    /**
1289     * Action to move to the next HTML element of a given type. For example, move
1290     * to the BUTTON, INPUT, TABLE, etc.
1291     * <p>
1292     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
1293     * <strong>Example:</strong>
1294     * <code><pre><p>
1295     *   Bundle arguments = new Bundle();
1296     *   arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
1297     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
1298     * </code></pre></p>
1299     * </p>
1300     */
1301    public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
1302
1303    /**
1304     * Action to move to the previous HTML element of a given type. For example, move
1305     * to the BUTTON, INPUT, TABLE, etc.
1306     * <p>
1307     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
1308     * <strong>Example:</strong>
1309     * <code><pre><p>
1310     *   Bundle arguments = new Bundle();
1311     *   arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
1312     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
1313     * </code></pre></p>
1314     * </p>
1315     */
1316    public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
1317
1318    /**
1319     * Action to scroll the node content forward.
1320     */
1321    public static final int ACTION_SCROLL_FORWARD = 0x00001000;
1322
1323    /**
1324     * Action to scroll the node content backward.
1325     */
1326    public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
1327
1328    // Actions introduced in JellyBeanMr2
1329
1330    /**
1331     * Action to copy the current selection to the clipboard.
1332     */
1333    public static final int ACTION_COPY = 0x00004000;
1334
1335    /**
1336     * Action to paste the current clipboard content.
1337     */
1338    public static final int ACTION_PASTE = 0x00008000;
1339
1340    /**
1341     * Action to cut the current selection and place it to the clipboard.
1342     */
1343    public static final int ACTION_CUT = 0x00010000;
1344
1345    /**
1346     * Action to set the selection. Performing this action with no arguments
1347     * clears the selection.
1348     * <p>
1349     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SELECTION_START_INT},
1350     * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
1351     * <strong>Example:</strong>
1352     * <code><pre><p>
1353     *   Bundle arguments = new Bundle();
1354     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
1355     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
1356     *   info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
1357     * </code></pre></p>
1358     * </p>
1359     *
1360     * @see #ACTION_ARGUMENT_SELECTION_START_INT
1361     * @see #ACTION_ARGUMENT_SELECTION_END_INT
1362     */
1363    public static final int ACTION_SET_SELECTION = 0x00020000;
1364
1365    /**
1366     * Action that sets the text of the node. Performing the action without argument, using <code>
1367     * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
1368     * cursor at the end of text.
1369     * <p>
1370     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
1371     * <strong>Example:</strong>
1372     * <code><pre><p>
1373     *   Bundle arguments = new Bundle();
1374     *   arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
1375     *       "android");
1376     *   info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
1377     * </code></pre></p>
1378     */
1379    public static final int ACTION_SET_TEXT = 0x00200000;
1380
1381    // Action arguments
1382
1383    /**
1384     * Argument for which movement granularity to be used when traversing the node text.
1385     * <p>
1386     * <strong>Type:</strong> int<br>
1387     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
1388     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
1389     * </p>
1390     */
1391    public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
1392        "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
1393
1394    /**
1395     * Argument for which HTML element to get moving to the next/previous HTML element.
1396     * <p>
1397     * <strong>Type:</strong> String<br>
1398     * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
1399     *         {@link #ACTION_PREVIOUS_HTML_ELEMENT}
1400     * </p>
1401     */
1402    public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
1403        "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
1404
1405    /**
1406     * Argument for whether when moving at granularity to extend the selection
1407     * or to move it otherwise.
1408     * <p>
1409     * <strong>Type:</strong> boolean<br>
1410     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
1411     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
1412     * </p>
1413     *
1414     * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1415     * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1416     */
1417    public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
1418            "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
1419
1420    /**
1421     * Argument for specifying the selection start.
1422     * <p>
1423     * <strong>Type:</strong> int<br>
1424     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
1425     * </p>
1426     *
1427     * @see #ACTION_SET_SELECTION
1428     */
1429    public static final String ACTION_ARGUMENT_SELECTION_START_INT =
1430            "ACTION_ARGUMENT_SELECTION_START_INT";
1431
1432    /**
1433     * Argument for specifying the selection end.
1434     * <p>
1435     * <strong>Type:</strong> int<br>
1436     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
1437     * </p>
1438     *
1439     * @see #ACTION_SET_SELECTION
1440     */
1441    public static final String ACTION_ARGUMENT_SELECTION_END_INT =
1442            "ACTION_ARGUMENT_SELECTION_END_INT";
1443
1444    /**
1445     * Argument for specifying the text content to set
1446     * <p>
1447     * <strong>Type:</strong> CharSequence<br>
1448     * <strong>Actions:</strong> {@link #ACTION_SET_TEXT}
1449     * </p>
1450     *
1451     * @see #ACTION_SET_TEXT
1452     */
1453    public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
1454            "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
1455
1456    // Focus types
1457
1458    /**
1459     * The input focus.
1460     */
1461    public static final int FOCUS_INPUT = 1;
1462
1463    /**
1464     * The accessibility focus.
1465     */
1466    public static final int FOCUS_ACCESSIBILITY = 2;
1467
1468    // Movement granularities
1469
1470    /**
1471     * Movement granularity bit for traversing the text of a node by character.
1472     */
1473    public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
1474
1475    /**
1476     * Movement granularity bit for traversing the text of a node by word.
1477     */
1478    public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
1479
1480    /**
1481     * Movement granularity bit for traversing the text of a node by line.
1482     */
1483    public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
1484
1485    /**
1486     * Movement granularity bit for traversing the text of a node by paragraph.
1487     */
1488    public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
1489
1490    /**
1491     * Movement granularity bit for traversing the text of a node by page.
1492     */
1493    public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
1494
1495    /**
1496     * Creates a wrapper for info implementation.
1497     *
1498     * @param object The info to wrap.
1499     * @return A wrapper for if the object is not null, null otherwise.
1500     */
1501    static AccessibilityNodeInfoCompat wrapNonNullInstance(Object object) {
1502        if (object != null) {
1503            return new AccessibilityNodeInfoCompat(object);
1504        }
1505        return null;
1506    }
1507
1508    /**
1509     * Creates a new instance wrapping an
1510     * {@link android.view.accessibility.AccessibilityNodeInfo}.
1511     *
1512     * @param info The info.
1513     */
1514    public AccessibilityNodeInfoCompat(Object info) {
1515        mInfo = info;
1516    }
1517
1518    /**
1519     * @return The wrapped {@link android.view.accessibility.AccessibilityNodeInfo}.
1520     */
1521    public Object getInfo() {
1522        return mInfo;
1523    }
1524
1525    /**
1526     * Returns a cached instance if such is available otherwise a new one and
1527     * sets the source.
1528     *
1529     * @return An instance.
1530     * @see #setSource(View)
1531     */
1532    public static AccessibilityNodeInfoCompat obtain(View source) {
1533        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain(source));
1534    }
1535
1536    /**
1537     * Returns a cached instance if such is available otherwise a new one
1538     * and sets the source.
1539     *
1540     * @param root The root of the virtual subtree.
1541     * @param virtualDescendantId The id of the virtual descendant.
1542     * @return An instance.
1543     *
1544     * @see #setSource(View, int)
1545     */
1546    public static AccessibilityNodeInfoCompat obtain(View root, int virtualDescendantId) {
1547        return AccessibilityNodeInfoCompat.wrapNonNullInstance(
1548                IMPL.obtain(root, virtualDescendantId));
1549    }
1550
1551    /**
1552     * Returns a cached instance if such is available otherwise a new one.
1553     *
1554     * @return An instance.
1555     */
1556    public static AccessibilityNodeInfoCompat obtain() {
1557        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain());
1558    }
1559
1560    /**
1561     * Returns a cached instance if such is available or a new one is create.
1562     * The returned instance is initialized from the given <code>info</code>.
1563     *
1564     * @param info The other info.
1565     * @return An instance.
1566     */
1567    public static AccessibilityNodeInfoCompat obtain(AccessibilityNodeInfoCompat info) {
1568        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain(info.mInfo));
1569    }
1570
1571    /**
1572     * Sets the source.
1573     *
1574     * @param source The info source.
1575     */
1576    public void setSource(View source) {
1577        IMPL.setSource(mInfo, source);
1578    }
1579
1580    /**
1581     * Sets the source to be a virtual descendant of the given <code>root</code>.
1582     * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
1583     * is set as the source.
1584     * <p>
1585     * A virtual descendant is an imaginary View that is reported as a part of the view
1586     * hierarchy for accessibility purposes. This enables custom views that draw complex
1587     * content to report themselves as a tree of virtual views, thus conveying their
1588     * logical structure.
1589     * </p>
1590     * <p>
1591     *   <strong>Note:</strong> Cannot be called from an
1592     *   {@link android.accessibilityservice.AccessibilityService}.
1593     *   This class is made immutable before being delivered to an AccessibilityService.
1594     * </p>
1595     *
1596     * @param root The root of the virtual subtree.
1597     * @param virtualDescendantId The id of the virtual descendant.
1598     */
1599    public void setSource(View root, int virtualDescendantId) {
1600        IMPL.setSource(mInfo, root, virtualDescendantId);
1601    }
1602
1603    /**
1604     * Find the view that has the specified focus type. The search starts from
1605     * the view represented by this node info.
1606     *
1607     * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
1608     *         {@link #FOCUS_ACCESSIBILITY}.
1609     * @return The node info of the focused view or null.
1610     *
1611     * @see #FOCUS_INPUT
1612     * @see #FOCUS_ACCESSIBILITY
1613     */
1614    public AccessibilityNodeInfoCompat findFocus(int focus) {
1615        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.findFocus(mInfo, focus));
1616    }
1617
1618    /**
1619     * Searches for the nearest view in the specified direction that can take
1620     * input focus.
1621     *
1622     * @param direction The direction. Can be one of:
1623     *     {@link View#FOCUS_DOWN},
1624     *     {@link View#FOCUS_UP},
1625     *     {@link View#FOCUS_LEFT},
1626     *     {@link View#FOCUS_RIGHT},
1627     *     {@link View#FOCUS_FORWARD},
1628     *     {@link View#FOCUS_BACKWARD}.
1629     *
1630     * @return The node info for the view that can take accessibility focus.
1631     */
1632    public AccessibilityNodeInfoCompat focusSearch(int direction) {
1633        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.focusSearch(mInfo, direction));
1634    }
1635
1636    /**
1637     * Gets the id of the window from which the info comes from.
1638     *
1639     * @return The window id.
1640     */
1641    public int getWindowId() {
1642        return IMPL.getWindowId(mInfo);
1643    }
1644
1645    /**
1646     * Gets the number of children.
1647     *
1648     * @return The child count.
1649     */
1650    public int getChildCount() {
1651        return IMPL.getChildCount(mInfo);
1652    }
1653
1654    /**
1655     * Get the child at given index.
1656     * <p>
1657     * <strong>Note:</strong> It is a client responsibility to recycle the
1658     * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} to
1659     * avoid creating of multiple instances.
1660     * </p>
1661     *
1662     * @param index The child index.
1663     * @return The child node.
1664     * @throws IllegalStateException If called outside of an
1665     *             AccessibilityService.
1666     */
1667    public AccessibilityNodeInfoCompat getChild(int index) {
1668        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getChild(mInfo, index));
1669    }
1670
1671    /**
1672     * Adds a child.
1673     * <p>
1674     * <strong>Note:</strong> Cannot be called from an
1675     * {@link android.accessibilityservice.AccessibilityService}. This class is
1676     * made immutable before being delivered to an AccessibilityService.
1677     * </p>
1678     *
1679     * @param child The child.
1680     * @throws IllegalStateException If called from an AccessibilityService.
1681     */
1682    public void addChild(View child) {
1683        IMPL.addChild(mInfo, child);
1684    }
1685
1686    /**
1687     * Adds a virtual child which is a descendant of the given <code>root</code>.
1688     * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
1689     * is added as a child.
1690     * <p>
1691     * A virtual descendant is an imaginary View that is reported as a part of the view
1692     * hierarchy for accessibility purposes. This enables custom views that draw complex
1693     * content to report them selves as a tree of virtual views, thus conveying their
1694     * logical structure.
1695     * </p>
1696     *
1697     * @param root The root of the virtual subtree.
1698     * @param virtualDescendantId The id of the virtual child.
1699     */
1700    public void addChild(View root, int virtualDescendantId) {
1701        IMPL.addChild(mInfo, root, virtualDescendantId);
1702    }
1703
1704    /**
1705     * Gets the actions that can be performed on the node.
1706     *
1707     * @return The bit mask of with actions.
1708     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_FOCUS
1709     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
1710     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_SELECT
1711     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
1712     */
1713    public int getActions() {
1714        return IMPL.getActions(mInfo);
1715    }
1716
1717    /**
1718     * Adds an action that can be performed on the node.
1719     * <p>
1720     * <strong>Note:</strong> Cannot be called from an
1721     * {@link android.accessibilityservice.AccessibilityService}. This class is
1722     * made immutable before being delivered to an AccessibilityService.
1723     * </p>
1724     *
1725     * @param action The action.
1726     * @throws IllegalStateException If called from an AccessibilityService.
1727     */
1728    public void addAction(int action) {
1729        IMPL.addAction(mInfo, action);
1730    }
1731
1732    /**
1733     * Adds an action that can be performed on the node.
1734     * <p>
1735     * <strong>Note:</strong> Cannot be called from an
1736     * {@link android.accessibilityservice.AccessibilityService}. This class is
1737     * made immutable before being delivered to an AccessibilityService.
1738     * </p>
1739     *
1740     * @param action The action.
1741     * @throws IllegalStateException If called from an AccessibilityService.
1742     */
1743    public void addAction(AccessibilityActionCompat action) {
1744        IMPL.addAction(mInfo, action.mAction);
1745    }
1746
1747    /**
1748     * Performs an action on the node.
1749     * <p>
1750     * <strong>Note:</strong> An action can be performed only if the request is
1751     * made from an {@link android.accessibilityservice.AccessibilityService}.
1752     * </p>
1753     *
1754     * @param action The action to perform.
1755     * @return True if the action was performed.
1756     * @throws IllegalStateException If called outside of an
1757     *             AccessibilityService.
1758     */
1759    public boolean performAction(int action) {
1760        return IMPL.performAction(mInfo, action);
1761    }
1762
1763    /**
1764     * Performs an action on the node.
1765     * <p>
1766     *   <strong>Note:</strong> An action can be performed only if the request is made
1767     *   from an {@link android.accessibilityservice.AccessibilityService}.
1768     * </p>
1769     *
1770     * @param action The action to perform.
1771     * @param arguments A bundle with additional arguments.
1772     * @return True if the action was performed.
1773     *
1774     * @throws IllegalStateException If called outside of an AccessibilityService.
1775     */
1776    public boolean performAction(int action, Bundle arguments) {
1777        return IMPL.performAction(mInfo, action, arguments);
1778    }
1779
1780    /**
1781     * Sets the movement granularities for traversing the text of this node.
1782     * <p>
1783     *   <strong>Note:</strong> Cannot be called from an
1784     *   {@link android.accessibilityservice.AccessibilityService}.
1785     *   This class is made immutable before being delivered to an AccessibilityService.
1786     * </p>
1787     *
1788     * @param granularities The bit mask with granularities.
1789     *
1790     * @throws IllegalStateException If called from an AccessibilityService.
1791     */
1792    public void setMovementGranularities(int granularities) {
1793        IMPL.setMovementGranularities(mInfo, granularities);
1794    }
1795
1796    /**
1797     * Gets the movement granularities for traversing the text of this node.
1798     *
1799     * @return The bit mask with granularities.
1800     */
1801    public int getMovementGranularities() {
1802        return IMPL.getMovementGranularities(mInfo);
1803    }
1804
1805    /**
1806     * Finds {@link android.view.accessibility.AccessibilityNodeInfo}s by text. The match
1807     * is case insensitive containment. The search is relative to this info i.e. this
1808     * info is the root of the traversed tree.
1809     * <p>
1810     * <strong>Note:</strong> It is a client responsibility to recycle the
1811     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
1812     * to avoid creating of multiple instances.
1813     * </p>
1814     *
1815     * @param text The searched text.
1816     * @return A list of node info.
1817     */
1818    public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text) {
1819        List<AccessibilityNodeInfoCompat> result = new ArrayList<AccessibilityNodeInfoCompat>();
1820        List<Object> infos = IMPL.findAccessibilityNodeInfosByText(mInfo, text);
1821        final int infoCount = infos.size();
1822        for (int i = 0; i < infoCount; i++) {
1823            Object info = infos.get(i);
1824            result.add(new AccessibilityNodeInfoCompat(info));
1825        }
1826        return result;
1827    }
1828
1829    /**
1830     * Gets the parent.
1831     * <p>
1832     * <strong>Note:</strong> It is a client responsibility to recycle the
1833     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
1834     * to avoid creating of multiple instances.
1835     * </p>
1836     *
1837     * @return The parent.
1838     */
1839    public AccessibilityNodeInfoCompat getParent() {
1840        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getParent(mInfo));
1841    }
1842
1843    /**
1844     * Sets the parent.
1845     * <p>
1846     * <strong>Note:</strong> Cannot be called from an
1847     * {@link android.accessibilityservice.AccessibilityService}. This class is
1848     * made immutable before being delivered to an AccessibilityService.
1849     * </p>
1850     *
1851     * @param parent The parent.
1852     * @throws IllegalStateException If called from an AccessibilityService.
1853     */
1854    public void setParent(View parent) {
1855        IMPL.setParent(mInfo, parent);
1856    }
1857
1858    /**
1859     * Sets the parent to be a virtual descendant of the given <code>root</code>.
1860     * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1861     * is set as the parent.
1862     * <p>
1863     * A virtual descendant is an imaginary View that is reported as a part of the view
1864     * hierarchy for accessibility purposes. This enables custom views that draw complex
1865     * content to report them selves as a tree of virtual views, thus conveying their
1866     * logical structure.
1867     * </p>
1868     * <p>
1869     *   <strong>Note:</strong> Cannot be called from an
1870     *   {@link android.accessibilityservice.AccessibilityService}.
1871     *   This class is made immutable before being delivered to an AccessibilityService.
1872     * </p>
1873     *
1874     * @param root The root of the virtual subtree.
1875     * @param virtualDescendantId The id of the virtual descendant.
1876     */
1877    public void setParent(View root, int virtualDescendantId) {
1878        IMPL.setParent(mInfo, root, virtualDescendantId);
1879    }
1880
1881    /**
1882     * Gets the node bounds in parent coordinates.
1883     *
1884     * @param outBounds The output node bounds.
1885     */
1886    public void getBoundsInParent(Rect outBounds) {
1887        IMPL.getBoundsInParent(mInfo, outBounds);
1888    }
1889
1890    /**
1891     * Sets the node bounds in parent coordinates.
1892     * <p>
1893     * <strong>Note:</strong> Cannot be called from an
1894     * {@link android.accessibilityservice.AccessibilityService}. This class is
1895     * made immutable before being delivered to an AccessibilityService.
1896     * </p>
1897     *
1898     * @param bounds The node bounds.
1899     *@throws IllegalStateException If called from an AccessibilityService.
1900     */
1901    public void setBoundsInParent(Rect bounds) {
1902        IMPL.setBoundsInParent(mInfo, bounds);
1903    }
1904
1905    /**
1906     * Gets the node bounds in screen coordinates.
1907     *
1908     * @param outBounds The output node bounds.
1909     */
1910    public void getBoundsInScreen(Rect outBounds) {
1911        IMPL.getBoundsInScreen(mInfo, outBounds);
1912    }
1913
1914    /**
1915     * Sets the node bounds in screen coordinates.
1916     * <p>
1917     * <strong>Note:</strong> Cannot be called from an
1918     * {@link android.accessibilityservice.AccessibilityService}. This class is
1919     * made immutable before being delivered to an AccessibilityService.
1920     * </p>
1921     *
1922     * @param bounds The node bounds.
1923     * @throws IllegalStateException If called from an AccessibilityService.
1924     */
1925    public void setBoundsInScreen(Rect bounds) {
1926        IMPL.setBoundsInScreen(mInfo, bounds);
1927    }
1928
1929    /**
1930     * Gets whether this node is checkable.
1931     *
1932     * @return True if the node is checkable.
1933     */
1934    public boolean isCheckable() {
1935        return IMPL.isCheckable(mInfo);
1936    }
1937
1938    /**
1939     * Sets whether this node is checkable.
1940     * <p>
1941     * <strong>Note:</strong> Cannot be called from an
1942     * {@link android.accessibilityservice.AccessibilityService}. This class is
1943     * made immutable before being delivered to an AccessibilityService.
1944     * </p>
1945     *
1946     * @param checkable True if the node is checkable.
1947     * @throws IllegalStateException If called from an AccessibilityService.
1948     */
1949    public void setCheckable(boolean checkable) {
1950        IMPL.setCheckable(mInfo, checkable);
1951    }
1952
1953    /**
1954     * Gets whether this node is checked.
1955     *
1956     * @return True if the node is checked.
1957     */
1958    public boolean isChecked() {
1959        return IMPL.isChecked(mInfo);
1960    }
1961
1962    /**
1963     * Sets whether this node is checked.
1964     * <p>
1965     * <strong>Note:</strong> Cannot be called from an
1966     * {@link android.accessibilityservice.AccessibilityService}. This class is
1967     * made immutable before being delivered to an AccessibilityService.
1968     * </p>
1969     *
1970     * @param checked True if the node is checked.
1971     * @throws IllegalStateException If called from an AccessibilityService.
1972     */
1973    public void setChecked(boolean checked) {
1974        IMPL.setChecked(mInfo, checked);
1975    }
1976
1977    /**
1978     * Gets whether this node is focusable.
1979     *
1980     * @return True if the node is focusable.
1981     */
1982    public boolean isFocusable() {
1983        return IMPL.isFocusable(mInfo);
1984    }
1985
1986    /**
1987     * Sets whether this node is focusable.
1988     * <p>
1989     * <strong>Note:</strong> Cannot be called from an
1990     * {@link android.accessibilityservice.AccessibilityService}. This class is
1991     * made immutable before being delivered to an AccessibilityService.
1992     * </p>
1993     *
1994     * @param focusable True if the node is focusable.
1995     * @throws IllegalStateException If called from an AccessibilityService.
1996     */
1997    public void setFocusable(boolean focusable) {
1998        IMPL.setFocusable(mInfo, focusable);
1999    }
2000
2001    /**
2002     * Gets whether this node is focused.
2003     *
2004     * @return True if the node is focused.
2005     */
2006    public boolean isFocused() {
2007        return IMPL.isFocused(mInfo);
2008    }
2009
2010    /**
2011     * Sets whether this node is focused.
2012     * <p>
2013     * <strong>Note:</strong> Cannot be called from an
2014     * {@link android.accessibilityservice.AccessibilityService}. This class is
2015     * made immutable before being delivered to an AccessibilityService.
2016     * </p>
2017     *
2018     * @param focused True if the node is focused.
2019     * @throws IllegalStateException If called from an AccessibilityService.
2020     */
2021    public void setFocused(boolean focused) {
2022        IMPL.setFocused(mInfo, focused);
2023    }
2024
2025    /**
2026     * Sets whether this node is visible to the user.
2027     *
2028     * @return Whether the node is visible to the user.
2029     */
2030    public boolean isVisibleToUser() {
2031        return IMPL.isVisibleToUser(mInfo);
2032    }
2033
2034    /**
2035     * Sets whether this node is visible to the user.
2036     * <p>
2037     *   <strong>Note:</strong> Cannot be called from an
2038     *   {@link android.accessibilityservice.AccessibilityService}.
2039     *   This class is made immutable before being delivered to an AccessibilityService.
2040     * </p>
2041     *
2042     * @param visibleToUser Whether the node is visible to the user.
2043     *
2044     * @throws IllegalStateException If called from an AccessibilityService.
2045     */
2046    public void setVisibleToUser(boolean visibleToUser) {
2047        IMPL.setVisibleToUser(mInfo, visibleToUser);
2048    }
2049
2050    /**
2051     * Gets whether this node is accessibility focused.
2052     *
2053     * @return True if the node is accessibility focused.
2054     */
2055    public boolean isAccessibilityFocused() {
2056        return IMPL.isAccessibilityFocused(mInfo);
2057    }
2058
2059    /**
2060     * Sets whether this node is accessibility focused.
2061     * <p>
2062     *   <strong>Note:</strong> Cannot be called from an
2063     *   {@link android.accessibilityservice.AccessibilityService}.
2064     *   This class is made immutable before being delivered to an AccessibilityService.
2065     * </p>
2066     *
2067     * @param focused True if the node is accessibility focused.
2068     *
2069     * @throws IllegalStateException If called from an AccessibilityService.
2070     */
2071    public void setAccessibilityFocused(boolean focused) {
2072        IMPL.setAccessibilityFocused(mInfo, focused);
2073    }
2074
2075    /**
2076     * Gets whether this node is selected.
2077     *
2078     * @return True if the node is selected.
2079     */
2080    public boolean isSelected() {
2081        return IMPL.isSelected(mInfo);
2082    }
2083
2084    /**
2085     * Sets whether this node is selected.
2086     * <p>
2087     * <strong>Note:</strong> Cannot be called from an
2088     * {@link android.accessibilityservice.AccessibilityService}. This class is
2089     * made immutable before being delivered to an AccessibilityService.
2090     * </p>
2091     *
2092     * @param selected True if the node is selected.
2093     * @throws IllegalStateException If called from an AccessibilityService.
2094     */
2095    public void setSelected(boolean selected) {
2096        IMPL.setSelected(mInfo, selected);
2097    }
2098
2099    /**
2100     * Gets whether this node is clickable.
2101     *
2102     * @return True if the node is clickable.
2103     */
2104    public boolean isClickable() {
2105        return IMPL.isClickable(mInfo);
2106    }
2107
2108    /**
2109     * Sets whether this node is clickable.
2110     * <p>
2111     * <strong>Note:</strong> Cannot be called from an
2112     * {@link android.accessibilityservice.AccessibilityService}. This class is
2113     * made immutable before being delivered to an AccessibilityService.
2114     * </p>
2115     *
2116     * @param clickable True if the node is clickable.
2117     * @throws IllegalStateException If called from an AccessibilityService.
2118     */
2119    public void setClickable(boolean clickable) {
2120        IMPL.setClickable(mInfo, clickable);
2121    }
2122
2123    /**
2124     * Gets whether this node is long clickable.
2125     *
2126     * @return True if the node is long clickable.
2127     */
2128    public boolean isLongClickable() {
2129        return IMPL.isLongClickable(mInfo);
2130    }
2131
2132    /**
2133     * Sets whether this node is long clickable.
2134     * <p>
2135     * <strong>Note:</strong> Cannot be called from an
2136     * {@link android.accessibilityservice.AccessibilityService}. This class is
2137     * made immutable before being delivered to an AccessibilityService.
2138     * </p>
2139     *
2140     * @param longClickable True if the node is long clickable.
2141     * @throws IllegalStateException If called from an AccessibilityService.
2142     */
2143    public void setLongClickable(boolean longClickable) {
2144        IMPL.setLongClickable(mInfo, longClickable);
2145    }
2146
2147    /**
2148     * Gets whether this node is enabled.
2149     *
2150     * @return True if the node is enabled.
2151     */
2152    public boolean isEnabled() {
2153        return IMPL.isEnabled(mInfo);
2154    }
2155
2156    /**
2157     * Sets whether this node is enabled.
2158     * <p>
2159     * <strong>Note:</strong> Cannot be called from an
2160     * {@link android.accessibilityservice.AccessibilityService}. This class is
2161     * made immutable before being delivered to an AccessibilityService.
2162     * </p>
2163     *
2164     * @param enabled True if the node is enabled.
2165     * @throws IllegalStateException If called from an AccessibilityService.
2166     */
2167    public void setEnabled(boolean enabled) {
2168        IMPL.setEnabled(mInfo, enabled);
2169    }
2170
2171    /**
2172     * Gets whether this node is a password.
2173     *
2174     * @return True if the node is a password.
2175     */
2176    public boolean isPassword() {
2177        return IMPL.isPassword(mInfo);
2178    }
2179
2180    /**
2181     * Sets whether this node is a password.
2182     * <p>
2183     * <strong>Note:</strong> Cannot be called from an
2184     * {@link android.accessibilityservice.AccessibilityService}. This class is
2185     * made immutable before being delivered to an AccessibilityService.
2186     * </p>
2187     *
2188     * @param password True if the node is a password.
2189     * @throws IllegalStateException If called from an AccessibilityService.
2190     */
2191    public void setPassword(boolean password) {
2192        IMPL.setPassword(mInfo, password);
2193    }
2194
2195    /**
2196     * Gets if the node is scrollable.
2197     *
2198     * @return True if the node is scrollable, false otherwise.
2199     */
2200    public boolean isScrollable() {
2201        return IMPL.isScrollable(mInfo);
2202    }
2203
2204    /**
2205     * Sets if the node is scrollable.
2206     * <p>
2207     * <strong>Note:</strong> Cannot be called from an
2208     * {@link android.accessibilityservice.AccessibilityService}. This class is
2209     * made immutable before being delivered to an AccessibilityService.
2210     * </p>
2211     *
2212     * @param scrollable True if the node is scrollable, false otherwise.
2213     * @throws IllegalStateException If called from an AccessibilityService.
2214     */
2215    public void setScrollable(boolean scrollable) {
2216        IMPL.setScrollable(mInfo, scrollable);
2217    }
2218
2219    /**
2220     * Gets the package this node comes from.
2221     *
2222     * @return The package name.
2223     */
2224    public CharSequence getPackageName() {
2225        return IMPL.getPackageName(mInfo);
2226    }
2227
2228    /**
2229     * Sets the package this node comes from.
2230     * <p>
2231     * <strong>Note:</strong> Cannot be called from an
2232     * {@link android.accessibilityservice.AccessibilityService}. This class is
2233     * made immutable before being delivered to an AccessibilityService.
2234     * </p>
2235     *
2236     * @param packageName The package name.
2237     * @throws IllegalStateException If called from an AccessibilityService.
2238     */
2239    public void setPackageName(CharSequence packageName) {
2240        IMPL.setPackageName(mInfo, packageName);
2241    }
2242
2243    /**
2244     * Gets the class this node comes from.
2245     *
2246     * @return The class name.
2247     */
2248    public CharSequence getClassName() {
2249        return IMPL.getClassName(mInfo);
2250    }
2251
2252    /**
2253     * Sets the class this node comes from.
2254     * <p>
2255     * <strong>Note:</strong> Cannot be called from an
2256     * {@link android.accessibilityservice.AccessibilityService}. This class is
2257     * made immutable before being delivered to an AccessibilityService.
2258     * </p>
2259     *
2260     * @param className The class name.
2261     * @throws IllegalStateException If called from an AccessibilityService.
2262     */
2263    public void setClassName(CharSequence className) {
2264        IMPL.setClassName(mInfo, className);
2265    }
2266
2267    /**
2268     * Gets the text of this node.
2269     *
2270     * @return The text.
2271     */
2272    public CharSequence getText() {
2273        return IMPL.getText(mInfo);
2274    }
2275
2276    /**
2277     * Sets the text of this node.
2278     * <p>
2279     * <strong>Note:</strong> Cannot be called from an
2280     * {@link android.accessibilityservice.AccessibilityService}. This class is
2281     * made immutable before being delivered to an AccessibilityService.
2282     * </p>
2283     *
2284     * @param text The text.
2285     * @throws IllegalStateException If called from an AccessibilityService.
2286     */
2287    public void setText(CharSequence text) {
2288        IMPL.setText(mInfo, text);
2289    }
2290
2291    /**
2292     * Gets the content description of this node.
2293     *
2294     * @return The content description.
2295     */
2296    public CharSequence getContentDescription() {
2297        return IMPL.getContentDescription(mInfo);
2298    }
2299
2300    /**
2301     * Sets the content description of this node.
2302     * <p>
2303     * <strong>Note:</strong> Cannot be called from an
2304     * {@link android.accessibilityservice.AccessibilityService}. This class is
2305     * made immutable before being delivered to an AccessibilityService.
2306     * </p>
2307     *
2308     * @param contentDescription The content description.
2309     * @throws IllegalStateException If called from an AccessibilityService.
2310     */
2311    public void setContentDescription(CharSequence contentDescription) {
2312        IMPL.setContentDescription(mInfo, contentDescription);
2313    }
2314
2315    /**
2316     * Return an instance back to be reused.
2317     * <p>
2318     * <strong>Note:</strong> You must not touch the object after calling this function.
2319     *
2320     * @throws IllegalStateException If the info is already recycled.
2321     */
2322    public void recycle() {
2323        IMPL.recycle(mInfo);
2324    }
2325
2326    /**
2327     * Sets the fully qualified resource name of the source view's id.
2328     *
2329     * <p>
2330     *   <strong>Note:</strong> Cannot be called from an
2331     *   {@link android.accessibilityservice.AccessibilityService}.
2332     *   This class is made immutable before being delivered to an AccessibilityService.
2333     * </p>
2334     *
2335     * @param viewId The id resource name.
2336     */
2337    public void setViewIdResourceName(String viewId) {
2338        IMPL.setViewIdResourceName(mInfo, viewId);
2339    }
2340
2341    /**
2342     * Gets the fully qualified resource name of the source view's id.
2343     *
2344     * <p>
2345     *   <strong>Note:</strong> The primary usage of this API is for UI test automation
2346     *   and in order to report the source view id of an {@link AccessibilityNodeInfoCompat}
2347     *   the client has to set the {@link AccessibilityServiceInfoCompat#FLAG_REPORT_VIEW_IDS}
2348     *   flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
2349     * </p>
2350     *
2351     * @return The id resource name.
2352     */
2353    public String getViewIdResourceName() {
2354        return IMPL.getViewIdResourceName(mInfo);
2355    }
2356
2357    /**
2358     * Gets the node's live region mode.
2359     * <p>
2360     * A live region is a node that contains information that is important for
2361     * the user and when it changes the user should be notified. For example,
2362     * in a login screen with a TextView that displays an "incorrect password"
2363     * notification, that view should be marked as a live region with mode
2364     * {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_POLITE}.
2365     * <p>
2366     * It is the responsibility of the accessibility service to monitor
2367     * {@link AccessibilityEventCompat#TYPE_WINDOW_CONTENT_CHANGED} events
2368     * indicating changes to live region nodes and their children.
2369     *
2370     * @return The live region mode, or
2371     *         {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is
2372     *         not a live region.
2373     * @see ViewCompat#getAccessibilityLiveRegion(View)
2374     */
2375    public int getLiveRegion() {
2376        return IMPL.getLiveRegion(mInfo);
2377    }
2378
2379    /**
2380     * Sets the node's live region mode.
2381     * <p>
2382     * <strong>Note:</strong> Cannot be called from an
2383     * {@link android.accessibilityservice.AccessibilityService}. This class is
2384     * made immutable before being delivered to an AccessibilityService.
2385     *
2386     * @param mode The live region mode, or
2387     *        {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is
2388     *        not a live region.
2389     * @see ViewCompat#setAccessibilityLiveRegion(View, int)
2390     */
2391    public void setLiveRegion(int mode) {
2392        IMPL.setLiveRegion(mInfo, mode);
2393    }
2394
2395    /**
2396     * Gets the collection info if the node is a collection. A collection
2397     * child is always a collection item.
2398     *
2399     * @return The collection info.
2400     */
2401    public CollectionInfoCompat getCollectionInfo() {
2402        Object info = IMPL.getCollectionInfo(mInfo);
2403        if (info == null) return null;
2404        return new CollectionInfoCompat(info);
2405    }
2406
2407    public void setCollectionInfo(Object collectionInfo) {
2408        IMPL.setCollectionInfo(mInfo, ((CollectionInfoCompat) collectionInfo).mInfo);
2409    }
2410
2411    public void setCollectionItemInfo(Object collectionItemInfo) {
2412        IMPL.setCollectionItemInfo(mInfo, ((CollectionItemInfoCompat) collectionItemInfo).mInfo);
2413    }
2414
2415    /**
2416     * Gets the collection item info if the node is a collection item. A collection
2417     * item is always a child of a collection.
2418     *
2419     * @return The collection item info.
2420     */
2421    public CollectionItemInfoCompat getCollectionItemInfo() {
2422        Object info = IMPL.getCollectionItemInfo(mInfo);
2423        if (info == null) return null;
2424        return new CollectionItemInfoCompat(info);
2425    }
2426
2427    /**
2428     * Gets the range info if this node is a range.
2429     *
2430     * @return The range.
2431     */
2432    public RangeInfoCompat getRangeInfo() {
2433        Object info = IMPL.getRangeInfo(mInfo);
2434        if (info == null) return null;
2435        return new RangeInfoCompat(info);
2436    }
2437
2438    /**
2439     * Gets the actions that can be performed on the node.
2440     *
2441     * @return A list of AccessibilityActions.
2442     */
2443    public List<AccessibilityActionCompat> getActionList() {
2444        List<Object> actions = IMPL.getActionList(mInfo);
2445        if (actions != null) {
2446            List<AccessibilityActionCompat> result = new ArrayList<AccessibilityActionCompat>();
2447            final int actionCount = actions.size();
2448            for (int i = 0; i < actionCount; i++) {
2449                Object action = actions.get(i);
2450                result.add(new AccessibilityActionCompat(action));
2451            }
2452            return result;
2453        } else {
2454            return Collections.<AccessibilityActionCompat>emptyList();
2455        }
2456    }
2457
2458
2459    @Override
2460    public int hashCode() {
2461        return (mInfo == null) ? 0 : mInfo.hashCode();
2462    }
2463
2464    @Override
2465    public boolean equals(Object obj) {
2466        if (this == obj) {
2467            return true;
2468        }
2469        if (obj == null) {
2470            return false;
2471        }
2472        if (getClass() != obj.getClass()) {
2473            return false;
2474        }
2475        AccessibilityNodeInfoCompat other = (AccessibilityNodeInfoCompat) obj;
2476        if (mInfo == null) {
2477            if (other.mInfo != null) {
2478                return false;
2479            }
2480        } else if (!mInfo.equals(other.mInfo)) {
2481            return false;
2482        }
2483        return true;
2484    }
2485
2486    @Override
2487    public String toString() {
2488        StringBuilder builder = new StringBuilder();
2489        builder.append(super.toString());
2490
2491        Rect bounds = new Rect();
2492
2493        getBoundsInParent(bounds);
2494        builder.append("; boundsInParent: " + bounds);
2495
2496        getBoundsInScreen(bounds);
2497        builder.append("; boundsInScreen: " + bounds);
2498
2499        builder.append("; packageName: ").append(getPackageName());
2500        builder.append("; className: ").append(getClassName());
2501        builder.append("; text: ").append(getText());
2502        builder.append("; contentDescription: ").append(getContentDescription());
2503        builder.append("; viewId: ").append(getViewIdResourceName());
2504
2505        builder.append("; checkable: ").append(isCheckable());
2506        builder.append("; checked: ").append(isChecked());
2507        builder.append("; focusable: ").append(isFocusable());
2508        builder.append("; focused: ").append(isFocused());
2509        builder.append("; selected: ").append(isSelected());
2510        builder.append("; clickable: ").append(isClickable());
2511        builder.append("; longClickable: ").append(isLongClickable());
2512        builder.append("; enabled: ").append(isEnabled());
2513        builder.append("; password: ").append(isPassword());
2514        builder.append("; scrollable: " + isScrollable());
2515
2516        builder.append("; [");
2517        for (int actionBits = getActions(); actionBits != 0;) {
2518            final int action = 1 << Integer.numberOfTrailingZeros(actionBits);
2519            actionBits &= ~action;
2520            builder.append(getActionSymbolicName(action));
2521            if (actionBits != 0) {
2522                builder.append(", ");
2523            }
2524        }
2525        builder.append("]");
2526
2527        return builder.toString();
2528    }
2529
2530    private static String getActionSymbolicName(int action) {
2531        switch (action) {
2532            case ACTION_FOCUS:
2533                return "ACTION_FOCUS";
2534            case ACTION_CLEAR_FOCUS:
2535                return "ACTION_CLEAR_FOCUS";
2536            case ACTION_SELECT:
2537                return "ACTION_SELECT";
2538            case ACTION_CLEAR_SELECTION:
2539                return "ACTION_CLEAR_SELECTION";
2540            case ACTION_CLICK:
2541                return "ACTION_CLICK";
2542            case ACTION_LONG_CLICK:
2543                return "ACTION_LONG_CLICK";
2544            case ACTION_ACCESSIBILITY_FOCUS:
2545                return "ACTION_ACCESSIBILITY_FOCUS";
2546            case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
2547                return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
2548            case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
2549                return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
2550            case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
2551                return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
2552            case ACTION_NEXT_HTML_ELEMENT:
2553                return "ACTION_NEXT_HTML_ELEMENT";
2554            case ACTION_PREVIOUS_HTML_ELEMENT:
2555                return "ACTION_PREVIOUS_HTML_ELEMENT";
2556            case ACTION_SCROLL_FORWARD:
2557                return "ACTION_SCROLL_FORWARD";
2558            case ACTION_SCROLL_BACKWARD:
2559                return "ACTION_SCROLL_BACKWARD";
2560            case ACTION_CUT:
2561                return "ACTION_CUT";
2562            case ACTION_COPY:
2563                return "ACTION_COPY";
2564            case ACTION_PASTE:
2565                return "ACTION_PASTE";
2566            case ACTION_SET_SELECTION:
2567                return "ACTION_SET_SELECTION";
2568            default:
2569                return"ACTION_UNKNOWN";
2570        }
2571    }
2572}
2573