1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view.accessibility.cts; 18 19 import android.graphics.Rect; 20 import android.graphics.Region; 21 import android.os.Bundle; 22 import android.os.Parcel; 23 import android.platform.test.annotations.Presubmit; 24 import android.test.AndroidTestCase; 25 import android.test.suitebuilder.annotation.SmallTest; 26 import android.text.InputType; 27 import android.text.TextUtils; 28 import android.util.ArrayMap; 29 import android.view.View; 30 import android.view.accessibility.AccessibilityEvent; 31 import android.view.accessibility.AccessibilityNodeInfo; 32 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 33 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo; 34 import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo; 35 import android.view.accessibility.AccessibilityNodeInfo.RangeInfo; 36 import android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo; 37 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.List; 41 42 /** 43 * Class for testing {@link AccessibilityNodeInfo}. 44 */ 45 @Presubmit 46 public class AccessibilityNodeInfoTest extends AndroidTestCase { 47 48 @SmallTest 49 public void testMarshaling() throws Exception { 50 // fully populate the node info to marshal 51 AccessibilityNodeInfo sentInfo = AccessibilityNodeInfo.obtain(new View(getContext())); 52 fullyPopulateAccessibilityNodeInfo(sentInfo); 53 54 // marshal and unmarshal the node info 55 Parcel parcel = Parcel.obtain(); 56 sentInfo.writeToParcelNoRecycle(parcel, 0); 57 parcel.setDataPosition(0); 58 AccessibilityNodeInfo receivedInfo = AccessibilityNodeInfo.CREATOR.createFromParcel(parcel); 59 60 // make sure all fields properly marshaled 61 assertEqualsAccessibilityNodeInfo(sentInfo, receivedInfo); 62 63 parcel.recycle(); 64 } 65 66 /** 67 * Tests if {@link AccessibilityNodeInfo}s are properly reused. 68 */ 69 @SmallTest 70 public void testReuse() { 71 AccessibilityEvent firstInfo = AccessibilityEvent.obtain(); 72 firstInfo.recycle(); 73 AccessibilityEvent secondInfo = AccessibilityEvent.obtain(); 74 assertSame("AccessibilityNodeInfo not properly reused", firstInfo, secondInfo); 75 } 76 77 /** 78 * Tests if {@link AccessibilityNodeInfo} are properly recycled. 79 */ 80 @SmallTest 81 public void testRecycle() { 82 // obtain and populate an node info 83 AccessibilityNodeInfo populatedInfo = AccessibilityNodeInfo.obtain(); 84 fullyPopulateAccessibilityNodeInfo(populatedInfo); 85 86 // recycle and obtain the same recycled instance 87 populatedInfo.recycle(); 88 AccessibilityNodeInfo recycledInfo = AccessibilityNodeInfo.obtain(); 89 90 // check expectations 91 assertAccessibilityNodeInfoCleared(recycledInfo); 92 } 93 94 /** 95 * Tests whether the event describes its contents consistently. 96 */ 97 @SmallTest 98 public void testDescribeContents() { 99 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 100 assertSame("Accessibility node infos always return 0 for this method.", 0, 101 info.describeContents()); 102 fullyPopulateAccessibilityNodeInfo(info); 103 assertSame("Accessibility node infos always return 0 for this method.", 0, 104 info.describeContents()); 105 } 106 107 /** 108 * Tests whether accessibility actions are properly added. 109 */ 110 @SmallTest 111 public void testAddActions() { 112 List<AccessibilityAction> customActions = new ArrayList<AccessibilityAction>(); 113 customActions.add(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo")); 114 customActions.add(new AccessibilityAction(R.id.foo_custom_action, "Foo")); 115 116 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 117 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 118 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 119 for (AccessibilityAction customAction : customActions) { 120 info.addAction(customAction); 121 } 122 123 assertSame(info.getActions(), (AccessibilityNodeInfo.ACTION_FOCUS 124 | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS)); 125 126 List<AccessibilityAction> allActions = new ArrayList<AccessibilityAction>(); 127 allActions.add(AccessibilityAction.ACTION_CLEAR_FOCUS); 128 allActions.addAll(customActions); 129 assertEquals(info.getActionList(), allActions); 130 } 131 132 /** 133 * Tests whether we catch addition of an action with invalid id. 134 */ 135 @SmallTest 136 public void testCreateInvalidActionId() { 137 try { 138 new AccessibilityAction(3, null); 139 } catch (IllegalArgumentException iae) { 140 /* expected */ 141 } 142 } 143 144 /** 145 * Tests whether accessibility actions are properly removed. 146 */ 147 @SmallTest 148 public void testRemoveActions() { 149 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 150 151 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 152 assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS); 153 154 info.removeAction(AccessibilityNodeInfo.ACTION_FOCUS); 155 assertSame(info.getActions(), 0); 156 assertTrue(info.getActionList().isEmpty()); 157 158 AccessibilityAction customFocus = new AccessibilityAction( 159 AccessibilityNodeInfo.ACTION_FOCUS, "Foo"); 160 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 161 info.addAction(customFocus); 162 assertSame(info.getActionList().size(), 1); 163 assertEquals(info.getActionList().get(0), customFocus); 164 assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS); 165 166 info.removeAction(customFocus); 167 assertSame(info.getActions(), 0); 168 assertTrue(info.getActionList().isEmpty()); 169 } 170 171 /** 172 * While CharSequence is immutable, some classes implementing it are mutable. Make sure they 173 * can't change the object by changing the objects backing CharSequence 174 */ 175 @SmallTest 176 public void testChangeTextAfterSetting_shouldNotAffectInfo() { 177 final String originalText = "Cassowaries"; 178 final String newText = "Hornbill"; 179 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 180 StringBuffer updatingString = new StringBuffer(originalText); 181 info.setText(updatingString); 182 info.setError(updatingString); 183 info.setContentDescription(updatingString); 184 185 updatingString.delete(0, updatingString.length()); 186 updatingString.append(newText); 187 188 assertTrue(TextUtils.equals(originalText, info.getText())); 189 assertTrue(TextUtils.equals(originalText, info.getError())); 190 assertTrue(TextUtils.equals(originalText, info.getContentDescription())); 191 } 192 193 @SmallTest 194 public void testIsHeadingTakesOldApiIntoAccount() { 195 final AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 196 assertFalse(info.isHeading()); 197 final CollectionItemInfo headingItemInfo = CollectionItemInfo.obtain(0, 1, 0, 1, true); 198 info.setCollectionItemInfo(headingItemInfo); 199 assertTrue(info.isHeading()); 200 final CollectionItemInfo nonHeadingItemInfo = CollectionItemInfo.obtain(0, 1, 0, 1, false); 201 info.setCollectionItemInfo(nonHeadingItemInfo); 202 assertFalse(info.isHeading()); 203 } 204 205 /** 206 * Fully populates the {@link AccessibilityNodeInfo} to marshal. 207 * 208 * @param info The node info to populate. 209 */ 210 private void fullyPopulateAccessibilityNodeInfo(AccessibilityNodeInfo info) { 211 // Populate 10 fields 212 info.setBoundsInParent(new Rect(1,1,1,1)); 213 info.setBoundsInScreen(new Rect(2,2,2,2)); 214 info.setClassName("foo.bar.baz.Class"); 215 info.setContentDescription("content description"); 216 info.setTooltipText("tooltip"); 217 info.setPackageName("foo.bar.baz"); 218 info.setText("text"); 219 info.setHintText("hint"); 220 // 2 children = 1 field 221 info.addChild(new View(getContext())); 222 info.addChild(new View(getContext()), 1); 223 // 2 built-in actions and 2 custom actions, but all are in 1 field 224 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 225 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 226 info.addAction(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo")); 227 info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo")); 228 229 // Populate 10 fields 230 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE); 231 info.setViewIdResourceName("foo.bar:id/baz"); 232 info.setDrawingOrder(5); 233 info.setAvailableExtraData( 234 Arrays.asList(AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)); 235 info.setPaneTitle("Pane title"); 236 info.setError("Error text"); 237 info.setMaxTextLength(42); 238 // Text selection is 2 fields 239 info.setTextSelection(3, 7); 240 info.setLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE); 241 242 // Populate 10 fields 243 Bundle extras = info.getExtras(); 244 extras.putBoolean("areCassowariesAwesome", true); 245 info.setInputType(InputType.TYPE_CLASS_TEXT); 246 info.setRangeInfo(RangeInfo.obtain(RangeInfo.RANGE_TYPE_FLOAT, 0.05f, 1.0f, 0.01f)); 247 info.setCollectionInfo( 248 CollectionInfo.obtain(2, 2, true, CollectionInfo.SELECTION_MODE_MULTIPLE)); 249 info.setCollectionItemInfo(CollectionItemInfo.obtain(1, 2, 3, 4, true, true)); 250 info.setParent(new View(getContext())); 251 info.setSource(new View(getContext())); // Populates 2 fields: source and window id 252 info.setTraversalBefore(new View(getContext())); 253 info.setTraversalAfter(new View(getContext())); 254 255 // Populate 3 fields 256 info.setLabeledBy(new View(getContext())); 257 info.setLabelFor(new View(getContext())); 258 populateTouchDelegateTargetMap(info); 259 260 // And Boolean properties are another field. Total is 34 261 262 // 10 Boolean properties 263 info.setCheckable(true); 264 info.setChecked(true); 265 info.setFocusable(true); 266 info.setFocused(true); 267 info.setSelected(true); 268 info.setClickable(true); 269 info.setLongClickable(true); 270 info.setEnabled(true); 271 info.setPassword(true); 272 info.setScrollable(true); 273 274 // 10 Boolean properties 275 info.setAccessibilityFocused(true); 276 info.setVisibleToUser(true); 277 info.setEditable(true); 278 info.setCanOpenPopup(true); 279 info.setDismissable(true); 280 info.setMultiLine(true); 281 info.setContentInvalid(true); 282 info.setContextClickable(true); 283 info.setImportantForAccessibility(true); 284 info.setScreenReaderFocusable(true); 285 286 // 3 Boolean properties, for a total of 23 287 info.setShowingHintText(true); 288 info.setHeading(true); 289 info.setTextEntryKey(true); 290 } 291 292 /** 293 * Populates touch delegate target map. 294 */ 295 private void populateTouchDelegateTargetMap(AccessibilityNodeInfo info) { 296 final ArrayMap<Region, View> targetMap = new ArrayMap<>(3); 297 final Rect rect1 = new Rect(1, 1, 10, 10); 298 final Rect rect2 = new Rect(2, 2, 20, 20); 299 final Rect rect3 = new Rect(3, 3, 30, 30); 300 targetMap.put(new Region(rect1), new View(getContext())); 301 targetMap.put(new Region(rect2), new View(getContext())); 302 targetMap.put(new Region(rect3), new View(getContext())); 303 304 final TouchDelegateInfo touchDelegateInfo = new TouchDelegateInfo(targetMap); 305 info.setTouchDelegateInfo(touchDelegateInfo); 306 } 307 308 private static void assertEqualsTouchDelegateInfo(String message, 309 AccessibilityNodeInfo.TouchDelegateInfo expected, 310 AccessibilityNodeInfo.TouchDelegateInfo actual) { 311 if (expected == actual) return; 312 assertEquals(message, expected.getRegionCount(), actual.getRegionCount()); 313 for (int i = 0; i < expected.getRegionCount(); i++) { 314 final Region expectedRegion = expected.getRegionAt(i); 315 final Long expectedId = expected.getAccessibilityIdForRegion(expectedRegion); 316 boolean matched = false; 317 for (int j = 0; j < actual.getRegionCount(); j++) { 318 final Region actualRegion = actual.getRegionAt(j); 319 final Long actualId = actual.getAccessibilityIdForRegion(actualRegion); 320 if (expectedRegion.equals(actualRegion) && expectedId.equals(actualId)) { 321 matched = true; 322 break; 323 } 324 } 325 assertTrue(message, matched); 326 } 327 } 328 329 /** 330 * Compares all properties of the <code>expectedInfo</code> and the 331 * <code>receivedInfo</code> to verify that the received node info is 332 * the one that is expected. 333 */ 334 public static void assertEqualsAccessibilityNodeInfo(AccessibilityNodeInfo expectedInfo, 335 AccessibilityNodeInfo receivedInfo) { 336 // Check 10 fields 337 Rect expectedBounds = new Rect(); 338 Rect receivedBounds = new Rect(); 339 expectedInfo.getBoundsInParent(expectedBounds); 340 receivedInfo.getBoundsInParent(receivedBounds); 341 assertEquals("boundsInParent has incorrect value", expectedBounds, receivedBounds); 342 expectedInfo.getBoundsInScreen(expectedBounds); 343 receivedInfo.getBoundsInScreen(receivedBounds); 344 assertEquals("boundsInScreen has incorrect value", expectedBounds, receivedBounds); 345 assertEquals("className has incorrect value", expectedInfo.getClassName(), 346 receivedInfo.getClassName()); 347 assertEquals("contentDescription has incorrect value", expectedInfo.getContentDescription(), 348 receivedInfo.getContentDescription()); 349 assertEquals("tooltip text has incorrect value", expectedInfo.getTooltipText(), 350 receivedInfo.getTooltipText()); 351 assertEquals("packageName has incorrect value", expectedInfo.getPackageName(), 352 receivedInfo.getPackageName()); 353 assertEquals("text has incorrect value", expectedInfo.getText(), receivedInfo.getText()); 354 assertEquals("Hint text has incorrect value", 355 expectedInfo.getHintText(), receivedInfo.getHintText()); 356 assertSame("childCount has incorrect value", expectedInfo.getChildCount(), 357 receivedInfo.getChildCount()); 358 // Actions is just 1 field, but we check it 2 ways 359 assertSame("actions has incorrect value", expectedInfo.getActions(), 360 receivedInfo.getActions()); 361 assertEquals("actionsSet has incorrect value", expectedInfo.getActionList(), 362 receivedInfo.getActionList()); 363 364 // Check 10 fields 365 assertSame("movementGranularities has incorrect value", 366 expectedInfo.getMovementGranularities(), 367 receivedInfo.getMovementGranularities()); 368 assertEquals("viewId has incorrect value", expectedInfo.getViewIdResourceName(), 369 receivedInfo.getViewIdResourceName()); 370 assertEquals("drawing order has incorrect value", expectedInfo.getDrawingOrder(), 371 receivedInfo.getDrawingOrder()); 372 assertEquals("Extra data flags have incorrect value", expectedInfo.getAvailableExtraData(), 373 receivedInfo.getAvailableExtraData()); 374 assertEquals("Pane title has incorrect value", expectedInfo.getPaneTitle(), 375 receivedInfo.getPaneTitle()); 376 assertEquals("Error text has incorrect value", expectedInfo.getError(), 377 receivedInfo.getError()); 378 assertEquals("Max text length has incorrect value", expectedInfo.getMaxTextLength(), 379 receivedInfo.getMaxTextLength()); 380 assertEquals("Text selection start has incorrect value", 381 expectedInfo.getTextSelectionStart(), receivedInfo.getTextSelectionStart()); 382 assertEquals("Text selection end has incorrect value", 383 expectedInfo.getTextSelectionEnd(), receivedInfo.getTextSelectionEnd()); 384 assertEquals("Live region has incorrect value", expectedInfo.getLiveRegion(), 385 receivedInfo.getLiveRegion()); 386 387 // Check 2 fields 388 // Extras is a Bundle, and Bundle doesn't declare equals. Comparing the keyset gets us 389 // what we need, though 390 assertEquals("Extras have incorrect value", expectedInfo.getExtras().keySet(), 391 receivedInfo.getExtras().keySet()); 392 assertEquals("InputType has incorrect value", expectedInfo.getInputType(), 393 receivedInfo.getInputType()); 394 395 // Check 3 fields with sub-objects 396 RangeInfo expectedRange = expectedInfo.getRangeInfo(); 397 RangeInfo receivedRange = receivedInfo.getRangeInfo(); 398 assertEquals("Range info has incorrect value", (expectedRange != null), 399 (receivedRange != null)); 400 if (expectedRange != null) { 401 assertEquals("RangeInfo#getCurrent has incorrect value", expectedRange.getCurrent(), 402 receivedRange.getCurrent()); 403 assertEquals("RangeInfo#getMin has incorrect value", expectedRange.getMin(), 404 receivedRange.getMin()); 405 assertEquals("RangeInfo#getMax has incorrect value", expectedRange.getMax(), 406 receivedRange.getMax()); 407 assertEquals("RangeInfo#getType has incorrect value", expectedRange.getType(), 408 receivedRange.getType()); 409 } 410 411 CollectionInfo expectedCollectionInfo = expectedInfo.getCollectionInfo(); 412 CollectionInfo receivedCollectionInfo = receivedInfo.getCollectionInfo(); 413 assertEquals("Collection info has incorrect value", (expectedCollectionInfo != null), 414 (receivedCollectionInfo != null)); 415 if (expectedCollectionInfo != null) { 416 assertEquals("CollectionInfo#getColumnCount has incorrect value", 417 expectedCollectionInfo.getColumnCount(), 418 receivedCollectionInfo.getColumnCount()); 419 assertEquals("CollectionInfo#getRowCount has incorrect value", 420 expectedCollectionInfo.getRowCount(), receivedCollectionInfo.getRowCount()); 421 assertEquals("CollectionInfo#getSelectionMode has incorrect value", 422 expectedCollectionInfo.getSelectionMode(), 423 receivedCollectionInfo.getSelectionMode()); 424 } 425 426 CollectionItemInfo expectedItemInfo = expectedInfo.getCollectionItemInfo(); 427 CollectionItemInfo receivedItemInfo = receivedInfo.getCollectionItemInfo(); 428 assertEquals("Collection item info has incorrect value", (expectedItemInfo != null), 429 (receivedItemInfo != null)); 430 if (expectedItemInfo != null) { 431 assertEquals("CollectionItemInfo#getColumnIndex has incorrect value", 432 expectedItemInfo.getColumnIndex(), 433 receivedItemInfo.getColumnIndex()); 434 assertEquals("CollectionItemInfo#getColumnSpan has incorrect value", 435 expectedItemInfo.getColumnSpan(), 436 receivedItemInfo.getColumnSpan()); 437 assertEquals("CollectionItemInfo#getRowIndex has incorrect value", 438 expectedItemInfo.getRowIndex(), 439 receivedItemInfo.getRowIndex()); 440 assertEquals("CollectionItemInfo#getRowSpan has incorrect value", 441 expectedItemInfo.getRowSpan(), 442 receivedItemInfo.getRowSpan()); 443 } 444 445 assertEqualsTouchDelegateInfo("TouchDelegate target map has incorrect value", 446 expectedInfo.getTouchDelegateInfo(), 447 receivedInfo.getTouchDelegateInfo()); 448 449 // And the boolean properties are another field, for a total of 26 450 // Missing parent: Tested end-to-end in AccessibilityWindowTraversalTest#testObjectContract 451 // (getting a child is also checked there) 452 // traversalbefore: AccessibilityEndToEndTest 453 // #testTraversalBeforeReportedToAccessibility 454 // traversalafter: AccessibilityEndToEndTest 455 // #testTraversalAfterReportedToAccessibility 456 // labelfor: AccessibilityEndToEndTest#testLabelForReportedToAccessibility 457 // labeledby: AccessibilityEndToEndTest#testLabelForReportedToAccessibility 458 // windowid: Not directly observable 459 // sourceid: Not directly observable 460 // Which brings us to a total of 33 461 462 // 10 Boolean properties 463 assertSame("checkable has incorrect value", expectedInfo.isCheckable(), 464 receivedInfo.isCheckable()); 465 assertSame("checked has incorrect value", expectedInfo.isChecked(), 466 receivedInfo.isChecked()); 467 assertSame("focusable has incorrect value", expectedInfo.isFocusable(), 468 receivedInfo.isFocusable()); 469 assertSame("focused has incorrect value", expectedInfo.isFocused(), 470 receivedInfo.isFocused()); 471 assertSame("selected has incorrect value", expectedInfo.isSelected(), 472 receivedInfo.isSelected()); 473 assertSame("clickable has incorrect value", expectedInfo.isClickable(), 474 receivedInfo.isClickable()); 475 assertSame("longClickable has incorrect value", expectedInfo.isLongClickable(), 476 receivedInfo.isLongClickable()); 477 assertSame("enabled has incorrect value", expectedInfo.isEnabled(), 478 receivedInfo.isEnabled()); 479 assertSame("password has incorrect value", expectedInfo.isPassword(), 480 receivedInfo.isPassword()); 481 assertSame("scrollable has incorrect value", expectedInfo.isScrollable(), 482 receivedInfo.isScrollable()); 483 484 // 10 Boolean properties 485 assertSame("AccessibilityFocused has incorrect value", 486 expectedInfo.isAccessibilityFocused(), 487 receivedInfo.isAccessibilityFocused()); 488 assertSame("VisibleToUser has incorrect value", expectedInfo.isVisibleToUser(), 489 receivedInfo.isVisibleToUser()); 490 assertSame("Editable has incorrect value", expectedInfo.isEditable(), 491 receivedInfo.isEditable()); 492 assertSame("canOpenPopup has incorrect value", expectedInfo.canOpenPopup(), 493 receivedInfo.canOpenPopup()); 494 assertSame("Dismissable has incorrect value", expectedInfo.isDismissable(), 495 receivedInfo.isDismissable()); 496 assertSame("Multiline has incorrect value", expectedInfo.isMultiLine(), 497 receivedInfo.isMultiLine()); 498 assertSame("ContentInvalid has incorrect value", expectedInfo.isContentInvalid(), 499 receivedInfo.isContentInvalid()); 500 assertSame("contextClickable has incorrect value", expectedInfo.isContextClickable(), 501 receivedInfo.isContextClickable()); 502 assertSame("importantForAccessibility has incorrect value", 503 expectedInfo.isImportantForAccessibility(), 504 receivedInfo.isImportantForAccessibility()); 505 assertSame("isScreenReaderFocusable has incorrect value", 506 expectedInfo.isScreenReaderFocusable(), receivedInfo.isScreenReaderFocusable()); 507 508 // 3 Boolean properties, for a total of 23 509 assertSame("isShowingHint has incorrect value", 510 expectedInfo.isShowingHintText(), receivedInfo.isShowingHintText()); 511 assertSame("isHeading has incorrect value", 512 expectedInfo.isHeading(), receivedInfo.isHeading()); 513 assertSame("isTextEntryKey has incorrect value", 514 expectedInfo.isTextEntryKey(), receivedInfo.isTextEntryKey()); 515 } 516 517 /** 518 * Asserts that an {@link AccessibilityNodeInfo} is cleared. 519 * 520 * @param info The node info to check. 521 */ 522 public static void assertAccessibilityNodeInfoCleared(AccessibilityNodeInfo info) { 523 // Check 10 fields 524 Rect bounds = new Rect(); 525 info.getBoundsInParent(bounds); 526 assertTrue("boundsInParent not properly recycled", bounds.isEmpty()); 527 info.getBoundsInScreen(bounds); 528 assertTrue("boundsInScreen not properly recycled", bounds.isEmpty()); 529 assertNull("className not properly recycled", info.getClassName()); 530 assertNull("contentDescription not properly recycled", info.getContentDescription()); 531 assertNull("tooltiptext not properly recycled", info.getTooltipText()); 532 assertNull("packageName not properly recycled", info.getPackageName()); 533 assertNull("text not properly recycled", info.getText()); 534 assertNull("Hint text not properly recycled", info.getHintText()); 535 assertEquals("Children list not properly recycled", 0, info.getChildCount()); 536 // Actions are in one field 537 assertSame("actions not properly recycled", 0, info.getActions()); 538 assertTrue("action list not properly recycled", info.getActionList().isEmpty()); 539 540 // Check 10 fields 541 assertSame("movementGranularities not properly recycled", 0, 542 info.getMovementGranularities()); 543 assertNull("viewId not properly recycled", info.getViewIdResourceName()); 544 assertEquals(0, info.getDrawingOrder()); 545 assertTrue(info.getAvailableExtraData().isEmpty()); 546 assertNull("Pane title not properly recycled", info.getPaneTitle()); 547 assertNull("Error text not properly recycled", info.getError()); 548 assertEquals("Max text length not properly recycled", -1, info.getMaxTextLength()); 549 assertEquals("Text selection start not properly recycled", 550 -1, info.getTextSelectionStart()); 551 assertEquals("Text selection end not properly recycled", -1, info.getTextSelectionEnd()); 552 assertEquals("Live region not properly recycled", 0, info.getLiveRegion()); 553 554 // Check 6 fields 555 assertEquals("Extras not properly recycled", 0, info.getExtras().keySet().size()); 556 assertEquals("Input type not properly recycled", 0, info.getInputType()); 557 assertNull("Range info not properly recycled", info.getRangeInfo()); 558 assertNull("Collection info not properly recycled", info.getCollectionInfo()); 559 assertNull("Collection item info not properly recycled", info.getCollectionItemInfo()); 560 assertNull("TouchDelegate target map not recycled", info.getTouchDelegateInfo()); 561 562 // And Boolean properties brings up to 26 fields 563 // Missing: 564 // parent (can't be performed on sealed instance, even if null) 565 // traversalbefore (can't be performed on sealed instance, even if null) 566 // traversalafter (can't be performed on sealed instance, even if null) 567 // labelfor (can't be performed on sealed instance, even if null) 568 // labeledby (can't be performed on sealed instance, even if null) 569 // sourceId (not directly observable) 570 // windowId (not directly observable) 571 // a total of 33 572 573 // 10 Boolean properties 574 assertFalse("checkable not properly recycled", info.isCheckable()); 575 assertFalse("checked not properly recycled", info.isChecked()); 576 assertFalse("focusable not properly recycled", info.isFocusable()); 577 assertFalse("focused not properly recycled", info.isFocused()); 578 assertFalse("selected not properly recycled", info.isSelected()); 579 assertFalse("clickable not properly recycled", info.isClickable()); 580 assertFalse("longClickable not properly recycled", info.isLongClickable()); 581 assertFalse("enabled not properly recycled", info.isEnabled()); 582 assertFalse("password not properly recycled", info.isPassword()); 583 assertFalse("scrollable not properly recycled", info.isScrollable()); 584 585 // 10 Boolean properties 586 assertFalse("accessibility focused not properly recycled", info.isAccessibilityFocused()); 587 assertFalse("VisibleToUser not properly recycled", info.isVisibleToUser()); 588 assertFalse("Editable not properly recycled", info.isEditable()); 589 assertFalse("canOpenPopup not properly recycled", info.canOpenPopup()); 590 assertFalse("Dismissable not properly recycled", info.isDismissable()); 591 assertFalse("Multiline not properly recycled", info.isMultiLine()); 592 assertFalse("ContentInvalid not properly recycled", info.isContentInvalid()); 593 assertFalse("contextClickable not properly recycled", info.isContextClickable()); 594 assertFalse("importantForAccessibility not properly recycled", 595 info.isImportantForAccessibility()); 596 assertFalse("ScreenReaderFocusable not properly recycled", info.isScreenReaderFocusable()); 597 598 // 3 Boolean properties 599 assertFalse("isShowingHint not properly reset", info.isShowingHintText()); 600 assertFalse("isHeading not properly reset", info.isHeading()); 601 assertFalse("isTextEntryKey not properly reset", info.isTextEntryKey()); 602 } 603 } 604