Add Accessibility API for rate-limiting CONTENT_CHANGE_TYPE* events

Bug: 222759137
Test: ran cts test
Change-Id: Ia49209d7138bd5bd1026dc18210552b3f359664e
This commit is contained in:
Zeyin Wu
2022-10-26 22:31:54 +00:00
parent ebdae6ccb8
commit a1c0adb050
5 changed files with 70 additions and 1 deletions

View File

@@ -52350,6 +52350,7 @@ package android.view.accessibility {
method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy();
method public int getLiveRegion();
method public int getMaxTextLength();
method public int getMinMillisBetweenContentChanges();
method public int getMovementGranularities();
method public CharSequence getPackageName();
method @Nullable public CharSequence getPaneTitle();
@@ -52437,6 +52438,7 @@ package android.view.accessibility {
method public void setLiveRegion(int);
method public void setLongClickable(boolean);
method public void setMaxTextLength(int);
method public void setMinMillisBetweenContentChanges(int);
method public void setMovementGranularities(int);
method public void setMultiLine(boolean);
method public void setPackageName(CharSequence);
@@ -52516,11 +52518,13 @@ package android.view.accessibility {
field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
field public static final int FOCUS_INPUT = 1; // 0x1
field public static final int MAX_NUMBER_OF_PREFETCHED_NODES = 50; // 0x32
field public static final int MINIMUM_MIN_MILLIS_BETWEEN_CONTENT_CHANGES = 100; // 0x64
field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
field public static final int MOVEMENT_GRANULARITY_LINE = 4; // 0x4
field public static final int MOVEMENT_GRANULARITY_PAGE = 16; // 0x10
field public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 8; // 0x8
field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2
field public static final int UNDEFINED_MIN_MILLIS_BETWEEN_CONTENT_CHANGES = -1; // 0xffffffff
}
public static final class AccessibilityNodeInfo.AccessibilityAction implements android.os.Parcelable {

View File

@@ -2944,6 +2944,7 @@ package android.view {
method public static int getHoverTooltipHideTimeout();
method public static int getHoverTooltipShowTimeout();
method public static int getLongPressTooltipHideTimeout();
method public static long getSendRecurringAccessibilityEventsInterval();
method public boolean isPreferKeepClearForFocusEnabled();
}

View File

@@ -822,6 +822,7 @@ public class ViewConfiguration {
*
* @hide
*/
@TestApi
public static long getSendRecurringAccessibilityEventsInterval() {
return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS;
}

View File

@@ -127,6 +127,16 @@ public class AccessibilityNodeInfo implements Parcelable {
/** @hide */
public static final long UNDEFINED_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
/**
* The default value for {@link #getMinMillisBetweenContentChanges};
*/
public static final int UNDEFINED_MIN_MILLIS_BETWEEN_CONTENT_CHANGES = -1;
/**
* The minimum value for {@link #setMinMillisBetweenContentChanges};
*/
public static final int MINIMUM_MIN_MILLIS_BETWEEN_CONTENT_CHANGES = 100;
/** @hide */
public static final long ROOT_NODE_ID = makeNodeId(ROOT_ITEM_ID,
AccessibilityNodeProvider.HOST_VIEW_ID);
@@ -879,6 +889,9 @@ public class AccessibilityNodeInfo implements Parcelable {
private long mTraversalBefore = UNDEFINED_NODE_ID;
private long mTraversalAfter = UNDEFINED_NODE_ID;
private int mMinMillisBetweenContentChanges =
UNDEFINED_MIN_MILLIS_BETWEEN_CONTENT_CHANGES;
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
private final Rect mBoundsInScreen = new Rect();
@@ -1781,6 +1794,42 @@ public class AccessibilityNodeInfo implements Parcelable {
return mMovementGranularities;
}
/**
* Sets the minimum time duration between two content change events, which is used in throttling
* content change events in accessibility services.
*
* <p>
* <strong>Note:</strong>
* This value should not be smaller than {@link #MINIMUM_MIN_MILLIS_BETWEEN_CONTENT_CHANGES},
* otherwise it would be ignored by accessibility services.
* </p>
*
* <p>
* Example: An app can set MinMillisBetweenContentChanges as 1 min for a view which sends
* content change events to accessibility services one event per second.
* Accessibility service will throttle those content change events and only handle one event
* per minute for that view.
* </p>
*
* @see AccessibilityEvent#getContentChangeTypes for all content change types.
* @param minMillisBetweenContentChanges the minimum duration between content change events.
*/
public void setMinMillisBetweenContentChanges(int minMillisBetweenContentChanges) {
enforceNotSealed();
mMinMillisBetweenContentChanges = minMillisBetweenContentChanges
>= MINIMUM_MIN_MILLIS_BETWEEN_CONTENT_CHANGES
? minMillisBetweenContentChanges
: UNDEFINED_MIN_MILLIS_BETWEEN_CONTENT_CHANGES;
}
/**
* Gets the minimum time duration between two content change events. This method may return
* {@link #UNDEFINED_MIN_MILLIS_BETWEEN_CONTENT_CHANGES}
*/
public int getMinMillisBetweenContentChanges() {
return mMinMillisBetweenContentChanges;
}
/**
* Performs an action on the node.
* <p>
@@ -3951,6 +4000,11 @@ public class AccessibilityNodeInfo implements Parcelable {
fieldIndex++;
if (mTraversalAfter != DEFAULT.mTraversalAfter) nonDefaultFields |= bitAt(fieldIndex);
fieldIndex++;
if (mMinMillisBetweenContentChanges
!= DEFAULT.mMinMillisBetweenContentChanges) {
nonDefaultFields |= bitAt(fieldIndex);
}
fieldIndex++;
if (mConnectionId != DEFAULT.mConnectionId) nonDefaultFields |= bitAt(fieldIndex);
fieldIndex++;
if (!LongArray.elementsEqual(mChildNodeIds, DEFAULT.mChildNodeIds)) {
@@ -4080,6 +4134,9 @@ public class AccessibilityNodeInfo implements Parcelable {
if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabeledById);
if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalBefore);
if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalAfter);
if (isBitSet(nonDefaultFields, fieldIndex++)) {
parcel.writeInt(mMinMillisBetweenContentChanges);
}
if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mConnectionId);
@@ -4235,6 +4292,7 @@ public class AccessibilityNodeInfo implements Parcelable {
mLabeledById = other.mLabeledById;
mTraversalBefore = other.mTraversalBefore;
mTraversalAfter = other.mTraversalAfter;
mMinMillisBetweenContentChanges = other.mMinMillisBetweenContentChanges;
mWindowId = other.mWindowId;
mConnectionId = other.mConnectionId;
mUniqueId = other.mUniqueId;
@@ -4338,6 +4396,9 @@ public class AccessibilityNodeInfo implements Parcelable {
if (isBitSet(nonDefaultFields, fieldIndex++)) mLabeledById = parcel.readLong();
if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalBefore = parcel.readLong();
if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalAfter = parcel.readLong();
if (isBitSet(nonDefaultFields, fieldIndex++)) {
mMinMillisBetweenContentChanges = parcel.readInt();
}
if (isBitSet(nonDefaultFields, fieldIndex++)) mConnectionId = parcel.readInt();
@@ -4686,6 +4747,8 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; mParentNodeId: 0x").append(Long.toHexString(mParentNodeId));
builder.append("; traversalBefore: 0x").append(Long.toHexString(mTraversalBefore));
builder.append("; traversalAfter: 0x").append(Long.toHexString(mTraversalAfter));
builder.append("; minMillisBetweenContentChanges: ")
.append(mMinMillisBetweenContentChanges);
int granularities = mMovementGranularities;
builder.append("; MovementGranularities: [");

View File

@@ -46,7 +46,7 @@ public class AccessibilityNodeInfoTest {
// The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest:
// See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo,
// and assertAccessibilityNodeInfoCleared in that class.
private static final int NUM_MARSHALLED_PROPERTIES = 41;
private static final int NUM_MARSHALLED_PROPERTIES = 42;
/**
* The number of properties that are purposely not marshalled