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

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

Merge "Fix accessibility action parceling" into pi-dev

am: fc0c8d9b

Change-Id: Ia8ef042191e3e1abbb4a45d2c31f41cbb802edab
parents 38318635 fc0c8d9b
Loading
Loading
Loading
Loading
+11 −11
Original line number Original line Diff line number Diff line
@@ -3333,7 +3333,7 @@ public class AccessibilityNodeInfo implements Parcelable {
                final int actionCount = mActions.size();
                final int actionCount = mActions.size();


                int nonStandardActionCount = 0;
                int nonStandardActionCount = 0;
                int defaultStandardActions = 0;
                long defaultStandardActions = 0;
                for (int i = 0; i < actionCount; i++) {
                for (int i = 0; i < actionCount; i++) {
                    AccessibilityAction action = mActions.get(i);
                    AccessibilityAction action = mActions.get(i);
                    if (isDefaultStandardAction(action)) {
                    if (isDefaultStandardAction(action)) {
@@ -3342,7 +3342,7 @@ public class AccessibilityNodeInfo implements Parcelable {
                        nonStandardActionCount++;
                        nonStandardActionCount++;
                    }
                    }
                }
                }
                parcel.writeInt(defaultStandardActions);
                parcel.writeLong(defaultStandardActions);


                parcel.writeInt(nonStandardActionCount);
                parcel.writeInt(nonStandardActionCount);
                for (int i = 0; i < actionCount; i++) {
                for (int i = 0; i < actionCount; i++) {
@@ -3353,7 +3353,7 @@ public class AccessibilityNodeInfo implements Parcelable {
                    }
                    }
                }
                }
            } else {
            } else {
                parcel.writeInt(0);
                parcel.writeLong(0);
                parcel.writeInt(0);
                parcel.writeInt(0);
            }
            }
        }
        }
@@ -3540,7 +3540,7 @@ public class AccessibilityNodeInfo implements Parcelable {
        }
        }


        if (isBitSet(nonDefaultFields, fieldIndex++)) {
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            final int standardActions = parcel.readInt();
            final long standardActions = parcel.readLong();
            addStandardActions(standardActions);
            addStandardActions(standardActions);
            final int nonStandardActionCount = parcel.readInt();
            final int nonStandardActionCount = parcel.readInt();
            for (int i = 0; i < nonStandardActionCount; i++) {
            for (int i = 0; i < nonStandardActionCount; i++) {
@@ -3621,7 +3621,7 @@ public class AccessibilityNodeInfo implements Parcelable {
    }
    }


    private static boolean isDefaultStandardAction(AccessibilityAction action) {
    private static boolean isDefaultStandardAction(AccessibilityAction action) {
        return action.mSerializationFlag != -1 && TextUtils.isEmpty(action.getLabel());
        return (action.mSerializationFlag != -1L) && TextUtils.isEmpty(action.getLabel());
    }
    }


    private static AccessibilityAction getActionSingleton(int actionId) {
    private static AccessibilityAction getActionSingleton(int actionId) {
@@ -3636,7 +3636,7 @@ public class AccessibilityNodeInfo implements Parcelable {
        return null;
        return null;
    }
    }


    private static AccessibilityAction getActionSingletonBySerializationFlag(int flag) {
    private static AccessibilityAction getActionSingletonBySerializationFlag(long flag) {
        final int actions = AccessibilityAction.sStandardActions.size();
        final int actions = AccessibilityAction.sStandardActions.size();
        for (int i = 0; i < actions; i++) {
        for (int i = 0; i < actions; i++) {
            AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
            AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
@@ -3648,10 +3648,10 @@ public class AccessibilityNodeInfo implements Parcelable {
        return null;
        return null;
    }
    }


    private void addStandardActions(int serializationIdMask) {
    private void addStandardActions(long serializationIdMask) {
        int remainingIds = serializationIdMask;
        long remainingIds = serializationIdMask;
        while (remainingIds > 0) {
        while (remainingIds > 0) {
            final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
            final long id = 1L << Long.numberOfTrailingZeros(remainingIds);
            remainingIds &= ~id;
            remainingIds &= ~id;
            AccessibilityAction action = getActionSingletonBySerializationFlag(id);
            AccessibilityAction action = getActionSingletonBySerializationFlag(id);
            addAction(action);
            addAction(action);
@@ -4276,7 +4276,7 @@ public class AccessibilityNodeInfo implements Parcelable {
        private final CharSequence mLabel;
        private final CharSequence mLabel;


        /** @hide */
        /** @hide */
        public int mSerializationFlag = -1;
        public long mSerializationFlag = -1L;


        /**
        /**
         * Creates a new AccessibilityAction. For adding a standard action without a specific label,
         * Creates a new AccessibilityAction. For adding a standard action without a specific label,
@@ -4310,7 +4310,7 @@ public class AccessibilityNodeInfo implements Parcelable {
        private AccessibilityAction(int standardActionId) {
        private AccessibilityAction(int standardActionId) {
            this(standardActionId, null);
            this(standardActionId, null);


            mSerializationFlag = (int) bitAt(sStandardActions.size());
            mSerializationFlag = bitAt(sStandardActions.size());
            sStandardActions.add(this);
            sStandardActions.add(this);
        }
        }


+40 −3
Original line number Original line Diff line number Diff line
@@ -16,8 +16,13 @@


package android.view.accessibility;
package android.view.accessibility;


import static org.hamcrest.Matchers.emptyCollectionOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assert.fail;


import android.os.Parcel;
import android.support.test.filters.LargeTest;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.AndroidJUnit4;
import android.util.ArraySet;
import android.util.ArraySet;
@@ -38,10 +43,10 @@ public class AccessibilityNodeInfoTest {
    public void testStandardActions_serializationFlagIsValid() {
    public void testStandardActions_serializationFlagIsValid() {
        AccessibilityAction brokenStandardAction = CollectionUtils.find(
        AccessibilityAction brokenStandardAction = CollectionUtils.find(
                new ArrayList<>(AccessibilityAction.sStandardActions),
                new ArrayList<>(AccessibilityAction.sStandardActions),
                action -> Integer.bitCount(action.mSerializationFlag) != 1);
                action -> Long.bitCount(action.mSerializationFlag) != 1);
        if (brokenStandardAction != null) {
        if (brokenStandardAction != null) {
            String message = "Invalid serialization flag(0x"
            String message = "Invalid serialization flag(0x"
                    + Integer.toHexString(brokenStandardAction.mSerializationFlag)
                    + Long.toHexString(brokenStandardAction.mSerializationFlag)
                    + ") in " + brokenStandardAction;
                    + ") in " + brokenStandardAction;
            if (brokenStandardAction.mSerializationFlag == 0L) {
            if (brokenStandardAction.mSerializationFlag == 0L) {
                message += "\nThis is likely due to an overflow";
                message += "\nThis is likely due to an overflow";
@@ -56,7 +61,7 @@ public class AccessibilityNodeInfoTest {
                        && action.getId() != action.mSerializationFlag);
                        && action.getId() != action.mSerializationFlag);
        if (brokenStandardAction != null) {
        if (brokenStandardAction != null) {
            fail("Serialization flag(0x"
            fail("Serialization flag(0x"
                    + Integer.toHexString(brokenStandardAction.mSerializationFlag)
                    + Long.toHexString(brokenStandardAction.mSerializationFlag)
                    + ") is different from legacy action id(0x"
                    + ") is different from legacy action id(0x"
                    + Integer.toHexString(brokenStandardAction.getId())
                    + Integer.toHexString(brokenStandardAction.getId())
                    + ") in " + brokenStandardAction);
                    + ") in " + brokenStandardAction);
@@ -77,4 +82,36 @@ public class AccessibilityNodeInfoTest {
        }
        }
    }
    }


    @Test
    public void testStandardActions_allComeThroughParceling() {
        for (AccessibilityAction action : AccessibilityAction.sStandardActions) {
            final AccessibilityNodeInfo nodeWithAction = AccessibilityNodeInfo.obtain();
            nodeWithAction.addAction(action);
            assertThat(nodeWithAction.getActionList(), hasItem(action));
            final Parcel parcel = Parcel.obtain();
            nodeWithAction.writeToParcel(parcel, 0);
            parcel.setDataPosition(0);
            final AccessibilityNodeInfo unparceledNode =
                    AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
            assertThat(unparceledNode.getActionList(), hasItem(action));
        }
    }

    @Test
    public void testEmptyListOfActions_parcelsCorrectly() {
        // Also set text, as if there's nothing else in the parcel it can unparcel even with
        // a bug present.
        final String text = "text";
        final AccessibilityNodeInfo nodeWithEmptyActionList = AccessibilityNodeInfo.obtain();
        nodeWithEmptyActionList.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
        nodeWithEmptyActionList.removeAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
        nodeWithEmptyActionList.setText(text);
        final Parcel parcel = Parcel.obtain();
        nodeWithEmptyActionList.writeToParcel(parcel, 0);
        parcel.setDataPosition(0);
        final AccessibilityNodeInfo unparceledNode =
                AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
        assertThat(unparceledNode.getActionList(), emptyCollectionOf(AccessibilityAction.class));
        assertThat(unparceledNode.getText(), equalTo(text));
    }
}
}