Merge "Adding APIs to enable apps to influence accessibility traversal." into lmp-mr1-dev

This commit is contained in:
Svetoslav
2014-10-31 19:53:31 +00:00
committed by Android (Google) Code Review
6 changed files with 329 additions and 21 deletions

View File

@@ -239,6 +239,8 @@ package android {
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
field public static final int accessibilityFlags = 16843652; // 0x1010384
field public static final int accessibilityLiveRegion = 16843758; // 0x10103ee
field public static final int accessibilityTraversalAfter = 16844036; // 0x1010504
field public static final int accessibilityTraversalBefore = 16844035; // 0x1010503
field public static final int accountPreferences = 16843423; // 0x101029f
field public static final int accountType = 16843407; // 0x101028f
field public static final int action = 16842797; // 0x101002d
@@ -33610,6 +33612,8 @@ package android.view {
method public static int generateViewId();
method public int getAccessibilityLiveRegion();
method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
method public int getAccessibilityTraversalAfter();
method public int getAccessibilityTraversalBefore();
method public float getAlpha();
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
@@ -33886,6 +33890,8 @@ package android.view {
method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
method public void setAccessibilityDelegate(android.view.View.AccessibilityDelegate);
method public void setAccessibilityLiveRegion(int);
method public void setAccessibilityTraversalAfter(int);
method public void setAccessibilityTraversalBefore(int);
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
@@ -35165,6 +35171,8 @@ package android.view.accessibility {
method public java.lang.CharSequence getText();
method public int getTextSelectionEnd();
method public int getTextSelectionStart();
method public android.view.accessibility.AccessibilityNodeInfo getTraversalAfter();
method public android.view.accessibility.AccessibilityNodeInfo getTraversalBefore();
method public java.lang.String getViewIdResourceName();
method public android.view.accessibility.AccessibilityWindowInfo getWindow();
method public int getWindowId();
@@ -35235,6 +35243,10 @@ package android.view.accessibility {
method public void setSource(android.view.View, int);
method public void setText(java.lang.CharSequence);
method public void setTextSelection(int, int);
method public void setTraversalAfter(android.view.View);
method public void setTraversalAfter(android.view.View, int);
method public void setTraversalBefore(android.view.View);
method public void setTraversalBefore(android.view.View, int);
method public void setViewIdResourceName(java.lang.String);
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
@@ -38432,6 +38444,8 @@ package android.widget {
method public boolean onLoadClass(java.lang.Class);
method public void reapply(android.content.Context, android.view.View);
method public void removeAllViews(int);
method public void setAccessibilityTraversalAfter(int, int);
method public void setAccessibilityTraversalBefore(int, int);
method public void setBitmap(int, java.lang.String, android.graphics.Bitmap);
method public void setBoolean(int, java.lang.String, boolean);
method public void setBundle(int, java.lang.String, android.os.Bundle);

View File

@@ -3108,6 +3108,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private MatchLabelForPredicate mMatchLabelForPredicate;
/**
* Specifies a view before which this one is visited in accessibility traversal.
*/
private int mAccessibilityTraversalBeforeId = NO_ID;
/**
* Specifies a view after which this one is visited in accessibility traversal.
*/
private int mAccessibilityTraversalAfterId = NO_ID;
/**
* Predicate for matching a view by its id.
*/
@@ -3888,6 +3898,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
case com.android.internal.R.styleable.View_contentDescription:
setContentDescription(a.getString(attr));
break;
case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
break;
case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
break;
case com.android.internal.R.styleable.View_labelFor:
setLabelFor(a.getResourceId(attr, NO_ID));
break;
@@ -5611,6 +5627,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (rootView == null) {
rootView = this;
}
View label = rootView.findLabelForView(this, mID);
if (label != null) {
info.setLabeledBy(label);
@@ -5639,6 +5656,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
if (mAccessibilityTraversalBeforeId != View.NO_ID) {
View rootView = getRootView();
if (rootView == null) {
rootView = this;
}
View next = rootView.findViewInsideOutShouldExist(this,
mAccessibilityTraversalBeforeId);
if (next != null) {
info.setTraversalBefore(next);
}
}
if (mAccessibilityTraversalAfterId != View.NO_ID) {
View rootView = getRootView();
if (rootView == null) {
rootView = this;
}
View next = rootView.findViewInsideOutShouldExist(this,
mAccessibilityTraversalAfterId);
if (next != null) {
info.setTraversalAfter(next);
}
}
info.setVisibleToUser(isVisibleToUser());
info.setPackageName(mContext.getPackageName());
@@ -6042,6 +6083,94 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
/**
* Sets the id of a view before which this one is visited in accessibility traversal.
* A screen-reader must visit the content of this view before the content of the one
* it precedes. For example, if view B is set to be before view A, then a screen-reader
* will traverse the entire content of B before traversing the entire content of A,
* regardles of what traversal strategy it is using.
* <p>
* Views that do not have specified before/after relationships are traversed in order
* determined by the screen-reader.
* </p>
* <p>
* Setting that this view is before a view that is not important for accessibility
* or if this view is not important for accessibility will have no effect as the
* screen-reader is not aware of unimportant views.
* </p>
*
* @param beforeId The id of a view this one precedes in accessibility traversal.
*
* @attr ref android.R.styleable#View_accessibilityTraversalBefore
*
* @see #setImportantForAccessibility(int)
*/
@RemotableViewMethod
public void setAccessibilityTraversalBefore(int beforeId) {
if (mAccessibilityTraversalBeforeId == beforeId) {
return;
}
mAccessibilityTraversalBeforeId = beforeId;
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
/**
* Gets the id of a view before which this one is visited in accessibility traversal.
*
* @return The id of a view this one precedes in accessibility traversal if
* specified, otherwise {@link #NO_ID}.
*
* @see #setAccessibilityTraversalBefore(int)
*/
public int getAccessibilityTraversalBefore() {
return mAccessibilityTraversalBeforeId;
}
/**
* Sets the id of a view after which this one is visited in accessibility traversal.
* A screen-reader must visit the content of the other view before the content of this
* one. For example, if view B is set to be after view A, then a screen-reader
* will traverse the entire content of A before traversing the entire content of B,
* regardles of what traversal strategy it is using.
* <p>
* Views that do not have specified before/after relationships are traversed in order
* determined by the screen-reader.
* </p>
* <p>
* Setting that this view is after a view that is not important for accessibility
* or if this view is not important for accessibility will have no effect as the
* screen-reader is not aware of unimportant views.
* </p>
*
* @param afterId The id of a view this one succedees in accessibility traversal.
*
* @attr ref android.R.styleable#View_accessibilityTraversalAfter
*
* @see #setImportantForAccessibility(int)
*/
@RemotableViewMethod
public void setAccessibilityTraversalAfter(int afterId) {
if (mAccessibilityTraversalAfterId == afterId) {
return;
}
mAccessibilityTraversalAfterId = afterId;
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
/**
* Gets the id of a view after which this one is visited in accessibility traversal.
*
* @return The id of a view this one succeedes in accessibility traversal if
* specified, otherwise {@link #NO_ID}.
*
* @see #setAccessibilityTraversalAfter(int)
*/
public int getAccessibilityTraversalAfter() {
return mAccessibilityTraversalAfterId;
}
/**
* Gets the id of a view for which this view serves as a label for
* accessibility purposes.
@@ -6061,11 +6190,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@RemotableViewMethod
public void setLabelFor(int id) {
if (mLabelForId == id) {
return;
}
mLabelForId = id;
if (mLabelForId != View.NO_ID
&& mID == View.NO_ID) {
mID = generateViewId();
}
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
/**

View File

@@ -547,6 +547,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private long mParentNodeId = ROOT_NODE_ID;
private long mLabelForId = ROOT_NODE_ID;
private long mLabeledById = ROOT_NODE_ID;
private long mTraversalBefore = ROOT_NODE_ID;
private long mTraversalAfter = ROOT_NODE_ID;
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
@@ -1045,6 +1047,126 @@ public class AccessibilityNodeInfo implements Parcelable {
return mActions.remove(action);
}
/**
* Gets the node before which this one is visited during traversal. A screen-reader
* must visit the content of this node before the content of the one it precedes.
*
* @return The succeeding node if such or <code>null</code>.
*
* @see #setTraversalBefore(android.view.View)
* @see #setTraversalBefore(android.view.View, int)
*/
public AccessibilityNodeInfo getTraversalBefore() {
enforceSealed();
return getNodeForAccessibilityId(mTraversalBefore);
}
/**
* Sets the view before whose node this one should be visited during traversal. A
* screen-reader must visit the content of this node before the content of the one
* it precedes.
* <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 view The view providing the preceding node.
*
* @see #getTraversalBefore()
*/
public void setTraversalBefore(View view) {
setTraversalBefore(view, UNDEFINED_ITEM_ID);
}
/**
* Sets the node before which this one is visited during traversal. A screen-reader
* must visit the content of this node before the content of the one it precedes.
* The successor is a virtual descendant of the given <code>root</code>. If
* <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
* as the successor.
* <p>
* A virtual descendant is an imaginary View that is reported as a part of the view
* hierarchy for accessibility purposes. This enables custom views that draw complex
* content to report them selves as a tree of virtual views, thus conveying their
* logical structure.
* </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 root The root of the virtual subtree.
* @param virtualDescendantId The id of the virtual descendant.
*/
public void setTraversalBefore(View root, int virtualDescendantId) {
enforceNotSealed();
final int rootAccessibilityViewId = (root != null)
? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
}
/**
* Gets the node after which this one is visited in accessibility traversal.
* A screen-reader must visit the content of the other node before the content
* of this one.
*
* @return The succeeding node if such or <code>null</code>.
*
* @see #setTraversalAfter(android.view.View)
* @see #setTraversalAfter(android.view.View, int)
*/
public AccessibilityNodeInfo getTraversalAfter() {
enforceSealed();
return getNodeForAccessibilityId(mTraversalAfter);
}
/**
* Sets the view whose node is visited after this one in accessibility traversal.
* A screen-reader must visit the content of the other node before the content
* of this one.
* <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 view The previous view.
*
* @see #getTraversalAfter()
*/
public void setTraversalAfter(View view) {
setTraversalAfter(view, UNDEFINED_ITEM_ID);
}
/**
* Sets the node after which this one is visited in accessibility traversal.
* A screen-reader must visit the content of the other node before the content
* of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
* the root is set as the predecessor.
* <p>
* A virtual descendant is an imaginary View that is reported as a part of the view
* hierarchy for accessibility purposes. This enables custom views that draw complex
* content to report them selves as a tree of virtual views, thus conveying their
* logical structure.
* </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 root The root of the virtual subtree.
* @param virtualDescendantId The id of the virtual descendant.
*/
public void setTraversalAfter(View root, int virtualDescendantId) {
enforceNotSealed();
final int rootAccessibilityViewId = (root != null)
? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
}
/**
* Sets the maximum text length, or -1 for no limit.
* <p>
@@ -1229,13 +1351,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getParent() {
enforceSealed();
if (!canPerformRequestOverConnection(mParentNodeId)) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mWindowId, mParentNodeId, false, FLAG_PREFETCH_PREDECESSORS
| FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
return getNodeForAccessibilityId(mParentNodeId);
}
/**
@@ -2055,13 +2171,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getLabelFor() {
enforceSealed();
if (!canPerformRequestOverConnection(mLabelForId)) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mWindowId, mLabelForId, false, FLAG_PREFETCH_PREDECESSORS
| FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
return getNodeForAccessibilityId(mLabelForId);
}
/**
@@ -2113,13 +2223,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getLabeledBy() {
enforceSealed();
if (!canPerformRequestOverConnection(mLabeledById)) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mWindowId, mLabeledById, false, FLAG_PREFETCH_PREDECESSORS
| FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
return getNodeForAccessibilityId(mLabeledById);
}
/**
@@ -2453,6 +2557,9 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeLong(mParentNodeId);
parcel.writeLong(mLabelForId);
parcel.writeLong(mLabeledById);
parcel.writeLong(mTraversalBefore);
parcel.writeLong(mTraversalAfter);
parcel.writeInt(mConnectionId);
final LongArray childIds = mChildNodeIds;
@@ -2571,6 +2678,8 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = other.mParentNodeId;
mLabelForId = other.mLabelForId;
mLabeledById = other.mLabeledById;
mTraversalBefore = other.mTraversalBefore;
mTraversalAfter = other.mTraversalAfter;
mWindowId = other.mWindowId;
mConnectionId = other.mConnectionId;
mBoundsInParent.set(other.mBoundsInParent);
@@ -2633,6 +2742,9 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = parcel.readLong();
mLabelForId = parcel.readLong();
mLabeledById = parcel.readLong();
mTraversalBefore = parcel.readLong();
mTraversalAfter = parcel.readLong();
mConnectionId = parcel.readInt();
final int childrenSize = parcel.readInt();
@@ -2725,6 +2837,8 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = ROOT_NODE_ID;
mLabelForId = ROOT_NODE_ID;
mLabeledById = ROOT_NODE_ID;
mTraversalBefore = ROOT_NODE_ID;
mTraversalAfter = ROOT_NODE_ID;
mWindowId = UNDEFINED_ITEM_ID;
mConnectionId = UNDEFINED_CONNECTION_ID;
mMaxTextLength = -1;
@@ -2911,6 +3025,8 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
builder.append("; mParentNodeId: " + mParentNodeId);
builder.append("; traversalBefore: ").append(mTraversalBefore);
builder.append("; traversalAfter: ").append(mTraversalAfter);
int granularities = mMovementGranularities;
builder.append("; MovementGranularities: [");
@@ -2963,6 +3079,16 @@ public class AccessibilityNodeInfo implements Parcelable {
return builder.toString();
}
private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
if (!canPerformRequestOverConnection(accessibilityId)) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
| FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
}
/**
* 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.

View File

@@ -2527,6 +2527,26 @@ public class RemoteViews implements Parcelable, Filter {
setCharSequence(viewId, "setContentDescription", contentDescription);
}
/**
* Equivalent to calling {@link android.view.View#setAccessibilityTraversalBefore(int)}.
*
* @param viewId The id of the view whose before view in accessibility traversal to set.
* @param nextId The id of the next in the accessibility traversal.
**/
public void setAccessibilityTraversalBefore(int viewId, int nextId) {
setInt(viewId, "setAccessibilityTraversalBefore", nextId);
}
/**
* Equivalent to calling {@link android.view.View#setAccessibilityTraversalAfter(int)}.
*
* @param viewId The id of the view whose after view in accessibility traversal to set.
* @param nextId The id of the next in the accessibility traversal.
**/
public void setAccessibilityTraversalAfter(int viewId, int nextId) {
setInt(viewId, "setAccessibilityTraversalAfter", nextId);
}
/**
* Equivalent to calling View.setLabelFor(int).
*

View File

@@ -2363,6 +2363,18 @@
representation this attribute can be used for providing such. -->
<attr name="contentDescription" format="string" localization="suggested" />
<!-- Sets the id of a view before which this one is visited in accessibility traversal.
A screen-reader must visit the content of this view before the content of the one
it precedes.
@see android.view.View#setAccessibilityTraversalBefore(int)} -->
<attr name="accessibilityTraversalBefore" format="integer" />
<!-- Sets the id of a view after which this one is visited in accessibility traversal.
A screen-reader must visit the content of the other view before the content of
this one.
@see android.view.View#setAccessibilityTraversalAfter(int)} -->
<attr name="accessibilityTraversalAfter" format="integer" />
<!-- Name of the method in this View's context to invoke when the view is
clicked. This name must correspond to a public method that takes
exactly one parameter of type View. For instance, if you specify

View File

@@ -2597,5 +2597,7 @@
<public type="attr" name="resizeClip"/>
<public type="attr" name="collapseContentDescription"/>
<public type="attr" name="accessibilityTraversalBefore" />
<public type="attr" name="accessibilityTraversalAfter" />
</resources>