diff options
Diffstat (limited to 'core/java/android/accessibilityservice/AccessibilityService.java')
| -rw-r--r-- | core/java/android/accessibilityservice/AccessibilityService.java | 265 |
1 files changed, 155 insertions, 110 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 164acbcdf71f..68c992671f97 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -31,82 +31,151 @@ import android.view.accessibility.AccessibilityNodeInfo; * An accessibility service runs in the background and receives callbacks by the system * when {@link AccessibilityEvent}s are fired. Such events denote some state transition * in the user interface, for example, the focus has changed, a button has been clicked, - * etc. + * etc. Such a service can optionally request the capability for querying the content + * of the active window. Development of an accessibility service requires extends this + * class and implements its abstract methods. * <p> - * An accessibility service extends this class and implements its abstract methods. Such - * a service is declared as any other service in an AndroidManifest.xml but it must also - * specify that it handles the "android.accessibilityservice.AccessibilityService" - * {@link android.content.Intent}. Following is an example of such a declaration: - * <p> - * <code> - * <service android:name=".MyAccessibilityService"><br> - * <intent-filter><br> - * <action android:name="android.accessibilityservice.AccessibilityService" /><br> - * </intent-filter><br> - * </service><br> - * </code> + * <strong>Lifecycle</strong> * </p> * <p> - * The lifecycle of an accessibility service is managed exclusively by the system. Starting - * or stopping an accessibility service is triggered by an explicit user action through + * The lifecycle of an accessibility service is managed exclusively by the system and + * follows the established service life cycle. Additionally, starting or stopping an + * accessibility service is triggered exclusively by an explicit user action through * enabling or disabling it in the device settings. After the system binds to a service it * calls {@link AccessibilityService#onServiceConnected()}. This method can be * overriden by clients that want to perform post binding setup. * </p> * <p> + * <strong>Declaration</strong> + * </p> + * <p> + * An accessibility is declared as any other service in an AndroidManifest.xml but it + * must also specify that it handles the "android.accessibilityservice.AccessibilityService" + * {@link android.content.Intent}. Failure to declare this intent will cause the system to + * ignore the accessibility service. Following is an example declaration: + * </p> + * <p> + * <code> + * <pre> + * <service android:name=".MyAccessibilityService"> + * <intent-filter> + * <action android:name="android.accessibilityservice.AccessibilityService" /> + * </intent-filter> + * . . . + * </service> + * </pre> + * </code> + * </p> + * <p> + * <strong>Configuration</strong> + * </p> + * <p> * An accessibility service can be configured to receive specific types of accessibility events, * listen only to specific packages, get events from each type only once in a given time frame, * retrieve window content, specify a settings activity, etc. * </p> + * <p> * There are two approaches for configuring an accessibility service: + * </p> * <ul> - * <li> - * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring - * the service. A service declaration with a meta-data tag is presented below: - * <p> - * <code> - * <service android:name=".MyAccessibilityService"><br> - * <intent-filter><br> - * <action android:name="android.accessibilityservice.AccessibilityService" /><br> - * </intent-filter><br> - * <meta-data android:name="android.accessibilityservice.as" android:resource="@xml/accessibilityservice" /><br> - * </service><br> - * </code> - * </p> - * <p> - * <strong> - * This approach enables setting all accessibility service properties. - * </strong> - * </p> - * <p> - * For more details refer to {@link #SERVICE_META_DATA}. - * </p> - * </li> - * <li> - * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note - * that this method can be called any time to change the service configuration.<br> - * <p> - * <strong> - * This approach enables setting only dynamically configurable accessibility - * service properties: - * {@link AccessibilityServiceInfo#eventTypes}, - * {@link AccessibilityServiceInfo#feedbackType}, - * {@link AccessibilityServiceInfo#flags}, - * {@link AccessibilityServiceInfo#notificationTimeout}, - * {@link AccessibilityServiceInfo#packageNames} - * </strong> - * </p> - * <p> - * For more details refer to {@link AccessibilityServiceInfo}. - * </p> - * </li> + * <li> + * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring + * the service. A service declaration with a meta-data tag is presented below: + * <p> + * <code> + * <pre> + * <service android:name=".MyAccessibilityService"> + * <intent-filter> + * <action android:name="android.accessibilityservice.AccessibilityService" /> + * </intent-filter> + * <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" /> + * </service> + * </pre> + * </code> + * </p> + * <p> + * <strong>Note:</strong>This approach enables setting all properties. + * </p> + * <p> + * For more details refer to {@link #SERVICE_META_DATA} and + * <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code>.. + * </p> + * </li> + * <li> + * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note + * that this method can be called any time to dynamically change the service configuration. + * <p> + * <strong>Note:</strong> This approach enables setting only dynamically configurable properties: + * {@link AccessibilityServiceInfo#eventTypes}, + * {@link AccessibilityServiceInfo#feedbackType}, + * {@link AccessibilityServiceInfo#flags}, + * {@link AccessibilityServiceInfo#notificationTimeout}, + * {@link AccessibilityServiceInfo#packageNames} + * </p> + * <p> + * For more details refer to {@link AccessibilityServiceInfo}. + * </p> + * </li> * </ul> * <p> - * An accessibility service can be registered for events in specific packages to provide a - * specific type of feedback and is notified with a certain timeout after the last event - * of interest has been fired. + * <strong>Retrieving window content</strong> + * </p> + * <p> + * An service can specify in its declaration that it can retrieve the active window + * content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that + * declaring this capability requires that the service declares its configuration via + * an XML resource referenced by {@link #SERVICE_META_DATA}. + * </p> + * <p> + * For security purposes an accessibility service can retrieve only the content of the + * currently active window. The currently active window is defined as the window from + * which was fired the last event of the following types: + * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}, + * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}, + * {@link AccessibilityEvent#TYPE_VIEW_CLICKED}, + * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}, + * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}, + * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}, + * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}, + * {@link AccessibilityEvent#TYPE_VIEW_SELECTED}, + * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}, + * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}, + * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}, + * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}, + * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}. + * In other words, the active window is the one where the user interaction is taking place. + * </p> + * <p> + * The entry point for retrieving window content is through calling + * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()} of the last received + * event of the above types or a previous event from the same window + * (see {@link AccessibilityEvent#getWindowId() AccessibilityEvent.getWindowId()}). Invoking + * this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the + * window content which represented as a tree of such objects. + * </p> + * <p> + * <strong>Note</strong>An accessibility service may have requested to be notified for + * a subset of the event types, thus be unaware that the active window has changed. Therefore + * accessibility service that would like to retrieve window content should: + * <ul> + * <li> + * Register for all event types with no notification timeout and keep track for the active + * window by calling {@link AccessibilityEvent#getWindowId()} of the last received event and + * compare this with the {@link AccessibilityNodeInfo#getWindowId()} before calling retrieval + * methods on the latter. + * </li> + * <li> + * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the + * active window has changed and the service did not get the accessibility event yet. Note + * that it is possible to have a retrieval method failing event adopting the strategy + * specified in the previous bullet because the accessibility event dispatch is asynchronous + * and crosses process boundaries. + * </li> + * </ul> + * </p> * <p> * <b>Notification strategy</b> + * </p> * <p> * For each feedback type only one accessibility service is notified. Services are notified * in the order of registration. Hence, if two services are registered for the same @@ -117,9 +186,10 @@ import android.view.accessibility.AccessibilityNodeInfo; * registration order. This enables "generic" accessibility services that work reasonably * well with most applications to coexist with "polished" ones that are targeted for * specific applications. + * </p> * <p> * <b>Event types</b> - * <p> + * </p> * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED} * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED} @@ -127,9 +197,16 @@ import android.view.accessibility.AccessibilityNodeInfo; * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} * {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} - * <p> - * <b>Feedback types</b> - * <p> + * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START} + * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} + * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER} + * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT} + * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} + * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} + * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} + * <p> + * <b>Feedback types</b> + * <p> * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE} * {@link AccessibilityServiceInfo#FEEDBACK_HAPTIC} * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE} @@ -140,10 +217,10 @@ import android.view.accessibility.AccessibilityNodeInfo; * @see AccessibilityServiceInfo * @see android.view.accessibility.AccessibilityManager * - * Note: The event notification timeout is useful to avoid propagating events to the client - * too frequently since this is accomplished via an expensive interprocess call. - * One can think of the timeout as a criteria to determine when event generation has - * settled down. + * <strong>Note:</strong> The event notification timeout is useful to avoid propagating + * events to the client too frequently since this is accomplished via an expensive + * interprocess call. One can think of the timeout as a criteria to determine when + * event generation has settled down. */ public abstract class AccessibilityService extends Service { /** @@ -154,57 +231,25 @@ public abstract class AccessibilityService extends Service { /** * Name under which an AccessibilityService component publishes information - * about itself. This meta-data must reference an XML resource containing - * an + * about itself. This meta-data must reference an XML resource containing an * <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code> * tag. This is a a sample XML file configuring an accessibility service: * <p> * <code> - * <?xml version="1.0" encoding="utf-8"?><br> - * <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"<br> - * android:accessibilityEventTypes="typeViewClicked|typeViewFocused"<br> - * android:packageNames="foo.bar, foo.baz"<br> - * android:accessibilityFeedbackType="feedbackSpoken"<br> - * android:notificationTimeout="100"<br> - * android:accessibilityFlags="flagDefault"<br> - * android:settingsActivity="foo.bar.TestBackActivity"<br> - * . . .<br> + * <pre> + * <accessibility-service + * android:accessibilityEventTypes="typeViewClicked|typeViewFocused" + * android:packageNames="foo.bar, foo.baz" + * android:accessibilityFeedbackType="feedbackSpoken" + * android:notificationTimeout="100" + * android:accessibilityFlags="flagDefault" + * android:settingsActivity="foo.bar.TestBackActivity" + * android:canRetrieveWindowContent="true" + * . . . * /> + * </pre> * </code> * </p> - * <p> - * <strong>Note:</strong> A service can retrieve only the content of the active window. - * An active window is the source of the most recent event of type - * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}, - * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}, - * {@link AccessibilityEvent#TYPE_VIEW_CLICKED}, - * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}, - * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}, - * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}, - * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}, - * {@link AccessibilityEvent#TYPE_VIEW_SELECTED}, - * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}, - * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}. - * Therefore the service should: - * <ul> - * <li> - * Register for all event types with no notification timeout and keep track - * for the active window by calling - * {@link AccessibilityEvent#getWindowId()} of the last received - * event and compare this with the - * {@link AccessibilityNodeInfo#getWindowId()} before calling - * retrieval methods on the latter. - * </li> - * <li> - * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail - * since the active window has changed and the service did not get the - * accessibility event. Note that it is possible to have a retrieval method - * failing event adopting the strategy specified in the previous bullet - * because the accessibility event dispatch is asynchronous and crosses - * process boundaries. - * </li> - * <ul> - * </p> */ public static final String SERVICE_META_DATA = "android.accessibilityservice"; |
