blob: 3b56fb540deb25f368bfab461122216e15b7038e [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view.accessibility.cts;
import static androidx.test.InstrumentationRegistry.getContext;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
import android.os.Bundle;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.text.InputType;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.text.style.ReplacementSpan;
import android.util.ArrayMap;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
import android.view.accessibility.AccessibilityNodeInfo.RangeInfo;
import android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Class for testing {@link AccessibilityNodeInfo}.
*/
@Presubmit
@RunWith(AndroidJUnit4.class)
public class AccessibilityNodeInfoTest {
@Rule
public final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
new AccessibilityDumpOnFailureRule();
@SmallTest
@Test
public void testMarshaling() throws Exception {
// fully populate the node info to marshal
AccessibilityNodeInfo sentInfo = AccessibilityNodeInfo.obtain(new View(getContext()));
fullyPopulateAccessibilityNodeInfo(sentInfo);
// marshal and unmarshal the node info
Parcel parcel = Parcel.obtain();
sentInfo.writeToParcelNoRecycle(parcel, 0);
parcel.setDataPosition(0);
AccessibilityNodeInfo receivedInfo = AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
// make sure all fields properly marshaled
assertEqualsAccessibilityNodeInfo(sentInfo, receivedInfo);
parcel.recycle();
}
/**
* Tests if {@link AccessibilityNodeInfo} are correctly constructed.
*/
@SmallTest
@Test
public void testConstructor() {
final View view = new View(getContext());
AccessibilityNodeInfo firstInfo = new AccessibilityNodeInfo(view);
AccessibilityNodeInfo secondInfo = new AccessibilityNodeInfo();
secondInfo.setSource(view);
assertEquals(firstInfo.getWindowId(), secondInfo.getWindowId());
assertEquals(firstInfo.getSourceNodeId(), secondInfo.getSourceNodeId());
firstInfo = new AccessibilityNodeInfo(view, /* virtualDescendantId */ 1);
secondInfo.setSource(view, /* virtualDescendantId */ 1);
assertEquals(firstInfo.getWindowId(), secondInfo.getWindowId());
assertEquals(firstInfo.getSourceNodeId(), secondInfo.getSourceNodeId());
}
/**
* Tests if {@link AccessibilityNodeInfo}s are properly reused.
*/
@SmallTest
@Test
public void testReuse() {
AccessibilityEvent firstInfo = AccessibilityEvent.obtain();
firstInfo.recycle();
AccessibilityEvent secondInfo = AccessibilityEvent.obtain();
assertSame("AccessibilityNodeInfo not properly reused", firstInfo, secondInfo);
}
/**
* Tests if {@link AccessibilityNodeInfo} are properly recycled.
*/
@SmallTest
@Test
public void testRecycle() {
// obtain and populate an node info
AccessibilityNodeInfo populatedInfo = AccessibilityNodeInfo.obtain();
fullyPopulateAccessibilityNodeInfo(populatedInfo);
// recycle and obtain the same recycled instance
populatedInfo.recycle();
AccessibilityNodeInfo recycledInfo = AccessibilityNodeInfo.obtain();
// check expectations
assertAccessibilityNodeInfoCleared(recycledInfo);
}
/**
* Tests whether the event describes its contents consistently.
*/
@SmallTest
@Test
public void testDescribeContents() {
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
assertSame("Accessibility node infos always return 0 for this method.", 0,
info.describeContents());
fullyPopulateAccessibilityNodeInfo(info);
assertSame("Accessibility node infos always return 0 for this method.", 0,
info.describeContents());
}
/**
* Tests whether accessibility actions are properly added.
*/
@SmallTest
@Test
public void testAddActions() {
List<AccessibilityAction> customActions = new ArrayList<AccessibilityAction>();
customActions.add(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
customActions.add(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
for (AccessibilityAction customAction : customActions) {
info.addAction(customAction);
}
assertSame(info.getActions(), (AccessibilityNodeInfo.ACTION_FOCUS
| AccessibilityNodeInfo.ACTION_CLEAR_FOCUS));
List<AccessibilityAction> allActions = new ArrayList<AccessibilityAction>();
allActions.add(AccessibilityAction.ACTION_CLEAR_FOCUS);
allActions.addAll(customActions);
assertEquals(info.getActionList(), allActions);
}
/**
* Tests whether we catch addition of an action with invalid id.
*/
@SmallTest
@Test
public void testCreateInvalidActionId() {
try {
new AccessibilityAction(3, null);
} catch (IllegalArgumentException iae) {
/* expected */
}
}
/**
* Tests whether accessibility actions are properly removed.
*/
@SmallTest
@Test
public void testRemoveActions() {
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
info.removeAction(AccessibilityNodeInfo.ACTION_FOCUS);
assertSame(info.getActions(), 0);
assertTrue(info.getActionList().isEmpty());
AccessibilityAction customFocus = new AccessibilityAction(
AccessibilityNodeInfo.ACTION_FOCUS, "Foo");
info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
info.addAction(customFocus);
assertSame(info.getActionList().size(), 1);
assertEquals(info.getActionList().get(0), customFocus);
assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
info.removeAction(customFocus);
assertSame(info.getActions(), 0);
assertTrue(info.getActionList().isEmpty());
}
/**
* While CharSequence is immutable, some classes implementing it are mutable. Make sure they
* can't change the object by changing the objects backing CharSequence
*/
@SmallTest
@Test
public void testChangeTextAfterSetting_shouldNotAffectInfo() {
final String originalText = "Cassowaries";
final String newText = "Hornbill";
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
StringBuffer updatingString = new StringBuffer(originalText);
info.setText(updatingString);
info.setError(updatingString);
info.setContentDescription(updatingString);
info.setStateDescription(updatingString);
updatingString.delete(0, updatingString.length());
updatingString.append(newText);
assertTrue(TextUtils.equals(originalText, info.getText()));
assertTrue(TextUtils.equals(originalText, info.getError()));
assertTrue(TextUtils.equals(originalText, info.getContentDescription()));
assertTrue(TextUtils.equals(originalText, info.getStateDescription()));
}
@SmallTest
@Test
public void testParcelTextImageSpans_haveSameContentDescriptions() {
final Bitmap bitmap = Bitmap.createBitmap(/* width= */10, /* height= */10,
Bitmap.Config.ARGB_8888);
final ImageSpan span1 = new ImageSpan(getContext(), bitmap);
span1.setContentDescription("Span1 contentDescription");
final ImageSpan span2 = new ImageSpan(getContext(), bitmap);
span2.setContentDescription("Span2 contentDescription");
final String testString = "test string%s";
final String replaceSpan1 = " ";
final String replaceSpan2 = "%s";
final Spannable stringWithSpans = new SpannableString(testString);
final int span1Start = testString.indexOf(replaceSpan1);
final int span1End = span1Start + replaceSpan1.length();
final int span2Start = testString.indexOf(replaceSpan2);
final int span2End = span2Start + replaceSpan2.length();
final AccessibilityNodeInfo sentInfo = AccessibilityNodeInfo.obtain();
final Parcel parcel = Parcel.obtain();
stringWithSpans.setSpan(span1, span1Start, span1End, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
stringWithSpans.setSpan(span2, span2Start, span2End, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
sentInfo.setText(stringWithSpans);
sentInfo.writeToParcelNoRecycle(parcel, 0);
parcel.setDataPosition(0);
final AccessibilityNodeInfo receivedInfo = AccessibilityNodeInfo.CREATOR.createFromParcel(
parcel);
final Spanned receivedString = (Spanned) receivedInfo.getText();
final ReplacementSpan[] actualSpans = receivedString.getSpans(0, receivedString.length(),
ReplacementSpan.class);
assertEquals(span1.getContentDescription(), actualSpans[0].getContentDescription());
assertEquals(span2.getContentDescription(), actualSpans[1].getContentDescription());
}
@SmallTest
@Test
public void testIsHeadingTakesOldApiIntoAccount() {
final AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
assertFalse(info.isHeading());
final CollectionItemInfo headingItemInfo = CollectionItemInfo.obtain(0, 1, 0, 1, true);
info.setCollectionItemInfo(headingItemInfo);
assertTrue(info.isHeading());
final CollectionItemInfo nonHeadingItemInfo = CollectionItemInfo.obtain(0, 1, 0, 1, false);
info.setCollectionItemInfo(nonHeadingItemInfo);
assertFalse(info.isHeading());
}
/**
* Fully populates the {@link AccessibilityNodeInfo} to marshal.
*
* @param info The node info to populate.
*/
private void fullyPopulateAccessibilityNodeInfo(AccessibilityNodeInfo info) {
// Populate 10 fields
info.setBoundsInParent(new Rect(1,1,1,1));
info.setBoundsInScreen(new Rect(2,2,2,2));
info.setClassName("foo.bar.baz.Class");
info.setContentDescription("content description");
info.setStateDescription("state description");
info.setTooltipText("tooltip");
info.setPackageName("foo.bar.baz");
// setText is 2 fields
info.setText("text");
info.setHintText("hint");
// 2 children = 1 field
info.addChild(new View(getContext()));
info.addChild(new View(getContext()), 1);
// Leashed child = 1 field
info.addChild(new MockBinder());
// 2 built-in actions and 2 custom actions, but all are in 1 field
info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
info.addAction(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
// Populate 10 fields
info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
info.setViewIdResourceName("foo.bar:id/baz");
info.setDrawingOrder(5);
info.setAvailableExtraData(
Arrays.asList(AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
info.setPaneTitle("Pane title");
info.setError("Error text");
info.setMaxTextLength(42);
// Text selection is 2 fields
info.setTextSelection(3, 7);
info.setLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
// Populate 11 fields
Bundle extras = info.getExtras();
extras.putBoolean("areCassowariesAwesome", true);
info.setInputType(InputType.TYPE_CLASS_TEXT);
info.setRangeInfo(RangeInfo.obtain(RangeInfo.RANGE_TYPE_FLOAT, 0.05f, 1.0f, 0.01f));
info.setCollectionInfo(
CollectionInfo.obtain(2, 2, true, CollectionInfo.SELECTION_MODE_MULTIPLE));
info.setCollectionItemInfo(CollectionItemInfo.obtain(1, 2, 3, 4, true, true));
info.setParent(new View(getContext()));
info.setSource(new View(getContext())); // Populates 2 fields: source and window id
info.setLeashedParent(new MockBinder(), 1); // Populates 2 fields
info.setTraversalBefore(new View(getContext()));
info.setTraversalAfter(new View(getContext()));
// Populate 3 fields
info.setLabeledBy(new View(getContext()));
info.setLabelFor(new View(getContext()));
populateTouchDelegateTargetMap(info);
// And Boolean properties are another field. Total is 38
// 10 Boolean properties
info.setCheckable(true);
info.setChecked(true);
info.setFocusable(true);
info.setFocused(true);
info.setSelected(true);
info.setClickable(true);
info.setLongClickable(true);
info.setEnabled(true);
info.setPassword(true);
info.setScrollable(true);
// 10 Boolean properties
info.setAccessibilityFocused(true);
info.setVisibleToUser(true);
info.setEditable(true);
info.setCanOpenPopup(true);
info.setDismissable(true);
info.setMultiLine(true);
info.setContentInvalid(true);
info.setContextClickable(true);
info.setImportantForAccessibility(true);
info.setScreenReaderFocusable(true);
// 3 Boolean properties
info.setShowingHintText(true);
info.setHeading(true);
info.setTextEntryKey(true);
}
/**
* Populates touch delegate target map.
*/
private void populateTouchDelegateTargetMap(AccessibilityNodeInfo info) {
final ArrayMap<Region, View> targetMap = new ArrayMap<>(3);
final Rect rect1 = new Rect(1, 1, 10, 10);
final Rect rect2 = new Rect(2, 2, 20, 20);
final Rect rect3 = new Rect(3, 3, 30, 30);
targetMap.put(new Region(rect1), new View(getContext()));
targetMap.put(new Region(rect2), new View(getContext()));
targetMap.put(new Region(rect3), new View(getContext()));
final TouchDelegateInfo touchDelegateInfo = new TouchDelegateInfo(targetMap);
info.setTouchDelegateInfo(touchDelegateInfo);
}
private static void assertEqualsTouchDelegateInfo(String message,
AccessibilityNodeInfo.TouchDelegateInfo expected,
AccessibilityNodeInfo.TouchDelegateInfo actual) {
if (expected == actual) return;
assertEquals(message, expected.getRegionCount(), actual.getRegionCount());
for (int i = 0; i < expected.getRegionCount(); i++) {
final Region expectedRegion = expected.getRegionAt(i);
final Long expectedId = expected.getAccessibilityIdForRegion(expectedRegion);
boolean matched = false;
for (int j = 0; j < actual.getRegionCount(); j++) {
final Region actualRegion = actual.getRegionAt(j);
final Long actualId = actual.getAccessibilityIdForRegion(actualRegion);
if (expectedRegion.equals(actualRegion) && expectedId.equals(actualId)) {
matched = true;
break;
}
}
assertTrue(message, matched);
}
}
/**
* Compares all properties of the <code>expectedInfo</code> and the
* <code>receivedInfo</code> to verify that the received node info is
* the one that is expected.
*/
public static void assertEqualsAccessibilityNodeInfo(AccessibilityNodeInfo expectedInfo,
AccessibilityNodeInfo receivedInfo) {
// Check 9 fields
Rect expectedBounds = new Rect();
Rect receivedBounds = new Rect();
expectedInfo.getBoundsInParent(expectedBounds);
receivedInfo.getBoundsInParent(receivedBounds);
assertEquals("boundsInParent has incorrect value", expectedBounds, receivedBounds);
expectedInfo.getBoundsInScreen(expectedBounds);
receivedInfo.getBoundsInScreen(receivedBounds);
assertEquals("boundsInScreen has incorrect value", expectedBounds, receivedBounds);
assertEquals("className has incorrect value", expectedInfo.getClassName(),
receivedInfo.getClassName());
assertEquals("contentDescription has incorrect value", expectedInfo.getContentDescription(),
receivedInfo.getContentDescription());
assertEquals("stateDescription has incorrect value", expectedInfo.getStateDescription(),
receivedInfo.getStateDescription());
assertEquals("tooltip text has incorrect value", expectedInfo.getTooltipText(),
receivedInfo.getTooltipText());
assertEquals("packageName has incorrect value", expectedInfo.getPackageName(),
receivedInfo.getPackageName());
assertEquals("text has incorrect value", expectedInfo.getText(), receivedInfo.getText());
assertEquals("Hint text has incorrect value",
expectedInfo.getHintText(), receivedInfo.getHintText());
// Check 2 fields
assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
receivedInfo.getChildCount());
// Actions is just 1 field, but we check it 2 ways
assertSame("actions has incorrect value", expectedInfo.getActions(),
receivedInfo.getActions());
assertEquals("actionsSet has incorrect value", expectedInfo.getActionList(),
receivedInfo.getActionList());
// Check 10 fields
assertSame("movementGranularities has incorrect value",
expectedInfo.getMovementGranularities(),
receivedInfo.getMovementGranularities());
assertEquals("viewId has incorrect value", expectedInfo.getViewIdResourceName(),
receivedInfo.getViewIdResourceName());
assertEquals("drawing order has incorrect value", expectedInfo.getDrawingOrder(),
receivedInfo.getDrawingOrder());
assertEquals("Extra data flags have incorrect value", expectedInfo.getAvailableExtraData(),
receivedInfo.getAvailableExtraData());
assertEquals("Pane title has incorrect value", expectedInfo.getPaneTitle(),
receivedInfo.getPaneTitle());
assertEquals("Error text has incorrect value", expectedInfo.getError(),
receivedInfo.getError());
assertEquals("Max text length has incorrect value", expectedInfo.getMaxTextLength(),
receivedInfo.getMaxTextLength());
assertEquals("Text selection start has incorrect value",
expectedInfo.getTextSelectionStart(), receivedInfo.getTextSelectionStart());
assertEquals("Text selection end has incorrect value",
expectedInfo.getTextSelectionEnd(), receivedInfo.getTextSelectionEnd());
assertEquals("Live region has incorrect value", expectedInfo.getLiveRegion(),
receivedInfo.getLiveRegion());
// Check 2 fields
// Extras is a Bundle, and Bundle doesn't declare equals. Comparing the keyset gets us
// what we need, though
assertEquals("Extras have incorrect value", expectedInfo.getExtras().keySet(),
receivedInfo.getExtras().keySet());
assertEquals("InputType has incorrect value", expectedInfo.getInputType(),
receivedInfo.getInputType());
// Check 3 fields with sub-objects
RangeInfo expectedRange = expectedInfo.getRangeInfo();
RangeInfo receivedRange = receivedInfo.getRangeInfo();
assertEquals("Range info has incorrect value", (expectedRange != null),
(receivedRange != null));
if (expectedRange != null) {
assertEquals("RangeInfo#getCurrent has incorrect value", expectedRange.getCurrent(),
receivedRange.getCurrent(), 0.0);
assertEquals("RangeInfo#getMin has incorrect value", expectedRange.getMin(),
receivedRange.getMin(), 0.0);
assertEquals("RangeInfo#getMax has incorrect value", expectedRange.getMax(),
receivedRange.getMax(), 0.0);
assertEquals("RangeInfo#getType has incorrect value", expectedRange.getType(),
receivedRange.getType());
}
CollectionInfo expectedCollectionInfo = expectedInfo.getCollectionInfo();
CollectionInfo receivedCollectionInfo = receivedInfo.getCollectionInfo();
assertEquals("Collection info has incorrect value", (expectedCollectionInfo != null),
(receivedCollectionInfo != null));
if (expectedCollectionInfo != null) {
assertEquals("CollectionInfo#getColumnCount has incorrect value",
expectedCollectionInfo.getColumnCount(),
receivedCollectionInfo.getColumnCount());
assertEquals("CollectionInfo#getRowCount has incorrect value",
expectedCollectionInfo.getRowCount(), receivedCollectionInfo.getRowCount());
assertEquals("CollectionInfo#getSelectionMode has incorrect value",
expectedCollectionInfo.getSelectionMode(),
receivedCollectionInfo.getSelectionMode());
}
CollectionItemInfo expectedItemInfo = expectedInfo.getCollectionItemInfo();
CollectionItemInfo receivedItemInfo = receivedInfo.getCollectionItemInfo();
assertEquals("Collection item info has incorrect value", (expectedItemInfo != null),
(receivedItemInfo != null));
if (expectedItemInfo != null) {
assertEquals("CollectionItemInfo#getColumnIndex has incorrect value",
expectedItemInfo.getColumnIndex(),
receivedItemInfo.getColumnIndex());
assertEquals("CollectionItemInfo#getColumnSpan has incorrect value",
expectedItemInfo.getColumnSpan(),
receivedItemInfo.getColumnSpan());
assertEquals("CollectionItemInfo#getRowIndex has incorrect value",
expectedItemInfo.getRowIndex(),
receivedItemInfo.getRowIndex());
assertEquals("CollectionItemInfo#getRowSpan has incorrect value",
expectedItemInfo.getRowSpan(),
receivedItemInfo.getRowSpan());
}
// Check 1 field
assertEqualsTouchDelegateInfo("TouchDelegate target map has incorrect value",
expectedInfo.getTouchDelegateInfo(),
receivedInfo.getTouchDelegateInfo());
// And the boolean properties are another field, for a total of 28
// Missing parent: Tested end-to-end in AccessibilityWindowTraversalTest#testObjectContract
// (getting a child is also checked there)
// traversalbefore: AccessibilityEndToEndTest
// #testTraversalBeforeReportedToAccessibility
// traversalafter: AccessibilityEndToEndTest
// #testTraversalAfterReportedToAccessibility
// labelfor: AccessibilityEndToEndTest#testLabelForReportedToAccessibility
// labeledby: AccessibilityEndToEndTest#testLabelForReportedToAccessibility
// windowid: Not directly observable
// sourceid: Not directly observable
// leashedChild: Not directly accessible
// leashedParent: Not directly accessible
// leashedParentNodeId: Not directly accessible
// Which brings us to a total of 38
// 10 Boolean properties
assertSame("checkable has incorrect value", expectedInfo.isCheckable(),
receivedInfo.isCheckable());
assertSame("checked has incorrect value", expectedInfo.isChecked(),
receivedInfo.isChecked());
assertSame("focusable has incorrect value", expectedInfo.isFocusable(),
receivedInfo.isFocusable());
assertSame("focused has incorrect value", expectedInfo.isFocused(),
receivedInfo.isFocused());
assertSame("selected has incorrect value", expectedInfo.isSelected(),
receivedInfo.isSelected());
assertSame("clickable has incorrect value", expectedInfo.isClickable(),
receivedInfo.isClickable());
assertSame("longClickable has incorrect value", expectedInfo.isLongClickable(),
receivedInfo.isLongClickable());
assertSame("enabled has incorrect value", expectedInfo.isEnabled(),
receivedInfo.isEnabled());
assertSame("password has incorrect value", expectedInfo.isPassword(),
receivedInfo.isPassword());
assertSame("scrollable has incorrect value", expectedInfo.isScrollable(),
receivedInfo.isScrollable());
// 10 Boolean properties
assertSame("AccessibilityFocused has incorrect value",
expectedInfo.isAccessibilityFocused(),
receivedInfo.isAccessibilityFocused());
assertSame("VisibleToUser has incorrect value", expectedInfo.isVisibleToUser(),
receivedInfo.isVisibleToUser());
assertSame("Editable has incorrect value", expectedInfo.isEditable(),
receivedInfo.isEditable());
assertSame("canOpenPopup has incorrect value", expectedInfo.canOpenPopup(),
receivedInfo.canOpenPopup());
assertSame("Dismissable has incorrect value", expectedInfo.isDismissable(),
receivedInfo.isDismissable());
assertSame("Multiline has incorrect value", expectedInfo.isMultiLine(),
receivedInfo.isMultiLine());
assertSame("ContentInvalid has incorrect value", expectedInfo.isContentInvalid(),
receivedInfo.isContentInvalid());
assertSame("contextClickable has incorrect value", expectedInfo.isContextClickable(),
receivedInfo.isContextClickable());
assertSame("importantForAccessibility has incorrect value",
expectedInfo.isImportantForAccessibility(),
receivedInfo.isImportantForAccessibility());
assertSame("isScreenReaderFocusable has incorrect value",
expectedInfo.isScreenReaderFocusable(), receivedInfo.isScreenReaderFocusable());
// 3 Boolean properties
assertSame("isShowingHint has incorrect value",
expectedInfo.isShowingHintText(), receivedInfo.isShowingHintText());
assertSame("isHeading has incorrect value",
expectedInfo.isHeading(), receivedInfo.isHeading());
assertSame("isTextEntryKey has incorrect value",
expectedInfo.isTextEntryKey(), receivedInfo.isTextEntryKey());
}
/**
* Asserts that an {@link AccessibilityNodeInfo} is cleared.
*
* @param info The node info to check.
*/
public static void assertAccessibilityNodeInfoCleared(AccessibilityNodeInfo info) {
// Check 11 fields
Rect bounds = new Rect();
info.getBoundsInParent(bounds);
assertTrue("boundsInParent not properly recycled", bounds.isEmpty());
info.getBoundsInScreen(bounds);
assertTrue("boundsInScreen not properly recycled", bounds.isEmpty());
assertNull("className not properly recycled", info.getClassName());
assertNull("contentDescription not properly recycled", info.getContentDescription());
assertNull("stateDescription not properly recycled", info.getStateDescription());
assertNull("tooltiptext not properly recycled", info.getTooltipText());
assertNull("packageName not properly recycled", info.getPackageName());
assertNull("text not properly recycled", info.getText());
assertNull("Hint text not properly recycled", info.getHintText());
assertEquals("Children list not properly recycled", 0, info.getChildCount());
// Actions are in one field
assertSame("actions not properly recycled", 0, info.getActions());
assertTrue("action list not properly recycled", info.getActionList().isEmpty());
// Check 10 fields
assertSame("movementGranularities not properly recycled", 0,
info.getMovementGranularities());
assertNull("viewId not properly recycled", info.getViewIdResourceName());
assertEquals(0, info.getDrawingOrder());
assertTrue(info.getAvailableExtraData().isEmpty());
assertNull("Pane title not properly recycled", info.getPaneTitle());
assertNull("Error text not properly recycled", info.getError());
assertEquals("Max text length not properly recycled", -1, info.getMaxTextLength());
assertEquals("Text selection start not properly recycled",
-1, info.getTextSelectionStart());
assertEquals("Text selection end not properly recycled", -1, info.getTextSelectionEnd());
assertEquals("Live region not properly recycled", 0, info.getLiveRegion());
// Check 6 fields
assertEquals("Extras not properly recycled", 0, info.getExtras().keySet().size());
assertEquals("Input type not properly recycled", 0, info.getInputType());
assertNull("Range info not properly recycled", info.getRangeInfo());
assertNull("Collection info not properly recycled", info.getCollectionInfo());
assertNull("Collection item info not properly recycled", info.getCollectionItemInfo());
assertNull("TouchDelegate target map not recycled", info.getTouchDelegateInfo());
// And Boolean properties brings up to 28 fields
// Missing:
// parent (can't be performed on sealed instance, even if null)
// traversalbefore (can't be performed on sealed instance, even if null)
// traversalafter (can't be performed on sealed instance, even if null)
// labelfor (can't be performed on sealed instance, even if null)
// labeledby (can't be performed on sealed instance, even if null)
// sourceId (not directly observable)
// windowId (not directly observable)
// leashedChild (not directly observable)
// leashedParent (not directly observable)
// leashedParentNodeId (not directly observable)
// a total of 38
// 10 Boolean properties
assertFalse("checkable not properly recycled", info.isCheckable());
assertFalse("checked not properly recycled", info.isChecked());
assertFalse("focusable not properly recycled", info.isFocusable());
assertFalse("focused not properly recycled", info.isFocused());
assertFalse("selected not properly recycled", info.isSelected());
assertFalse("clickable not properly recycled", info.isClickable());
assertFalse("longClickable not properly recycled", info.isLongClickable());
assertFalse("enabled not properly recycled", info.isEnabled());
assertFalse("password not properly recycled", info.isPassword());
assertFalse("scrollable not properly recycled", info.isScrollable());
// 10 Boolean properties
assertFalse("accessibility focused not properly recycled", info.isAccessibilityFocused());
assertFalse("VisibleToUser not properly recycled", info.isVisibleToUser());
assertFalse("Editable not properly recycled", info.isEditable());
assertFalse("canOpenPopup not properly recycled", info.canOpenPopup());
assertFalse("Dismissable not properly recycled", info.isDismissable());
assertFalse("Multiline not properly recycled", info.isMultiLine());
assertFalse("ContentInvalid not properly recycled", info.isContentInvalid());
assertFalse("contextClickable not properly recycled", info.isContextClickable());
assertFalse("importantForAccessibility not properly recycled",
info.isImportantForAccessibility());
assertFalse("ScreenReaderFocusable not properly recycled", info.isScreenReaderFocusable());
// 3 Boolean properties
assertFalse("isShowingHint not properly reset", info.isShowingHintText());
assertFalse("isHeading not properly reset", info.isHeading());
assertFalse("isTextEntryKey not properly reset", info.isTextEntryKey());
}
private static class MockBinder extends Binder {
}
}