diff options
3 files changed, 43 insertions, 29 deletions
diff --git a/core/java/android/text/style/AccessibilityClickableSpan.java b/core/java/android/text/style/AccessibilityClickableSpan.java index 9c305ff0f6ae..7f39cc14718a 100644 --- a/core/java/android/text/style/AccessibilityClickableSpan.java +++ b/core/java/android/text/style/AccessibilityClickableSpan.java @@ -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 = diff --git a/core/java/android/text/style/AccessibilityURLSpan.java b/core/java/android/text/style/AccessibilityURLSpan.java index 014700945c57..bd816234a652 100644 --- a/core/java/android/text/style/AccessibilityURLSpan.java +++ b/core/java/android/text/style/AccessibilityURLSpan.java @@ -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); } } diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 255574f8cee7..94a4547fca64 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -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; @@ -2841,6 +2841,17 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Get the connection ID. + * + * @return The connection id + * + * @hide + */ + public int getConnectionId() { + return mConnectionId; + } + + /** * {@inheritDoc} */ @Override @@ -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 |