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.accessibilityservice; 18 19import android.accessibilityservice.AccessibilityService; 20import android.accessibilityservice.AccessibilityServiceInfo; 21import android.content.pm.ResolveInfo; 22import android.os.Build; 23import android.view.View; 24 25/** 26 * Helper for accessing features in {@link android.accessibilityservice.AccessibilityService} 27 * introduced after API level 4 in a backwards compatible fashion. 28 */ 29public class AccessibilityServiceInfoCompat { 30 31 static interface AccessibilityServiceInfoVersionImpl { 32 public String getId(AccessibilityServiceInfo info); 33 public ResolveInfo getResolveInfo(AccessibilityServiceInfo info); 34 public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info); 35 public String getDescription(AccessibilityServiceInfo info); 36 public String getSettingsActivityName(AccessibilityServiceInfo info); 37 public int getCapabilities(AccessibilityServiceInfo info); 38 } 39 40 static class AccessibilityServiceInfoStubImpl implements AccessibilityServiceInfoVersionImpl { 41 42 public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { 43 return false; 44 } 45 46 public String getDescription(AccessibilityServiceInfo info) { 47 return null; 48 } 49 50 public String getId(AccessibilityServiceInfo info) { 51 return null; 52 } 53 54 public ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { 55 return null; 56 } 57 58 public String getSettingsActivityName(AccessibilityServiceInfo info) { 59 return null; 60 } 61 62 public int getCapabilities(AccessibilityServiceInfo info) { 63 return 0; 64 } 65 } 66 67 static class AccessibilityServiceInfoIcsImpl extends AccessibilityServiceInfoStubImpl { 68 69 @Override 70 public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { 71 return AccessibilityServiceInfoCompatIcs.getCanRetrieveWindowContent(info); 72 } 73 74 @Override 75 public String getDescription(AccessibilityServiceInfo info) { 76 return AccessibilityServiceInfoCompatIcs.getDescription(info); 77 } 78 79 @Override 80 public String getId(AccessibilityServiceInfo info) { 81 return AccessibilityServiceInfoCompatIcs.getId(info); 82 } 83 84 @Override 85 public ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { 86 return AccessibilityServiceInfoCompatIcs.getResolveInfo(info); 87 } 88 89 @Override 90 public String getSettingsActivityName(AccessibilityServiceInfo info) { 91 return AccessibilityServiceInfoCompatIcs.getSettingsActivityName(info); 92 } 93 94 @Override 95 public int getCapabilities(AccessibilityServiceInfo info) { 96 if (getCanRetrieveWindowContent(info)) { 97 return CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT; 98 } 99 return 0; 100 } 101 } 102 103 static class AccessibilityServiceInfoJellyBeanMr2 extends AccessibilityServiceInfoIcsImpl { 104 @Override 105 public int getCapabilities(AccessibilityServiceInfo info) { 106 return AccessibilityServiceInfoCompatJellyBeanMr2.getCapabilities(info); 107 } 108 } 109 110 static { 111 if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2 112 IMPL = new AccessibilityServiceInfoJellyBeanMr2(); 113 } else if (Build.VERSION.SDK_INT >= 14) { // ICS 114 IMPL = new AccessibilityServiceInfoIcsImpl(); 115 } else { 116 IMPL = new AccessibilityServiceInfoStubImpl(); 117 } 118 } 119 120 // Capabilities 121 122 private static final AccessibilityServiceInfoVersionImpl IMPL; 123 124 /** 125 * Capability: This accessibility service can retrieve the active window content. 126 */ 127 public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001; 128 129 /** 130 * Capability: This accessibility service can request touch exploration mode in which 131 * touched items are spoken aloud and the UI can be explored via gestures. 132 */ 133 public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002; 134 135 /** 136 * Capability: This accessibility service can request enhanced web accessibility 137 * enhancements. For example, installing scripts to make app content more accessible. 138 */ 139 public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004; 140 141 /** 142 * Capability: This accessibility service can filter the key event stream. 143 */ 144 public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 0x00000008; 145 146 // Feedback types 147 148 /** 149 * Denotes braille feedback. 150 */ 151 public static final int FEEDBACK_BRAILLE = 0x0000020; 152 153 /** 154 * Mask for all feedback types. 155 * 156 * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN 157 * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC 158 * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE 159 * @see AccessibilityServiceInfo#FEEDBACK_VISUAL 160 * @see AccessibilityServiceInfo#FEEDBACK_GENERIC 161 * @see FEEDBACK_BRAILLE 162 */ 163 public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF; 164 165 // Flags 166 167 /** 168 * If an {@link AccessibilityService} is the default for a given type. 169 * Default service is invoked only if no package specific one exists. In case of 170 * more than one package specific service only the earlier registered is notified. 171 */ 172 public static final int DEFAULT = 0x0000001; 173 174 /** 175 * If this flag is set the system will regard views that are not important 176 * for accessibility in addition to the ones that are important for accessibility. 177 * That is, views that are marked as not important for accessibility via 178 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or 179 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are 180 * marked as potentially important for accessibility via 181 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined 182 * that are not important for accessibility, are both reported while querying the 183 * window content and also the accessibility service will receive accessibility events 184 * from them. 185 * <p> 186 * <strong>Note:</strong> For accessibility services targeting API version 187 * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly 188 * set for the system to regard views that are not important for accessibility. For 189 * accessibility services targeting API version lower than 190 * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are 191 * regarded for accessibility purposes. 192 * </p> 193 * <p> 194 * Usually views not important for accessibility are layout managers that do not 195 * react to user actions, do not draw any content, and do not have any special 196 * semantics in the context of the screen content. For example, a three by three 197 * grid can be implemented as three horizontal linear layouts and one vertical, 198 * or three vertical linear layouts and one horizontal, or one grid layout, etc. 199 * In this context the actual layout mangers used to achieve the grid configuration 200 * are not important, rather it is important that there are nine evenly distributed 201 * elements. 202 * </p> 203 */ 204 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002; 205 206 /** 207 * This flag requests that the system gets into touch exploration mode. 208 * In this mode a single finger moving on the screen behaves as a mouse 209 * pointer hovering over the user interface. The system will also detect 210 * certain gestures performed on the touch screen and notify this service. 211 * The system will enable touch exploration mode if there is at least one 212 * accessibility service that has this flag set. Hence, clearing this 213 * flag does not guarantee that the device will not be in touch exploration 214 * mode since there may be another enabled service that requested it. 215 * <p> 216 * For accessibility services targeting API version higher than 217 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set 218 * this flag have to declare this capability in their meta-data by setting 219 * the attribute canRequestTouchExplorationMode to true, otherwise this flag 220 * will be ignored. For how to declare the meta-data of a service refer to 221 * {@value AccessibilityService#SERVICE_META_DATA}. 222 * </p> 223 * <p> 224 * Services targeting API version equal to or lower than 225 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e. 226 * the first time they are run, if this flag is specified, a dialog is 227 * shown to the user to confirm enabling explore by touch. 228 * </p> 229 */ 230 public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004; 231 232 /** 233 * This flag requests from the system to enable web accessibility enhancing 234 * extensions. Such extensions aim to provide improved accessibility support 235 * for content presented in a {@link android.webkit.WebView}. An example of such 236 * an extension is injecting JavaScript from a secure source. The system will enable 237 * enhanced web accessibility if there is at least one accessibility service 238 * that has this flag set. Hence, clearing this flag does not guarantee that the 239 * device will not have enhanced web accessibility enabled since there may be 240 * another enabled service that requested it. 241 * <p> 242 * Services that want to set this flag have to declare this capability 243 * in their meta-data by setting the attribute canRequestEnhancedWebAccessibility 244 * to true, otherwise this flag will be ignored. For how to declare the meta-data 245 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 246 * </p> 247 */ 248 public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008; 249 250 /** 251 * This flag requests that the AccessibilityNodeInfos obtained 252 * by an {@link AccessibilityService} contain the id of the source view. 253 * The source view id will be a fully qualified resource name of the 254 * form "package:id/name", for example "foo.bar:id/my_list", and it is 255 * useful for UI test automation. This flag is not set by default. 256 */ 257 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010; 258 259 /** 260 * This flag requests from the system to filter key events. If this flag 261 * is set the accessibility service will receive the key events before 262 * applications allowing it implement global shortcuts. Setting this flag 263 * does not guarantee that this service will filter key events since only 264 * one service can do so at any given time. This avoids user confusion due 265 * to behavior change in case different key filtering services are enabled. 266 * If there is already another key filtering service enabled, this one will 267 * not receive key events. 268 * <p> 269 * Services that want to set this flag have to declare this capability 270 * in their meta-data by setting the attribute canRequestFilterKeyEvents 271 * to true, otherwise this flag will be ignored. For how to declare the meta 272 * -data of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 273 * </p> 274 */ 275 public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020; 276 277 /* 278 * Hide constructor 279 */ 280 private AccessibilityServiceInfoCompat() { 281 282 } 283 284 /** 285 * The accessibility service id. 286 * <p> 287 * <strong>Generated by the system.</strong> 288 * </p> 289 * 290 * @return The id. 291 */ 292 public static String getId(AccessibilityServiceInfo info) { 293 return IMPL.getId(info); 294 } 295 296 /** 297 * The service {@link ResolveInfo}. 298 * <p> 299 * <strong>Generated by the system.</strong> 300 * </p> 301 * 302 * @return The info. 303 */ 304 public static ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { 305 return IMPL.getResolveInfo(info); 306 } 307 308 /** 309 * The settings activity name. 310 * <p> 311 * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA 312 * meta-data}.</strong> 313 * </p> 314 * 315 * @return The settings activity name. 316 */ 317 public static String getSettingsActivityName(AccessibilityServiceInfo info) { 318 return IMPL.getSettingsActivityName(info); 319 } 320 321 /** 322 * Whether this service can retrieve the current window's content. 323 * <p> 324 * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA 325 * meta-data}.</strong> 326 * </p> 327 * 328 * @return True window content can be retrieved. 329 */ 330 public static boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { 331 return IMPL.getCanRetrieveWindowContent(info); 332 } 333 334 /** 335 * Description of the accessibility service. 336 * <p> 337 * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA 338 * meta-data}.</strong> 339 * </p> 340 * 341 * @return The description. 342 */ 343 public static String getDescription(AccessibilityServiceInfo info) { 344 return IMPL.getDescription(info); 345 } 346 347 /** 348 * Returns the string representation of a feedback type. For example, 349 * {@link AccessibilityServiceInfo#FEEDBACK_SPOKEN} is represented by the 350 * string FEEDBACK_SPOKEN. 351 * 352 * @param feedbackType The feedback type. 353 * @return The string representation. 354 */ 355 public static String feedbackTypeToString(int feedbackType) { 356 StringBuilder builder = new StringBuilder(); 357 builder.append("["); 358 while (feedbackType > 0) { 359 final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType); 360 feedbackType &= ~feedbackTypeFlag; 361 if (builder.length() > 1) { 362 builder.append(", "); 363 } 364 switch (feedbackTypeFlag) { 365 case AccessibilityServiceInfo.FEEDBACK_AUDIBLE: 366 builder.append("FEEDBACK_AUDIBLE"); 367 break; 368 case AccessibilityServiceInfo.FEEDBACK_HAPTIC: 369 builder.append("FEEDBACK_HAPTIC"); 370 break; 371 case AccessibilityServiceInfo.FEEDBACK_GENERIC: 372 builder.append("FEEDBACK_GENERIC"); 373 break; 374 case AccessibilityServiceInfo.FEEDBACK_SPOKEN: 375 builder.append("FEEDBACK_SPOKEN"); 376 break; 377 case AccessibilityServiceInfo.FEEDBACK_VISUAL: 378 builder.append("FEEDBACK_VISUAL"); 379 break; 380 } 381 } 382 builder.append("]"); 383 return builder.toString(); 384 } 385 386 /** 387 * Returns the string representation of a flag. For example, 388 * {@link AccessibilityServiceInfo#DEFAULT} is represented by the 389 * string DEFAULT. 390 * 391 * @param flag The flag. 392 * @return The string representation. 393 */ 394 public static String flagToString(int flag) { 395 switch (flag) { 396 case DEFAULT: 397 return "DEFAULT"; 398 case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS: 399 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS"; 400 case FLAG_REQUEST_TOUCH_EXPLORATION_MODE: 401 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE"; 402 case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 403 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 404 case FLAG_REPORT_VIEW_IDS: 405 return "FLAG_REPORT_VIEW_IDS"; 406 case FLAG_REQUEST_FILTER_KEY_EVENTS: 407 return "FLAG_REQUEST_FILTER_KEY_EVENTS"; 408 default: 409 return null; 410 } 411 } 412 413 /** 414 * Returns the bit mask of capabilities this accessibility service has such as 415 * being able to retrieve the active window content, etc. 416 * 417 * @param info The service info whose capabilities to get. 418 * @return The capability bit mask. 419 * 420 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 421 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 422 * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY 423 * @see #CAPABILITY_CAN_FILTER_KEY_EVENTS 424 */ 425 public static int getCapabilities(AccessibilityServiceInfo info) { 426 return IMPL.getCapabilities(info); 427 } 428 429 /** 430 * Returns the string representation of a capability. For example, 431 * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented 432 * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT. 433 * 434 * @param capability The capability. 435 * @return The string representation. 436 */ 437 public static String capabilityToString(int capability) { 438 switch (capability) { 439 case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT: 440 return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT"; 441 case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION: 442 return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION"; 443 case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 444 return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 445 case CAPABILITY_CAN_FILTER_KEY_EVENTS: 446 return "CAPABILITY_CAN_FILTER_KEY_EVENTS"; 447 default: 448 return "UNKNOWN"; 449 } 450 } 451} 452