1/*
2 * Copyright (C) 2012 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 androidx.core.view.accessibility;
18
19import android.os.Build;
20import android.os.Bundle;
21import android.view.accessibility.AccessibilityNodeInfo;
22import android.view.accessibility.AccessibilityNodeProvider;
23
24import androidx.annotation.Nullable;
25import androidx.annotation.RequiresApi;
26
27import java.util.ArrayList;
28import java.util.List;
29
30/**
31 * Helper for accessing {@link android.view.accessibility.AccessibilityNodeProvider}.
32 */
33public class AccessibilityNodeProviderCompat {
34    @RequiresApi(16)
35    static class AccessibilityNodeProviderApi16 extends AccessibilityNodeProvider {
36        final AccessibilityNodeProviderCompat mCompat;
37
38        AccessibilityNodeProviderApi16(AccessibilityNodeProviderCompat compat) {
39            mCompat = compat;
40        }
41
42        @Override
43        public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
44            final AccessibilityNodeInfoCompat compatInfo =
45                    mCompat.createAccessibilityNodeInfo(virtualViewId);
46            if (compatInfo == null) {
47                return null;
48            } else {
49                return compatInfo.unwrap();
50            }
51        }
52
53        @Override
54        public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(
55                String text, int virtualViewId) {
56            final List<AccessibilityNodeInfoCompat> compatInfos =
57                    mCompat.findAccessibilityNodeInfosByText(text, virtualViewId);
58            if (compatInfos == null) {
59                return null;
60            } else {
61                final List<AccessibilityNodeInfo> infoList = new ArrayList<>();
62                final int infoCount = compatInfos.size();
63                for (int i = 0; i < infoCount; i++) {
64                    AccessibilityNodeInfoCompat infoCompat = compatInfos.get(i);
65                    infoList.add(infoCompat.unwrap());
66                }
67                return infoList;
68            }
69        }
70
71        @Override
72        public boolean performAction(int virtualViewId, int action, Bundle arguments) {
73            return mCompat.performAction(virtualViewId, action, arguments);
74        }
75    }
76
77    @RequiresApi(19)
78    static class AccessibilityNodeProviderApi19 extends AccessibilityNodeProviderApi16 {
79        AccessibilityNodeProviderApi19(AccessibilityNodeProviderCompat compat) {
80            super(compat);
81        }
82
83        @Override
84        public AccessibilityNodeInfo findFocus(int focus) {
85            final AccessibilityNodeInfoCompat compatInfo = mCompat.findFocus(focus);
86            if (compatInfo == null) {
87                return null;
88            } else {
89                return compatInfo.unwrap();
90            }
91        }
92    }
93
94    /**
95     * The virtual id for the hosting View.
96     */
97    public static final int HOST_VIEW_ID = -1;
98
99    private final Object mProvider;
100
101    /**
102     * Creates a new instance.
103     */
104    public AccessibilityNodeProviderCompat() {
105        if (Build.VERSION.SDK_INT >= 19) {
106            mProvider = new AccessibilityNodeProviderApi19(this);
107        } else if (Build.VERSION.SDK_INT >= 16) {
108            mProvider = new AccessibilityNodeProviderApi16(this);
109        } else {
110            mProvider = null;
111        }
112    }
113
114    /**
115     * Creates a new instance wrapping an
116     * {@link android.view.accessibility.AccessibilityNodeProvider}.
117     *
118     * @param provider The provider.
119     */
120    public AccessibilityNodeProviderCompat(Object provider) {
121        mProvider = provider;
122    }
123
124    /**
125     * @return The wrapped {@link android.view.accessibility.AccessibilityNodeProvider}.
126     */
127    public Object getProvider() {
128        return mProvider;
129    }
130
131    /**
132     * Returns an {@link AccessibilityNodeInfoCompat} representing a virtual view,
133     * i.e. a descendant of the host View, with the given <code>virtualViewId</code>
134     * or the host View itself if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
135     * <p>
136     * A virtual descendant is an imaginary View that is reported as a part of the view
137     * hierarchy for accessibility purposes. This enables custom views that draw complex
138     * content to report them selves as a tree of virtual views, thus conveying their
139     * logical structure.
140     * </p>
141     * <p>
142     * The implementer is responsible for obtaining an accessibility node info from the
143     * pool of reusable instances and setting the desired properties of the node info
144     * before returning it.
145     * </p>
146     *
147     * @param virtualViewId A client defined virtual view id.
148     * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual descendant
149     *     or the host View.
150     *
151     * @see AccessibilityNodeInfoCompat
152     */
153    @Nullable
154    public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) {
155        return null;
156    }
157
158    /**
159     * Performs an accessibility action on a virtual view, i.e. a descendant of the
160     * host View, with the given <code>virtualViewId</code> or the host View itself
161     * if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
162     *
163     * @param virtualViewId A client defined virtual view id.
164     * @param action The action to perform.
165     * @param arguments Optional arguments.
166     * @return True if the action was performed.
167     *
168     * @see #createAccessibilityNodeInfo(int)
169     * @see AccessibilityNodeInfoCompat
170     */
171    public boolean performAction(int virtualViewId, int action, Bundle arguments) {
172        return false;
173    }
174
175    /**
176     * Finds {@link AccessibilityNodeInfoCompat}s by text. The match is case insensitive
177     * containment. The search is relative to the virtual view, i.e. a descendant of the
178     * host View, with the given <code>virtualViewId</code> or the host View itself
179     * <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
180     *
181     * @param virtualViewId A client defined virtual view id which defined
182     *     the root of the tree in which to perform the search.
183     * @param text The searched text.
184     * @return A list of node info.
185     *
186     * @see #createAccessibilityNodeInfo(int)
187     * @see AccessibilityNodeInfoCompat
188     */
189    @Nullable
190    public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text,
191            int virtualViewId) {
192        return null;
193    }
194
195    /**
196     * Find the virtual view, i.e. a descendant of the host View, that has the
197     * specified focus type.
198     *
199     * @param focus The focus to find. One of
200     *            {@link AccessibilityNodeInfoCompat#FOCUS_INPUT} or
201     *            {@link AccessibilityNodeInfoCompat#FOCUS_ACCESSIBILITY}.
202     * @return The node info of the focused view or null.
203     * @see AccessibilityNodeInfoCompat#FOCUS_INPUT
204     * @see AccessibilityNodeInfoCompat#FOCUS_ACCESSIBILITY
205     */
206    @Nullable
207    public AccessibilityNodeInfoCompat findFocus(int focus) {
208        return null;
209    }
210}
211