Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88ac6d96 authored by Phil Weaver's avatar Phil Weaver Committed by android-build-merger
Browse files

Merge "Make a11y clickable span work after node recycle" into oc-dev am: 5d25f429

am: 0b3408a3

Change-Id: I8e354ba1ecb353c696d6a7df07701c5c19544b6e
parents 81cacd87 0b3408a3
Loading
Loading
Loading
Loading
+23 −20
Original line number Diff line number Diff line
@@ -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 =
+2 −2
Original line number Diff line number Diff line
@@ -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);
    }
}
+18 −7
Original line number Diff line number Diff line
@@ -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