Merge "Adding custom events to AccessibilityNodeInfo"
diff --git a/api/current.txt b/api/current.txt
index b52b2e1..f8b6f59 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -32956,7 +32956,8 @@
}
public class AccessibilityNodeInfo implements android.os.Parcelable {
- method public void addAction(int);
+ method public void addAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
+ method public deprecated void addAction(int);
method public void addChild(android.view.View);
method public void addChild(android.view.View, int);
method public boolean canOpenPopup();
@@ -32965,7 +32966,8 @@
method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(java.lang.String);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int);
- method public int getActions();
+ method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList();
+ method public deprecated int getActions();
method public void getBoundsInParent(android.graphics.Rect);
method public void getBoundsInScreen(android.graphics.Rect);
method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
@@ -33013,7 +33015,8 @@
method public boolean performAction(int, android.os.Bundle);
method public void recycle();
method public boolean refresh();
- method public void removeAction(int);
+ method public deprecated void removeAction(int);
+ method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
method public boolean removeChild(android.view.View);
method public boolean removeChild(android.view.View, int);
method public void setAccessibilityFocused(boolean);
@@ -33094,6 +33097,34 @@
field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2
}
+ public static final class AccessibilityNodeInfo.AccessibilityAction {
+ ctor public AccessibilityNodeInfo.AccessibilityAction(int, java.lang.CharSequence);
+ method public int getId();
+ method public java.lang.CharSequence getLabel();
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_ACCESSIBILITY_FOCUS;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_FOCUS;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_SELECTION;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLICK;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_COLLAPSE;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_COPY;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CUT;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_DISMISS;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_EXPAND;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_FOCUS;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_LONG_CLICK;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_HTML_ELEMENT;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PASTE;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_BACKWARD;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_FORWARD;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SELECT;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
+ }
+
public static final class AccessibilityNodeInfo.CollectionInfo {
method public int getColumnCount();
method public int getRowCount();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e829141..ab518d9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7147,6 +7147,9 @@
if (viewRootImpl != null) {
viewRootImpl.setAccessibilityFocus(this, null);
}
+ Rect rect = (mAttachInfo != null) ? mAttachInfo.mTmpInvalRect : new Rect();
+ getDrawingRect(rect);
+ requestRectangleOnScreen(rect, false);
invalidate();
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
return true;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 9d10930..34967df 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -17,15 +17,19 @@
package android.view.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.InputType;
+import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.LongArray;
import android.util.Pools.SynchronizedPool;
import android.view.View;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -112,7 +116,7 @@
public static final int ACTION_SELECT = 0x00000004;
/**
- * Action that unselects the node.
+ * Action that deselects the node.
*/
public static final int ACTION_CLEAR_SELECTION = 0x00000008;
@@ -307,6 +311,18 @@
*/
public static final int ACTION_SET_TEXT = 0x00200000;
+ private static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
+
+ /**
+ * Mask to see if the value is larger than the largest ACTION_ constant
+ */
+ private static final int ACTION_TYPE_MASK = 0xFF000000;
+
+ /**
+ * Mask to define standard not legacy actions.
+ */
+ private static final int STANDARD_NON_LEGACY_ACTION_MASK = 0x01000000;
+
// Action arguments
/**
@@ -548,7 +564,7 @@
private String mViewIdResourceName;
private LongArray mChildNodeIds;
- private int mActions;
+ private ArrayList<AccessibilityAction> mActions;
private int mMovementGranularities;
@@ -875,6 +891,17 @@
/**
* Gets the actions that can be performed on the node.
+ */
+ public List<AccessibilityAction> getActionList() {
+ if (mActions == null) {
+ return Collections.emptyList();
+ }
+
+ return mActions;
+ }
+
+ /**
+ * Gets the actions that can be performed on the node.
*
* @return The bit mask of with actions.
*
@@ -892,9 +919,61 @@
* @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
* @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
* @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
+ *
+ * @deprecated Use {@link #getActionList()}.
*/
+ @Deprecated
public int getActions() {
- return mActions;
+ int returnValue = 0;
+
+ if (mActions == null) {
+ return returnValue;
+ }
+
+ final int actionSize = mActions.size();
+ for (int i = 0; i < actionSize; i++) {
+ int actionId = mActions.get(i).getId();
+ if (actionId <= LAST_LEGACY_STANDARD_ACTION) {
+ returnValue |= actionId;
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * Adds an action that can be performed on the node.
+ * <p>
+ * To add a standard action use the static constants on {@link AccessibilityAction}.
+ * To add a custom action create a new {@link AccessibilityAction} by passing in a
+ * resource id from your application as the action id and an optional label that
+ * describes the action. To override one of the standard actions use as the action
+ * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that
+ * describes the action.
+ * </p>
+ * <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 action The action.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void addAction(AccessibilityAction action) {
+ enforceNotSealed();
+
+ if (action == null) {
+ return;
+ }
+
+ if (mActions == null) {
+ mActions = new ArrayList<AccessibilityAction>();
+ }
+
+ mActions.remove(action);
+ mActions.add(action);
}
/**
@@ -908,10 +987,21 @@
* @param action The action.
*
* @throws IllegalStateException If called from an AccessibilityService.
+ * @throws IllegalArgumentException If the argument is not one of the standard actions.
+ *
+ * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)}
*/
+ @Deprecated
public void addAction(int action) {
enforceNotSealed();
- mActions |= action;
+
+ AccessibilityAction newAction = getActionSingleton(action);
+ if (newAction == null) {
+ // This means it is not one of the standard actions
+ throw new IllegalArgumentException("Argument is not one of the standard actions");
+ }
+
+ addAction(newAction);
}
/**
@@ -923,13 +1013,40 @@
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
*
- * @param action The action.
+ * @param action The action to be removed.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ * @deprecated Use {@link #removeAction(AccessibilityAction)}
+ */
+ @Deprecated
+ public void removeAction(int action) {
+ enforceNotSealed();
+
+ removeAction(getActionSingleton(action));
+ }
+
+ /**
+ * Removes an action that can be performed on the node. If the action was
+ * not already added to the node, calling this method has no effect.
+ * <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 action The action to be removed.
+ * @return The action removed from the list of actions.
*
* @throws IllegalStateException If called from an AccessibilityService.
*/
- public void removeAction(int action) {
+ public boolean removeAction(AccessibilityAction action) {
enforceNotSealed();
- mActions &= ~action;
+
+ if (mActions == null || action == null) {
+ return false;
+ }
+
+ return mActions.remove(action);
}
/**
@@ -2307,7 +2424,29 @@
parcel.writeInt(mBoundsInScreen.left);
parcel.writeInt(mBoundsInScreen.right);
- parcel.writeInt(mActions);
+ if (mActions != null && !mActions.isEmpty()) {
+ final int actionCount = mActions.size();
+ parcel.writeInt(actionCount);
+
+ int defaultLegacyStandardActions = 0;
+ for (int i = 0; i < actionCount; i++) {
+ AccessibilityAction action = mActions.get(i);
+ if (isDefaultLegacyStandardAction(action)) {
+ defaultLegacyStandardActions |= action.getId();
+ }
+ }
+ parcel.writeInt(defaultLegacyStandardActions);
+
+ for (int i = 0; i < actionCount; i++) {
+ AccessibilityAction action = mActions.get(i);
+ if (!isDefaultLegacyStandardAction(action)) {
+ parcel.writeInt(action.getId());
+ parcel.writeCharSequence(action.getLabel());
+ }
+ }
+ } else {
+ parcel.writeInt(0);
+ }
parcel.writeInt(mMovementGranularities);
@@ -2388,7 +2527,17 @@
mText = other.mText;
mContentDescription = other.mContentDescription;
mViewIdResourceName = other.mViewIdResourceName;
- mActions= other.mActions;
+
+ final ArrayList<AccessibilityAction> otherActions = other.mActions;
+ if (otherActions != null && otherActions.size() > 0) {
+ if (mActions == null) {
+ mActions = new ArrayList(otherActions);
+ } else {
+ mActions.clear();
+ mActions.addAll(other.mActions);
+ }
+ }
+
mBooleanProperties = other.mBooleanProperties;
mMovementGranularities = other.mMovementGranularities;
@@ -2452,7 +2601,17 @@
mBoundsInScreen.left = parcel.readInt();
mBoundsInScreen.right = parcel.readInt();
- mActions = parcel.readInt();
+ final int actionCount = parcel.readInt();
+ if (actionCount > 0) {
+ final int legacyStandardActions = parcel.readInt();
+ addLegacyStandardActions(legacyStandardActions);
+ final int nonLegacyActionCount = actionCount - Integer.bitCount(legacyStandardActions);
+ for (int i = 0; i < nonLegacyActionCount; i++) {
+ AccessibilityAction action = new AccessibilityAction(
+ parcel.readInt(), parcel.readCharSequence());
+ addAction(action);
+ }
+ }
mMovementGranularities = parcel.readInt();
@@ -2524,7 +2683,9 @@
mText = null;
mContentDescription = null;
mViewIdResourceName = null;
- mActions = 0;
+ if (mActions != null) {
+ mActions.clear();
+ }
mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
mInputType = InputType.TYPE_NULL;
@@ -2546,6 +2707,33 @@
}
}
+ private static boolean isDefaultLegacyStandardAction(AccessibilityAction action) {
+ return (action.getId() <= LAST_LEGACY_STANDARD_ACTION
+ && TextUtils.isEmpty(action.getLabel()));
+ }
+
+ private static AccessibilityAction getActionSingleton(int actionId) {
+ final int actions = AccessibilityAction.sStandardActions.size();
+ for (int i = 0; i < actions; i++) {
+ AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
+ if (actionId == currentAction.getId()) {
+ return currentAction;
+ }
+ }
+
+ return null;
+ }
+
+ private void addLegacyStandardActions(int actionMask) {
+ int remainingIds = actionMask;
+ while (remainingIds > 0) {
+ final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
+ remainingIds &= ~id;
+ AccessibilityAction action = getActionSingleton(id);
+ addAction(action);
+ }
+ }
+
/**
* Gets the human readable action symbolic name.
*
@@ -2709,23 +2897,432 @@
builder.append("; longClickable: ").append(isLongClickable());
builder.append("; enabled: ").append(isEnabled());
builder.append("; password: ").append(isPassword());
- builder.append("; scrollable: " + isScrollable());
-
- builder.append("; [");
- for (int actionBits = mActions; actionBits != 0;) {
- final int action = 1 << Integer.numberOfTrailingZeros(actionBits);
- actionBits &= ~action;
- builder.append(getActionSymbolicName(action));
- if (actionBits != 0) {
- builder.append(", ");
- }
- }
- builder.append("]");
+ builder.append("; scrollable: ").append(isScrollable());
+ builder.append("; actions: ").append(mActions);
return builder.toString();
}
/**
+ * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
+ * Each action has a unique id that is mandatory and optional data.
+ * <p>
+ * There are three categories of actions:
+ * <ul>
+ * <li><strong>Standard actions</strong> - These are actions that are reported and
+ * handled by the standard UI widgets in the platform. For each standard action
+ * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
+ * </li>
+ * <li><strong>Custom actions action</strong> - These are actions that are reported
+ * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
+ * example, an application may define a custom action for clearing the user history.
+ * </li>
+ * <li><strong>Overriden standard actions</strong> - These are actions that override
+ * standard actions to customize them. For example, an app may add a label to the
+ * standard click action to announce that this action clears browsing history.
+ * </ul>
+ * </p>
+ */
+ public static final class AccessibilityAction {
+
+ /**
+ * Action that gives input focus to the node.
+ */
+ public static final AccessibilityAction ACTION_FOCUS =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_FOCUS, null);
+
+ /**
+ * Action that clears input focus of the node.
+ */
+ public static final AccessibilityAction ACTION_CLEAR_FOCUS =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CLEAR_FOCUS, null);
+
+ /**
+ * Action that selects the node.
+ */
+ public static final AccessibilityAction ACTION_SELECT =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_SELECT, null);
+
+ /**
+ * Action that deselects the node.
+ */
+ public static final AccessibilityAction ACTION_CLEAR_SELECTION =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CLEAR_SELECTION, null);
+
+ /**
+ * Action that clicks on the node info.
+ */
+ public static final AccessibilityAction ACTION_CLICK =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CLICK, null);
+
+ /**
+ * Action that long clicks on the node.
+ */
+ public static final AccessibilityAction ACTION_LONG_CLICK =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_LONG_CLICK, null);
+
+ /**
+ * Action that gives accessibility focus to the node.
+ */
+ public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+
+ /**
+ * Action that clears accessibility focus of the node.
+ */
+ public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
+
+ /**
+ * Action that requests to go to the next entity in this node's text
+ * at a given movement granularity. For example, move to the next character,
+ * word, etc.
+ * <p>
+ * <strong>Arguments:</strong>
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
+ * <strong>Example:</strong> Move to the previous character and do not extend selection.
+ * <code><pre><p>
+ * Bundle arguments = new Bundle();
+ * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
+ * false);
+ * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(),
+ * arguments);
+ * </code></pre></p>
+ * </p>
+ *
+ * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
+ * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
+ *
+ * @see AccessibilityNodeInfo#setMovementGranularities(int)
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
+ * @see AccessibilityNodeInfo#getMovementGranularities()
+ * AccessibilityNodeInfo.getMovementGranularities()
+ *
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
+ */
+ public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, null);
+
+ /**
+ * Action that requests to go to the previous entity in this node's text
+ * at a given movement granularity. For example, move to the next character,
+ * word, etc.
+ * <p>
+ * <strong>Arguments:</strong>
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
+ * <strong>Example:</strong> Move to the next character and do not extend selection.
+ * <code><pre><p>
+ * Bundle arguments = new Bundle();
+ * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
+ * false);
+ * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(),
+ * arguments);
+ * </code></pre></p>
+ * </p>
+ *
+ * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
+ * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
+ *
+ * @see AccessibilityNodeInfo#setMovementGranularities(int)
+ * AccessibilityNodeInfo.setMovementGranularities(int)
+ * @see AccessibilityNodeInfo#getMovementGranularities()
+ * AccessibilityNodeInfo.getMovementGranularities()
+ *
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+ * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
+ */
+ public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, null);
+
+ /**
+ * Action to move to the next HTML element of a given type. For example, move
+ * to the BUTTON, INPUT, TABLE, etc.
+ * <p>
+ * <strong>Arguments:</strong>
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
+ * <strong>Example:</strong>
+ * <code><pre><p>
+ * Bundle arguments = new Bundle();
+ * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
+ * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments);
+ * </code></pre></p>
+ * </p>
+ */
+ public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, null);
+
+ /**
+ * Action to move to the previous HTML element of a given type. For example, move
+ * to the BUTTON, INPUT, TABLE, etc.
+ * <p>
+ * <strong>Arguments:</strong>
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
+ * <strong>Example:</strong>
+ * <code><pre><p>
+ * Bundle arguments = new Bundle();
+ * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
+ * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments);
+ * </code></pre></p>
+ * </p>
+ */
+ public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, null);
+
+ /**
+ * Action to scroll the node content forward.
+ */
+ public static final AccessibilityAction ACTION_SCROLL_FORWARD =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, null);
+
+ /**
+ * Action to scroll the node content backward.
+ */
+ public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, null);
+
+ /**
+ * Action to copy the current selection to the clipboard.
+ */
+ public static final AccessibilityAction ACTION_COPY =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_COPY, null);
+
+ /**
+ * Action to paste the current clipboard content.
+ */
+ public static final AccessibilityAction ACTION_PASTE =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_PASTE, null);
+
+ /**
+ * Action to cut the current selection and place it to the clipboard.
+ */
+ public static final AccessibilityAction ACTION_CUT =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CUT, null);
+
+ /**
+ * Action to set the selection. Performing this action with no arguments
+ * clears the selection.
+ * <p>
+ * <strong>Arguments:</strong>
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT},
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br>
+ * <strong>Example:</strong>
+ * <code><pre><p>
+ * Bundle arguments = new Bundle();
+ * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
+ * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
+ * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments);
+ * </code></pre></p>
+ * </p>
+ *
+ * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT
+ * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT
+ */
+ public static final AccessibilityAction ACTION_SET_SELECTION =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_SET_SELECTION, null);
+
+ /**
+ * Action to expand an expandable node.
+ */
+ public static final AccessibilityAction ACTION_EXPAND =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_EXPAND, null);
+
+ /**
+ * Action to collapse an expandable node.
+ */
+ public static final AccessibilityAction ACTION_COLLAPSE =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_COLLAPSE, null);
+
+ /**
+ * Action to dismiss a dismissable node.
+ */
+ public static final AccessibilityAction ACTION_DISMISS =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_DISMISS, null);
+
+ /**
+ * Action that sets the text of the node. Performing the action without argument,
+ * using <code> null</code> or empty {@link CharSequence} will clear the text. This
+ * action will also put the cursor at the end of text.
+ * <p>
+ * <strong>Arguments:</strong>
+ * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
+ * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
+ * <strong>Example:</strong>
+ * <code><pre><p>
+ * Bundle arguments = new Bundle();
+ * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
+ * "android");
+ * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments);
+ * </code></pre></p>
+ */
+ public static final AccessibilityAction ACTION_SET_TEXT =
+ new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_SET_TEXT, null);
+
+ private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<AccessibilityAction>();
+ static {
+ sStandardActions.add(ACTION_FOCUS);
+ sStandardActions.add(ACTION_CLEAR_FOCUS);
+ sStandardActions.add(ACTION_SELECT);
+ sStandardActions.add(ACTION_CLEAR_SELECTION);
+ sStandardActions.add(ACTION_CLICK);
+ sStandardActions.add(ACTION_LONG_CLICK);
+ sStandardActions.add(ACTION_ACCESSIBILITY_FOCUS);
+ sStandardActions.add(ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ sStandardActions.add(ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
+ sStandardActions.add(ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
+ sStandardActions.add(ACTION_NEXT_HTML_ELEMENT);
+ sStandardActions.add(ACTION_PREVIOUS_HTML_ELEMENT);
+ sStandardActions.add(ACTION_SCROLL_FORWARD);
+ sStandardActions.add(ACTION_SCROLL_BACKWARD);
+ sStandardActions.add(ACTION_COPY);
+ sStandardActions.add(ACTION_PASTE);
+ sStandardActions.add(ACTION_CUT);
+ sStandardActions.add(ACTION_SET_SELECTION);
+ sStandardActions.add(ACTION_EXPAND);
+ sStandardActions.add(ACTION_COLLAPSE);
+ sStandardActions.add(ACTION_DISMISS);
+ sStandardActions.add(ACTION_SET_TEXT);
+ }
+
+ private final int mActionId;
+ private final CharSequence mLabel;
+
+ /**
+ * Creates a new AccessibilityAction. For adding a standard action without a specific label,
+ * use the static constants.
+ *
+ * You can also override the description for one the standard actions. Below is an example
+ * how to override the standard click action by adding a custom label:
+ * <pre>
+ * AccessibilityAction action = new AccessibilityAction(
+ * AccessibilityAction.ACTION_ACTION_CLICK, getLocalizedLabel());
+ * node.addAction(action);
+ * </pre>
+ *
+ * @param actionId The id for this action. This should either be one of the
+ * standard actions or a specific action for your app. In that case it is
+ * required to use a resource identifier.
+ * @param label The label for the new AccessibilityAction.
+ */
+ public AccessibilityAction(int actionId, @Nullable CharSequence label) {
+ if ((actionId & ACTION_TYPE_MASK) == 0 && Integer.bitCount(actionId) > 1) {
+ throw new IllegalArgumentException("Invalid standard action id");
+ }
+
+ if ((actionId & STANDARD_NON_LEGACY_ACTION_MASK) != 0) {
+ throw new IllegalArgumentException("action id not a resource id");
+ }
+
+ mActionId = actionId;
+ mLabel = label;
+ }
+
+ /**
+ * Gets the id for this action.
+ *
+ * @return The action id.
+ */
+ public int getId() {
+ return mActionId;
+ }
+
+ /**
+ * Gets the label for this action. Its purpose is to describe the
+ * action to user.
+ *
+ * @return The label.
+ */
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ @Override
+ public int hashCode() {
+ return mActionId;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ }
+
+ if (other == this) {
+ return true;
+ }
+
+ if (getClass() != other.getClass()) {
+ return false;
+ }
+
+ return mActionId == ((AccessibilityAction)other).mActionId;
+ }
+
+ @Override
+ public String toString() {
+ return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
+ }
+ }
+
+ /**
* Class with information if a node is a range. Use
* {@link RangeInfo#obtain(int, float, float, float)} to get an instance.
*/
diff --git a/services/core/java/com/android/server/wm/ViewServer.java b/services/core/java/com/android/server/wm/ViewServer.java
index a763e2c..741cee3 100644
--- a/services/core/java/com/android/server/wm/ViewServer.java
+++ b/services/core/java/com/android/server/wm/ViewServer.java
@@ -314,7 +314,7 @@
out.flush();
}
if (needFocusedWindowUpdate) {
- out.write("FOCUS UPDATE\n");
+ out.write("ACTION_FOCUS UPDATE\n");
out.flush();
}
}