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 final 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 * The accessibility service id. 284 * <p> 285 * <strong>Generated by the system.</strong> 286 * </p> 287 * 288 * @return The id. 289 */ 290 public static String getId(AccessibilityServiceInfo info) { 291 return IMPL.getId(info); 292 } 293 294 /** 295 * The service {@link ResolveInfo}. 296 * <p> 297 * <strong>Generated by the system.</strong> 298 * </p> 299 * 300 * @return The info. 301 */ 302 public static ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { 303 return IMPL.getResolveInfo(info); 304 } 305 306 /** 307 * The settings activity name. 308 * <p> 309 * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA 310 * meta-data}.</strong> 311 * </p> 312 * 313 * @return The settings activity name. 314 */ 315 public static String getSettingsActivityName(AccessibilityServiceInfo info) { 316 return IMPL.getSettingsActivityName(info); 317 } 318 319 /** 320 * Whether this service can retrieve the current window's content. 321 * <p> 322 * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA 323 * meta-data}.</strong> 324 * </p> 325 * 326 * @return True window content can be retrieved. 327 */ 328 public static boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { 329 return IMPL.getCanRetrieveWindowContent(info); 330 } 331 332 /** 333 * Description of the accessibility service. 334 * <p> 335 * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA 336 * meta-data}.</strong> 337 * </p> 338 * 339 * @return The description. 340 */ 341 public static String getDescription(AccessibilityServiceInfo info) { 342 return IMPL.getDescription(info); 343 } 344 345 /** 346 * Returns the string representation of a feedback type. For example, 347 * {@link AccessibilityServiceInfo#FEEDBACK_SPOKEN} is represented by the 348 * string FEEDBACK_SPOKEN. 349 * 350 * @param feedbackType The feedback type. 351 * @return The string representation. 352 */ 353 public static String feedbackTypeToString(int feedbackType) { 354 StringBuilder builder = new StringBuilder(); 355 builder.append("["); 356 while (feedbackType > 0) { 357 final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType); 358 feedbackType &= ~feedbackTypeFlag; 359 if (builder.length() > 1) { 360 builder.append(", "); 361 } 362 switch (feedbackTypeFlag) { 363 case AccessibilityServiceInfo.FEEDBACK_AUDIBLE: 364 builder.append("FEEDBACK_AUDIBLE"); 365 break; 366 case AccessibilityServiceInfo.FEEDBACK_HAPTIC: 367 builder.append("FEEDBACK_HAPTIC"); 368 break; 369 case AccessibilityServiceInfo.FEEDBACK_GENERIC: 370 builder.append("FEEDBACK_GENERIC"); 371 break; 372 case AccessibilityServiceInfo.FEEDBACK_SPOKEN: 373 builder.append("FEEDBACK_SPOKEN"); 374 break; 375 case AccessibilityServiceInfo.FEEDBACK_VISUAL: 376 builder.append("FEEDBACK_VISUAL"); 377 break; 378 } 379 } 380 builder.append("]"); 381 return builder.toString(); 382 } 383 384 /** 385 * Returns the string representation of a flag. For example, 386 * {@link AccessibilityServiceInfo#DEFAULT} is represented by the 387 * string DEFAULT. 388 * 389 * @param flag The flag. 390 * @return The string representation. 391 */ 392 public static String flagToString(int flag) { 393 switch (flag) { 394 case DEFAULT: 395 return "DEFAULT"; 396 case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS: 397 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS"; 398 case FLAG_REQUEST_TOUCH_EXPLORATION_MODE: 399 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE"; 400 case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 401 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 402 case FLAG_REPORT_VIEW_IDS: 403 return "FLAG_REPORT_VIEW_IDS"; 404 case FLAG_REQUEST_FILTER_KEY_EVENTS: 405 return "FLAG_REQUEST_FILTER_KEY_EVENTS"; 406 default: 407 return null; 408 } 409 } 410 411 /** 412 * Returns the bit mask of capabilities this accessibility service has such as 413 * being able to retrieve the active window content, etc. 414 * 415 * @param info The service info whose capabilities to get. 416 * @return The capability bit mask. 417 * 418 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 419 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 420 * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY 421 * @see #CAPABILITY_CAN_FILTER_KEY_EVENTS 422 */ 423 public static int getCapabilities(AccessibilityServiceInfo info) { 424 return IMPL.getCapabilities(info); 425 } 426 427 /** 428 * Returns the string representation of a capability. For example, 429 * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented 430 * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT. 431 * 432 * @param capability The capability. 433 * @return The string representation. 434 */ 435 public static String capabilityToString(int capability) { 436 switch (capability) { 437 case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT: 438 return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT"; 439 case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION: 440 return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION"; 441 case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 442 return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 443 case CAPABILITY_CAN_FILTER_KEY_EVENTS: 444 return "CAPABILITY_CAN_FILTER_KEY_EVENTS"; 445 default: 446 return "UNKNOWN"; 447 } 448 } 449} 450