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