summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt10
-rw-r--r--core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl6
-rw-r--r--core/java/android/accessibilityservice/UiTestAutomationBridge.java12
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java13
-rw-r--r--core/java/android/view/View.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java7
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java8
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java175
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeProvider.java13
-rw-r--r--core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl7
-rw-r--r--core/java/android/widget/NumberPicker.java5
-rw-r--r--core/res/res/values/public.xml4
-rwxr-xr-xcore/res/res/values/strings.xml9
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java11
14 files changed, 236 insertions, 47 deletions
diff --git a/api/current.txt b/api/current.txt
index 5c53ab7..217d3e3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23958,7 +23958,7 @@ package android.view {
method public void onWindowSystemUiVisibilityChanged(int);
method protected void onWindowVisibilityChanged(int);
method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
- method public boolean performAccessibilityAction(int);
+ method public boolean performAccessibilityAction(int, android.os.Bundle);
method public boolean performClick();
method public boolean performHapticFeedback(int);
method public boolean performHapticFeedback(int, int);
@@ -25027,6 +25027,7 @@ package android.view.accessibility {
method public int getChildCount();
method public java.lang.CharSequence getClassName();
method public java.lang.CharSequence getContentDescription();
+ method public java.lang.CharSequence[] getGranularities();
method public java.lang.CharSequence getPackageName();
method public android.view.accessibility.AccessibilityNodeInfo getParent();
method public java.lang.CharSequence getText();
@@ -25047,6 +25048,7 @@ package android.view.accessibility {
method public static android.view.accessibility.AccessibilityNodeInfo obtain();
method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.accessibility.AccessibilityNodeInfo);
method public boolean performAction(int);
+ method public boolean performAction(int, android.os.Bundle);
method public void recycle();
method public void setAccessibilityFocused(boolean);
method public void setBoundsInParent(android.graphics.Rect);
@@ -25059,6 +25061,7 @@ package android.view.accessibility {
method public void setEnabled(boolean);
method public void setFocusable(boolean);
method public void setFocused(boolean);
+ method public void setGranularities(java.lang.CharSequence[]);
method public void setLongClickable(boolean);
method public void setPackageName(java.lang.CharSequence);
method public void setParent(android.view.View);
@@ -25071,12 +25074,15 @@ package android.view.accessibility {
method public void setText(java.lang.CharSequence);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
+ field public static final java.lang.String ACTION_ARGUMENT_GRANULARITY = "ACTION_ARGUMENT_GRANULARITY";
field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
field public static final int ACTION_CLICK = 16; // 0x10
field public static final int ACTION_FOCUS = 1; // 0x1
field public static final int ACTION_LONG_CLICK = 32; // 0x20
+ field public static final int ACTION_NEXT_AT_GRANULARITY = 256; // 0x100
+ field public static final int ACTION_PREVIOUS_AT_GRANULARITY = 512; // 0x200
field public static final int ACTION_SELECT = 4; // 0x4
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
@@ -25089,7 +25095,7 @@ package android.view.accessibility {
method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
method public android.view.accessibility.AccessibilityNodeInfo findAccessibilitiyFocus(int);
method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int);
- method public boolean performAccessibilityAction(int, int);
+ method public boolean performAction(int, int, android.os.Bundle);
}
public class AccessibilityRecord {
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 6e85665..dd50f3c 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -16,6 +16,7 @@
package android.accessibilityservice;
+import android.os.Bundle;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -147,14 +148,15 @@ interface IAccessibilityServiceConnection {
* {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
* to start from the root.
* @param action The action to perform.
+ * @param arguments Optional action arguments.
* @param interactionId The id of the interaction for matching with the callback result.
* @param callback Callback which to receive the result.
* @param threadId The id of the calling thread.
* @return Whether the action was performed.
*/
boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
- int action, int interactionId, IAccessibilityInteractionConnectionCallback callback,
- long threadId);
+ int action, in Bundle arguments, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, long threadId);
/**
* @return The associated accessibility service info.
diff --git a/core/java/android/accessibilityservice/UiTestAutomationBridge.java b/core/java/android/accessibilityservice/UiTestAutomationBridge.java
index 1697df0..4d4bfeb 100644
--- a/core/java/android/accessibilityservice/UiTestAutomationBridge.java
+++ b/core/java/android/accessibilityservice/UiTestAutomationBridge.java
@@ -19,6 +19,7 @@ package android.accessibilityservice;
import android.accessibilityservice.AccessibilityService.Callbacks;
import android.accessibilityservice.AccessibilityService.IAccessibilityServiceClientWrapper;
import android.content.Context;
+import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.RemoteException;
@@ -444,10 +445,12 @@ public class UiTestAutomationBridge {
*
* @param accessibilityNodeId A unique node id (accessibility and virtual descendant id).
* @param action The action to perform.
+ * @param arguments Optional action arguments.
* @return Whether the action was performed.
*/
- public boolean performAccessibilityActionInActiveWindow(long accessibilityNodeId, int action) {
- return performAccessibilityAction(ACTIVE_WINDOW_ID, accessibilityNodeId, action);
+ public boolean performAccessibilityActionInActiveWindow(long accessibilityNodeId, int action,
+ Bundle arguments) {
+ return performAccessibilityAction(ACTIVE_WINDOW_ID, accessibilityNodeId, action, arguments);
}
/**
@@ -457,15 +460,16 @@ public class UiTestAutomationBridge {
* {@link #ACTIVE_WINDOW_ID} to query the currently active window.
* @param accessibilityNodeId A unique node id (accessibility and virtual descendant id).
* @param action The action to perform.
+ * @param arguments Optional action arguments.
* @return Whether the action was performed.
*/
public boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
- int action) {
+ int action, Bundle arguments) {
// Cache the id to avoid locking
final int connectionId = mConnectionId;
ensureValidConnection(connectionId);
return AccessibilityInteractionClient.getInstance().performAccessibilityAction(connectionId,
- accessibilityWindowId, accessibilityNodeId, action);
+ accessibilityWindowId, accessibilityNodeId, action, arguments);
}
/**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index e3f5b96..7d569ad 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -18,6 +18,7 @@ package android.view;
import static android.view.accessibility.AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -514,8 +515,9 @@ final class AccessibilityInteractionController {
}
public void performAccessibilityActionClientThread(long accessibilityNodeId, int action,
- int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
- int interogatingPid, long interrogatingTid) {
+ Bundle arguments, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+ long interrogatingTid) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_PERFORM_ACCESSIBILITY_ACTION;
message.arg1 = flags;
@@ -525,6 +527,7 @@ final class AccessibilityInteractionController {
args.argi2 = action;
args.argi3 = interactionId;
args.arg1 = callback;
+ args.arg2 = arguments;
message.obj = args;
// If the interrogation is performed by the same thread as the main UI
// thread in this process, set the message as a static reference so
@@ -547,6 +550,7 @@ final class AccessibilityInteractionController {
final int interactionId = args.argi3;
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
+ Bundle arguments = (Bundle) args.arg2;
mPool.release(args);
boolean succeeded = false;
try {
@@ -564,9 +568,10 @@ final class AccessibilityInteractionController {
if (target != null && target.isDisplayedOnScreen()) {
AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
if (provider != null) {
- succeeded = provider.performAccessibilityAction(action, virtualDescendantId);
+ succeeded = provider.performAction(virtualDescendantId, action,
+ arguments);
} else if (virtualDescendantId == View.NO_ID) {
- succeeded = target.performAccessibilityAction(action);
+ succeeded = target.performAccessibilityAction(action, arguments);
}
}
} finally {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ce02113..e6d7c02 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -39,6 +39,7 @@ import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
@@ -6390,7 +6391,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* @param action The action to perform.
* @return Whether the action was performed.
*/
- public boolean performAccessibilityAction(int action) {
+ public boolean performAccessibilityAction(int action, Bundle args) {
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK: {
if (isClickable()) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 247f673..aa94765 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5132,12 +5132,13 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void performAccessibilityAction(long accessibilityNodeId, int action,
- int interactionId, IAccessibilityInteractionConnectionCallback callback,
- int flags, int interogatingPid, long interrogatingTid) {
+ Bundle arguments, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interogatingPid, long interrogatingTid) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
- .performAccessibilityActionClientThread(accessibilityNodeId, action,
+ .performAccessibilityActionClientThread(accessibilityNodeId, action, arguments,
interactionId, callback, flags, interogatingPid, interrogatingTid);
} else {
// We cannot make the call and notify the caller so it does not wait.
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index f73faf3..24e90fd 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -19,6 +19,7 @@ package android.view.accessibility;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -408,17 +409,18 @@ public final class AccessibilityInteractionClient
* {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
* to start from the root.
* @param action The action to perform.
+ * @param arguments Optional action arguments.
* @return Whether the action was performed.
*/
public boolean performAccessibilityAction(int connectionId, int accessibilityWindowId,
- long accessibilityNodeId, int action) {
+ long accessibilityNodeId, int action, Bundle arguments) {
try {
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final boolean success = connection.performAccessibilityAction(
- accessibilityWindowId, accessibilityNodeId, action, interactionId, this,
- Thread.currentThread().getId());
+ accessibilityWindowId, accessibilityNodeId, action, arguments,
+ interactionId, this, Thread.currentThread().getId());
if (success) {
return getPerformAccessibilityActionResultAndClear(interactionId);
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index c5f2062..7e565fc 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -17,9 +17,9 @@
package android.view.accessibility;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.text.TextUtils;
import android.util.SparseLongArray;
import android.view.View;
@@ -122,6 +122,80 @@ public class AccessibilityNodeInfo implements Parcelable {
public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
/**
+ * Action that requests from the node to go to the next entity in its content
+ * at a given granularity. For example, move to the next word, link, etc.
+ * <p>
+ * <strong>Arguments:</strong>
+ * <ul>
+ * <li>
+ * {@link #ACTION_ARGUMENT_GRANULARITY}
+ * </li>
+ * <li>
+ * </p>
+ * <p>
+ * <strong>Example:</strong>
+ * <code><pre><p>
+ * // Assume the first granularity was presented to the user and she is
+ * // making an explicit action to traverse the node at that granularity.
+ * CharSequence granularity = info.getGranularity(0);
+ * Bundle arguments = new Bundle();
+ * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY, granularity);
+ * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY, arguments);
+ * </code></pre></p>
+ * </li>
+ * </ul>
+ * </p>
+ * @see #setGranularities(CharSequence[])
+ * @see #getGranularities()
+ */
+ public static final int ACTION_NEXT_AT_GRANULARITY = 0x00000100;
+
+ /**
+ * Action that requests from the node to go to the previous entity in its content
+ * at a given granularity. For example, move to the next word, link, etc.
+ * <p>
+ * <strong>Arguments:</strong>
+ * <ul>
+ * <li>
+ * {@link #ACTION_ARGUMENT_GRANULARITY}
+ * </li>
+ * <li>
+ * </p>
+ * <p>
+ * <strong>Example:</strong>
+ * <code><pre><p>
+ * // Assume the first granularity was presented to the user and she is
+ * // making an explicit action to traverse the node at that granularity.
+ * CharSequence granularity = info.getGranularity(0);
+ * Bundle arguments = new Bundle();
+ * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY, granularity);
+ * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY, arguments);
+ * </code></pre></p>
+ * </li>
+ * </ul>
+ * </p>
+ * @see #setGranularities(CharSequence[])
+ * @see #getGranularities()
+ */
+ public static final int ACTION_PREVIOUS_AT_GRANULARITY = 0x00000200;
+
+ /**
+ * Argument for which content granularity to be used when traversing the node content.
+ * <p>
+ * <strong>Actions:</strong>
+ * <ul>
+ * <li>
+ * {@link #ACTION_PREVIOUS_AT_GRANULARITY}
+ * </li>
+ * <li>
+ * {@link #ACTION_PREVIOUS_AT_GRANULARITY}
+ * </li>
+ * </ul>
+ * </p>
+ */
+ public static final String ACTION_ARGUMENT_GRANULARITY = "ACTION_ARGUMENT_GRANULARITY";
+
+ /**
* The input focus.
*/
public static final int FOCUS_INPUT = 1;
@@ -231,9 +305,11 @@ public class AccessibilityNodeInfo implements Parcelable {
private CharSequence mText;
private CharSequence mContentDescription;
- private SparseLongArray mChildNodeIds = new SparseLongArray();
+ private final SparseLongArray mChildNodeIds = new SparseLongArray();
private int mActions;
+ private CharSequence[] mGranularities;
+
private int mConnectionId = UNDEFINED;
/**
@@ -458,6 +534,32 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Sets the granularities for traversing the content of this node.
+ * <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 granularities The granularity names.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setGranularities(CharSequence[] granularities) {
+ enforceNotSealed();
+ mGranularities = granularities;
+ }
+
+ /**
+ * Gets the granularities for traversing the content of this node.
+ *
+ * @return The count.
+ */
+ public CharSequence[] getGranularities() {
+ return mGranularities;
+ }
+
+ /**
* Performs an action on the node.
* <p>
* <strong>Note:</strong> An action can be performed only if the request is made
@@ -475,7 +577,31 @@ public class AccessibilityNodeInfo implements Parcelable {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId, action);
+ return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
+ action, null);
+ }
+
+ /**
+ * Performs an action on the node.
+ * <p>
+ * <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.
+ * @param arguments A bundle with additional arguments.
+ * @return True if the action was performed.
+ *
+ * @throws IllegalStateException If called outside of an AccessibilityService.
+ */
+ public boolean performAction(int action, Bundle arguments) {
+ enforceSealed();
+ if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ return false;
+ }
+ AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+ return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
+ action, arguments);
}
/**
@@ -1215,6 +1341,8 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeLong(mParentNodeId);
parcel.writeInt(mConnectionId);
+ parcel.writeCharSequenceArray(mGranularities);
+
SparseLongArray childIds = mChildNodeIds;
final int childIdsSize = childIds.size();
parcel.writeInt(childIdsSize);
@@ -1236,10 +1364,10 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeInt(mBooleanProperties);
- TextUtils.writeToParcel(mPackageName, parcel, flags);
- TextUtils.writeToParcel(mClassName, parcel, flags);
- TextUtils.writeToParcel(mText, parcel, flags);
- TextUtils.writeToParcel(mContentDescription, parcel, flags);
+ parcel.writeCharSequence(mPackageName);
+ parcel.writeCharSequence(mClassName);
+ parcel.writeCharSequence(mText);
+ parcel.writeCharSequence(mContentDescription);
// Since instances of this class are fetched via synchronous i.e. blocking
// calls in IPCs we always recycle as soon as the instance is marshaled.
@@ -1251,6 +1379,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*
* @param other The other instance.
*/
+ @SuppressWarnings("unchecked")
private void init(AccessibilityNodeInfo other) {
mSealed = other.mSealed;
mSourceNodeId = other.mSourceNodeId;
@@ -1265,7 +1394,11 @@ public class AccessibilityNodeInfo implements Parcelable {
mContentDescription = other.mContentDescription;
mActions= other.mActions;
mBooleanProperties = other.mBooleanProperties;
- mChildNodeIds = other.mChildNodeIds.clone();
+ mGranularities = other.mGranularities.clone();
+ final int otherChildIdCount = other.mChildNodeIds.size();
+ for (int i = 0; i < otherChildIdCount; i++) {
+ mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i));
+ }
}
/**
@@ -1280,6 +1413,8 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = parcel.readLong();
mConnectionId = parcel.readInt();
+ mGranularities = parcel.readCharSequenceArray();
+
SparseLongArray childIds = mChildNodeIds;
final int childrenSize = parcel.readInt();
for (int i = 0; i < childrenSize; i++) {
@@ -1301,10 +1436,10 @@ public class AccessibilityNodeInfo implements Parcelable {
mBooleanProperties = parcel.readInt();
- mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+ mPackageName = parcel.readCharSequence();
+ mClassName = parcel.readCharSequence();
+ mText = parcel.readCharSequence();
+ mContentDescription = parcel.readCharSequence();
}
/**
@@ -1316,6 +1451,7 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = ROOT_NODE_ID;
mWindowId = UNDEFINED;
mConnectionId = UNDEFINED;
+ mGranularities = null;
mChildNodeIds.clear();
mBoundsInParent.set(0, 0, 0, 0);
mBoundsInScreen.set(0, 0, 0, 0);
@@ -1394,6 +1530,17 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
builder.append("; mParentNodeId: " + mParentNodeId);
+
+ CharSequence[] granularities = mGranularities;
+ builder.append("; granularities: [");
+ for (int i = 0, count = granularities.length; i < count; i++) {
+ builder.append(granularities[i]);
+ if (i < count - 1) {
+ builder.append(", ");
+ }
+ }
+ builder.append("]");
+
SparseLongArray childIds = mChildNodeIds;
builder.append("; childAccessibilityIds: [");
for (int i = 0, count = childIds.size(); i < count; i++) {
@@ -1401,8 +1548,8 @@ public class AccessibilityNodeInfo implements Parcelable {
if (i < count - 1) {
builder.append(", ");
}
- }
- builder.append("]");
+ }
+ builder.append("]");
}
builder.append("; boundsInParent: " + mBoundsInParent);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
index 19e35dd..ba6433f 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
@@ -17,6 +17,7 @@
package android.view.accessibility;
import android.accessibilityservice.AccessibilityService;
+import android.os.Bundle;
import android.view.View;
import java.util.List;
@@ -47,12 +48,13 @@ import java.util.List;
* getAccessibilityNodeProvider(
* if (mAccessibilityNodeProvider == null) {
* mAccessibilityNodeProvider = new AccessibilityNodeProvider() {
- * public boolean performAccessibilityAction(int action, int virtualDescendantId) {
+ * public boolean performAction(int action, int virtualDescendantId) {
* // Implementation.
* return false;
* }
*
- * public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text, int virtualDescendantId) {
+ * public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text,
+ * int virtualDescendantId) {
* // Implementation.
* return null;
* }
@@ -99,15 +101,16 @@ public abstract class AccessibilityNodeProvider {
* host View, with the given <code>virtualViewId</code> or the host View itself
* if <code>virtualViewId</code> equals to {@link View#NO_ID}.
*
- * @param action The action to perform.
* @param virtualViewId A client defined virtual view id.
+ * @param action The action to perform.
+ * @param arguments Optional action arguments.
* @return True if the action was performed.
*
- * @see View#performAccessibilityAction(int)
+ * @see View#performAccessibilityAction(int, Bundle)
* @see #createAccessibilityNodeInfo(int)
* @see AccessibilityNodeInfo
*/
- public boolean performAccessibilityAction(int action, int virtualViewId) {
+ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
return false;
}
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 8182d29..9d7a928 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -16,6 +16,7 @@
package android.view.accessibility;
+import android.os.Bundle;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -47,7 +48,7 @@ oneway interface IAccessibilityInteractionConnection {
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid);
- void performAccessibilityAction(long accessibilityNodeId, int action, int interactionId,
- IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid);
+ void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+ int interrogatingPid, long interrogatingTid);
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 992849d..11d1ed0 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -26,6 +26,7 @@ import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;
@@ -2068,7 +2069,7 @@ public class NumberPicker extends LinearLayout {
}
@Override
- public boolean performAccessibilityAction(int action, int virtualViewId) {
+ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
switch (virtualViewId) {
case VIRTUAL_VIEW_ID_INPUT: {
switch (action) {
@@ -2086,7 +2087,7 @@ public class NumberPicker extends LinearLayout {
}
} break;
}
- return super.performAccessibilityAction(action, virtualViewId);
+ return super.performAction(virtualViewId, action, arguments);
}
public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) {
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3f8036b..a730770 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -865,6 +865,10 @@
<java-symbol type="string" name="yesterday" />
<java-symbol type="string" name="imei" />
<java-symbol type="string" name="meid" />
+ <java-symbol type="string" name="granularity_label_character" />
+ <java-symbol type="string" name="granularity_label_word" />
+ <java-symbol type="string" name="granularity_label_link" />
+ <java-symbol type="string" name="granularity_label_line" />
<java-symbol type="plurals" name="abbrev_in_num_days" />
<java-symbol type="plurals" name="abbrev_in_num_hours" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 149a78c..04866b9 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2027,6 +2027,15 @@
<!-- Label for ALT modifier key. Must be short to fit on key! -->
<string name="password_keyboard_label_alt_key">ALT</string>
+ <!-- Label for granularity to traverse the content on an AccessibilityNodeInfo by character. Only spoken to the user. [CHAR LIMIT=NONE] -->
+ <string name="granularity_label_character">character</string>
+ <!-- Label for granularity to traverse the content on an AccessibilityNodeInfo by word. Only spoken to the user. [CHAR LIMIT=NONE] -->
+ <string name="granularity_label_word">word</string>
+ <!-- Label for granularity to traverse the content on an AccessibilityNodeInfo by link. Only spoken to the user. [CHAR LIMIT=NONE] -->
+ <string name="granularity_label_link">link</string>
+ <!-- Label for granularity to traverse the content on an AccessibilityNodeInfo by line. Only spoken to the user. [CHAR LIMIT=NONE] -->
+ <string name="granularity_label_line">line</string>
+
<!-- A format string for 12-hour time of day, just the hour, not the minute, with lower-case "am" or "pm" (example: "3pm"). -->
<string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string>
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 7361062..e9a21c6 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -41,6 +41,7 @@ import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -1545,7 +1546,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
@Override
public boolean performAccessibilityAction(int accessibilityWindowId,
- long accessibilityNodeId, int action, int interactionId,
+ long accessibilityNodeId, int action, Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) {
final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
IAccessibilityInteractionConnection connection = null;
@@ -1566,8 +1567,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final int flags = (mIncludeNotImportantViews) ?
AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
final int interrogatingPid = Binder.getCallingPid();
- connection.performAccessibilityAction(accessibilityNodeId, action, interactionId,
- callback, flags, interrogatingPid, interrogatingTid);
+ connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
+ interactionId, callback, flags, interrogatingPid, interrogatingTid);
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
@@ -1696,7 +1697,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
| AccessibilityNodeInfo.ACTION_SELECT
| AccessibilityNodeInfo.ACTION_CLEAR_SELECTION
| AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS
- | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+ | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS
+ | AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY
+ | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY;
private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
AccessibilityEvent.TYPE_VIEW_CLICKED