Merge "Make a11y clickable span work after node recycle" into oc-dev
am: 5d25f429bf
Change-Id: Ic25383f328c9dbe82241bc8a726fc5fa854b7811
This commit is contained in:
@@ -16,6 +16,9 @@
|
||||
package android.text.style;
|
||||
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.UNDEFINED_CONNECTION_ID;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.UNDEFINED_NODE_ID;
|
||||
import static android.view.accessibility.AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
@@ -24,13 +27,11 @@ import android.text.ParcelableSpan;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityInteractionClient;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
/**
|
||||
* {@link ClickableSpan} cannot be parceled, but accessibility services need to be able to cause
|
||||
* their callback handlers to be called. This class serves as a parcelable placeholder for the
|
||||
@@ -47,10 +48,9 @@ public class AccessibilityClickableSpan extends ClickableSpan
|
||||
// The id of the span this one replaces
|
||||
private final int mOriginalClickableSpanId;
|
||||
|
||||
// Only retain a weak reference to the node to avoid referencing cycles that could create memory
|
||||
// leaks.
|
||||
private WeakReference<AccessibilityNodeInfo> mAccessibilityNodeInfoRef;
|
||||
|
||||
private int mWindowId = UNDEFINED_WINDOW_ID;
|
||||
private long mSourceNodeId = UNDEFINED_NODE_ID;
|
||||
private int mConnectionId = UNDEFINED_CONNECTION_ID;
|
||||
|
||||
/**
|
||||
* @param originalClickableSpanId The id of the span this one replaces
|
||||
@@ -110,13 +110,15 @@ public class AccessibilityClickableSpan extends ClickableSpan
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the accessibilityNodeInfo that this placeholder belongs to. This node is not
|
||||
* included in the parceling logic, and must be set to allow the onClick handler to function.
|
||||
* Configure this object to perform clicks on the view that contains the original span.
|
||||
*
|
||||
* @param accessibilityNodeInfo The info this span is part of
|
||||
* @param accessibilityNodeInfo The info corresponding to the view containing the original
|
||||
* span.
|
||||
*/
|
||||
public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) {
|
||||
mAccessibilityNodeInfoRef = new WeakReference<>(accessibilityNodeInfo);
|
||||
public void copyConnectionDataFrom(AccessibilityNodeInfo accessibilityNodeInfo) {
|
||||
mConnectionId = accessibilityNodeInfo.getConnectionId();
|
||||
mWindowId = accessibilityNodeInfo.getWindowId();
|
||||
mSourceNodeId = accessibilityNodeInfo.getSourceNodeId();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,17 +130,18 @@ public class AccessibilityClickableSpan extends ClickableSpan
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View unused) {
|
||||
if (mAccessibilityNodeInfoRef == null) {
|
||||
return;
|
||||
}
|
||||
AccessibilityNodeInfo info = mAccessibilityNodeInfoRef.get();
|
||||
if (info == null) {
|
||||
return;
|
||||
}
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN, this);
|
||||
|
||||
info.performAction(R.id.accessibilityActionClickOnClickableSpan, arguments);
|
||||
if ((mWindowId == UNDEFINED_WINDOW_ID) || (mSourceNodeId == UNDEFINED_NODE_ID)
|
||||
|| (mConnectionId == UNDEFINED_CONNECTION_ID)) {
|
||||
throw new RuntimeException(
|
||||
"ClickableSpan for accessibility service not properly initialized");
|
||||
}
|
||||
|
||||
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
|
||||
client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
|
||||
R.id.accessibilityActionClickOnClickableSpan, arguments);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<AccessibilityClickableSpan> CREATOR =
|
||||
|
||||
@@ -73,7 +73,7 @@ public class AccessibilityURLSpan extends URLSpan implements Parcelable {
|
||||
* Delegated to AccessibilityClickableSpan
|
||||
* @param accessibilityNodeInfo
|
||||
*/
|
||||
public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) {
|
||||
mAccessibilityClickableSpan.setAccessibilityNodeInfo(accessibilityNodeInfo);
|
||||
public void copyConnectionDataFrom(AccessibilityNodeInfo accessibilityNodeInfo) {
|
||||
mAccessibilityClickableSpan.copyConnectionDataFrom(accessibilityNodeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,7 +695,7 @@ public class AccessibilityNodeInfo implements Parcelable {
|
||||
private boolean mSealed;
|
||||
|
||||
// Data.
|
||||
private int mWindowId = UNDEFINED_ITEM_ID;
|
||||
private int mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
|
||||
private long mSourceNodeId = UNDEFINED_NODE_ID;
|
||||
private long mParentNodeId = UNDEFINED_NODE_ID;
|
||||
private long mLabelForId = UNDEFINED_NODE_ID;
|
||||
@@ -2417,12 +2417,12 @@ public class AccessibilityNodeInfo implements Parcelable {
|
||||
AccessibilityClickableSpan[] clickableSpans =
|
||||
spanned.getSpans(0, mText.length(), AccessibilityClickableSpan.class);
|
||||
for (int i = 0; i < clickableSpans.length; i++) {
|
||||
clickableSpans[i].setAccessibilityNodeInfo(this);
|
||||
clickableSpans[i].copyConnectionDataFrom(this);
|
||||
}
|
||||
AccessibilityURLSpan[] urlSpans =
|
||||
spanned.getSpans(0, mText.length(), AccessibilityURLSpan.class);
|
||||
for (int i = 0; i < urlSpans.length; i++) {
|
||||
urlSpans[i].setAccessibilityNodeInfo(this);
|
||||
urlSpans[i].copyConnectionDataFrom(this);
|
||||
}
|
||||
}
|
||||
return mText;
|
||||
@@ -2840,6 +2840,17 @@ public class AccessibilityNodeInfo implements Parcelable {
|
||||
mConnectionId = connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the connection ID.
|
||||
*
|
||||
* @return The connection id
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public int getConnectionId() {
|
||||
return mConnectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -3354,7 +3365,7 @@ public class AccessibilityNodeInfo implements Parcelable {
|
||||
mLabeledById = UNDEFINED_NODE_ID;
|
||||
mTraversalBefore = UNDEFINED_NODE_ID;
|
||||
mTraversalAfter = UNDEFINED_NODE_ID;
|
||||
mWindowId = UNDEFINED_ITEM_ID;
|
||||
mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
|
||||
mConnectionId = UNDEFINED_CONNECTION_ID;
|
||||
mMaxTextLength = -1;
|
||||
mMovementGranularities = 0;
|
||||
@@ -3517,9 +3528,9 @@ public class AccessibilityNodeInfo implements Parcelable {
|
||||
}
|
||||
|
||||
private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
|
||||
return (mWindowId != UNDEFINED_ITEM_ID
|
||||
&& getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID
|
||||
&& mConnectionId != UNDEFINED_CONNECTION_ID);
|
||||
return ((mWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
|
||||
&& (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
|
||||
&& (mConnectionId != UNDEFINED_CONNECTION_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user