diff options
10 files changed, 572 insertions, 316 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"; diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index b9878cd9c97a..ef4adca97a82 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -37,13 +37,13 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; /** - * This class describes an {@link AccessibilityService}. The system - * notifies an {@link AccessibilityService} for - * {@link android.view.accessibility.AccessibilityEvent}s + * This class describes an {@link AccessibilityService}. The system notifies an + * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s * according to the information encapsulated in this class. * * @see AccessibilityService * @see android.view.accessibility.AccessibilityEvent + * @see android.view.accessibility.AccessibilityManager */ public class AccessibilityServiceInfo implements Parcelable { @@ -93,12 +93,19 @@ public class AccessibilityServiceInfo implements Parcelable { * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED + * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START + * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED + * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED */ public int eventTypes; /** * The package names an {@link AccessibilityService} is interested in. Setting - * to null is equivalent to all packages. + * to <code>null</code> is equivalent to all packages. * <p> * <strong>Can be dynamically set at runtime.</strong> * </p> @@ -125,10 +132,10 @@ public class AccessibilityServiceInfo implements Parcelable { * <strong>Can be dynamically set at runtime.</strong>. * </p> * <p> - * 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 long notificationTimeout; @@ -159,7 +166,7 @@ public class AccessibilityServiceInfo implements Parcelable { private String mSettingsActivityName; /** - * Flag whether this accessibility service can retrieve screen content. + * Flag whether this accessibility service can retrieve window content. */ private boolean mCanRetrieveWindowContent; @@ -296,12 +303,12 @@ public class AccessibilityServiceInfo implements Parcelable { } /** - * Whether this service can retrieve the currently focused window content. + * Whether this service can retrieve the current window's content. * <p> * <strong>Statically set from * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> * </p> - * @return True screen content is retrieved. + * @return True window content can be retrieved. */ public boolean getCanRetrieveWindowContent() { return mCanRetrieveWindowContent; diff --git a/core/java/android/accessibilityservice/package.html b/core/java/android/accessibilityservice/package.html new file mode 100644 index 000000000000..0c640d14368f --- /dev/null +++ b/core/java/android/accessibilityservice/package.html @@ -0,0 +1,22 @@ +<html> +<body> +<p> + The classes in this package are used for development of accessibility service that + provide alternative or augmented feedback to the user. +</p> +<p> + An {@link android.accessibilityservice.AccessibilityService} runs in the background and + receives callbacks by the system when {@link android.view.accessibility.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. 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> +<p> + An {@link android.accessibilityservice.AccessibilityServiceInfo} describes an + {@link android.accessibilityservice.AccessibilityService}. The system notifies an + AccessibilityService for {@link android.view.accessibility.AccessibilityEvent}s + according to the information encapsulated in this class. +</p> +</body> +</html> diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index 25f01a7dc9fa..ac867690724b 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -25,40 +25,51 @@ import java.util.ArrayList; import java.util.List; /** + * <p> * This class represents accessibility events that are sent by the system when * something notable happens in the user interface. For example, when a * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc. + * </p> * <p> * An accessibility event is fired by an individual view which populates the event with - * a record for its state and requests from its parent to send the event to interested - * parties. The parent can optionally add a record for itself before dispatching a similar - * request to its parent. A parent can also choose not to respect the request for sending - * an event. The accessibility event is sent by the topmost view in the view tree. - * Therefore, an {@link android.accessibilityservice.AccessibilityService} can explore - * all records in an accessibility event to obtain more information about the context - * in which the event was fired. + * data for its state and requests from its parent to send the event to interested + * parties. The parent can optionally add an {@link AccessibilityRecord} for itself before + * dispatching a similar request to its parent. A parent can also choose not to respect the + * request for sending an event. The accessibility event is sent by the topmost view in the + * view tree. Therefore, an {@link android.accessibilityservice.AccessibilityService} can + * explore all records in an accessibility event to obtain more information about the + * context in which the event was fired. + * </p> * <p> - * A client can add, remove, and modify records. The getters and setters for individual - * properties operate on the current record which can be explicitly set by the client. By - * default current is the first record. Thus, querying a record would require setting - * it as the current one and interacting with the property getters and setters. + * The main purpose of an accessibility event is to expose enough information for an + * {@link android.accessibilityservice.AccessibilityService} to provide meaningful feedback + * to the user. Sometimes however, an accessibility service may need more contextual + * information then the one in the event pay-load. In such cases the service can obtain + * the event source which is an {@link AccessibilityNodeInfo} (snapshot of a View state) + * which can be used for exploring the window content. Note that the privilege for accessing + * an event's source, thus the window content, has to be explicitly requested. For more + * details refer to {@link android.accessibilityservice.AccessibilityService}. If an + * accessibility service has not requested to retrieve the window content the event will + * not contain reference to its source. Also for events of type + * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available. + * </p> * <p> * This class represents various semantically different accessibility event - * types. Each event type has associated a set of related properties. In other + * types. Each event type has an associated set of related properties. In other * words, each event type is characterized via a subset of the properties exposed * by this class. For each event type there is a corresponding constant defined - * in this class. Since some event types are semantically close there are mask - * constants that group them together. Follows a specification of the event - * types and their associated properties: + * in this class. Follows a specification of the event types and their associated properties: + * </p> * <p> - * <b>VIEW TYPES</b> <br> + * <b>VIEW TYPES</b></br> + * </p> * <p> * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View} - * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br> - * Type:{@link #TYPE_VIEW_CLICKED} <br> - * Properties:</br> + * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.</br> + * <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> @@ -67,13 +78,14 @@ import java.util.List; * <li>{@link #isPassword()} - Whether the source is password.</li> * <li>{@link #isChecked()} - Whether the source is checked.</li> * </ul> + * </p> * <p> * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View} - * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br> - * Type:{@link #TYPE_VIEW_LONG_CLICKED} <br> - * Properties:</br> + * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br> + * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> @@ -82,13 +94,14 @@ import java.util.List; * <li>{@link #isPassword()} - Whether the source is password.</li> * <li>{@link #isChecked()} - Whether the source is checked.</li> * </ul> + * </p> * <p> * <b>View selected</b> - represents the event of selecting an item usually in - * the context of an {@link android.widget.AdapterView}. <br> - * Type: {@link #TYPE_VIEW_SELECTED} <br> - * Properties:</br> + * the context of an {@link android.widget.AdapterView}.</br> + * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> @@ -96,17 +109,17 @@ import java.util.List; * <li>{@link #isEnabled()} - Whether the source is enabled.</li> * <li>{@link #isPassword()} - Whether the source is password.</li> * <li>{@link #isChecked()} - Whether the source is checked.</li> - * <li>{@link #getItemCount()} -The number of selectable items of the source.</li> + * <li>{@link #getItemCount()} - The number of selectable items of the source.</li> * <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li> * </ul> - * <p> + * </p> * <p> * <b>View focused</b> - represents the event of focusing a - * {@link android.view.View}. <br> - * Type: {@link #TYPE_VIEW_FOCUSED} <br> - * Properties:</br> + * {@link android.view.View}.</br> + * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> @@ -114,16 +127,17 @@ import java.util.List; * <li>{@link #isEnabled()} - Whether the source is enabled.</li> * <li>{@link #isPassword()} - Whether the source is password.</li> * <li>{@link #isChecked()} - Whether the source is checked.</li> - * <li>{@link #getItemCount()} -The number of focusable items on the screen.</li> + * <li>{@link #getItemCount()} - The number of focusable items on the screen.</li> * <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li> * </ul> + * </p> * <p> * <b>View text changed</b> - represents the event of changing the text of an - * {@link android.widget.EditText}. <br> - * Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br> - * Properties:</br> + * {@link android.widget.EditText}.</br> + * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> @@ -136,13 +150,14 @@ import java.util.List; * <li>{@link #getRemovedCount()} - The number of removed characters.</li> * <li>{@link #getBeforeText()} - The text of the source before the change.</li> * </ul> + * </p> * <p> * <b>View text selection changed</b> - represents the event of changing the text - * selection of an {@link android.widget.EditText}.<br> - * Type: {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} <br> - * Properties:</br> + * selection of an {@link android.widget.EditText}.</br> + * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> @@ -152,7 +167,8 @@ import java.util.List; * <li>{@link #getFromIndex()} - The selection start index.</li> * <li>{@link #getToIndex()} - The selection end index.</li> * <li>{@link #getItemCount()} - The length of the source text.</li> - * <ul> + * </ul> + * </p> * <p> * <b>View scrolled</b> - represents the event of scrolling a view. If * the source is a descendant of {@link android.widget.AdapterView} the @@ -161,11 +177,11 @@ import java.util.List; * is unaware if its pixel size since its adapter is responsible for * creating views. In all other cases the scroll is reported as the current * scroll on the X and Y axis respectively plus the height of the source in - * pixels.<br> - * Type: {@link #TYPE_VIEW_SCROLLED} <br> - * Properties:</br> + * pixels.</br> + * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> @@ -181,41 +197,49 @@ import java.util.List; * (for descendants of AdapterView).</li> * <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView) * or the height of the source in pixels (all other cases).</li> - * <ul> - * <p> - * <b>TRANSITION TYPES</b> <br> + * </ul> + * </p> * <p> + * <b>TRANSITION TYPES</b></br> + * </p> * <b>Window state changed</b> - represents the event of opening a * {@link android.widget.PopupWindow}, {@link android.view.Menu}, - * {@link android.app.Dialog}, etc. <br> - * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br> - * Properties:</br> + * {@link android.app.Dialog}, etc.</br> + * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> * <li>{@link #getText()} - The text of the source.</li> * </ul> + * </p> * <p> * <b>Window content changed</b> - represents the event of change in the * content of a window. This change can be adding/removing view, changing - * a view size, etc.<br> - * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br> - * Properties:</br> + * a view size, etc.</br> + * <p> + * <strong>Note:</strong> This event is fired only for the window source of the + * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED}) + * and its purpose is to notify clients that the content of the user interaction + * window has changed. + * </p> + * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br> + * <em>Properties:</em></br> * <ul> - * <li>{@link #getSource()} - The source info (for registered clients).</li> * + * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> - * <ul> + * </ul> * <p> - * <b>NOTIFICATION TYPES</b> <br> + * <b>NOTIFICATION TYPES</b></br> * <p> - * <b>Notification state changed</b> - represents the event showing/hiding + * <b>Notification state changed</b> - represents the event showing * {@link android.app.Notification}. - * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br> - * Properties:</br> + * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br> + * <em>Properties:</em></br> * <ul> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> @@ -223,15 +247,17 @@ import java.util.List; * <li>{@link #getText()} - The text of the source.</li> * <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li> * </ul> + * </p> * <p> * <b>Security note</b> * <p> - * Since an event contains the text of its source privacy can be compromised by leaking of + * Since an event contains the text of its source privacy can be compromised by leaking * sensitive information such as passwords. To address this issue any event fired in response * to manipulation of a PASSWORD field does NOT CONTAIN the text of the password. * * @see android.view.accessibility.AccessibilityManager * @see android.accessibilityservice.AccessibilityService + * @see AccessibilityNodeInfo */ public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable { private static final boolean DEBUG = false; @@ -285,13 +311,13 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010; /** - * Represents the event of opening/closing a {@link android.widget.PopupWindow}, + * Represents the event of opening a {@link android.widget.PopupWindow}, * {@link android.view.Menu}, {@link android.app.Dialog}, etc. */ public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020; /** - * Represents the event showing/hiding a {@link android.app.Notification}. + * Represents the event showing a {@link android.app.Notification}. */ public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040; @@ -340,6 +366,13 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * @see #TYPE_VIEW_TEXT_CHANGED * @see #TYPE_WINDOW_STATE_CHANGED * @see #TYPE_NOTIFICATION_STATE_CHANGED + * @see #TYPE_VIEW_HOVER_ENTER + * @see #TYPE_VIEW_HOVER_EXIT + * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START + * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END + * @see #TYPE_WINDOW_CONTENT_CHANGED + * @see #TYPE_VIEW_SCROLLED + * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED */ public static final int TYPES_ALL_MASK = 0xFFFFFFFF; @@ -432,10 +465,10 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par } /** - * Gets the records at a given index. + * Gets the record at a given index. * * @param index The index. - * @return The records at the specified index. + * @return The record at the specified index. */ public AccessibilityRecord getRecord(int index) { return mRecords.get(index); @@ -506,7 +539,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par /** * Returns a cached instance if such is available or a new one is - * instantiated with type property set. + * instantiated with its type property set. * * @param eventType The event type. * @return An instance. @@ -519,7 +552,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par /** * Returns a cached instance if such is available or a new one is - * instantiated with type property set. + * initialized with from the given <code>event</code>. * * @param event The other event. * @return An instance. @@ -559,9 +592,10 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par } /** - * Return an instance back to be reused. + * Recycles an instance back to be reused. * <p> - * <b>Note: You must not touch the object after calling this function.</b> + * <b>Note: You must not touch the object after calling this function.</b> + * </p> * * @throws IllegalStateException If the event is already recycled. */ @@ -714,7 +748,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("; EventType: ").append(eventTypeToString(mEventType)); + builder.append("EventType: ").append(eventTypeToString(mEventType)); builder.append("; EventTime: ").append(mEventTime); builder.append("; PackageName: ").append(mPackageName); builder.append(super.toString()); @@ -758,11 +792,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * Returns the string representation of an event type. For example, * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED. * - * @param feedbackType The event type + * @param eventType The event type * @return The string representation. */ - public static String eventTypeToString(int feedbackType) { - switch (feedbackType) { + public static String eventTypeToString(int eventType) { + switch (eventType) { case TYPE_VIEW_CLICKED: return "TYPE_VIEW_CLICKED"; case TYPE_VIEW_LONG_CLICKED: diff --git a/core/java/android/view/accessibility/AccessibilityEventSource.java b/core/java/android/view/accessibility/AccessibilityEventSource.java index 3d70959b1ef9..f11880bc8c07 100644 --- a/core/java/android/view/accessibility/AccessibilityEventSource.java +++ b/core/java/android/view/accessibility/AccessibilityEventSource.java @@ -24,11 +24,12 @@ public interface AccessibilityEventSource { /** * Handles the request for sending an {@link AccessibilityEvent} given * the event type. The method must first check if accessibility is on - * via calling {@link AccessibilityManager#isEnabled()}, obtain - * an {@link AccessibilityEvent} from the event pool through calling - * {@link AccessibilityEvent#obtain(int)}, populate the event, and - * send it for dispatch via calling - * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)}. + * via calling {@link AccessibilityManager#isEnabled() AccessibilityManager.isEnabled()}, + * obtain an {@link AccessibilityEvent} from the event pool through calling + * {@link AccessibilityEvent#obtain(int) AccessibilityEvent.obtain(int)}, populate the + * event, and send it for dispatch via calling + * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent) + * AccessibilityManager.sendAccessibilityEvent(AccessibilityEvent)}. * * @see AccessibilityEvent * @see AccessibilityManager @@ -41,7 +42,8 @@ public interface AccessibilityEventSource { * Handles the request for sending an {@link AccessibilityEvent}. The * method does not guarantee to check if accessibility is on before * sending the event for dispatch. It is responsibility of the caller - * to do the check via calling {@link AccessibilityManager#isEnabled()}. + * to do the check via calling {@link AccessibilityManager#isEnabled() + * AccessibilityManager.isEnabled()}. * * @see AccessibilityEvent * @see AccessibilityManager diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index eece64af3e16..c654a398f88b 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -37,16 +37,30 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** - * System level service that serves as an event dispatch for {@link AccessibilityEvent}s. - * Such events are generated when something notable happens in the user interface, + * System level service that serves as an event dispatch for {@link AccessibilityEvent}s, + * and provides facilities for querying the accessibility state of the system. + * Accessibility events are generated when something notable happens in the user interface, * for example an {@link android.app.Activity} starts, the focus or selection of a * {@link android.view.View} changes etc. Parties interested in handling accessibility * events implement and register an accessibility service which extends * {@link android.accessibilityservice.AccessibilityService}. + * <p> + * To obtain a handle to the accessibility manager do the following: + * </p> + * <p> + * <code> + * <pre> + * AccessibilityManager accessibilityManager = + * (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); + * </pre> + * </code> + * </p> * * @see AccessibilityEvent + * @see AccessibilityNodeInfo * @see android.accessibilityservice.AccessibilityService - * @see android.content.Context#getSystemService + * @see Context#getSystemService + * @see Context#ACCESSIBILITY_SERVICE */ public final class AccessibilityManager { private static final boolean DEBUG = false; @@ -72,10 +86,11 @@ public final class AccessibilityManager { * Listener for the accessibility state. */ public interface AccessibilityStateChangeListener { + /** * Called back on change in the accessibility state. * - * @param enabled + * @param enabled Whether accessibility is enabled. */ public void onAccessibilityStateChanged(boolean enabled); } @@ -118,6 +133,9 @@ public final class AccessibilityManager { sInstance = new AccessibilityManager(context, service); } } + + AccessibilityManager accessibilityManager = + (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); return sInstance; } @@ -142,9 +160,9 @@ public final class AccessibilityManager { } /** - * Returns if the {@link AccessibilityManager} is enabled. + * Returns if the accessibility in the system is enabled. * - * @return True if this {@link AccessibilityManager} is enabled, false otherwise. + * @return True if accessibility is enabled, false otherwise. */ public boolean isEnabled() { synchronized (mHandler) { @@ -165,13 +183,11 @@ public final class AccessibilityManager { } /** - * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not - * enabled the call is a NOOP. + * Sends an {@link AccessibilityEvent}. * - * @param event The {@link AccessibilityEvent}. + * @param event The event to send. * - * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent} - * while accessibility is not enabled. + * @throws IllegalStateException if accessibility is not enabled. */ public void sendAccessibilityEvent(AccessibilityEvent event) { if (!mIsEnabled) { @@ -199,7 +215,7 @@ public final class AccessibilityManager { } /** - * Requests interruption of the accessibility feedback from all accessibility services. + * Requests feedback interruption from all accessibility services. */ public void interrupt() { if (!mIsEnabled) { @@ -256,13 +272,20 @@ public final class AccessibilityManager { * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services * for a given feedback type. * - * @param feedbackType The feedback type (can be bitwise or of multiple types). + * @param feedbackTypeFlags The feedback type flags. * @return An unmodifiable list with {@link AccessibilityServiceInfo}s. + * + * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE + * @see AccessibilityServiceInfo#FEEDBACK_GENERIC + * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC + * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN + * @see AccessibilityServiceInfo#FEEDBACK_VISUAL */ - public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) { + public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList( + int feedbackTypeFlags) { List<AccessibilityServiceInfo> services = null; try { - services = mService.getEnabledAccessibilityServiceList(feedbackType); + services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags); if (DEBUG) { Log.i(LOG_TAG, "Installed AccessibilityServices " + services); } @@ -273,7 +296,8 @@ public final class AccessibilityManager { } /** - * Registers an {@link AccessibilityStateChangeListener}. + * Registers an {@link AccessibilityStateChangeListener} for changes in + * the global accessibility state of the system. * * @param listener The listener. * @return True if successfully registered. diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index dbbe7be4d533..031c6aeffd21 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -22,7 +22,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.text.TextUtils; -import android.util.SparseArray; import android.util.SparseIntArray; import android.view.View; @@ -30,12 +29,26 @@ import java.util.Collections; import java.util.List; /** - * This class represents a node of the screen content. From the point of - * view of an accessibility service the screen content is presented as tree - * of accessibility nodes. + * This class represents a node of the window content as well as actions that + * can be requested from its source. From the point of view of an + * {@link android.accessibilityservice.AccessibilityService} a window content is + * presented as tree of accessibility node info which may or may not map one-to-one + * to the view hierarchy. In other words, a custom view is free to report itself as + * a tree of accessibility node info. + * </p> + * <p> + * Once an accessibility node info is delivered to an accessibility service it is + * made immutable and calling a state mutation method generates an error. + * </p> + * <p> + * Please refer to {@link android.accessibilityservice.AccessibilityService} for + * details about how to obtain a handle to window content as a tree of accessibility + * node info as well as familiarizing with the security model. + * </p> * - * TODO(svertoslavganov): Update the documentation, add sample, and describe - * the security policy. + * @see android.accessibilityservice.AccessibilityService + * @see AccessibilityEvent + * @see AccessibilityManager */ public class AccessibilityNodeInfo implements Parcelable { @@ -85,9 +98,6 @@ public class AccessibilityNodeInfo implements Parcelable { private static final int PROPERTY_SCROLLABLE = 0x00000200; - // Readable representations - lazily initialized. - private static SparseArray<String> sActionSymbolicNames; - // Housekeeping. private static final int MAX_POOL_SIZE = 50; private static final Object sPoolLock = new Object(); @@ -154,12 +164,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Get the child at given index. * <p> - * <strong> - * It is a client responsibility to recycle the received info by - * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating - * of multiple instances. - * </strong> + * <strong>Note:</strong> It is a client responsibility to recycle the + * received info by calling {@link AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. * </p> + * * @param index The child index. * @return The child node. * @@ -184,9 +193,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Adds a child. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param child The child. * * @throws IllegalStateException If called from an AccessibilityService. @@ -215,9 +226,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Adds an action that can be performed on the node. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param action The action. * * @throws IllegalStateException If called from an AccessibilityService. @@ -230,9 +243,10 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Performs an action on the node. * <p> - * Note: An action can be performed only if the request is made + * <strong>Note:</strong> An action can be performed only if the request is made * from an {@link android.accessibilityservice.AccessibilityService}. * </p> + * * @param action The action to perform. * @return True if the action was performed. * @@ -256,6 +270,11 @@ public class AccessibilityNodeInfo implements Parcelable { * Finds {@link AccessibilityNodeInfo}s by text. The match is case * insensitive containment. The search is relative to this info i.e. * this info is the root of the traversed tree. + * <p> + * <strong>Note:</strong> It is a client responsibility to recycle the + * received info by calling {@link AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. + * </p> * * @param text The searched text. * @return A list of node info. @@ -277,12 +296,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Gets the unique id identifying this node's parent. * <p> - * <strong> - * It is a client responsibility to recycle the received info by - * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating - * of multiple instances. - * </strong> + * <strong>Note:</strong> It is a client responsibility to recycle the + * received info by calling {@link AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. * </p> + * * @return The node's patent id. */ public AccessibilityNodeInfo getParent() { @@ -302,9 +320,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the parent. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param parent The parent. * * @throws IllegalStateException If called from an AccessibilityService. @@ -327,9 +347,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the node bounds in parent coordinates. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param bounds The node bounds. * * @throws IllegalStateException If called from an AccessibilityService. @@ -352,9 +374,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the node bounds in screen coordinates. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param bounds The node bounds. * * @throws IllegalStateException If called from an AccessibilityService. @@ -376,9 +400,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is checkable. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param checkable True if the node is checkable. * * @throws IllegalStateException If called from an AccessibilityService. @@ -399,9 +425,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is checked. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param checked True if the node is checked. * * @throws IllegalStateException If called from an AccessibilityService. @@ -422,9 +450,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is focusable. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param focusable True if the node is focusable. * * @throws IllegalStateException If called from an AccessibilityService. @@ -445,9 +475,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is focused. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param focused True if the node is focused. * * @throws IllegalStateException If called from an AccessibilityService. @@ -468,9 +500,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is selected. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param selected True if the node is selected. * * @throws IllegalStateException If called from an AccessibilityService. @@ -491,9 +525,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is clickable. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param clickable True if the node is clickable. * * @throws IllegalStateException If called from an AccessibilityService. @@ -514,9 +550,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is long clickable. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param longClickable True if the node is long clickable. * * @throws IllegalStateException If called from an AccessibilityService. @@ -537,9 +575,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is enabled. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param enabled True if the node is enabled. * * @throws IllegalStateException If called from an AccessibilityService. @@ -560,9 +600,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets whether this node is a password. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param password True if the node is a password. * * @throws IllegalStateException If called from an AccessibilityService. @@ -582,6 +624,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets if the node is scrollable. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> * * @param scrollable True if the node is scrollable, false otherwise. * @@ -604,9 +651,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the package this node comes from. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param packageName The package name. * * @throws IllegalStateException If called from an AccessibilityService. @@ -628,9 +677,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the class this node comes from. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param className The class name. * * @throws IllegalStateException If called from an AccessibilityService. @@ -652,9 +703,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the text of this node. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param text The text. * * @throws IllegalStateException If called from an AccessibilityService. @@ -676,9 +729,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the content description of this node. * <p> - * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> + * * @param contentDescription The content description. * * @throws IllegalStateException If called from an AccessibilityService. @@ -820,7 +875,7 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Return an instance back to be reused. * <p> - * <b>Note: You must not touch the object after calling this function.</b> + * <strong>Note:</strong> You must not touch the object after calling this function. * * @throws IllegalStateException If the info is already recycled. */ @@ -842,8 +897,8 @@ public class AccessibilityNodeInfo implements Parcelable { /** * {@inheritDoc} * <p> - * <b>Note: After the instance is written to a parcel it is recycled. - * You must not touch the object after calling this function.</b> + * <strong>Note:</strong> After the instance is written to a parcel it + * is recycled. You must not touch the object after calling this function. * </p> */ public void writeToParcel(Parcel parcel, int flags) { @@ -885,7 +940,7 @@ public class AccessibilityNodeInfo implements Parcelable { TextUtils.writeToParcel(mContentDescription, parcel, flags); // Since instances of this class are fetched via synchronous i.e. blocking - // calls in IPCs and we always recycle as soon as the instance is marshaled. + // calls in IPCs we always recycle as soon as the instance is marshaled. recycle(); } @@ -957,15 +1012,18 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The symbolic name. */ private static String getActionSymbolicName(int action) { - SparseArray<String> actionSymbolicNames = sActionSymbolicNames; - if (actionSymbolicNames == null) { - actionSymbolicNames = sActionSymbolicNames = new SparseArray<String>(); - actionSymbolicNames.put(ACTION_FOCUS, "ACTION_FOCUS"); - actionSymbolicNames.put(ACTION_CLEAR_FOCUS, "ACTION_UNFOCUS"); - actionSymbolicNames.put(ACTION_SELECT, "ACTION_SELECT"); - actionSymbolicNames.put(ACTION_CLEAR_SELECTION, "ACTION_UNSELECT"); + switch (action) { + case ACTION_FOCUS: + return "ACTION_FOCUS"; + case ACTION_CLEAR_FOCUS: + return "ACTION_CLEAR_FOCUS"; + case ACTION_SELECT: + return "ACTION_SELECT"; + case ACTION_CLEAR_SELECTION: + return "ACTION_CLEAR_SELECTION"; + default: + throw new IllegalArgumentException("Unknown action: " + action); } - return actionSymbolicNames.get(action); } private boolean canPerformRequestOverConnection(int accessibilityViewId) { diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java index b9815c5bbaef..f4d5e897e422 100644 --- a/core/java/android/view/accessibility/AccessibilityRecord.java +++ b/core/java/android/view/accessibility/AccessibilityRecord.java @@ -25,12 +25,28 @@ import java.util.ArrayList; import java.util.List; /** - * Represents a record in an accessibility event. This class encapsulates - * the information for a {@link android.view.View}. Note that not all properties - * are applicable to all view types. For detailed information please refer to - * {@link AccessibilityEvent}. + * Represents a record in an {@link AccessibilityEvent} and contains information + * about state change of its source {@link android.view.View}. When a view fires + * an accessibility event it requests from its parent to dispatch the + * constructed event. The parent may optionally append a record for itself + * for providing more context to + * {@link android.accessibilityservice.AccessibilityService}s. Hence, + * accessibility services can facilitate additional accessibility records + * to enhance feedback. + * </p> + * <p> + * Once the accessibility event containing a record is dispatched the record is + * made immutable and calling a state mutation method generates an error. + * </p> + * <p> + * <strong>Note:</strong> Not all properties are applicable to all accessibility + * event types. For detailed information please refer to {@link AccessibilityEvent}. + * </p> * * @see AccessibilityEvent + * @see AccessibilityManager + * @see android.accessibilityservice.AccessibilityService + * @see AccessibilityNodeInfo */ public class AccessibilityRecord { @@ -79,32 +95,6 @@ public class AccessibilityRecord { } /** - * Initialize this record from another one. - * - * @param record The to initialize from. - */ - void init(AccessibilityRecord record) { - mSealed = record.mSealed; - mBooleanProperties = record.mBooleanProperties; - mCurrentItemIndex = record.mCurrentItemIndex; - mItemCount = record.mItemCount; - mFromIndex = record.mFromIndex; - mToIndex = record.mToIndex; - mScrollX = record.mScrollX; - mScrollY = record.mScrollY; - mAddedCount = record.mAddedCount; - mRemovedCount = record.mRemovedCount; - mClassName = record.mClassName; - mContentDescription = record.mContentDescription; - mBeforeText = record.mBeforeText; - mParcelableData = record.mParcelableData; - mText.addAll(record.mText); - mSourceWindowId = record.mSourceWindowId; - mSourceViewId = record.mSourceViewId; - mConnection = record.mConnection; - } - - /** * Sets the event source. * * @param source The source. @@ -125,13 +115,12 @@ public class AccessibilityRecord { /** * Gets the {@link AccessibilityNodeInfo} of the event source. * <p> - * <strong> - * It is a client responsibility to recycle the received info by - * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating - * of multiple instances. - * </strong> + * <strong>Note:</strong> It is a client responsibility to recycle the received info + * by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. + * * </p> - * @return The info. + * @return The info of the source. */ public AccessibilityNodeInfo getSource() { enforceSealed(); @@ -641,7 +630,7 @@ public class AccessibilityRecord { /** * Return an instance back to be reused. * <p> - * <b>Note: You must not touch the object after calling this function.</b> + * <strong>Note:</strong> You must not touch the object after calling this function. * * @throws IllegalStateException If the record is already recycled. */ @@ -661,6 +650,32 @@ public class AccessibilityRecord { } /** + * Initialize this record from another one. + * + * @param record The to initialize from. + */ + void init(AccessibilityRecord record) { + mSealed = record.mSealed; + mBooleanProperties = record.mBooleanProperties; + mCurrentItemIndex = record.mCurrentItemIndex; + mItemCount = record.mItemCount; + mFromIndex = record.mFromIndex; + mToIndex = record.mToIndex; + mScrollX = record.mScrollX; + mScrollY = record.mScrollY; + mAddedCount = record.mAddedCount; + mRemovedCount = record.mRemovedCount; + mClassName = record.mClassName; + mContentDescription = record.mContentDescription; + mBeforeText = record.mBeforeText; + mParcelableData = record.mParcelableData; + mText.addAll(record.mText); + mSourceWindowId = record.mSourceWindowId; + mSourceViewId = record.mSourceViewId; + mConnection = record.mConnection; + } + + /** * Clears the state of this instance. */ void clear() { diff --git a/core/java/android/view/accessibility/package.html b/core/java/android/view/accessibility/package.html new file mode 100644 index 000000000000..4afafd3ca128 --- /dev/null +++ b/core/java/android/view/accessibility/package.html @@ -0,0 +1,39 @@ +<html> +<body> +<p> + The classes in this package are used to represent screen content and changes to it + as well as APIs for querying the global accessibility state of the system. +</p> +<p> + {@link android.view.accessibility.AccessibilityEvent}s are sent by the system when + something notable happens in the user interface. For example, when a + {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc. +</p> +<p> + {@link android.view.accessibility.AccessibilityRecord} contains information + about state change of its source {@link android.view.View}. When a view fires + an accessibility event it requests from its parent to dispatch the + constructed event. The parent may optionally append a record for itself for + providing more context to {@link android.accessibilityservice.AccessibilityService}s. + Hence, accessibility services can facilitate additional accessibility records + to enhance feedback. +</p> +<p> + {@link android.view.accessibility.AccessibilityNodeInfo} represents a node of the + window content as well as actions that can be requested from its source. From the point + of view of an {@link android.accessibilityservice.AccessibilityService} a window content is + presented as tree of accessibility node info which may or may not map one-to-one + to the view hierarchy. In other words, a custom view is free to report itself as + a tree of accessibility node info. +</p> +<p> + {@link android.view.accessibility.AccessibilityManager} is a system level service that + serves as an event dispatch for {@link android.view.accessibility.AccessibilityEvent}s, + and provides facilities for querying the accessibility state of the system. Accessibility + events are generated when something notable happens in the user interface, for example an + {@link android.app.Activity} starts, the focus or selection of a {@link android.view.View} + changes etc. Parties interested in handling accessibility events implement and register an + accessibility service which extends {@link android.accessibilityservice.AccessibilityService}. +</p> +</body> +</html> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index fd61cfdaf6b7..db33d1c4e19f 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2208,7 +2208,8 @@ <!-- The event types this serivce would like to receive as specified in {@link android.view.accessibility.AccessibilityEvent}. This setting can be changed at runtime by calling - {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> + {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) + android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> <attr name="accessibilityEventTypes"> <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} events.--> <flag name="typeViewClicked" value="0x00000001" /> @@ -2232,17 +2233,24 @@ <flag name="typeTouchExplorationGestureStart" value="0x00000200" /> <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} events. --> <flag name="typeTouchExplorationGestureEnd" value="0x00000400" /> + <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events. --> + <flag name="typeWindowContentChanged" value="0x00000800" /> + <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED} events. --> + <flag name="typeViewScrolled" value="0x000001000" /> + <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} events. --> + <flag name="typeViewTextSelectionChanged" value="0x000002000" /> <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. --> <flag name="typeAllMask" value="0xffffffff" /> </attr> <!-- Comma separated package names from which this serivce would like to receive events (leave out for all packages). - This setting can be changed at runtime by calling - {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> + {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) + android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> <attr name="packageNames" format="string" /> <!-- The feedback types this serivce provides as specified in {@link android.accessibilityservice.AccessibilityServiceInfo}. This setting can be changed at runtime by calling - {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> + {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) + android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> <attr name="accessibilityFeedbackType"> <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_SPOKEN} feedback. --> <flag name="feedbackSpoken" value="0x00000001" /> @@ -2255,14 +2263,16 @@ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. --> <flag name="feedbackGeneric" value="0x00000010" /> </attr> - <!-- The minimal period in milliseconds between two accessibility events are sent - to this serivce. This setting can be changed at runtime by calling - {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> + <!-- The minimal period in milliseconds between two accessibility events of the same type + are sent to this serivce. This setting can be changed at runtime by calling + {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) + android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->> <attr name="notificationTimeout" format="integer" /> <!-- Additional flags as specified in {@link android.accessibilityservice.AccessibilityServiceInfo}. This setting can be changed at runtime by calling - {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> + {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) + android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> <attr name="accessibilityFlags"> <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} --> <flag name="flagDefault" value="0x00000001" /> @@ -2271,7 +2281,7 @@ the settings for this service. This setting cannot be changed at runtime. --> <attr name="settingsActivity" /> <!-- Flag whether the accessibility service wants to be able to retrieve the - focused window content. This setting cannot be changed at runtime. --> + active window content. This setting cannot be changed at runtime. --> <attr name="canRetrieveWindowContent" format="boolean" /> </declare-styleable> |