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