AccessibilityServiceInfo.java revision d1ed3cea37e4156eab14b7dc8207a520c9eab700
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.TypedValue; 33import android.util.Xml; 34import android.view.View; 35import android.view.accessibility.AccessibilityEvent; 36import android.view.accessibility.AccessibilityNodeInfo; 37 38import org.xmlpull.v1.XmlPullParser; 39import org.xmlpull.v1.XmlPullParserException; 40 41import java.io.IOException; 42 43/** 44 * This class describes an {@link AccessibilityService}. The system notifies an 45 * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s 46 * according to the information encapsulated in this class. 47 * 48 * <div class="special reference"> 49 * <h3>Developer Guides</h3> 50 * <p>For more information about creating AccessibilityServices, read the 51 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 52 * developer guide.</p> 53 * </div> 54 * 55 * @see AccessibilityService 56 * @see android.view.accessibility.AccessibilityEvent 57 * @see android.view.accessibility.AccessibilityManager 58 */ 59public class AccessibilityServiceInfo implements Parcelable { 60 61 private static final String TAG_ACCESSIBILITY_SERVICE = "accessibility-service"; 62 63 /** 64 * Denotes spoken feedback. 65 */ 66 public static final int FEEDBACK_SPOKEN = 0x0000001; 67 68 /** 69 * Denotes haptic feedback. 70 */ 71 public static final int FEEDBACK_HAPTIC = 0x0000002; 72 73 /** 74 * Denotes audible (not spoken) feedback. 75 */ 76 public static final int FEEDBACK_AUDIBLE = 0x0000004; 77 78 /** 79 * Denotes visual feedback. 80 */ 81 public static final int FEEDBACK_VISUAL = 0x0000008; 82 83 /** 84 * Denotes generic feedback. 85 */ 86 public static final int FEEDBACK_GENERIC = 0x0000010; 87 88 /** 89 * Denotes braille feedback. 90 */ 91 public static final int FEEDBACK_BRAILLE = 0x0000020; 92 93 /** 94 * Mask for all feedback types. 95 * 96 * @see #FEEDBACK_SPOKEN 97 * @see #FEEDBACK_HAPTIC 98 * @see #FEEDBACK_AUDIBLE 99 * @see #FEEDBACK_VISUAL 100 * @see #FEEDBACK_GENERIC 101 * @see #FEEDBACK_BRAILLE 102 */ 103 public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF; 104 105 /** 106 * If an {@link AccessibilityService} is the default for a given type. 107 * Default service is invoked only if no package specific one exists. In case of 108 * more than one package specific service only the earlier registered is notified. 109 */ 110 public static final int DEFAULT = 0x0000001; 111 112 /** 113 * If this flag is set the system will regard views that are not important 114 * for accessibility in addition to the ones that are important for accessibility. 115 * That is, views that are marked as not important for accessibility via 116 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} and views that are marked as 117 * potentially important for accessibility via 118 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined 119 * that are not important for accessibility, are both reported while querying the 120 * window content and also the accessibility service will receive accessibility events 121 * from them. 122 * <p> 123 * <strong>Note:</strong> For accessibility services targeting API version 124 * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly 125 * set for the system to regard views that are not important for accessibility. For 126 * accessibility services targeting API version lower than 127 * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are 128 * regarded for accessibility purposes. 129 * </p> 130 * <p> 131 * Usually views not important for accessibility are layout managers that do not 132 * react to user actions, do not draw any content, and do not have any special 133 * semantics in the context of the screen content. For example, a three by three 134 * grid can be implemented as three horizontal linear layouts and one vertical, 135 * or three vertical linear layouts and one horizontal, or one grid layout, etc. 136 * In this context the actual layout mangers used to achieve the grid configuration 137 * are not important, rather it is important that there are nine evenly distributed 138 * elements. 139 * </p> 140 */ 141 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002; 142 143 /** 144 * This flag requests that the system gets into touch exploration mode. 145 * In this mode a single finger moving on the screen behaves as a mouse 146 * pointer hovering over the user interface. The system will also detect 147 * certain gestures performed on the touch screen and notify this service. 148 * The system will enable touch exploration mode if there is at least one 149 * accessibility service that has this flag set. Hence, clearing this 150 * flag does not guarantee that the device will not be in touch exploration 151 * mode since there may be another enabled service that requested it. 152 * <p> 153 * Clients that want to set this flag have to request the 154 * {@link android.Manifest.permission#CAN_REQUEST_TOUCH_EXPLORATION_MODE} 155 * permission or the flag will be ignored. 156 * </p> 157 */ 158 public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004; 159 160 /** 161 * This flag requests from the system to enable web accessibility enhancing 162 * extensions. Such extensions aim to provide improved accessibility support 163 * for content presented in a {@link android.webkit.WebView}. An example of such 164 * an extension is injecting JavaScript from Google. The system will enable 165 * enhanced web accessibility if there is at least one accessibility service 166 * that has this flag set. Hence, clearing this flag does not guarantee that the 167 * device will not have enhanced web accessibility enabled since there may be 168 * another enabled service that requested it. 169 * <p> 170 * Clients that want to set this flag have to request the 171 * {@link android.Manifest.permission#CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY} 172 * permission or the flag will be ignored. 173 * </p> 174 */ 175 public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008; 176 177 /** 178 * This flag requests that the {@link AccessibilityNodeInfo}s obtained 179 * by an {@link AccessibilityService} contain the id of the source view. 180 * The source view id will be a fully qualified resource name of the 181 * form "package:id/name", for example "foo.bar:id/my_list", and it is 182 * useful for UI test automation. This flag is not set by default. 183 */ 184 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010; 185 186 /** 187 * The event types an {@link AccessibilityService} is interested in. 188 * <p> 189 * <strong>Can be dynamically set at runtime.</strong> 190 * </p> 191 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED 192 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED 193 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED 194 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED 195 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED 196 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED 197 * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED 198 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START 199 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END 200 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER 201 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT 202 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED 203 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED 204 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED 205 */ 206 public int eventTypes; 207 208 /** 209 * The package names an {@link AccessibilityService} is interested in. Setting 210 * to <code>null</code> is equivalent to all packages. 211 * <p> 212 * <strong>Can be dynamically set at runtime.</strong> 213 * </p> 214 */ 215 public String[] packageNames; 216 217 /** 218 * The feedback type an {@link AccessibilityService} provides. 219 * <p> 220 * <strong>Can be dynamically set at runtime.</strong> 221 * </p> 222 * @see #FEEDBACK_AUDIBLE 223 * @see #FEEDBACK_GENERIC 224 * @see #FEEDBACK_HAPTIC 225 * @see #FEEDBACK_SPOKEN 226 * @see #FEEDBACK_VISUAL 227 * @see #FEEDBACK_BRAILLE 228 */ 229 public int feedbackType; 230 231 /** 232 * The timeout after the most recent event of a given type before an 233 * {@link AccessibilityService} is notified. 234 * <p> 235 * <strong>Can be dynamically set at runtime.</strong>. 236 * </p> 237 * <p> 238 * <strong>Note:</strong> The event notification timeout is useful to avoid propagating 239 * events to the client too frequently since this is accomplished via an expensive 240 * interprocess call. One can think of the timeout as a criteria to determine when 241 * event generation has settled down. 242 */ 243 public long notificationTimeout; 244 245 /** 246 * This field represents a set of flags used for configuring an 247 * {@link AccessibilityService}. 248 * <p> 249 * <strong>Can be dynamically set at runtime.</strong> 250 * </p> 251 * @see #DEFAULT 252 * @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 253 * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE 254 */ 255 public int flags; 256 257 /** 258 * The unique string Id to identify the accessibility service. 259 */ 260 private String mId; 261 262 /** 263 * The Service that implements this accessibility service component. 264 */ 265 private ResolveInfo mResolveInfo; 266 267 /** 268 * The accessibility service setting activity's name, used by the system 269 * settings to launch the setting activity of this accessibility service. 270 */ 271 private String mSettingsActivityName; 272 273 /** 274 * Flag whether this accessibility service can retrieve window content. 275 */ 276 private boolean mCanRetrieveWindowContent; 277 278 /** 279 * Resource id of the description of the accessibility service. 280 */ 281 private int mDescriptionResId; 282 283 /** 284 * Non localized description of the accessibility service. 285 */ 286 private String mNonLocalizedDescription; 287 288 /** 289 * Creates a new instance. 290 */ 291 public AccessibilityServiceInfo() { 292 /* do nothing */ 293 } 294 295 /** 296 * Creates a new instance. 297 * 298 * @param resolveInfo The service resolve info. 299 * @param context Context for accessing resources. 300 * @throws XmlPullParserException If a XML parsing error occurs. 301 * @throws IOException If a XML parsing error occurs. 302 * 303 * @hide 304 */ 305 public AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context) 306 throws XmlPullParserException, IOException { 307 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 308 mId = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToShortString(); 309 mResolveInfo = resolveInfo; 310 311 XmlResourceParser parser = null; 312 313 try { 314 PackageManager packageManager = context.getPackageManager(); 315 parser = serviceInfo.loadXmlMetaData(packageManager, 316 AccessibilityService.SERVICE_META_DATA); 317 if (parser == null) { 318 return; 319 } 320 321 int type = 0; 322 while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { 323 type = parser.next(); 324 } 325 326 String nodeName = parser.getName(); 327 if (!TAG_ACCESSIBILITY_SERVICE.equals(nodeName)) { 328 throw new XmlPullParserException( "Meta-data does not start with" 329 + TAG_ACCESSIBILITY_SERVICE + " tag"); 330 } 331 332 AttributeSet allAttributes = Xml.asAttributeSet(parser); 333 Resources resources = packageManager.getResourcesForApplication( 334 serviceInfo.applicationInfo); 335 TypedArray asAttributes = resources.obtainAttributes(allAttributes, 336 com.android.internal.R.styleable.AccessibilityService); 337 eventTypes = asAttributes.getInt( 338 com.android.internal.R.styleable.AccessibilityService_accessibilityEventTypes, 339 0); 340 String packageNamez = asAttributes.getString( 341 com.android.internal.R.styleable.AccessibilityService_packageNames); 342 if (packageNamez != null) { 343 packageNames = packageNamez.split("(\\s)*,(\\s)*"); 344 } 345 feedbackType = asAttributes.getInt( 346 com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType, 347 0); 348 notificationTimeout = asAttributes.getInt( 349 com.android.internal.R.styleable.AccessibilityService_notificationTimeout, 350 0); 351 flags = asAttributes.getInt( 352 com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0); 353 mSettingsActivityName = asAttributes.getString( 354 com.android.internal.R.styleable.AccessibilityService_settingsActivity); 355 mCanRetrieveWindowContent = asAttributes.getBoolean( 356 com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent, 357 false); 358 TypedValue peekedValue = asAttributes.peekValue( 359 com.android.internal.R.styleable.AccessibilityService_description); 360 if (peekedValue != null) { 361 mDescriptionResId = peekedValue.resourceId; 362 CharSequence nonLocalizedDescription = peekedValue.coerceToString(); 363 if (nonLocalizedDescription != null) { 364 mNonLocalizedDescription = nonLocalizedDescription.toString().trim(); 365 } 366 } 367 asAttributes.recycle(); 368 } catch (NameNotFoundException e) { 369 throw new XmlPullParserException( "Unable to create context for: " 370 + serviceInfo.packageName); 371 } finally { 372 if (parser != null) { 373 parser.close(); 374 } 375 } 376 } 377 378 /** 379 * Updates the properties that an AccessibilitySerivice can change dynamically. 380 * 381 * @param other The info from which to update the properties. 382 * 383 * @hide 384 */ 385 public void updateDynamicallyConfigurableProperties(AccessibilityServiceInfo other) { 386 eventTypes = other.eventTypes; 387 packageNames = other.packageNames; 388 feedbackType = other.feedbackType; 389 notificationTimeout = other.notificationTimeout; 390 flags = other.flags; 391 } 392 393 /** 394 * The accessibility service id. 395 * <p> 396 * <strong>Generated by the system.</strong> 397 * </p> 398 * @return The id. 399 */ 400 public String getId() { 401 return mId; 402 } 403 404 /** 405 * The service {@link ResolveInfo}. 406 * <p> 407 * <strong>Generated by the system.</strong> 408 * </p> 409 * @return The info. 410 */ 411 public ResolveInfo getResolveInfo() { 412 return mResolveInfo; 413 } 414 415 /** 416 * The settings activity name. 417 * <p> 418 * <strong>Statically set from 419 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 420 * </p> 421 * @return The settings activity name. 422 */ 423 public String getSettingsActivityName() { 424 return mSettingsActivityName; 425 } 426 427 /** 428 * Whether this service can retrieve the current window's content. 429 * <p> 430 * <strong>Statically set from 431 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 432 * </p> 433 * @return True if window content can be retrieved. 434 */ 435 public boolean getCanRetrieveWindowContent() { 436 return mCanRetrieveWindowContent; 437 } 438 439 /** 440 * Gets the non-localized description of the accessibility service. 441 * <p> 442 * <strong>Statically set from 443 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 444 * </p> 445 * @return The description. 446 * 447 * @deprecated Use {@link #loadDescription(PackageManager)}. 448 */ 449 public String getDescription() { 450 return mNonLocalizedDescription; 451 } 452 453 /** 454 * The localized description of the accessibility service. 455 * <p> 456 * <strong>Statically set from 457 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 458 * </p> 459 * @return The localized description. 460 */ 461 public String loadDescription(PackageManager packageManager) { 462 if (mDescriptionResId == 0) { 463 return mNonLocalizedDescription; 464 } 465 ServiceInfo serviceInfo = mResolveInfo.serviceInfo; 466 CharSequence description = packageManager.getText(serviceInfo.packageName, 467 mDescriptionResId, serviceInfo.applicationInfo); 468 if (description != null) { 469 return description.toString().trim(); 470 } 471 return null; 472 } 473 474 /** 475 * {@inheritDoc} 476 */ 477 public int describeContents() { 478 return 0; 479 } 480 481 public void writeToParcel(Parcel parcel, int flagz) { 482 parcel.writeInt(eventTypes); 483 parcel.writeStringArray(packageNames); 484 parcel.writeInt(feedbackType); 485 parcel.writeLong(notificationTimeout); 486 parcel.writeInt(flags); 487 parcel.writeString(mId); 488 parcel.writeParcelable(mResolveInfo, 0); 489 parcel.writeString(mSettingsActivityName); 490 parcel.writeInt(mCanRetrieveWindowContent ? 1 : 0); 491 parcel.writeInt(mDescriptionResId); 492 parcel.writeString(mNonLocalizedDescription); 493 } 494 495 private void initFromParcel(Parcel parcel) { 496 eventTypes = parcel.readInt(); 497 packageNames = parcel.readStringArray(); 498 feedbackType = parcel.readInt(); 499 notificationTimeout = parcel.readLong(); 500 flags = parcel.readInt(); 501 mId = parcel.readString(); 502 mResolveInfo = parcel.readParcelable(null); 503 mSettingsActivityName = parcel.readString(); 504 mCanRetrieveWindowContent = (parcel.readInt() == 1); 505 mDescriptionResId = parcel.readInt(); 506 mNonLocalizedDescription = parcel.readString(); 507 } 508 509 @Override 510 public String toString() { 511 StringBuilder stringBuilder = new StringBuilder(); 512 appendEventTypes(stringBuilder, eventTypes); 513 stringBuilder.append(", "); 514 appendPackageNames(stringBuilder, packageNames); 515 stringBuilder.append(", "); 516 appendFeedbackTypes(stringBuilder, feedbackType); 517 stringBuilder.append(", "); 518 stringBuilder.append("notificationTimeout: ").append(notificationTimeout); 519 stringBuilder.append(", "); 520 appendFlags(stringBuilder, flags); 521 stringBuilder.append(", "); 522 stringBuilder.append("id: ").append(mId); 523 stringBuilder.append(", "); 524 stringBuilder.append("resolveInfo: ").append(mResolveInfo); 525 stringBuilder.append(", "); 526 stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName); 527 stringBuilder.append(", "); 528 stringBuilder.append("retrieveScreenContent: ").append(mCanRetrieveWindowContent); 529 return stringBuilder.toString(); 530 } 531 532 private static void appendFeedbackTypes(StringBuilder stringBuilder, int feedbackTypes) { 533 stringBuilder.append("feedbackTypes:"); 534 stringBuilder.append("["); 535 while (feedbackTypes != 0) { 536 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackTypes)); 537 stringBuilder.append(feedbackTypeToString(feedbackTypeBit)); 538 feedbackTypes &= ~feedbackTypeBit; 539 if (feedbackTypes != 0) { 540 stringBuilder.append(", "); 541 } 542 } 543 stringBuilder.append("]"); 544 } 545 546 private static void appendPackageNames(StringBuilder stringBuilder, String[] packageNames) { 547 stringBuilder.append("packageNames:"); 548 stringBuilder.append("["); 549 if (packageNames != null) { 550 final int packageNameCount = packageNames.length; 551 for (int i = 0; i < packageNameCount; i++) { 552 stringBuilder.append(packageNames[i]); 553 if (i < packageNameCount - 1) { 554 stringBuilder.append(", "); 555 } 556 } 557 } 558 stringBuilder.append("]"); 559 } 560 561 private static void appendEventTypes(StringBuilder stringBuilder, int eventTypes) { 562 stringBuilder.append("eventTypes:"); 563 stringBuilder.append("["); 564 while (eventTypes != 0) { 565 final int eventTypeBit = (1 << Integer.numberOfTrailingZeros(eventTypes)); 566 stringBuilder.append(AccessibilityEvent.eventTypeToString(eventTypeBit)); 567 eventTypes &= ~eventTypeBit; 568 if (eventTypes != 0) { 569 stringBuilder.append(", "); 570 } 571 } 572 stringBuilder.append("]"); 573 } 574 575 private static void appendFlags(StringBuilder stringBuilder, int flags) { 576 stringBuilder.append("flags:"); 577 stringBuilder.append("["); 578 while (flags != 0) { 579 final int flagBit = (1 << Integer.numberOfTrailingZeros(flags)); 580 stringBuilder.append(flagToString(flagBit)); 581 flags &= ~flagBit; 582 if (flags != 0) { 583 stringBuilder.append(", "); 584 } 585 } 586 stringBuilder.append("]"); 587 } 588 589 /** 590 * Returns the string representation of a feedback type. For example, 591 * {@link #FEEDBACK_SPOKEN} is represented by the string FEEDBACK_SPOKEN. 592 * 593 * @param feedbackType The feedback type. 594 * @return The string representation. 595 */ 596 public static String feedbackTypeToString(int feedbackType) { 597 StringBuilder builder = new StringBuilder(); 598 builder.append("["); 599 while (feedbackType != 0) { 600 final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType); 601 feedbackType &= ~feedbackTypeFlag; 602 switch (feedbackTypeFlag) { 603 case FEEDBACK_AUDIBLE: 604 if (builder.length() > 1) { 605 builder.append(", "); 606 } 607 builder.append("FEEDBACK_AUDIBLE"); 608 break; 609 case FEEDBACK_HAPTIC: 610 if (builder.length() > 1) { 611 builder.append(", "); 612 } 613 builder.append("FEEDBACK_HAPTIC"); 614 break; 615 case FEEDBACK_GENERIC: 616 if (builder.length() > 1) { 617 builder.append(", "); 618 } 619 builder.append("FEEDBACK_GENERIC"); 620 break; 621 case FEEDBACK_SPOKEN: 622 if (builder.length() > 1) { 623 builder.append(", "); 624 } 625 builder.append("FEEDBACK_SPOKEN"); 626 break; 627 case FEEDBACK_VISUAL: 628 if (builder.length() > 1) { 629 builder.append(", "); 630 } 631 builder.append("FEEDBACK_VISUAL"); 632 break; 633 case FEEDBACK_BRAILLE: 634 if (builder.length() > 1) { 635 builder.append(", "); 636 } 637 builder.append("FEEDBACK_BRAILLE"); 638 break; 639 } 640 } 641 builder.append("]"); 642 return builder.toString(); 643 } 644 645 /** 646 * Returns the string representation of a flag. For example, 647 * {@link #DEFAULT} is represented by the string DEFAULT. 648 * 649 * @param flag The flag. 650 * @return The string representation. 651 */ 652 public static String flagToString(int flag) { 653 switch (flag) { 654 case DEFAULT: 655 return "DEFAULT"; 656 case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS: 657 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS"; 658 case FLAG_REQUEST_TOUCH_EXPLORATION_MODE: 659 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE"; 660 default: 661 return null; 662 } 663 } 664 665 /** 666 * @see Parcelable.Creator 667 */ 668 public static final Parcelable.Creator<AccessibilityServiceInfo> CREATOR = 669 new Parcelable.Creator<AccessibilityServiceInfo>() { 670 public AccessibilityServiceInfo createFromParcel(Parcel parcel) { 671 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 672 info.initFromParcel(parcel); 673 return info; 674 } 675 676 public AccessibilityServiceInfo[] newArray(int size) { 677 return new AccessibilityServiceInfo[size]; 678 } 679 }; 680} 681