From 38e8b4e5bc3c93affdffbc064fd9db5aeccc3e8e Mon Sep 17 00:00:00 2001
From: Svetoslav Ganov
- * 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:
- *
- *
- * 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.
*
+ * Declaration
+ *
+ * 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:
+ *
+ *
+ * Configuration
+ *
* 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.
*
* There are two approaches for configuring an accessibility service:
+ *
- *
- *
- * This approach enables setting all accessibility service properties.
- *
- *
- * For more details refer to {@link #SERVICE_META_DATA}.
- *
- *
- * 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}
- *
- *
- * For more details refer to {@link AccessibilityServiceInfo}.
- *
+ *
+ * Note:This approach enables setting all properties.
+ *
+ * For more details refer to {@link #SERVICE_META_DATA} and
+ *
+ * Note: This approach enables setting only dynamically configurable properties:
+ * {@link AccessibilityServiceInfo#eventTypes},
+ * {@link AccessibilityServiceInfo#feedbackType},
+ * {@link AccessibilityServiceInfo#flags},
+ * {@link AccessibilityServiceInfo#notificationTimeout},
+ * {@link AccessibilityServiceInfo#packageNames}
+ *
+ * For more details refer to {@link AccessibilityServiceInfo}.
+ *
- * 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.
+ * Retrieving window content
+ *
+ * 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}.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * NoteAn 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:
+ *
- * <service android:name=".MyAccessibilityService">
+ * Lifecycle
*
- * <intent-filter>
- * <action android:name="android.accessibilityservice.AccessibilityService" />
- * </intent-filter>
- * </service>
- *
+ *
+ *
+ * <service android:name=".MyAccessibilityService">
+ * <intent-filter>
+ * <action android:name="android.accessibilityservice.AccessibilityService" />
+ * </intent-filter>
+ * . . .
+ * </service>
+ *
+ *
- *
*
- * <service android:name=".MyAccessibilityService">
- *
- * <intent-filter>
- * <action android:name="android.accessibilityservice.AccessibilityService" />
- * </intent-filter>
- * <meta-data android:name="android.accessibilityservice.as" android:resource="@xml/accessibilityservice" />
- * </service>
- *
- *
+ *
+ *
+ * <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>
+ *
+ * <{@link android.R.styleable#AccessibilityService accessibility-service}>..
+ *
+ *
+ *
* Notification strategy + *
** 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. + *
** Event types - *
+ *
* {@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} - *- * Feedback types - *
+ * {@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} + *
+ * Feedback types + *
* {@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.
+ * 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.
*/
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
* <{@link android.R.styleable#AccessibilityService accessibility-service}>
* tag. This is a a sample XML file configuring an accessibility service:
*
*
- * <?xml version="1.0" encoding="utf-8"?>
*
- * <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
- * android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
- * android:packageNames="foo.bar, foo.baz"
- * android:accessibilityFeedbackType="feedbackSpoken"
- * android:notificationTimeout="100"
- * android:accessibilityFlags="flagDefault"
- * android:settingsActivity="foo.bar.TestBackActivity"
- * . . .
+ *
+ * <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"
+ * . . .
* />
+ *
*
- * Note: 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: - *
null is equivalent to all packages.
* * Can be dynamically set at runtime. *
@@ -125,10 +132,10 @@ public class AccessibilityServiceInfo implements Parcelable { * Can be dynamically set at runtime.. * *- * 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 + * 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. */ 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. *
* Statically set from * {@link AccessibilityService#SERVICE_META_DATA meta-data}. *
- * @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 @@ + + ++ The classes in this package are used for development of accessibility service that + provide alternative or augmented feedback to the user. +
++ 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. +
++ 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. +
+ + 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; /** + ** 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. + *
** 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. + *
*- * 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. + *
** 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: + *
*
- * VIEW TYPES
+ * VIEW TYPES
+ *
* View clicked - represents the event of clicking on a {@link android.view.View}
- * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
- * Type:{@link #TYPE_VIEW_CLICKED}
- * Properties:
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
+ * Type:{@link #TYPE_VIEW_CLICKED}
+ * Properties:
*
* View long clicked - represents the event of long clicking on a {@link android.view.View}
- * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
- * Type:{@link #TYPE_VIEW_LONG_CLICKED}
- * Properties:
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc
+ * Type:{@link #TYPE_VIEW_LONG_CLICKED}
+ * Properties:
*
* View selected - represents the event of selecting an item usually in
- * the context of an {@link android.widget.AdapterView}.
- * Type: {@link #TYPE_VIEW_SELECTED}
- * Properties:
+ * the context of an {@link android.widget.AdapterView}.
+ * Type: {@link #TYPE_VIEW_SELECTED}
+ * Properties:
*
+ *
*
* View focused - represents the event of focusing a
- * {@link android.view.View}.
- * Type: {@link #TYPE_VIEW_FOCUSED}
- * Properties:
+ * {@link android.view.View}.
+ * Type: {@link #TYPE_VIEW_FOCUSED}
+ * Properties:
*
* View text changed - represents the event of changing the text of an
- * {@link android.widget.EditText}.
- * Type: {@link #TYPE_VIEW_TEXT_CHANGED}
- * Properties:
+ * {@link android.widget.EditText}.
+ * Type: {@link #TYPE_VIEW_TEXT_CHANGED}
+ * Properties:
*
* View text selection changed - represents the event of changing the text
- * selection of an {@link android.widget.EditText}.
- * Type: {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED}
- * Properties:
+ * selection of an {@link android.widget.EditText}.
+ * Type: {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED}
+ * Properties:
*
* View scrolled - 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.
- * Type: {@link #TYPE_VIEW_SCROLLED}
- * Properties:
+ * pixels.
+ * Type: {@link #TYPE_VIEW_SCROLLED}
+ * Properties:
*
- * TRANSITION TYPES
+ *
+ * TRANSITION TYPES + *
* Window state changed - represents the event of opening a * {@link android.widget.PopupWindow}, {@link android.view.Menu}, - * {@link android.app.Dialog}, etc.
* Window content changed - represents the event of change in the
* content of a window. This change can be adding/removing view, changing
- * a view size, etc.
- * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED}
- * Properties:
+ * a view size, etc.
+ *
+ * Note: 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. + *
+ * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} + * Properties: *
- * NOTIFICATION TYPES
+ * NOTIFICATION TYPES
*
- * Notification state changed - represents the event showing/hiding
+ * Notification state changed - represents the event showing
* {@link android.app.Notification}.
- * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED}
- * Properties:
+ * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED}
+ * Properties:
*
* Security note *
- * 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 event.
*
* @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.
*
- * Note: You must not touch the object after calling this function. + * Note: You must not touch the object after calling this function. + *
* * @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}. + *+ * To obtain a handle to the accessibility manager do the following: + *
+ *
+ *
+ *
+ *
+ * AccessibilityManager accessibilityManager =
+ * (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ *
+ *
+ * Once an accessibility node info is delivered to an accessibility service it is + * made immutable and calling a state mutation method generates an error. + *
+ *+ * 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. + *
* - * 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- * - * It is a client responsibility to recycle the received info by - * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating - * of multiple instances. - * + * Note: It is a client responsibility to recycle the + * received info by calling {@link AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. *
+ * * @param index The child index. * @return The child node. * @@ -184,9 +193,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Adds a child. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: An action can be performed only if the request is made + * Note: An action can be performed only if the request is made * from an {@link android.accessibilityservice.AccessibilityService}. *
+ * * @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. + *+ * Note: It is a client responsibility to recycle the + * received info by calling {@link AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. + *
* * @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. *- * - * It is a client responsibility to recycle the received info by - * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating - * of multiple instances. - * + * Note: It is a client responsibility to recycle the + * received info by calling {@link AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. *
+ * * @return The node's patent id. */ public AccessibilityNodeInfo getParent() { @@ -302,9 +320,11 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Sets the parent. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. + *+ * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + *
* * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}. + * Note: Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. *
+ * * @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. *- * Note: You must not touch the object after calling this function. + * Note: 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} *
- * Note: After the instance is written to a parcel it is recycled. - * You must not touch the object after calling this function. + * Note: After the instance is written to a parcel it + * is recycled. You must not touch the object after calling this function. *
*/ 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+ * Once the accessibility event containing a record is dispatched the record is + * made immutable and calling a state mutation method generates an error. + *
+ *+ * Note: Not all properties are applicable to all accessibility + * event types. For detailed information please refer to {@link AccessibilityEvent}. + *
* * @see AccessibilityEvent + * @see AccessibilityManager + * @see android.accessibilityservice.AccessibilityService + * @see AccessibilityNodeInfo */ public class AccessibilityRecord { @@ -78,32 +94,6 @@ public class AccessibilityRecord { 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. * @@ -125,13 +115,12 @@ public class AccessibilityRecord { /** * Gets the {@link AccessibilityNodeInfo} of the event source. *- * - * It is a client responsibility to recycle the received info by - * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating - * of multiple instances. - * + * Note: It is a client responsibility to recycle the received info + * by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()} + * to avoid creating of multiple instances. + * *
- * @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. *- * Note: You must not touch the object after calling this function. + * Note: You must not touch the object after calling this function. * * @throws IllegalStateException If the record is already recycled. */ @@ -660,6 +649,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. */ 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 @@ + +
++ 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. +
++ {@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. +
++ {@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. +
++ {@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. +
++ {@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}. +
+ + diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 37e6027fd175..9592f257d4bb 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2190,7 +2190,8 @@ + {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) + android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->