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