1 /* 2 * Copyright (C) 2010 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 static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertSame; 21 import static org.junit.Assert.assertThrows; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 25 import android.accessibility.cts.common.AccessibilityDumpOnFailureRule; 26 import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule; 27 import android.app.Activity; 28 import android.app.Instrumentation; 29 import android.app.UiAutomation; 30 import android.content.Context; 31 import android.os.Message; 32 import android.os.Parcel; 33 import android.platform.test.annotations.Presubmit; 34 import android.text.SpannableString; 35 import android.text.TextUtils; 36 import android.text.style.LocaleSpan; 37 import android.view.Display; 38 import android.view.View; 39 import android.view.accessibility.AccessibilityEvent; 40 import android.view.accessibility.AccessibilityNodeInfo; 41 import android.view.accessibility.AccessibilityRecord; 42 import android.widget.LinearLayout; 43 import android.widget.TextView; 44 45 import androidx.test.InstrumentationRegistry; 46 import androidx.test.filters.SmallTest; 47 import androidx.test.rule.ActivityTestRule; 48 import androidx.test.runner.AndroidJUnit4; 49 50 import junit.framework.TestCase; 51 52 import org.junit.Before; 53 import org.junit.Rule; 54 import org.junit.Test; 55 import org.junit.rules.RuleChain; 56 import org.junit.runner.RunWith; 57 58 import java.util.ArrayList; 59 import java.util.List; 60 import java.util.Locale; 61 import java.util.concurrent.TimeoutException; 62 63 /** Class for testing {@link AccessibilityEvent}. */ 64 @Presubmit 65 @RunWith(AndroidJUnit4.class) 66 public class AccessibilityEventTest { 67 private static final long IDLE_TIMEOUT_MS = 500; 68 private static final long DEFAULT_TIMEOUT_MS = 1000; 69 70 private EventReportingLinearLayout mParentView; 71 private View mChildView; 72 private TextView mTextView; 73 private String mPackageName; 74 75 private static Instrumentation sInstrumentation; 76 private static UiAutomation sUiAutomation; 77 private final ActivityTestRule<DummyActivity> mActivityRule = 78 new ActivityTestRule<>(DummyActivity.class, false, false); 79 private final AccessibilityDumpOnFailureRule mDumpOnFailureRule = 80 new AccessibilityDumpOnFailureRule(); 81 private InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService> 82 mInstrumentedAccessibilityServiceRule = 83 new InstrumentedAccessibilityServiceTestRule<>( 84 SpeakingAccessibilityService.class, false); 85 86 @Rule 87 public final RuleChain mRuleChain = 88 RuleChain.outerRule(mActivityRule) 89 .around(mInstrumentedAccessibilityServiceRule) 90 .around(mDumpOnFailureRule); 91 92 @Before setUp()93 public void setUp() throws Throwable { 94 final Activity activity = mActivityRule.launchActivity(null); 95 mPackageName = activity.getApplicationContext().getPackageName(); 96 sInstrumentation = InstrumentationRegistry.getInstrumentation(); 97 sUiAutomation = sInstrumentation.getUiAutomation(); 98 mInstrumentedAccessibilityServiceRule.enableService(); 99 mActivityRule.runOnUiThread( 100 () -> { 101 final LinearLayout grandparent = new LinearLayout(activity); 102 activity.setContentView(grandparent); 103 mParentView = new EventReportingLinearLayout(activity); 104 mChildView = new View(activity); 105 mTextView = new TextView(activity); 106 grandparent.addView(mParentView); 107 mParentView.addView(mChildView); 108 mParentView.addView(mTextView); 109 }); 110 sUiAutomation.waitForIdle(IDLE_TIMEOUT_MS, DEFAULT_TIMEOUT_MS); 111 } 112 113 private static class EventReportingLinearLayout extends LinearLayout { 114 public List<AccessibilityEvent> mReceivedEvents = new ArrayList<AccessibilityEvent>(); 115 EventReportingLinearLayout(Context context)116 public EventReportingLinearLayout(Context context) { 117 super(context); 118 } 119 120 @Override requestSendAccessibilityEvent(View child, AccessibilityEvent event)121 public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) { 122 mReceivedEvents.add(AccessibilityEvent.obtain(event)); 123 return super.requestSendAccessibilityEvent(child, event); 124 } 125 } 126 127 @Test testScrollEvent()128 public void testScrollEvent() throws Exception { 129 sUiAutomation.executeAndWaitForEvent( 130 () -> mChildView.scrollTo(0, 100), new ScrollEventFilter(1), DEFAULT_TIMEOUT_MS); 131 } 132 133 @Test testScrollEventBurstCombined()134 public void testScrollEventBurstCombined() throws Exception { 135 sUiAutomation.executeAndWaitForEvent( 136 () -> { 137 mChildView.scrollTo(0, 100); 138 mChildView.scrollTo(0, 125); 139 mChildView.scrollTo(0, 150); 140 mChildView.scrollTo(0, 175); 141 }, 142 new ScrollEventFilter(1), 143 DEFAULT_TIMEOUT_MS); 144 } 145 146 @Test testScrollEventsDeliveredInCorrectInterval()147 public void testScrollEventsDeliveredInCorrectInterval() throws Exception { 148 sUiAutomation.executeAndWaitForEvent( 149 () -> { 150 try { 151 mChildView.scrollTo(0, 25); 152 mChildView.scrollTo(0, 50); 153 mChildView.scrollTo(0, 100); 154 Thread.sleep(150); 155 mChildView.scrollTo(0, 150); 156 mChildView.scrollTo(0, 175); 157 Thread.sleep(50); 158 mChildView.scrollTo(0, 200); 159 } catch (InterruptedException e) { 160 fail("Interrupted while dispatching event bursts."); 161 } 162 }, 163 new ScrollEventFilter(2), 164 DEFAULT_TIMEOUT_MS); 165 } 166 167 class ScrollEventFilter extends AccessibilityEventFilter { 168 private int mCount = 0; 169 private int mTargetCount; 170 ScrollEventFilter(int count)171 ScrollEventFilter(int count) { 172 mTargetCount = count; 173 } 174 accept(AccessibilityEvent event)175 public boolean accept(AccessibilityEvent event) { 176 if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { 177 mCount += 1; 178 mEvents.add(event); 179 return mCount >= mTargetCount; 180 } 181 return false; 182 } 183 } 184 185 @Test testScrollEventsClearedOnDetach()186 public void testScrollEventsClearedOnDetach() throws Throwable { 187 ScrollEventFilter scrollEventFilter = new ScrollEventFilter(1); 188 sUiAutomation.executeAndWaitForEvent( 189 () -> { 190 mChildView.scrollTo(0, 25); 191 mChildView.scrollTo(5, 50); 192 mChildView.scrollTo(7, 100); 193 }, 194 scrollEventFilter, 195 DEFAULT_TIMEOUT_MS); 196 mActivityRule.runOnUiThread( 197 () -> { 198 mParentView.removeView(mChildView); 199 mParentView.addView(mChildView); 200 }); 201 sUiAutomation.executeAndWaitForEvent( 202 () -> { 203 mChildView.scrollTo(0, 150); 204 }, 205 scrollEventFilter, 206 DEFAULT_TIMEOUT_MS); 207 AccessibilityEvent event = scrollEventFilter.getLastEvent(); 208 assertEquals(-7, event.getScrollDeltaX()); 209 assertEquals(50, event.getScrollDeltaY()); 210 } 211 212 @Test testScrollEventsCaptureTotalDelta()213 public void testScrollEventsCaptureTotalDelta() throws Throwable { 214 ScrollEventFilter scrollEventFilter = new ScrollEventFilter(1); 215 sUiAutomation.executeAndWaitForEvent( 216 () -> { 217 mChildView.scrollTo(0, 25); 218 mChildView.scrollTo(5, 50); 219 mChildView.scrollTo(7, 100); 220 }, 221 scrollEventFilter, 222 DEFAULT_TIMEOUT_MS); 223 AccessibilityEvent event = scrollEventFilter.getLastEvent(); 224 assertEquals(7, event.getScrollDeltaX()); 225 assertEquals(100, event.getScrollDeltaY()); 226 } 227 228 @Test testScrollEventsClearDeltaAfterSending()229 public void testScrollEventsClearDeltaAfterSending() throws Throwable { 230 ScrollEventFilter scrollEventFilter = new ScrollEventFilter(2); 231 sUiAutomation.executeAndWaitForEvent( 232 () -> { 233 try { 234 mChildView.scrollTo(0, 25); 235 mChildView.scrollTo(5, 50); 236 mChildView.scrollTo(7, 100); 237 Thread.sleep(100); 238 mChildView.scrollTo(0, 25); 239 mChildView.scrollTo(5, 50); 240 mChildView.scrollTo(7, 100); 241 mChildView.scrollTo(0, 150); 242 } catch (InterruptedException e) { 243 fail("Interrupted while dispatching event bursts."); 244 } 245 }, 246 scrollEventFilter, 247 DEFAULT_TIMEOUT_MS); 248 AccessibilityEvent event = scrollEventFilter.getLastEvent(); 249 assertEquals(-7, event.getScrollDeltaX()); 250 assertEquals(50, event.getScrollDeltaY()); 251 } 252 253 @Test testStateEvent()254 public void testStateEvent() throws Throwable { 255 sUiAutomation.executeAndWaitForEvent( 256 () -> { 257 sendStateDescriptionChangedEvent(mChildView); 258 }, 259 new StateDescriptionEventFilter(1), 260 DEFAULT_TIMEOUT_MS); 261 } 262 263 @Test testStateEventBurstCombined()264 public void testStateEventBurstCombined() throws Throwable { 265 sUiAutomation.executeAndWaitForEvent( 266 () -> { 267 sendStateDescriptionChangedEvent(mChildView); 268 sendStateDescriptionChangedEvent(mChildView); 269 sendStateDescriptionChangedEvent(mChildView); 270 sendStateDescriptionChangedEvent(mChildView); 271 }, 272 new StateDescriptionEventFilter(1), 273 DEFAULT_TIMEOUT_MS); 274 } 275 276 @Test testStateEventsDeliveredInCorrectInterval()277 public void testStateEventsDeliveredInCorrectInterval() throws Throwable { 278 sUiAutomation.executeAndWaitForEvent( 279 () -> { 280 try { 281 sendStateDescriptionChangedEvent(mChildView); 282 sendStateDescriptionChangedEvent(mChildView); 283 sendStateDescriptionChangedEvent(mChildView); 284 Thread.sleep(150); 285 sendStateDescriptionChangedEvent(mChildView); 286 sendStateDescriptionChangedEvent(mChildView); 287 Thread.sleep(50); 288 sendStateDescriptionChangedEvent(mChildView); 289 } catch (InterruptedException e) { 290 fail("Interrupted while dispatching event bursts."); 291 } 292 }, 293 new StateDescriptionEventFilter(2), 294 DEFAULT_TIMEOUT_MS); 295 } 296 297 @Test testStateEventsHaveLastEventText()298 public void testStateEventsHaveLastEventText() throws Throwable { 299 StateDescriptionEventFilter stateDescriptionEventFilter = 300 new StateDescriptionEventFilter(1); 301 String expectedState = "Second state"; 302 sUiAutomation.executeAndWaitForEvent( 303 () -> { 304 sendStateDescriptionChangedEvent(mChildView, "First state"); 305 sendStateDescriptionChangedEvent(mChildView, expectedState); 306 }, 307 stateDescriptionEventFilter, 308 DEFAULT_TIMEOUT_MS); 309 AccessibilityEvent event = stateDescriptionEventFilter.getLastEvent(); 310 assertEquals(expectedState, event.getText().get(0)); 311 } 312 313 class StateDescriptionEventFilter extends AccessibilityEventFilter { 314 private int mCount; 315 private int mTargetCount; 316 StateDescriptionEventFilter(int count)317 StateDescriptionEventFilter(int count) { 318 mTargetCount = count; 319 } 320 accept(AccessibilityEvent event)321 public boolean accept(AccessibilityEvent event) { 322 if (event.getContentChangeTypes() 323 == AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) { 324 mCount += 1; 325 mEvents.add(event); 326 return mCount >= mTargetCount; 327 } 328 return false; 329 } 330 } 331 ; 332 333 private abstract class AccessibilityEventFilter 334 implements UiAutomation.AccessibilityEventFilter { 335 protected List<AccessibilityEvent> mEvents = new ArrayList<>(); 336 accept(AccessibilityEvent event)337 public abstract boolean accept(AccessibilityEvent event); 338 assertReceivedEventCount(int count)339 void assertReceivedEventCount(int count) { 340 assertEquals(count, mEvents.size()); 341 } 342 getLastEvent()343 AccessibilityEvent getLastEvent() { 344 if (mEvents.size() > 0) { 345 return mEvents.get(mEvents.size() - 1); 346 } 347 return null; 348 } 349 } 350 sendStateDescriptionChangedEvent(View view)351 private void sendStateDescriptionChangedEvent(View view) { 352 sendStateDescriptionChangedEvent(view, null); 353 } 354 sendStateDescriptionChangedEvent(View view, CharSequence text)355 private void sendStateDescriptionChangedEvent(View view, CharSequence text) { 356 AccessibilityEvent event = 357 AccessibilityEvent.obtain(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 358 event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION); 359 event.getText().add(text); 360 view.sendAccessibilityEventUnchecked(event); 361 } 362 363 @Test setText_textChanged_receivesTextEvent()364 public void setText_textChanged_receivesTextEvent() throws Throwable { 365 sUiAutomation.executeAndWaitForEvent( 366 () -> sInstrumentation.runOnMainSync(() -> mTextView.setText("a")), 367 event -> isExpectedChangeType(event, AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT), 368 DEFAULT_TIMEOUT_MS); 369 370 sUiAutomation.executeAndWaitForEvent( 371 () -> { 372 sInstrumentation.runOnMainSync( 373 () -> { 374 mTextView.setText("b"); 375 }); 376 }, 377 event -> 378 isExpectedSource(event, mTextView) 379 && isExpectedChangeType( 380 event, AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT), 381 DEFAULT_TIMEOUT_MS); 382 } 383 384 @Test setText_parcelableSpanChanged_receivesUndefinedEvent()385 public void setText_parcelableSpanChanged_receivesUndefinedEvent() throws Throwable { 386 String text = "a"; 387 sUiAutomation.executeAndWaitForEvent( 388 () -> sInstrumentation.runOnMainSync(() -> mTextView.setText(text)), 389 event -> isExpectedChangeType(event, AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT), 390 DEFAULT_TIMEOUT_MS); 391 392 sUiAutomation.executeAndWaitForEvent( 393 () -> { 394 sInstrumentation.runOnMainSync( 395 () -> { 396 SpannableString spannableString = new SpannableString(text); 397 spannableString.setSpan(new LocaleSpan(Locale.ENGLISH), 0, 1, 0); 398 mTextView.setText(spannableString); 399 }); 400 }, 401 event -> 402 isExpectedSource(event, mTextView) 403 && isExpectedChangeType( 404 event, AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED), 405 DEFAULT_TIMEOUT_MS); 406 } 407 isExpectedSource(AccessibilityEvent event, View view)408 private static boolean isExpectedSource(AccessibilityEvent event, View view) { 409 return TextUtils.equals(view.getContext().getPackageName(), event.getPackageName()) 410 && TextUtils.equals(view.getAccessibilityClassName(), event.getClassName()); 411 } 412 isExpectedChangeType(AccessibilityEvent event, int changeType)413 private static boolean isExpectedChangeType(AccessibilityEvent event, int changeType) { 414 return (event.getContentChangeTypes() & changeType) == changeType; 415 } 416 417 /** 418 * Tests whether accessibility events are correctly written and read from a parcel (version 1). 419 */ 420 @SmallTest 421 @Test testMarshaling()422 public void testMarshaling() throws Exception { 423 // fully populate the event to marshal 424 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 425 fullyPopulateAccessibilityEvent(sentEvent); 426 427 // marshal and unmarshal the event 428 Parcel parcel = Parcel.obtain(); 429 sentEvent.writeToParcel(parcel, 0); 430 parcel.setDataPosition(0); 431 AccessibilityEvent receivedEvent = AccessibilityEvent.CREATOR.createFromParcel(parcel); 432 433 // make sure all fields properly marshaled 434 assertEqualsAccessibilityEvent(sentEvent, receivedEvent); 435 436 parcel.recycle(); 437 } 438 439 /** Tests if {@link AccessibilityEvent} can be acquired through obtain(). */ 440 @SmallTest 441 @Test testRecycle()442 public void testRecycle() { 443 // evaluate that recycle() can be called on an event acquired by obtain() 444 AccessibilityEvent.obtain().recycle(); 445 } 446 447 /** Tests whether the event types are correctly converted to strings. */ 448 @SmallTest 449 @Test testEventTypeToString()450 public void testEventTypeToString() { 451 assertEquals( 452 "TYPE_NOTIFICATION_STATE_CHANGED", 453 AccessibilityEvent.eventTypeToString( 454 AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)); 455 assertEquals( 456 "TYPE_TOUCH_EXPLORATION_GESTURE_END", 457 AccessibilityEvent.eventTypeToString( 458 AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END)); 459 assertEquals( 460 "TYPE_TOUCH_EXPLORATION_GESTURE_START", 461 AccessibilityEvent.eventTypeToString( 462 AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START)); 463 assertEquals( 464 "TYPE_VIEW_CLICKED", 465 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_CLICKED)); 466 assertEquals( 467 "TYPE_VIEW_FOCUSED", 468 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_FOCUSED)); 469 assertEquals( 470 "TYPE_VIEW_HOVER_ENTER", 471 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER)); 472 assertEquals( 473 "TYPE_VIEW_HOVER_EXIT", 474 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT)); 475 assertEquals( 476 "TYPE_VIEW_LONG_CLICKED", 477 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED)); 478 assertEquals( 479 "TYPE_VIEW_CONTEXT_CLICKED", 480 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED)); 481 assertEquals( 482 "TYPE_VIEW_SCROLLED", 483 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_SCROLLED)); 484 assertEquals( 485 "TYPE_VIEW_SELECTED", 486 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_SELECTED)); 487 assertEquals( 488 "TYPE_VIEW_TEXT_CHANGED", 489 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED)); 490 assertEquals( 491 "TYPE_VIEW_TEXT_SELECTION_CHANGED", 492 AccessibilityEvent.eventTypeToString( 493 AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED)); 494 assertEquals( 495 "TYPE_WINDOW_CONTENT_CHANGED", 496 AccessibilityEvent.eventTypeToString( 497 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)); 498 assertEquals( 499 "TYPE_WINDOW_STATE_CHANGED", 500 AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)); 501 } 502 503 /** Tests whether the event describes its contents consistently. */ 504 @SmallTest 505 @Test testDescribeContents()506 public void testDescribeContents() { 507 AccessibilityEvent event = AccessibilityEvent.obtain(); 508 assertSame( 509 "Accessibility events always return 0 for this method.", 510 0, 511 event.describeContents()); 512 fullyPopulateAccessibilityEvent(event); 513 assertSame( 514 "Accessibility events always return 0 for this method.", 515 0, 516 event.describeContents()); 517 } 518 519 /** 520 * Tests whether accessibility events are correctly written and read from a parcel (version 2). 521 */ 522 @SmallTest 523 @Test testMarshaling2()524 public void testMarshaling2() { 525 // fully populate the event to marshal 526 AccessibilityEvent marshaledEvent = AccessibilityEvent.obtain(); 527 fullyPopulateAccessibilityEvent(marshaledEvent); 528 529 // marshal and unmarshal the event 530 Parcel parcel = Parcel.obtain(); 531 marshaledEvent.writeToParcel(parcel, 0); 532 parcel.setDataPosition(0); 533 AccessibilityEvent unmarshaledEvent = AccessibilityEvent.obtain(); 534 unmarshaledEvent.initFromParcel(parcel); 535 536 // make sure all fields properly marshaled 537 assertEqualsAccessibilityEvent(marshaledEvent, unmarshaledEvent); 538 539 parcel.recycle(); 540 } 541 542 /** 543 * While CharSequence is immutable, some classes implementing it are mutable. Make sure they 544 * can't change the object by changing the objects backing CharSequence 545 */ 546 @SmallTest 547 @Test testChangeTextAfterSetting_shouldNotAffectEvent()548 public void testChangeTextAfterSetting_shouldNotAffectEvent() { 549 final String originalText = "Cassowary"; 550 final String newText = "Hornbill"; 551 AccessibilityEvent event = AccessibilityEvent.obtain(); 552 StringBuffer updatingString = new StringBuffer(originalText); 553 event.setBeforeText(updatingString); 554 event.setContentDescription(updatingString); 555 556 updatingString.delete(0, updatingString.length()); 557 updatingString.append(newText); 558 559 assertTrue(TextUtils.equals(originalText, event.getBeforeText())); 560 assertTrue(TextUtils.equals(originalText, event.getContentDescription())); 561 } 562 563 @SmallTest 564 @Test testConstructors()565 public void testConstructors() { 566 final AccessibilityEvent populatedEvent = new AccessibilityEvent(); 567 fullyPopulateAccessibilityEvent(populatedEvent); 568 final AccessibilityEvent event = new AccessibilityEvent(populatedEvent); 569 570 assertEqualsAccessibilityEvent(event, populatedEvent); 571 572 final AccessibilityEvent firstEvent = new AccessibilityEvent(); 573 firstEvent.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED); 574 final AccessibilityEvent secondEvent = 575 new AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 576 577 assertEqualsAccessibilityEvent(firstEvent, secondEvent); 578 } 579 580 /** 581 * Fully populates the {@link AccessibilityEvent} to marshal. 582 * 583 * @param sentEvent The event to populate. 584 */ fullyPopulateAccessibilityEvent(AccessibilityEvent sentEvent)585 private void fullyPopulateAccessibilityEvent(AccessibilityEvent sentEvent) { 586 sentEvent.setAddedCount(1); 587 sentEvent.setBeforeText("BeforeText"); 588 sentEvent.setChecked(true); 589 sentEvent.setClassName("foo.bar.baz.Class"); 590 sentEvent.setContentDescription("ContentDescription"); 591 sentEvent.setCurrentItemIndex(1); 592 sentEvent.setEnabled(true); 593 sentEvent.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED); 594 sentEvent.setEventTime(1000); 595 sentEvent.setFromIndex(1); 596 sentEvent.setFullScreen(true); 597 sentEvent.setItemCount(1); 598 sentEvent.setPackageName("foo.bar.baz"); 599 sentEvent.setParcelableData(Message.obtain(null, 1, 2, 3)); 600 sentEvent.setPassword(true); 601 sentEvent.setRemovedCount(1); 602 sentEvent.getText().add("Foo"); 603 sentEvent.setMaxScrollX(1); 604 sentEvent.setMaxScrollY(1); 605 sentEvent.setScrollX(1); 606 sentEvent.setScrollY(1); 607 sentEvent.setScrollDeltaX(3); 608 sentEvent.setScrollDeltaY(3); 609 sentEvent.setToIndex(1); 610 sentEvent.setScrollable(true); 611 sentEvent.setAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 612 sentEvent.setMovementGranularity(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE); 613 614 AccessibilityRecord record = AccessibilityRecord.obtain(); 615 AccessibilityRecordTest.fullyPopulateAccessibilityRecord(record); 616 sentEvent.appendRecord(record); 617 } 618 619 /** 620 * Compares all properties of the <code>expectedEvent</code> and the <code>receivedEvent</code> 621 * to verify that the received event is the one that is expected. 622 */ assertEqualsAccessibilityEvent( AccessibilityEvent expectedEvent, AccessibilityEvent receivedEvent)623 private static void assertEqualsAccessibilityEvent( 624 AccessibilityEvent expectedEvent, AccessibilityEvent receivedEvent) { 625 assertEquals( 626 "addedCount has incorrect value", 627 expectedEvent.getAddedCount(), 628 receivedEvent.getAddedCount()); 629 assertEquals( 630 "beforeText has incorrect value", 631 expectedEvent.getBeforeText(), 632 receivedEvent.getBeforeText()); 633 assertEquals( 634 "checked has incorrect value", 635 expectedEvent.isChecked(), 636 receivedEvent.isChecked()); 637 assertEquals( 638 "className has incorrect value", 639 expectedEvent.getClassName(), 640 receivedEvent.getClassName()); 641 assertEquals( 642 "contentDescription has incorrect value", 643 expectedEvent.getContentDescription(), 644 receivedEvent.getContentDescription()); 645 assertEquals( 646 "currentItemIndex has incorrect value", 647 expectedEvent.getCurrentItemIndex(), 648 receivedEvent.getCurrentItemIndex()); 649 assertEquals( 650 "enabled has incorrect value", 651 expectedEvent.isEnabled(), 652 receivedEvent.isEnabled()); 653 assertEquals( 654 "eventType has incorrect value", 655 expectedEvent.getEventType(), 656 receivedEvent.getEventType()); 657 assertEquals( 658 "fromIndex has incorrect value", 659 expectedEvent.getFromIndex(), 660 receivedEvent.getFromIndex()); 661 assertEquals( 662 "fullScreen has incorrect value", 663 expectedEvent.isFullScreen(), 664 receivedEvent.isFullScreen()); 665 assertEquals( 666 "itemCount has incorrect value", 667 expectedEvent.getItemCount(), 668 receivedEvent.getItemCount()); 669 assertEquals( 670 "password has incorrect value", 671 expectedEvent.isPassword(), 672 receivedEvent.isPassword()); 673 assertEquals( 674 "removedCount has incorrect value", 675 expectedEvent.getRemovedCount(), 676 receivedEvent.getRemovedCount()); 677 assertSame( 678 "maxScrollX has incorrect value", 679 expectedEvent.getMaxScrollX(), 680 receivedEvent.getMaxScrollX()); 681 assertSame( 682 "maxScrollY has incorrect value", 683 expectedEvent.getMaxScrollY(), 684 receivedEvent.getMaxScrollY()); 685 assertSame( 686 "scrollX has incorrect value", 687 expectedEvent.getScrollX(), 688 receivedEvent.getScrollX()); 689 assertSame( 690 "scrollY has incorrect value", 691 expectedEvent.getScrollY(), 692 receivedEvent.getScrollY()); 693 assertSame( 694 "scrollDeltaX has incorrect value", 695 expectedEvent.getScrollDeltaX(), 696 receivedEvent.getScrollDeltaX()); 697 assertSame( 698 "scrollDeltaY has incorrect value", 699 expectedEvent.getScrollDeltaY(), 700 receivedEvent.getScrollDeltaY()); 701 assertSame( 702 "toIndex has incorrect value", 703 expectedEvent.getToIndex(), 704 receivedEvent.getToIndex()); 705 assertSame( 706 "scrollable has incorrect value", 707 expectedEvent.isScrollable(), 708 receivedEvent.isScrollable()); 709 assertSame( 710 "granularity has incorrect value", 711 expectedEvent.getMovementGranularity(), 712 receivedEvent.getMovementGranularity()); 713 assertSame( 714 "action has incorrect value", expectedEvent.getAction(), receivedEvent.getAction()); 715 assertSame( 716 "windowChangeTypes has incorrect value", 717 expectedEvent.getWindowChanges(), 718 receivedEvent.getWindowChanges()); 719 720 AccessibilityRecordTest.assertEqualsText(expectedEvent.getText(), receivedEvent.getText()); 721 AccessibilityRecordTest.assertEqualAccessibilityRecord(expectedEvent, receivedEvent); 722 723 assertEqualAppendedRecord(expectedEvent, receivedEvent); 724 } 725 assertEqualAppendedRecord( AccessibilityEvent expectedEvent, AccessibilityEvent receivedEvent)726 private static void assertEqualAppendedRecord( 727 AccessibilityEvent expectedEvent, AccessibilityEvent receivedEvent) { 728 assertEquals( 729 "recordCount has incorrect value", 730 expectedEvent.getRecordCount(), 731 receivedEvent.getRecordCount()); 732 if (expectedEvent.getRecordCount() != 0 && receivedEvent.getRecordCount() != 0) { 733 AccessibilityRecord expectedRecord = expectedEvent.getRecord(0); 734 AccessibilityRecord receivedRecord = receivedEvent.getRecord(0); 735 AccessibilityRecordTest.assertEqualAccessibilityRecord(expectedRecord, receivedRecord); 736 } 737 } 738 739 /** 740 * Asserts that an {@link AccessibilityEvent} is cleared. 741 * 742 * @param event The event to check. 743 */ assertAccessibilityEventCleared(AccessibilityEvent event)744 private static void assertAccessibilityEventCleared(AccessibilityEvent event) { 745 AccessibilityRecordTest.assertAccessibilityRecordCleared(event); 746 TestCase.assertEquals("eventTime not properly recycled", 0, event.getEventTime()); 747 TestCase.assertEquals("eventType not properly recycled", 0, event.getEventType()); 748 TestCase.assertNull("packageName not properly recycled", event.getPackageName()); 749 } 750 } 751