AccessibilityServiceInfo.java revision 4acc16d1b611074baa9eeb7ec5628350b7eb5fa5
1/* 2 * Copyright (C) 2009 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.accessibilityservice; 18 19import android.content.ComponentName; 20import android.content.Context; 21import android.content.pm.PackageManager; 22import android.content.pm.PackageManager.NameNotFoundException; 23import android.content.pm.ResolveInfo; 24import android.content.pm.ServiceInfo; 25import android.content.res.Resources; 26import android.content.res.TypedArray; 27import android.content.res.XmlResourceParser; 28import android.os.Build; 29import android.os.Parcel; 30import android.os.Parcelable; 31import android.util.AttributeSet; 32import android.util.SparseArray; 33import android.util.TypedValue; 34import android.util.Xml; 35import android.view.View; 36import android.view.accessibility.AccessibilityEvent; 37import android.view.accessibility.AccessibilityNodeInfo; 38 39import com.android.internal.R; 40 41import org.xmlpull.v1.XmlPullParser; 42import org.xmlpull.v1.XmlPullParserException; 43 44import java.io.IOException; 45import java.util.ArrayList; 46import java.util.Collections; 47import java.util.List; 48 49/** 50 * This class describes an {@link AccessibilityService}. The system notifies an 51 * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s 52 * according to the information encapsulated in this class. 53 * 54 * <div class="special reference"> 55 * <h3>Developer Guides</h3> 56 * <p>For more information about creating AccessibilityServices, read the 57 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 58 * developer guide.</p> 59 * </div> 60 * 61 * @attr ref android.R.styleable#AccessibilityService_accessibilityEventTypes 62 * @attr ref android.R.styleable#AccessibilityService_accessibilityFeedbackType 63 * @attr ref android.R.styleable#AccessibilityService_accessibilityFlags 64 * @attr ref android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility 65 * @attr ref android.R.styleable#AccessibilityService_canRequestFilterKeyEvents 66 * @attr ref android.R.styleable#AccessibilityService_canRequestTouchExplorationMode 67 * @attr ref android.R.styleable#AccessibilityService_canRetrieveWindowContent 68 * @attr ref android.R.styleable#AccessibilityService_description 69 * @attr ref android.R.styleable#AccessibilityService_notificationTimeout 70 * @attr ref android.R.styleable#AccessibilityService_packageNames 71 * @attr ref android.R.styleable#AccessibilityService_settingsActivity 72 * 73 * @see AccessibilityService 74 * @see android.view.accessibility.AccessibilityEvent 75 * @see android.view.accessibility.AccessibilityManager 76 */ 77public class AccessibilityServiceInfo implements Parcelable { 78 79 private static final String TAG_ACCESSIBILITY_SERVICE = "accessibility-service"; 80 81 /** 82 * Capability: This accessibility service can retrieve the active window content. 83 * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent 84 */ 85 public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001; 86 87 /** 88 * Capability: This accessibility service can request touch exploration mode in which 89 * touched items are spoken aloud and the UI can be explored via gestures. 90 * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode 91 */ 92 public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002; 93 94 /** 95 * Capability: This accessibility service can request enhanced web accessibility 96 * enhancements. For example, installing scripts to make app content more accessible. 97 * @see android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility 98 */ 99 public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004; 100 101 /** 102 * Capability: This accessibility service can request to filter the key event stream. 103 * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents 104 */ 105 public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 0x00000008; 106 107 /** 108 * Capability: This accessibility service can control display magnification. 109 * @see android.R.styleable#AccessibilityService_canControlMagnification 110 */ 111 public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0x00000010; 112 113 /** 114 * Capability: This accessibility service can perform gestures. 115 * @see android.R.styleable#AccessibilityService_canPerformGestures 116 */ 117 public static final int CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020; 118 119 private static final SparseArray<CapabilityInfo> sAvailableCapabilityInfos = 120 new SparseArray<CapabilityInfo>(); 121 static { 122 sAvailableCapabilityInfos.put(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT, 123 new CapabilityInfo(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT, 124 R.string.capability_title_canRetrieveWindowContent, 125 R.string.capability_desc_canRetrieveWindowContent)); 126 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION, 127 new CapabilityInfo(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION, 128 R.string.capability_title_canRequestTouchExploration, 129 R.string.capability_desc_canRequestTouchExploration)); 130 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY, 131 new CapabilityInfo(CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY, 132 R.string.capability_title_canRequestEnhancedWebAccessibility, 133 R.string.capability_desc_canRequestEnhancedWebAccessibility)); 134 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS, 135 new CapabilityInfo(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS, 136 R.string.capability_title_canRequestFilterKeyEvents, 137 R.string.capability_desc_canRequestFilterKeyEvents)); 138 sAvailableCapabilityInfos.put(CAPABILITY_CAN_CONTROL_MAGNIFICATION, 139 new CapabilityInfo(CAPABILITY_CAN_CONTROL_MAGNIFICATION, 140 R.string.capability_title_canControlMagnification, 141 R.string.capability_desc_canControlMagnification)); 142 sAvailableCapabilityInfos.put(CAPABILITY_CAN_PERFORM_GESTURES, 143 new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES, 144 R.string.capability_title_canPerformGestures, 145 R.string.capability_desc_canPerformGestures)); 146 } 147 148 /** 149 * Denotes spoken feedback. 150 */ 151 public static final int FEEDBACK_SPOKEN = 0x0000001; 152 153 /** 154 * Denotes haptic feedback. 155 */ 156 public static final int FEEDBACK_HAPTIC = 0x0000002; 157 158 /** 159 * Denotes audible (not spoken) feedback. 160 */ 161 public static final int FEEDBACK_AUDIBLE = 0x0000004; 162 163 /** 164 * Denotes visual feedback. 165 */ 166 public static final int FEEDBACK_VISUAL = 0x0000008; 167 168 /** 169 * Denotes generic feedback. 170 */ 171 public static final int FEEDBACK_GENERIC = 0x0000010; 172 173 /** 174 * Denotes braille feedback. 175 */ 176 public static final int FEEDBACK_BRAILLE = 0x0000020; 177 178 /** 179 * Mask for all feedback types. 180 * 181 * @see #FEEDBACK_SPOKEN 182 * @see #FEEDBACK_HAPTIC 183 * @see #FEEDBACK_AUDIBLE 184 * @see #FEEDBACK_VISUAL 185 * @see #FEEDBACK_GENERIC 186 * @see #FEEDBACK_BRAILLE 187 */ 188 public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF; 189 190 /** 191 * If an {@link AccessibilityService} is the default for a given type. 192 * Default service is invoked only if no package specific one exists. In case of 193 * more than one package specific service only the earlier registered is notified. 194 */ 195 public static final int DEFAULT = 0x0000001; 196 197 /** 198 * If this flag is set the system will regard views that are not important 199 * for accessibility in addition to the ones that are important for accessibility. 200 * That is, views that are marked as not important for accessibility via 201 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or 202 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are 203 * marked as potentially important for accessibility via 204 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined 205 * that are not important for accessibility, are reported while querying the window 206 * content and also the accessibility service will receive accessibility events from 207 * them. 208 * <p> 209 * <strong>Note:</strong> For accessibility services targeting API version 210 * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly 211 * set for the system to regard views that are not important for accessibility. For 212 * accessibility services targeting API version lower than 213 * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are 214 * regarded for accessibility purposes. 215 * </p> 216 * <p> 217 * Usually views not important for accessibility are layout managers that do not 218 * react to user actions, do not draw any content, and do not have any special 219 * semantics in the context of the screen content. For example, a three by three 220 * grid can be implemented as three horizontal linear layouts and one vertical, 221 * or three vertical linear layouts and one horizontal, or one grid layout, etc. 222 * In this context the actual layout mangers used to achieve the grid configuration 223 * are not important, rather it is important that there are nine evenly distributed 224 * elements. 225 * </p> 226 */ 227 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002; 228 229 /** 230 * This flag requests that the system gets into touch exploration mode. 231 * In this mode a single finger moving on the screen behaves as a mouse 232 * pointer hovering over the user interface. The system will also detect 233 * certain gestures performed on the touch screen and notify this service. 234 * The system will enable touch exploration mode if there is at least one 235 * accessibility service that has this flag set. Hence, clearing this 236 * flag does not guarantee that the device will not be in touch exploration 237 * mode since there may be another enabled service that requested it. 238 * <p> 239 * For accessibility services targeting API version higher than 240 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set 241 * this flag have to declare this capability in their meta-data by setting 242 * the attribute {@link android.R.attr#canRequestTouchExplorationMode 243 * canRequestTouchExplorationMode} to true, otherwise this flag will 244 * be ignored. For how to declare the meta-data of a service refer to 245 * {@value AccessibilityService#SERVICE_META_DATA}. 246 * </p> 247 * <p> 248 * Services targeting API version equal to or lower than 249 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e. 250 * the first time they are run, if this flag is specified, a dialog is 251 * shown to the user to confirm enabling explore by touch. 252 * </p> 253 * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode 254 */ 255 public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004; 256 257 /** 258 * This flag requests from the system to enable web accessibility enhancing 259 * extensions. Such extensions aim to provide improved accessibility support 260 * for content presented in a {@link android.webkit.WebView}. An example of such 261 * an extension is injecting JavaScript from a secure source. The system will enable 262 * enhanced web accessibility if there is at least one accessibility service 263 * that has this flag set. Hence, clearing this flag does not guarantee that the 264 * device will not have enhanced web accessibility enabled since there may be 265 * another enabled service that requested it. 266 * <p> 267 * Services that want to set this flag have to declare this capability 268 * in their meta-data by setting the attribute {@link android.R.attr 269 * #canRequestEnhancedWebAccessibility canRequestEnhancedWebAccessibility} to 270 * true, otherwise this flag will be ignored. For how to declare the meta-data 271 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 272 * </p> 273 * @see android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility 274 */ 275 public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008; 276 277 /** 278 * This flag requests that the {@link AccessibilityNodeInfo}s obtained 279 * by an {@link AccessibilityService} contain the id of the source view. 280 * The source view id will be a fully qualified resource name of the 281 * form "package:id/name", for example "foo.bar:id/my_list", and it is 282 * useful for UI test automation. This flag is not set by default. 283 */ 284 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010; 285 286 /** 287 * This flag requests from the system to filter key events. If this flag 288 * is set the accessibility service will receive the key events before 289 * applications allowing it implement global shortcuts. 290 * <p> 291 * Services that want to set this flag have to declare this capability 292 * in their meta-data by setting the attribute {@link android.R.attr 293 * #canRequestFilterKeyEvents canRequestFilterKeyEvents} to true, 294 * otherwise this flag will be ignored. For how to declare the meta-data 295 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 296 * </p> 297 * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents 298 */ 299 public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020; 300 301 /** 302 * This flag indicates to the system that the accessibility service wants 303 * to access content of all interactive windows. An interactive window is a 304 * window that has input focus or can be touched by a sighted user when explore 305 * by touch is not enabled. If this flag is not set your service will not receive 306 * {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED} 307 * events, calling AccessibilityService{@link AccessibilityService#getWindows() 308 * AccessibilityService.getWindows()} will return an empty list, and {@link 309 * AccessibilityNodeInfo#getWindow() AccessibilityNodeInfo.getWindow()} will 310 * return null. 311 * <p> 312 * Services that want to set this flag have to declare the capability 313 * to retrieve window content in their meta-data by setting the attribute 314 * {@link android.R.attr#canRetrieveWindowContent canRetrieveWindowContent} to 315 * true, otherwise this flag will be ignored. For how to declare the meta-data 316 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 317 * </p> 318 * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent 319 */ 320 public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040; 321 322 /** 323 * This flag requests that all audio tracks system-wide with 324 * {@link android.media.AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY} be controlled by the 325 * {@link android.media.AudioManager#STREAM_ACCESSIBILITY} volume. 326 */ 327 public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080; 328 329 /** {@hide} */ 330 public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000; 331 332 /** 333 * The event types an {@link AccessibilityService} is interested in. 334 * <p> 335 * <strong>Can be dynamically set at runtime.</strong> 336 * </p> 337 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED 338 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED 339 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED 340 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED 341 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED 342 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED 343 * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED 344 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START 345 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END 346 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER 347 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT 348 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED 349 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED 350 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED 351 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_START 352 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_END 353 * @see android.view.accessibility.AccessibilityEvent#TYPE_ANNOUNCEMENT 354 * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_START 355 * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_END 356 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED 357 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED 358 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY 359 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED 360 */ 361 public int eventTypes; 362 363 /** 364 * The package names an {@link AccessibilityService} is interested in. Setting 365 * to <code>null</code> is equivalent to all packages. 366 * <p> 367 * <strong>Can be dynamically set at runtime.</strong> 368 * </p> 369 */ 370 public String[] packageNames; 371 372 /** 373 * The feedback type an {@link AccessibilityService} provides. 374 * <p> 375 * <strong>Can be dynamically set at runtime.</strong> 376 * </p> 377 * @see #FEEDBACK_AUDIBLE 378 * @see #FEEDBACK_GENERIC 379 * @see #FEEDBACK_HAPTIC 380 * @see #FEEDBACK_SPOKEN 381 * @see #FEEDBACK_VISUAL 382 * @see #FEEDBACK_BRAILLE 383 */ 384 public int feedbackType; 385 386 /** 387 * The timeout after the most recent event of a given type before an 388 * {@link AccessibilityService} is notified. 389 * <p> 390 * <strong>Can be dynamically set at runtime.</strong>. 391 * </p> 392 * <p> 393 * <strong>Note:</strong> The event notification timeout is useful to avoid propagating 394 * events to the client too frequently since this is accomplished via an expensive 395 * interprocess call. One can think of the timeout as a criteria to determine when 396 * event generation has settled down. 397 */ 398 public long notificationTimeout; 399 400 /** 401 * This field represents a set of flags used for configuring an 402 * {@link AccessibilityService}. 403 * <p> 404 * <strong>Can be dynamically set at runtime.</strong> 405 * </p> 406 * @see #DEFAULT 407 * @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 408 * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE 409 * @see #FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY 410 * @see #FLAG_REQUEST_FILTER_KEY_EVENTS 411 * @see #FLAG_REPORT_VIEW_IDS 412 * @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS 413 */ 414 public int flags; 415 416 /** 417 * The unique string Id to identify the accessibility service. 418 */ 419 private String mId; 420 421 /** 422 * The Service that implements this accessibility service component. 423 */ 424 private ResolveInfo mResolveInfo; 425 426 /** 427 * The accessibility service setting activity's name, used by the system 428 * settings to launch the setting activity of this accessibility service. 429 */ 430 private String mSettingsActivityName; 431 432 /** 433 * Bit mask with capabilities of this service. 434 */ 435 private int mCapabilities; 436 437 /** 438 * Resource id of the description of the accessibility service. 439 */ 440 private int mDescriptionResId; 441 442 /** 443 * Non localized description of the accessibility service. 444 */ 445 private String mNonLocalizedDescription; 446 447 /** 448 * Creates a new instance. 449 */ 450 public AccessibilityServiceInfo() { 451 /* do nothing */ 452 } 453 454 /** 455 * Creates a new instance. 456 * 457 * @param resolveInfo The service resolve info. 458 * @param context Context for accessing resources. 459 * @throws XmlPullParserException If a XML parsing error occurs. 460 * @throws IOException If a XML parsing error occurs. 461 * 462 * @hide 463 */ 464 public AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context) 465 throws XmlPullParserException, IOException { 466 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 467 mId = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToShortString(); 468 mResolveInfo = resolveInfo; 469 470 XmlResourceParser parser = null; 471 472 try { 473 PackageManager packageManager = context.getPackageManager(); 474 parser = serviceInfo.loadXmlMetaData(packageManager, 475 AccessibilityService.SERVICE_META_DATA); 476 if (parser == null) { 477 return; 478 } 479 480 int type = 0; 481 while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { 482 type = parser.next(); 483 } 484 485 String nodeName = parser.getName(); 486 if (!TAG_ACCESSIBILITY_SERVICE.equals(nodeName)) { 487 throw new XmlPullParserException( "Meta-data does not start with" 488 + TAG_ACCESSIBILITY_SERVICE + " tag"); 489 } 490 491 AttributeSet allAttributes = Xml.asAttributeSet(parser); 492 Resources resources = packageManager.getResourcesForApplication( 493 serviceInfo.applicationInfo); 494 TypedArray asAttributes = resources.obtainAttributes(allAttributes, 495 com.android.internal.R.styleable.AccessibilityService); 496 eventTypes = asAttributes.getInt( 497 com.android.internal.R.styleable.AccessibilityService_accessibilityEventTypes, 498 0); 499 String packageNamez = asAttributes.getString( 500 com.android.internal.R.styleable.AccessibilityService_packageNames); 501 if (packageNamez != null) { 502 packageNames = packageNamez.split("(\\s)*,(\\s)*"); 503 } 504 feedbackType = asAttributes.getInt( 505 com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType, 506 0); 507 notificationTimeout = asAttributes.getInt( 508 com.android.internal.R.styleable.AccessibilityService_notificationTimeout, 509 0); 510 flags = asAttributes.getInt( 511 com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0); 512 mSettingsActivityName = asAttributes.getString( 513 com.android.internal.R.styleable.AccessibilityService_settingsActivity); 514 if (asAttributes.getBoolean(com.android.internal.R.styleable 515 .AccessibilityService_canRetrieveWindowContent, false)) { 516 mCapabilities |= CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT; 517 } 518 if (asAttributes.getBoolean(com.android.internal.R.styleable 519 .AccessibilityService_canRequestTouchExplorationMode, false)) { 520 mCapabilities |= CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION; 521 } 522 if (asAttributes.getBoolean(com.android.internal.R.styleable 523 .AccessibilityService_canRequestEnhancedWebAccessibility, false)) { 524 mCapabilities |= CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY; 525 } 526 if (asAttributes.getBoolean(com.android.internal.R.styleable 527 .AccessibilityService_canRequestFilterKeyEvents, false)) { 528 mCapabilities |= CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS; 529 } 530 if (asAttributes.getBoolean(com.android.internal.R.styleable 531 .AccessibilityService_canControlMagnification, false)) { 532 mCapabilities |= CAPABILITY_CAN_CONTROL_MAGNIFICATION; 533 } 534 if (asAttributes.getBoolean(com.android.internal.R.styleable 535 .AccessibilityService_canPerformGestures, false)) { 536 mCapabilities |= CAPABILITY_CAN_PERFORM_GESTURES; 537 } 538 TypedValue peekedValue = asAttributes.peekValue( 539 com.android.internal.R.styleable.AccessibilityService_description); 540 if (peekedValue != null) { 541 mDescriptionResId = peekedValue.resourceId; 542 CharSequence nonLocalizedDescription = peekedValue.coerceToString(); 543 if (nonLocalizedDescription != null) { 544 mNonLocalizedDescription = nonLocalizedDescription.toString().trim(); 545 } 546 } 547 asAttributes.recycle(); 548 } catch (NameNotFoundException e) { 549 throw new XmlPullParserException( "Unable to create context for: " 550 + serviceInfo.packageName); 551 } finally { 552 if (parser != null) { 553 parser.close(); 554 } 555 } 556 } 557 558 /** 559 * Updates the properties that an AccessibilitySerivice can change dynamically. 560 * 561 * @param other The info from which to update the properties. 562 * 563 * @hide 564 */ 565 public void updateDynamicallyConfigurableProperties(AccessibilityServiceInfo other) { 566 eventTypes = other.eventTypes; 567 packageNames = other.packageNames; 568 feedbackType = other.feedbackType; 569 notificationTimeout = other.notificationTimeout; 570 flags = other.flags; 571 } 572 573 /** 574 * @hide 575 */ 576 public void setComponentName(ComponentName component) { 577 mId = component.flattenToShortString(); 578 } 579 580 /** 581 * The accessibility service id. 582 * <p> 583 * <strong>Generated by the system.</strong> 584 * </p> 585 * @return The id. 586 */ 587 public String getId() { 588 return mId; 589 } 590 591 /** 592 * The service {@link ResolveInfo}. 593 * <p> 594 * <strong>Generated by the system.</strong> 595 * </p> 596 * @return The info. 597 */ 598 public ResolveInfo getResolveInfo() { 599 return mResolveInfo; 600 } 601 602 /** 603 * The settings activity name. 604 * <p> 605 * <strong>Statically set from 606 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 607 * </p> 608 * @return The settings activity name. 609 */ 610 public String getSettingsActivityName() { 611 return mSettingsActivityName; 612 } 613 614 /** 615 * Whether this service can retrieve the current window's content. 616 * <p> 617 * <strong>Statically set from 618 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 619 * </p> 620 * @return True if window content can be retrieved. 621 * 622 * @deprecated Use {@link #getCapabilities()}. 623 */ 624 public boolean getCanRetrieveWindowContent() { 625 return (mCapabilities & CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; 626 } 627 628 /** 629 * Returns the bit mask of capabilities this accessibility service has such as 630 * being able to retrieve the active window content, etc. 631 * 632 * @return The capability bit mask. 633 * 634 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 635 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 636 * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY 637 * @see #CAPABILITY_FILTER_KEY_EVENTS 638 * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION 639 * @see #CAPABILITY_CAN_PERFORM_GESTURES 640 */ 641 public int getCapabilities() { 642 return mCapabilities; 643 } 644 645 /** 646 * Sets the bit mask of capabilities this accessibility service has such as 647 * being able to retrieve the active window content, etc. 648 * 649 * @param capabilities The capability bit mask. 650 * 651 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 652 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 653 * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY 654 * @see #CAPABILITY_FILTER_KEY_EVENTS 655 * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION 656 * @see #CAPABILITY_CAN_PERFORM_GESTURES 657 * 658 * @hide 659 */ 660 public void setCapabilities(int capabilities) { 661 mCapabilities = capabilities; 662 } 663 664 /** 665 * Gets the non-localized description of the accessibility service. 666 * <p> 667 * <strong>Statically set from 668 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 669 * </p> 670 * @return The description. 671 * 672 * @deprecated Use {@link #loadDescription(PackageManager)}. 673 */ 674 public String getDescription() { 675 return mNonLocalizedDescription; 676 } 677 678 /** 679 * The localized description of the accessibility service. 680 * <p> 681 * <strong>Statically set from 682 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 683 * </p> 684 * @return The localized description. 685 */ 686 public String loadDescription(PackageManager packageManager) { 687 if (mDescriptionResId == 0) { 688 return mNonLocalizedDescription; 689 } 690 ServiceInfo serviceInfo = mResolveInfo.serviceInfo; 691 CharSequence description = packageManager.getText(serviceInfo.packageName, 692 mDescriptionResId, serviceInfo.applicationInfo); 693 if (description != null) { 694 return description.toString().trim(); 695 } 696 return null; 697 } 698 699 /** {@hide} */ 700 public boolean isDirectBootAware() { 701 return ((flags & FLAG_FORCE_DIRECT_BOOT_AWARE) != 0) 702 || mResolveInfo.serviceInfo.directBootAware; 703 } 704 705 /** 706 * {@inheritDoc} 707 */ 708 public int describeContents() { 709 return 0; 710 } 711 712 public void writeToParcel(Parcel parcel, int flagz) { 713 parcel.writeInt(eventTypes); 714 parcel.writeStringArray(packageNames); 715 parcel.writeInt(feedbackType); 716 parcel.writeLong(notificationTimeout); 717 parcel.writeInt(flags); 718 parcel.writeString(mId); 719 parcel.writeParcelable(mResolveInfo, 0); 720 parcel.writeString(mSettingsActivityName); 721 parcel.writeInt(mCapabilities); 722 parcel.writeInt(mDescriptionResId); 723 parcel.writeString(mNonLocalizedDescription); 724 } 725 726 private void initFromParcel(Parcel parcel) { 727 eventTypes = parcel.readInt(); 728 packageNames = parcel.readStringArray(); 729 feedbackType = parcel.readInt(); 730 notificationTimeout = parcel.readLong(); 731 flags = parcel.readInt(); 732 mId = parcel.readString(); 733 mResolveInfo = parcel.readParcelable(null); 734 mSettingsActivityName = parcel.readString(); 735 mCapabilities = parcel.readInt(); 736 mDescriptionResId = parcel.readInt(); 737 mNonLocalizedDescription = parcel.readString(); 738 } 739 740 @Override 741 public int hashCode() { 742 return 31 * 1 + ((mId == null) ? 0 : mId.hashCode()); 743 } 744 745 @Override 746 public boolean equals(Object obj) { 747 if (this == obj) { 748 return true; 749 } 750 if (obj == null) { 751 return false; 752 } 753 if (getClass() != obj.getClass()) { 754 return false; 755 } 756 AccessibilityServiceInfo other = (AccessibilityServiceInfo) obj; 757 if (mId == null) { 758 if (other.mId != null) { 759 return false; 760 } 761 } else if (!mId.equals(other.mId)) { 762 return false; 763 } 764 return true; 765 } 766 767 @Override 768 public String toString() { 769 StringBuilder stringBuilder = new StringBuilder(); 770 appendEventTypes(stringBuilder, eventTypes); 771 stringBuilder.append(", "); 772 appendPackageNames(stringBuilder, packageNames); 773 stringBuilder.append(", "); 774 appendFeedbackTypes(stringBuilder, feedbackType); 775 stringBuilder.append(", "); 776 stringBuilder.append("notificationTimeout: ").append(notificationTimeout); 777 stringBuilder.append(", "); 778 appendFlags(stringBuilder, flags); 779 stringBuilder.append(", "); 780 stringBuilder.append("id: ").append(mId); 781 stringBuilder.append(", "); 782 stringBuilder.append("resolveInfo: ").append(mResolveInfo); 783 stringBuilder.append(", "); 784 stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName); 785 stringBuilder.append(", "); 786 appendCapabilities(stringBuilder, mCapabilities); 787 return stringBuilder.toString(); 788 } 789 790 private static void appendFeedbackTypes(StringBuilder stringBuilder, int feedbackTypes) { 791 stringBuilder.append("feedbackTypes:"); 792 stringBuilder.append("["); 793 while (feedbackTypes != 0) { 794 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackTypes)); 795 stringBuilder.append(feedbackTypeToString(feedbackTypeBit)); 796 feedbackTypes &= ~feedbackTypeBit; 797 if (feedbackTypes != 0) { 798 stringBuilder.append(", "); 799 } 800 } 801 stringBuilder.append("]"); 802 } 803 804 private static void appendPackageNames(StringBuilder stringBuilder, String[] packageNames) { 805 stringBuilder.append("packageNames:"); 806 stringBuilder.append("["); 807 if (packageNames != null) { 808 final int packageNameCount = packageNames.length; 809 for (int i = 0; i < packageNameCount; i++) { 810 stringBuilder.append(packageNames[i]); 811 if (i < packageNameCount - 1) { 812 stringBuilder.append(", "); 813 } 814 } 815 } 816 stringBuilder.append("]"); 817 } 818 819 private static void appendEventTypes(StringBuilder stringBuilder, int eventTypes) { 820 stringBuilder.append("eventTypes:"); 821 stringBuilder.append("["); 822 while (eventTypes != 0) { 823 final int eventTypeBit = (1 << Integer.numberOfTrailingZeros(eventTypes)); 824 stringBuilder.append(AccessibilityEvent.eventTypeToString(eventTypeBit)); 825 eventTypes &= ~eventTypeBit; 826 if (eventTypes != 0) { 827 stringBuilder.append(", "); 828 } 829 } 830 stringBuilder.append("]"); 831 } 832 833 private static void appendFlags(StringBuilder stringBuilder, int flags) { 834 stringBuilder.append("flags:"); 835 stringBuilder.append("["); 836 while (flags != 0) { 837 final int flagBit = (1 << Integer.numberOfTrailingZeros(flags)); 838 stringBuilder.append(flagToString(flagBit)); 839 flags &= ~flagBit; 840 if (flags != 0) { 841 stringBuilder.append(", "); 842 } 843 } 844 stringBuilder.append("]"); 845 } 846 847 private static void appendCapabilities(StringBuilder stringBuilder, int capabilities) { 848 stringBuilder.append("capabilities:"); 849 stringBuilder.append("["); 850 while (capabilities != 0) { 851 final int capabilityBit = (1 << Integer.numberOfTrailingZeros(capabilities)); 852 stringBuilder.append(capabilityToString(capabilityBit)); 853 capabilities &= ~capabilityBit; 854 if (capabilities != 0) { 855 stringBuilder.append(", "); 856 } 857 } 858 stringBuilder.append("]"); 859 } 860 861 /** 862 * Returns the string representation of a feedback type. For example, 863 * {@link #FEEDBACK_SPOKEN} is represented by the string FEEDBACK_SPOKEN. 864 * 865 * @param feedbackType The feedback type. 866 * @return The string representation. 867 */ 868 public static String feedbackTypeToString(int feedbackType) { 869 StringBuilder builder = new StringBuilder(); 870 builder.append("["); 871 while (feedbackType != 0) { 872 final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType); 873 feedbackType &= ~feedbackTypeFlag; 874 switch (feedbackTypeFlag) { 875 case FEEDBACK_AUDIBLE: 876 if (builder.length() > 1) { 877 builder.append(", "); 878 } 879 builder.append("FEEDBACK_AUDIBLE"); 880 break; 881 case FEEDBACK_HAPTIC: 882 if (builder.length() > 1) { 883 builder.append(", "); 884 } 885 builder.append("FEEDBACK_HAPTIC"); 886 break; 887 case FEEDBACK_GENERIC: 888 if (builder.length() > 1) { 889 builder.append(", "); 890 } 891 builder.append("FEEDBACK_GENERIC"); 892 break; 893 case FEEDBACK_SPOKEN: 894 if (builder.length() > 1) { 895 builder.append(", "); 896 } 897 builder.append("FEEDBACK_SPOKEN"); 898 break; 899 case FEEDBACK_VISUAL: 900 if (builder.length() > 1) { 901 builder.append(", "); 902 } 903 builder.append("FEEDBACK_VISUAL"); 904 break; 905 case FEEDBACK_BRAILLE: 906 if (builder.length() > 1) { 907 builder.append(", "); 908 } 909 builder.append("FEEDBACK_BRAILLE"); 910 break; 911 } 912 } 913 builder.append("]"); 914 return builder.toString(); 915 } 916 917 /** 918 * Returns the string representation of a flag. For example, 919 * {@link #DEFAULT} is represented by the string DEFAULT. 920 * 921 * @param flag The flag. 922 * @return The string representation. 923 */ 924 public static String flagToString(int flag) { 925 switch (flag) { 926 case DEFAULT: 927 return "DEFAULT"; 928 case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS: 929 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS"; 930 case FLAG_REQUEST_TOUCH_EXPLORATION_MODE: 931 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE"; 932 case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 933 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 934 case FLAG_REPORT_VIEW_IDS: 935 return "FLAG_REPORT_VIEW_IDS"; 936 case FLAG_REQUEST_FILTER_KEY_EVENTS: 937 return "FLAG_REQUEST_FILTER_KEY_EVENTS"; 938 case FLAG_RETRIEVE_INTERACTIVE_WINDOWS: 939 return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS"; 940 case FLAG_ENABLE_ACCESSIBILITY_VOLUME: 941 return "FLAG_ENABLE_ACCESSIBILITY_VOLUME"; 942 default: 943 return null; 944 } 945 } 946 947 /** 948 * Returns the string representation of a capability. For example, 949 * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented 950 * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT. 951 * 952 * @param capability The capability. 953 * @return The string representation. 954 */ 955 public static String capabilityToString(int capability) { 956 switch (capability) { 957 case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT: 958 return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT"; 959 case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION: 960 return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION"; 961 case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 962 return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 963 case CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS: 964 return "CAPABILITY_CAN_FILTER_KEY_EVENTS"; 965 case CAPABILITY_CAN_CONTROL_MAGNIFICATION: 966 return "CAPABILITY_CAN_CONTROL_MAGNIFICATION"; 967 case CAPABILITY_CAN_PERFORM_GESTURES: 968 return "CAPABILITY_CAN_PERFORM_GESTURES"; 969 default: 970 return "UNKNOWN"; 971 } 972 } 973 974 /** 975 * @hide 976 * @return The list of {@link CapabilityInfo} objects. 977 */ 978 public List<CapabilityInfo> getCapabilityInfos() { 979 if (mCapabilities == 0) { 980 return Collections.emptyList(); 981 } 982 int capabilities = mCapabilities; 983 List<CapabilityInfo> capabilityInfos = new ArrayList<CapabilityInfo>(); 984 while (capabilities != 0) { 985 final int capabilityBit = 1 << Integer.numberOfTrailingZeros(capabilities); 986 capabilities &= ~capabilityBit; 987 CapabilityInfo capabilityInfo = sAvailableCapabilityInfos.get(capabilityBit); 988 if (capabilityInfo != null) { 989 capabilityInfos.add(capabilityInfo); 990 } 991 } 992 return capabilityInfos; 993 } 994 995 /** 996 * @hide 997 */ 998 public static final class CapabilityInfo { 999 public final int capability; 1000 public final int titleResId; 1001 public final int descResId; 1002 1003 public CapabilityInfo(int capability, int titleResId, int descResId) { 1004 this.capability = capability; 1005 this.titleResId = titleResId; 1006 this.descResId = descResId; 1007 } 1008 } 1009 1010 /** 1011 * @see Parcelable.Creator 1012 */ 1013 public static final Parcelable.Creator<AccessibilityServiceInfo> CREATOR = 1014 new Parcelable.Creator<AccessibilityServiceInfo>() { 1015 public AccessibilityServiceInfo createFromParcel(Parcel parcel) { 1016 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 1017 info.initFromParcel(parcel); 1018 return info; 1019 } 1020 1021 public AccessibilityServiceInfo[] newArray(int size) { 1022 return new AccessibilityServiceInfo[size]; 1023 } 1024 }; 1025} 1026