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

Commit 651fe9fc authored by Phil Weaver's avatar Phil Weaver
Browse files

Stop populating accessibility nodes with events

This mostly rolls back ag/710190, which caused
AccessibilityEvents to contain their source nodes. These
nodes were not completely accurate, and populating them
increases the overhead of AccessibilityEvents, particularly
when large numbers of content changes happen. Having the
service reload the node if it needs the update content
should be sufficient. I have fixed several bugs since this
change went in to address issues with the accessibility
cache containing stale data. I think ensuring that the newly
loaded data is up-to-date will fix whatever issues carrying
the node along was intended to fix.

Bug: 33961523
Test: A11y CTS still passes. I also tried TalkBack on a
couple of switch controls, which is where I have previously
seen the most issues with up-to-date announcements.

Change-Id: Ie5a70bb0e89d49255c6a4c1c83d32b755c06902f
parent 863b7fea
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -1110,7 +1110,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
        record.mParcelableData = parcel.readParcelable(null);
        parcel.readList(record.mText, null);
        record.mSourceWindowId = parcel.readInt();
        record.mSourceNode = parcel.readParcelable(null);
        record.mSourceNodeId = parcel.readLong();
        record.mSealed = (parcel.readInt() == 1);
    }

@@ -1162,10 +1162,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
        parcel.writeParcelable(record.mParcelableData, flags);
        parcel.writeList(record.mText);
        parcel.writeInt(record.mSourceWindowId);
        // create copy of the node here because the node would be recycled just after it is written
        // to parcel
        parcel.writeParcelable(record.mSourceNode != null ?
                AccessibilityNodeInfo.obtain(record.mSourceNode) : null, flags);
        parcel.writeLong(record.mSourceNodeId);
        parcel.writeInt(record.mSealed ? 1 : 0);
    }

@@ -1189,9 +1186,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
            builder.append("\n");
            builder.append("; ContentChangeTypes: ").append(mContentChangeTypes);
            builder.append("; sourceWindowId: ").append(mSourceWindowId);
            if (mSourceNode != null) {
                builder.append("; mSourceNodeId: ").append(mSourceNode.getSourceNodeId());
            }
            builder.append("; mSourceNodeId: ").append(mSourceNodeId);
            for (int i = 0; i < getRecordCount(); i++) {
                final AccessibilityRecord record = getRecord(i);
                builder.append("  Record ");
+0 −1
Original line number Diff line number Diff line
@@ -85,7 +85,6 @@ public class AccessibilityNodeInfo implements Parcelable {
    /** @hide */
    public static final int UNDEFINED_SELECTION_INDEX = -1;

    /* Special IDs for node source IDs */
    /** @hide */
    public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE;

+24 −53
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view.accessibility;

import android.annotation.Nullable;
import android.os.Parcelable;
import android.view.View;

@@ -90,7 +91,7 @@ public class AccessibilityRecord {

    int mAddedCount= UNDEFINED;
    int mRemovedCount = UNDEFINED;
    AccessibilityNodeInfo mSourceNode;
    long mSourceNodeId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
    int mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;

    CharSequence mClassName;
@@ -116,7 +117,7 @@ public class AccessibilityRecord {
     * @throws IllegalStateException If called from an AccessibilityService.
     */
    public void setSource(View source) {
        setSource(source, UNDEFINED);
        setSource(source, AccessibilityNodeInfo.UNDEFINED_ITEM_ID);
    }

    /**
@@ -133,46 +134,28 @@ public class AccessibilityRecord {
     * @param root The root of the virtual subtree.
     * @param virtualDescendantId The id of the virtual descendant.
     */
    public void setSource(View root, int virtualDescendantId) {
    public void setSource(@Nullable View root, int virtualDescendantId) {
        enforceNotSealed();
        boolean important = true;
        int rootViewId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
        mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
        clearSourceNode();
        if (root != null) {
            if (virtualDescendantId == View.NO_ID
                    || virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID
                    || virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
            important = root.isImportantForAccessibility();
                mSourceNode = root.createAccessibilityNodeInfo();
            } else {
                AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
                if (provider != null) {
                    mSourceNode = provider.createAccessibilityNodeInfo(virtualDescendantId);
                }
            }

            rootViewId = root.getAccessibilityViewId();
            mSourceWindowId = root.getAccessibilityWindowId();
        }
        setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
        mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
    }

    /**
     * Set the source directly to an AccessibilityNodeInfo rather than indirectly via a View
     *
     * @param info The source
     * Set the source node ID directly
     *
     * @param sourceNodeId The source node Id
     * @hide
     */
    public void setSource(AccessibilityNodeInfo info) {
        enforceNotSealed();
        clearSourceNode();
        mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
        if (info != null) {
            mSourceNode = AccessibilityNodeInfo.obtain(info);
            setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY,
                    mSourceNode.isImportantForAccessibility());
            mSourceWindowId = info.getWindowId();
        }
    public void setSourceNodeId(long sourceNodeId) {
        mSourceNodeId = sourceNodeId;
    }

    /**
@@ -186,12 +169,16 @@ public class AccessibilityRecord {
     */
    public AccessibilityNodeInfo getSource() {
        enforceSealed();
        if (mSourceNode != null) {
            return AccessibilityNodeInfo.obtain(mSourceNode);
        }

        if ((mConnectionId == UNDEFINED)
                || (mSourceWindowId == AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
                || (AccessibilityNodeInfo.getAccessibilityViewId(mSourceNodeId)
                        == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)) {
            return null;
        }
        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
                mSourceNodeId, false, GET_SOURCE_PREFETCH_FLAGS, null);
    }

    /**
     * Sets the window id.
@@ -647,7 +634,7 @@ public class AccessibilityRecord {
     * @hide
     */
    public long getSourceNodeId() {
        return mSourceNode != null ? mSourceNode.getSourceNodeId() : UNDEFINED;
        return mSourceNodeId;
    }

    /**
@@ -661,9 +648,6 @@ public class AccessibilityRecord {
    public void setConnectionId(int connectionId) {
        enforceNotSealed();
        mConnectionId = connectionId;
        if (mSourceNode != null) {
            mSourceNode.setConnectionId(mConnectionId);
        }
    }

    /**
@@ -675,9 +659,6 @@ public class AccessibilityRecord {
     */
    public void setSealed(boolean sealed) {
        mSealed = sealed;
        if (mSourceNode != null) {
            mSourceNode.setSealed(sealed);
        }
    }

    /**
@@ -816,9 +797,7 @@ public class AccessibilityRecord {
        mParcelableData = record.mParcelableData;
        mText.addAll(record.mText);
        mSourceWindowId = record.mSourceWindowId;
        if (record.mSourceNode != null) {
            mSourceNode = AccessibilityNodeInfo.obtain(record.mSourceNode);
        }
        mSourceNodeId = record.mSourceNodeId;
        mConnectionId = record.mConnectionId;
    }

@@ -843,19 +822,11 @@ public class AccessibilityRecord {
        mBeforeText = null;
        mParcelableData = null;
        mText.clear();
        clearSourceNode();
        mSourceWindowId = UNDEFINED;
        mSourceNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
        mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
        mConnectionId = UNDEFINED;
    }

    private void clearSourceNode() {
        if (mSourceNode != null) {
            mSourceNode.recycle();
            mSourceNode = null;
        }

    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
+2 −8
Original line number Diff line number Diff line
@@ -376,10 +376,7 @@ public class PipTouchHandler {
                if (!mSendingHoverAccessibilityEvents) {
                    AccessibilityEvent event = AccessibilityEvent.obtain(
                            AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
                    AccessibilityNodeInfo info =
                            PipAccessibilityInteractionConnection.obtainRootAccessibilityNodeInfo();
                    event.setSource(info);
                    info.recycle();
                    event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
                    mAccessibilityManager.sendAccessibilityEvent(event);
                    mSendingHoverAccessibilityEvents = true;
                }
@@ -389,10 +386,7 @@ public class PipTouchHandler {
                if (mSendingHoverAccessibilityEvents) {
                    AccessibilityEvent event = AccessibilityEvent.obtain(
                            AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
                    AccessibilityNodeInfo info =
                            PipAccessibilityInteractionConnection.obtainRootAccessibilityNodeInfo();
                    event.setSource(info);
                    info.recycle();
                    event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
                    mAccessibilityManager.sendAccessibilityEvent(event);
                    mSendingHoverAccessibilityEvents = false;
                }
+0 −9
Original line number Diff line number Diff line
@@ -487,15 +487,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                if (pip != null) {
                    int pipId = pip.getId();
                    event.setWindowId(pipId);
                    event.setSealed(true);
                    AccessibilityNodeInfo info = event.getSource();
                    info.setSealed(false);
                    event.setSealed(false);
                    if (info != null) {
                        info.setSourceNodeId(info.getSourceNodeId(), pipId);
                        event.setSource(info);
                        info.recycle();
                    }
                }
            }