Loading core/java/android/view/accessibility/AccessibilityNodeInfo.java +11 −11 Original line number Diff line number Diff line Loading @@ -3333,7 +3333,7 @@ public class AccessibilityNodeInfo implements Parcelable { final int actionCount = mActions.size(); int nonStandardActionCount = 0; int defaultStandardActions = 0; long defaultStandardActions = 0; for (int i = 0; i < actionCount; i++) { AccessibilityAction action = mActions.get(i); if (isDefaultStandardAction(action)) { Loading @@ -3342,7 +3342,7 @@ public class AccessibilityNodeInfo implements Parcelable { nonStandardActionCount++; } } parcel.writeInt(defaultStandardActions); parcel.writeLong(defaultStandardActions); parcel.writeInt(nonStandardActionCount); for (int i = 0; i < actionCount; i++) { Loading @@ -3353,7 +3353,7 @@ public class AccessibilityNodeInfo implements Parcelable { } } } else { parcel.writeInt(0); parcel.writeLong(0); parcel.writeInt(0); } } Loading Loading @@ -3540,7 +3540,7 @@ public class AccessibilityNodeInfo implements Parcelable { } if (isBitSet(nonDefaultFields, fieldIndex++)) { final int standardActions = parcel.readInt(); final long standardActions = parcel.readLong(); addStandardActions(standardActions); final int nonStandardActionCount = parcel.readInt(); for (int i = 0; i < nonStandardActionCount; i++) { Loading Loading @@ -3621,7 +3621,7 @@ public class AccessibilityNodeInfo implements Parcelable { } 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) { Loading @@ -3636,7 +3636,7 @@ public class AccessibilityNodeInfo implements Parcelable { return null; } private static AccessibilityAction getActionSingletonBySerializationFlag(int flag) { private static AccessibilityAction getActionSingletonBySerializationFlag(long flag) { final int actions = AccessibilityAction.sStandardActions.size(); for (int i = 0; i < actions; i++) { AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i); Loading @@ -3648,10 +3648,10 @@ public class AccessibilityNodeInfo implements Parcelable { return null; } private void addStandardActions(int serializationIdMask) { int remainingIds = serializationIdMask; private void addStandardActions(long serializationIdMask) { long remainingIds = serializationIdMask; while (remainingIds > 0) { final int id = 1 << Integer.numberOfTrailingZeros(remainingIds); final long id = 1L << Long.numberOfTrailingZeros(remainingIds); remainingIds &= ~id; AccessibilityAction action = getActionSingletonBySerializationFlag(id); addAction(action); Loading Loading @@ -4276,7 +4276,7 @@ public class AccessibilityNodeInfo implements Parcelable { private final CharSequence mLabel; /** @hide */ public int mSerializationFlag = -1; public long mSerializationFlag = -1L; /** * Creates a new AccessibilityAction. For adding a standard action without a specific label, Loading Loading @@ -4310,7 +4310,7 @@ public class AccessibilityNodeInfo implements Parcelable { private AccessibilityAction(int standardActionId) { this(standardActionId, null); mSerializationFlag = (int) bitAt(sStandardActions.size()); mSerializationFlag = bitAt(sStandardActions.size()); sStandardActions.add(this); } Loading core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java +40 −3 Original line number Diff line number Diff line Loading @@ -16,8 +16,13 @@ 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 android.os.Parcel; import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; import android.util.ArraySet; Loading @@ -38,10 +43,10 @@ public class AccessibilityNodeInfoTest { public void testStandardActions_serializationFlagIsValid() { AccessibilityAction brokenStandardAction = CollectionUtils.find( new ArrayList<>(AccessibilityAction.sStandardActions), action -> Integer.bitCount(action.mSerializationFlag) != 1); action -> Long.bitCount(action.mSerializationFlag) != 1); if (brokenStandardAction != null) { String message = "Invalid serialization flag(0x" + Integer.toHexString(brokenStandardAction.mSerializationFlag) + Long.toHexString(brokenStandardAction.mSerializationFlag) + ") in " + brokenStandardAction; if (brokenStandardAction.mSerializationFlag == 0L) { message += "\nThis is likely due to an overflow"; Loading @@ -56,7 +61,7 @@ public class AccessibilityNodeInfoTest { && action.getId() != action.mSerializationFlag); if (brokenStandardAction != null) { fail("Serialization flag(0x" + Integer.toHexString(brokenStandardAction.mSerializationFlag) + Long.toHexString(brokenStandardAction.mSerializationFlag) + ") is different from legacy action id(0x" + Integer.toHexString(brokenStandardAction.getId()) + ") in " + brokenStandardAction); Loading @@ -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)); } } Loading
core/java/android/view/accessibility/AccessibilityNodeInfo.java +11 −11 Original line number Diff line number Diff line Loading @@ -3333,7 +3333,7 @@ public class AccessibilityNodeInfo implements Parcelable { final int actionCount = mActions.size(); int nonStandardActionCount = 0; int defaultStandardActions = 0; long defaultStandardActions = 0; for (int i = 0; i < actionCount; i++) { AccessibilityAction action = mActions.get(i); if (isDefaultStandardAction(action)) { Loading @@ -3342,7 +3342,7 @@ public class AccessibilityNodeInfo implements Parcelable { nonStandardActionCount++; } } parcel.writeInt(defaultStandardActions); parcel.writeLong(defaultStandardActions); parcel.writeInt(nonStandardActionCount); for (int i = 0; i < actionCount; i++) { Loading @@ -3353,7 +3353,7 @@ public class AccessibilityNodeInfo implements Parcelable { } } } else { parcel.writeInt(0); parcel.writeLong(0); parcel.writeInt(0); } } Loading Loading @@ -3540,7 +3540,7 @@ public class AccessibilityNodeInfo implements Parcelable { } if (isBitSet(nonDefaultFields, fieldIndex++)) { final int standardActions = parcel.readInt(); final long standardActions = parcel.readLong(); addStandardActions(standardActions); final int nonStandardActionCount = parcel.readInt(); for (int i = 0; i < nonStandardActionCount; i++) { Loading Loading @@ -3621,7 +3621,7 @@ public class AccessibilityNodeInfo implements Parcelable { } 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) { Loading @@ -3636,7 +3636,7 @@ public class AccessibilityNodeInfo implements Parcelable { return null; } private static AccessibilityAction getActionSingletonBySerializationFlag(int flag) { private static AccessibilityAction getActionSingletonBySerializationFlag(long flag) { final int actions = AccessibilityAction.sStandardActions.size(); for (int i = 0; i < actions; i++) { AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i); Loading @@ -3648,10 +3648,10 @@ public class AccessibilityNodeInfo implements Parcelable { return null; } private void addStandardActions(int serializationIdMask) { int remainingIds = serializationIdMask; private void addStandardActions(long serializationIdMask) { long remainingIds = serializationIdMask; while (remainingIds > 0) { final int id = 1 << Integer.numberOfTrailingZeros(remainingIds); final long id = 1L << Long.numberOfTrailingZeros(remainingIds); remainingIds &= ~id; AccessibilityAction action = getActionSingletonBySerializationFlag(id); addAction(action); Loading Loading @@ -4276,7 +4276,7 @@ public class AccessibilityNodeInfo implements Parcelable { private final CharSequence mLabel; /** @hide */ public int mSerializationFlag = -1; public long mSerializationFlag = -1L; /** * Creates a new AccessibilityAction. For adding a standard action without a specific label, Loading Loading @@ -4310,7 +4310,7 @@ public class AccessibilityNodeInfo implements Parcelable { private AccessibilityAction(int standardActionId) { this(standardActionId, null); mSerializationFlag = (int) bitAt(sStandardActions.size()); mSerializationFlag = bitAt(sStandardActions.size()); sStandardActions.add(this); } Loading
core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java +40 −3 Original line number Diff line number Diff line Loading @@ -16,8 +16,13 @@ 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 android.os.Parcel; import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; import android.util.ArraySet; Loading @@ -38,10 +43,10 @@ public class AccessibilityNodeInfoTest { public void testStandardActions_serializationFlagIsValid() { AccessibilityAction brokenStandardAction = CollectionUtils.find( new ArrayList<>(AccessibilityAction.sStandardActions), action -> Integer.bitCount(action.mSerializationFlag) != 1); action -> Long.bitCount(action.mSerializationFlag) != 1); if (brokenStandardAction != null) { String message = "Invalid serialization flag(0x" + Integer.toHexString(brokenStandardAction.mSerializationFlag) + Long.toHexString(brokenStandardAction.mSerializationFlag) + ") in " + brokenStandardAction; if (brokenStandardAction.mSerializationFlag == 0L) { message += "\nThis is likely due to an overflow"; Loading @@ -56,7 +61,7 @@ public class AccessibilityNodeInfoTest { && action.getId() != action.mSerializationFlag); if (brokenStandardAction != null) { fail("Serialization flag(0x" + Integer.toHexString(brokenStandardAction.mSerializationFlag) + Long.toHexString(brokenStandardAction.mSerializationFlag) + ") is different from legacy action id(0x" + Integer.toHexString(brokenStandardAction.getId()) + ") in " + brokenStandardAction); Loading @@ -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)); } }