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

Commit 0eb2b6e5 authored by Eugene Susla's avatar Eugene Susla
Browse files

Avoid marshalling default-valued fields

Test: 1. AccessibilityNodeInfoTest#testMarshaling
2. Hack the check from the above test to run on each parcel, then turn on
TalkBack and ensure to system crashes and stack traces in logcat
3. A11y CTS: CtsAccessibilityServiceTestCases, CtsAccessibilityTestCases,
CtsUiAutomationTestCases
Bug: 33949542

Change-Id: I2cef9fcef9d6f84334614b0e81c6717484ef3436
parent 957bdf0e
Loading
Loading
Loading
Loading
+310 −235
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.view.accessibility;

import static com.android.internal.util.BitUtils.bitAt;
import static com.android.internal.util.BitUtils.isBitSet;

import static java.util.Collections.EMPTY_LIST;

import android.accessibilityservice.AccessibilityService;
@@ -41,10 +44,12 @@ import android.util.Pools.SynchronizedPool;
import android.view.View;

import com.android.internal.R;
import com.android.internal.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
@@ -636,7 +641,6 @@ public class AccessibilityNodeInfo implements Parcelable {
     * Bits that provide the id of a virtual descendant of a view.
     */
    private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;

    /**
     * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
     * virtual descendant of a view. Such a descendant does not exist in the view
@@ -692,6 +696,8 @@ public class AccessibilityNodeInfo implements Parcelable {
    private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
            new SynchronizedPool<>(MAX_POOL_SIZE);

    private static final AccessibilityNodeInfo DEFAULT = new AccessibilityNodeInfo();

    private boolean mSealed;

    // Data.
@@ -1068,11 +1074,7 @@ public class AccessibilityNodeInfo implements Parcelable {
     * Gets the actions that can be performed on the node.
     */
    public List<AccessibilityAction> getActionList() {
        if (mActions == null) {
            return Collections.emptyList();
        }

        return mActions;
        return CollectionUtils.emptyIfNull(mActions);
    }

    /**
@@ -3050,17 +3052,118 @@ public class AccessibilityNodeInfo implements Parcelable {
     */
    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(isSealed() ? 1 : 0);
        parcel.writeLong(mSourceNodeId);
        parcel.writeInt(mWindowId);
        parcel.writeLong(mParentNodeId);
        parcel.writeLong(mLabelForId);
        parcel.writeLong(mLabeledById);
        parcel.writeLong(mTraversalBefore);
        parcel.writeLong(mTraversalAfter);

        parcel.writeInt(mConnectionId);

        // Write bit set of indices of fields with values differing from default
        long nonDefaultFields = 0;
        int fieldIndex = 0; // index of the current field
        if (isSealed() != DEFAULT.isSealed()) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mSourceNodeId != DEFAULT.mSourceNodeId) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mWindowId != DEFAULT.mWindowId) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mParentNodeId != DEFAULT.mParentNodeId) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mLabelForId != DEFAULT.mLabelForId) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mLabeledById != DEFAULT.mLabeledById) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mTraversalBefore != DEFAULT.mTraversalBefore) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mTraversalAfter != DEFAULT.mTraversalAfter) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mConnectionId != DEFAULT.mConnectionId) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (!Objects.equals(mChildNodeIds, DEFAULT.mChildNodeIds)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mBoundsInParent, DEFAULT.mBoundsInParent)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mBoundsInScreen, DEFAULT.mBoundsInScreen)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mActions, DEFAULT.mActions)) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mMaxTextLength != DEFAULT.mMaxTextLength) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mMovementGranularities != DEFAULT.mMovementGranularities) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (mBooleanProperties != DEFAULT.mBooleanProperties) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (!Objects.equals(mPackageName, DEFAULT.mPackageName)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mClassName, DEFAULT.mClassName)) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (!Objects.equals(mText, DEFAULT.mText)) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (!Objects.equals(mHintText, DEFAULT.mHintText)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mError, DEFAULT.mError)) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (!Objects.equals(mContentDescription, DEFAULT.mContentDescription)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mViewIdResourceName, DEFAULT.mViewIdResourceName)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (mTextSelectionStart != DEFAULT.mTextSelectionStart) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (mTextSelectionEnd != DEFAULT.mTextSelectionEnd) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (mInputType != DEFAULT.mInputType) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mLiveRegion != DEFAULT.mLiveRegion) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (mDrawingOrderInParent != DEFAULT.mDrawingOrderInParent) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mExtraDataKeys, DEFAULT.mExtraDataKeys)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mExtras, DEFAULT.mExtras)) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (!Objects.equals(mRangeInfo, DEFAULT.mRangeInfo)) nonDefaultFields |= bitAt(fieldIndex);
        fieldIndex++;
        if (!Objects.equals(mCollectionInfo, DEFAULT.mCollectionInfo)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mCollectionItemInfo, DEFAULT.mCollectionItemInfo)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        int totalFields = fieldIndex;
        parcel.writeLong(nonDefaultFields);

        fieldIndex = 0;
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(isSealed() ? 1 : 0);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mSourceNodeId);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mWindowId);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mParentNodeId);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabelForId);
        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(mConnectionId);

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            final LongArray childIds = mChildNodeIds;
            if (childIds == null) {
                parcel.writeInt(0);
@@ -3071,17 +3174,23 @@ public class AccessibilityNodeInfo implements Parcelable {
                    parcel.writeLong(childIds.get(i));
                }
            }
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeInt(mBoundsInParent.top);
            parcel.writeInt(mBoundsInParent.bottom);
            parcel.writeInt(mBoundsInParent.left);
            parcel.writeInt(mBoundsInParent.right);
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeInt(mBoundsInScreen.top);
            parcel.writeInt(mBoundsInScreen.bottom);
            parcel.writeInt(mBoundsInScreen.left);
            parcel.writeInt(mBoundsInScreen.right);
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            if (mActions != null && !mActions.isEmpty()) {
                final int actionCount = mActions.size();

@@ -3109,68 +3218,61 @@ public class AccessibilityNodeInfo implements Parcelable {
                parcel.writeInt(0);
                parcel.writeInt(0);
            }
        }

        parcel.writeInt(mMaxTextLength);
        parcel.writeInt(mMovementGranularities);
        parcel.writeInt(mBooleanProperties);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMaxTextLength);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMovementGranularities);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mBooleanProperties);

        parcel.writeCharSequence(mPackageName);
        parcel.writeCharSequence(mClassName);
        parcel.writeCharSequence(mText);
        parcel.writeCharSequence(mHintText);
        parcel.writeCharSequence(mError);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPackageName);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mClassName);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mText);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mHintText);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mError);
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeCharSequence(mContentDescription);
        parcel.writeString(mViewIdResourceName);

        parcel.writeInt(mTextSelectionStart);
        parcel.writeInt(mTextSelectionEnd);
        parcel.writeInt(mInputType);
        parcel.writeInt(mLiveRegion);
        parcel.writeInt(mDrawingOrderInParent);
        if (mExtraDataKeys != null) {
            parcel.writeInt(1);
            parcel.writeStringList(mExtraDataKeys);
        } else {
            parcel.writeInt(0);
        }
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeString(mViewIdResourceName);

        if (mExtras != null) {
            parcel.writeInt(1);
            parcel.writeBundle(mExtras);
        } else {
            parcel.writeInt(0);
        }
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionStart);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionEnd);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mInputType);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mLiveRegion);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mDrawingOrderInParent);

        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeStringList(mExtraDataKeys);

        if (mRangeInfo != null) {
            parcel.writeInt(1);
        if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeBundle(mExtras);

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeInt(mRangeInfo.getType());
            parcel.writeFloat(mRangeInfo.getMin());
            parcel.writeFloat(mRangeInfo.getMax());
            parcel.writeFloat(mRangeInfo.getCurrent());
        } else {
            parcel.writeInt(0);
        }

        if (mCollectionInfo != null) {
            parcel.writeInt(1);
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeInt(mCollectionInfo.getRowCount());
            parcel.writeInt(mCollectionInfo.getColumnCount());
            parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
            parcel.writeInt(mCollectionInfo.getSelectionMode());
        } else {
            parcel.writeInt(0);
        }

        if (mCollectionItemInfo != null) {
            parcel.writeInt(1);
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeInt(mCollectionItemInfo.getRowIndex());
            parcel.writeInt(mCollectionItemInfo.getRowSpan());
            parcel.writeInt(mCollectionItemInfo.getColumnIndex());
            parcel.writeInt(mCollectionItemInfo.getColumnSpan());
            parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
            parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
        } else {
            parcel.writeInt(0);
        }

        if (DEBUG) {
            fieldIndex--;
            if (totalFields != fieldIndex) {
                throw new IllegalStateException("Number of fields mismatch: " + totalFields
                        + " vs " + fieldIndex);
            }
        }

        // Since instances of this class are fetched via synchronous i.e. blocking
@@ -3203,12 +3305,12 @@ public class AccessibilityNodeInfo implements Parcelable {
        mContentDescription = other.mContentDescription;
        mViewIdResourceName = other.mViewIdResourceName;

        if (mActions != null) mActions.clear();
        final ArrayList<AccessibilityAction> otherActions = other.mActions;
        if (otherActions != null && otherActions.size() > 0) {
            if (mActions == null) {
                mActions = new ArrayList(otherActions);
            } else {
                mActions.clear();
                mActions.addAll(other.mActions);
            }
        }
@@ -3217,12 +3319,13 @@ public class AccessibilityNodeInfo implements Parcelable {
        mMaxTextLength = other.mMaxTextLength;
        mMovementGranularities = other.mMovementGranularities;


        if (mChildNodeIds != null) mChildNodeIds.clear();
        final LongArray otherChildNodeIds = other.mChildNodeIds;
        if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) {
            if (mChildNodeIds == null) {
                mChildNodeIds = otherChildNodeIds.clone();
            } else {
                mChildNodeIds.clear();
                mChildNodeIds.addAll(otherChildNodeIds);
            }
        }
@@ -3232,17 +3335,18 @@ public class AccessibilityNodeInfo implements Parcelable {
        mInputType = other.mInputType;
        mLiveRegion = other.mLiveRegion;
        mDrawingOrderInParent = other.mDrawingOrderInParent;

        mExtraDataKeys = other.mExtraDataKeys;

        if (other.mExtras != null) {
            mExtras = new Bundle(other.mExtras);
        } else {
            mExtras = null;
        }
        mExtras = other.mExtras != null ? new Bundle(other.mExtras) : null;

        if (mRangeInfo != null) mRangeInfo.recycle();
        mRangeInfo = (other.mRangeInfo != null)
                ? RangeInfo.obtain(other.mRangeInfo) : null;
        if (mCollectionInfo != null) mCollectionInfo.recycle();
        mCollectionInfo = (other.mCollectionInfo != null)
                ? CollectionInfo.obtain(other.mCollectionInfo) : null;
        if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
        mCollectionItemInfo =  (other.mCollectionItemInfo != null)
                ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
    }
@@ -3253,17 +3357,23 @@ public class AccessibilityNodeInfo implements Parcelable {
     * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
     */
    private void initFromParcel(Parcel parcel) {
        final boolean sealed = (parcel.readInt()  == 1);
        mSourceNodeId = parcel.readLong();
        mWindowId = parcel.readInt();
        mParentNodeId = parcel.readLong();
        mLabelForId = parcel.readLong();
        mLabeledById = parcel.readLong();
        mTraversalBefore = parcel.readLong();
        mTraversalAfter = parcel.readLong();

        mConnectionId = parcel.readInt();

        // Bit mask of non-default-valued field indices
        long nonDefaultFields = parcel.readLong();
        int fieldIndex = 0;
        final boolean sealed = isBitSet(nonDefaultFields, fieldIndex++)
                ? (parcel.readInt() == 1)
                : DEFAULT.mSealed;
        if (isBitSet(nonDefaultFields, fieldIndex++)) mSourceNodeId = parcel.readLong();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mWindowId = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mParentNodeId = parcel.readLong();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mLabelForId = parcel.readLong();
        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++)) mConnectionId = parcel.readInt();

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            final int childrenSize = parcel.readInt();
            if (childrenSize <= 0) {
                mChildNodeIds = null;
@@ -3274,17 +3384,23 @@ public class AccessibilityNodeInfo implements Parcelable {
                    mChildNodeIds.add(childId);
                }
            }
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            mBoundsInParent.top = parcel.readInt();
            mBoundsInParent.bottom = parcel.readInt();
            mBoundsInParent.left = parcel.readInt();
            mBoundsInParent.right = parcel.readInt();
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            mBoundsInScreen.top = parcel.readInt();
            mBoundsInScreen.bottom = parcel.readInt();
            mBoundsInScreen.left = parcel.readInt();
            mBoundsInScreen.right = parcel.readInt();
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            final int legacyStandardActions = parcel.readInt();
            addLegacyStandardActions(legacyStandardActions);
            final int nonLegacyActionCount = parcel.readInt();
@@ -3293,63 +3409,65 @@ public class AccessibilityNodeInfo implements Parcelable {
                        parcel.readInt(), parcel.readCharSequence());
                addActionUnchecked(action);
            }
        }

        mMaxTextLength = parcel.readInt();
        mMovementGranularities = parcel.readInt();
        mBooleanProperties = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mMaxTextLength = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mMovementGranularities = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mBooleanProperties = parcel.readInt();

        mPackageName = parcel.readCharSequence();
        mClassName = parcel.readCharSequence();
        mText = parcel.readCharSequence();
        mHintText = parcel.readCharSequence();
        mError = parcel.readCharSequence();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mPackageName = parcel.readCharSequence();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mClassName = parcel.readCharSequence();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mText = parcel.readCharSequence();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mHintText = parcel.readCharSequence();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mError = parcel.readCharSequence();
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            mContentDescription = parcel.readCharSequence();
        mViewIdResourceName = parcel.readString();
        }
        if (isBitSet(nonDefaultFields, fieldIndex++)) mViewIdResourceName = parcel.readString();

        mTextSelectionStart = parcel.readInt();
        mTextSelectionEnd = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionStart = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionEnd = parcel.readInt();

        mInputType = parcel.readInt();
        mLiveRegion = parcel.readInt();
        mDrawingOrderInParent = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mInputType = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mLiveRegion = parcel.readInt();
        if (isBitSet(nonDefaultFields, fieldIndex++)) mDrawingOrderInParent = parcel.readInt();

        if (parcel.readInt() == 1) {
            mExtraDataKeys = parcel.createStringArrayList();
        } else {
            mExtraDataKeys = null;
        }
        mExtraDataKeys = isBitSet(nonDefaultFields, fieldIndex++)
                ? parcel.createStringArrayList()
                : null;

        if (parcel.readInt() == 1) {
            mExtras = parcel.readBundle();
        } else {
            mExtras = null;
        }
        mExtras = isBitSet(nonDefaultFields, fieldIndex++)
                ? parcel.readBundle()
                : null;

        if (parcel.readInt() == 1) {
            mRangeInfo = RangeInfo.obtain(
        if (mRangeInfo != null) mRangeInfo.recycle();
        mRangeInfo = isBitSet(nonDefaultFields, fieldIndex++)
                ? RangeInfo.obtain(
                        parcel.readInt(),
                        parcel.readFloat(),
                        parcel.readFloat(),
                    parcel.readFloat());
        }
                        parcel.readFloat())
                : null;

        if (parcel.readInt() == 1) {
            mCollectionInfo = CollectionInfo.obtain(
        if (mCollectionInfo != null) mCollectionInfo.recycle();
        mCollectionInfo = isBitSet(nonDefaultFields, fieldIndex++)
                ? CollectionInfo.obtain(
                        parcel.readInt(),
                        parcel.readInt(),
                        parcel.readInt() == 1,
                    parcel.readInt());
        }
                        parcel.readInt())
                : null;

        if (parcel.readInt() == 1) {
            mCollectionItemInfo = CollectionItemInfo.obtain(
        if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
        mCollectionItemInfo = isBitSet(nonDefaultFields, fieldIndex++)
                ? CollectionItemInfo.obtain(
                        parcel.readInt(),
                        parcel.readInt(),
                        parcel.readInt(),
                        parcel.readInt(),
                        parcel.readInt() == 1,
                    parcel.readInt() == 1);
        }
                        parcel.readInt() == 1)
                : null;

        mSealed = sealed;
    }
@@ -3358,50 +3476,7 @@ public class AccessibilityNodeInfo implements Parcelable {
     * Clears the state of this instance.
     */
    private void clear() {
        mSealed = false;
        mSourceNodeId = UNDEFINED_NODE_ID;
        mParentNodeId = UNDEFINED_NODE_ID;
        mLabelForId = UNDEFINED_NODE_ID;
        mLabeledById = UNDEFINED_NODE_ID;
        mTraversalBefore = UNDEFINED_NODE_ID;
        mTraversalAfter = UNDEFINED_NODE_ID;
        mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
        mConnectionId = UNDEFINED_CONNECTION_ID;
        mMaxTextLength = -1;
        mMovementGranularities = 0;
        if (mChildNodeIds != null) {
            mChildNodeIds.clear();
        }
        mBoundsInParent.set(0, 0, 0, 0);
        mBoundsInScreen.set(0, 0, 0, 0);
        mBooleanProperties = 0;
        mDrawingOrderInParent = 0;
        mExtraDataKeys = null;
        mPackageName = null;
        mClassName = null;
        mText = null;
        mHintText = null;
        mError = null;
        mContentDescription = null;
        mViewIdResourceName = null;
        removeAllActions();
        mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
        mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
        mInputType = InputType.TYPE_NULL;
        mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
        mExtras = null;
        if (mRangeInfo != null) {
            mRangeInfo.recycle();
            mRangeInfo = null;
        }
        if (mCollectionInfo != null) {
            mCollectionInfo.recycle();
            mCollectionInfo = null;
        }
        if (mCollectionItemInfo != null) {
            mCollectionItemInfo.recycle();
            mCollectionItemInfo = null;
        }
        init(DEFAULT);
    }

    private static boolean isDefaultLegacyStandardAction(AccessibilityAction action) {
+8 −0
Original line number Diff line number Diff line
@@ -124,4 +124,12 @@ public final class BitUtils {
        buffer.put(bytes);
        buffer.position(original);
    }

    public static boolean isBitSet(long flags, int bitIndex) {
        return (flags & bitAt(bitIndex)) != 0;
    }

    public static long bitAt(int bitIndex) {
        return 1L << bitIndex;
    }
}