AccessibilityManagerServiceTest.java revision 5637745e59e1c0c22ec2e0adb1f48f8f4edcb7be
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 17package com.android.server; 18 19import android.accessibilityservice.AccessibilityService; 20import android.accessibilityservice.AccessibilityServiceInfo; 21import android.content.ComponentName; 22import android.content.Context; 23import android.content.pm.ServiceInfo; 24import android.os.IBinder; 25import android.os.Message; 26import android.os.ServiceManager; 27import android.os.SystemClock; 28import android.provider.Settings; 29import android.test.AndroidTestCase; 30import android.test.suitebuilder.annotation.LargeTest; 31import android.view.accessibility.AccessibilityEvent; 32import android.view.accessibility.IAccessibilityManager; 33import android.view.accessibility.IAccessibilityManagerClient; 34 35/** 36 * This test exercises the 37 * {@link com.android.server.AccessibilityManagerService} by mocking the 38 * {@link android.view.accessibility.AccessibilityManager} which talks to to the 39 * service. The service itself is interacting with the platform. Note: Testing 40 * the service in full isolation would require significant amount of work for 41 * mocking all system interactions. It would also require a lot of mocking code. 42 */ 43public class AccessibilityManagerServiceTest extends AndroidTestCase { 44 45 /** 46 * Timeout required for pending Binder calls or event processing to 47 * complete. 48 */ 49 private static final long TIMEOUT_BINDER_CALL = 100; 50 51 /** 52 * Timeout in which we are waiting for the system to start the mock 53 * accessibility services. 54 */ 55 private static final long TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES = 300; 56 57 /** 58 * Timeout used for testing that a service is notified only upon a 59 * notification timeout. 60 */ 61 private static final long TIMEOUT_TEST_NOTIFICATION_TIMEOUT = 300; 62 63 /** 64 * The package name. 65 */ 66 private static String sPackageName; 67 68 /** 69 * The interface used to talk to the tested service. 70 */ 71 private IAccessibilityManager mManagerService; 72 73 @Override 74 public void setContext(Context context) { 75 super.setContext(context); 76 if (sPackageName == null) { 77 sPackageName = context.getPackageName(); 78 } 79 } 80 81 /** 82 * Creates a new instance. 83 */ 84 public AccessibilityManagerServiceTest() { 85 IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE); 86 mManagerService = IAccessibilityManager.Stub.asInterface(iBinder); 87 } 88 89 @LargeTest 90 public void testAddClient_AccessibilityDisabledThenEnabled() throws Exception { 91 // make sure accessibility is disabled 92 ensureAccessibilityEnabled(mContext, false); 93 94 // create a client mock instance 95 MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient(); 96 97 // invoke the method under test 98 boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient); 99 100 // check expected result 101 assertFalse("The client must be disabled since accessibility is disabled.", 102 enabledAccessibilityDisabled); 103 104 // enable accessibility 105 ensureAccessibilityEnabled(mContext, true); 106 107 // invoke the method under test 108 boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient); 109 110 // check expected result 111 assertTrue("The client must be enabled since accessibility is enabled.", 112 enabledAccessibilityEnabled); 113 } 114 115 @LargeTest 116 public void testAddClient_AccessibilityEnabledThenDisabled() throws Exception { 117 // enable accessibility before registering the client 118 ensureAccessibilityEnabled(mContext, true); 119 120 // create a client mock instance 121 MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient(); 122 123 // invoke the method under test 124 boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient); 125 126 // check expected result 127 assertTrue("The client must be enabled since accessibility is enabled.", 128 enabledAccessibilityEnabled); 129 130 // disable accessibility 131 ensureAccessibilityEnabled(mContext, false); 132 133 // invoke the method under test 134 boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient); 135 136 // check expected result 137 assertFalse("The client must be disabled since accessibility is disabled.", 138 enabledAccessibilityDisabled); 139 } 140 141 @LargeTest 142 public void testGetAccessibilityServicesList() throws Exception { 143 boolean firstMockServiceInstalled = false; 144 boolean secondMockServiceInstalled = false; 145 146 String packageName = getContext().getPackageName(); 147 String firstMockServiceClassName = MyFirstMockAccessibilityService.class.getName(); 148 String secondMockServiceClassName = MySecondMockAccessibilityService.class.getName(); 149 150 // look for the two mock services 151 for (ServiceInfo serviceInfo : mManagerService.getAccessibilityServiceList()) { 152 if (packageName.equals(serviceInfo.packageName)) { 153 if (firstMockServiceClassName.equals(serviceInfo.name)) { 154 firstMockServiceInstalled = true; 155 } else if (secondMockServiceClassName.equals(serviceInfo.name)) { 156 secondMockServiceInstalled = true; 157 } 158 } 159 } 160 161 // check expected result 162 assertTrue("First mock service must be installed", firstMockServiceInstalled); 163 assertTrue("Second mock service must be installed", secondMockServiceInstalled); 164 } 165 166 @LargeTest 167 public void testSendAccessibilityEvent_OneService_MatchingPackageAndEventType() 168 throws Exception { 169 // set the accessibility setting value 170 ensureAccessibilityEnabled(mContext, true); 171 172 // enable the mock accessibility service 173 ensureOnlyMockServicesEnabled(mContext, true, false); 174 175 // configure the mock service 176 MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; 177 service.setServiceInfo(MockAccessibilityService.createDefaultInfo()); 178 179 // wait for the binder call to #setService to complete 180 Thread.sleep(TIMEOUT_BINDER_CALL); 181 182 // create and populate an event to be sent 183 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 184 fullyPopulateDefaultAccessibilityEvent(sentEvent); 185 186 // set expectations 187 service.expectEvent(sentEvent); 188 service.replay(); 189 190 // send the event 191 mManagerService.sendAccessibilityEvent(sentEvent); 192 193 // verify if all expected methods have been called 194 assertMockServiceVerifiedWithinTimeout(service); 195 } 196 197 @LargeTest 198 public void testSendAccessibilityEvent_OneService_NotMatchingPackage() throws Exception { 199 // set the accessibility setting value 200 ensureAccessibilityEnabled(mContext, true); 201 202 // enable the mock accessibility service 203 ensureOnlyMockServicesEnabled(mContext, true, false); 204 205 // configure the mock service 206 MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; 207 service.setServiceInfo(MockAccessibilityService.createDefaultInfo()); 208 209 // wait for the binder call to #setService to complete 210 Thread.sleep(TIMEOUT_BINDER_CALL); 211 212 // create and populate an event to be sent 213 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 214 fullyPopulateDefaultAccessibilityEvent(sentEvent); 215 sentEvent.setPackageName("no.service.registered.for.this.package"); 216 217 // set expectations 218 service.replay(); 219 220 // send the event 221 mManagerService.sendAccessibilityEvent(sentEvent); 222 223 // verify if all expected methods have been called 224 assertMockServiceVerifiedWithinTimeout(service); 225 } 226 227 @LargeTest 228 public void testSendAccessibilityEvent_OneService_NotMatchingEventType() throws Exception { 229 // set the accessibility setting value 230 ensureAccessibilityEnabled(mContext, true); 231 232 // enable the mock accessibility service 233 ensureOnlyMockServicesEnabled(mContext, true, false); 234 235 // configure the mock service 236 MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; 237 service.setServiceInfo(MockAccessibilityService.createDefaultInfo()); 238 239 // wait for the binder call to #setService to complete 240 Thread.sleep(TIMEOUT_BINDER_CALL); 241 242 // create and populate an event to be sent 243 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 244 fullyPopulateDefaultAccessibilityEvent(sentEvent); 245 sentEvent.setEventType(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); 246 247 // set expectations 248 service.replay(); 249 250 // send the event 251 mManagerService.sendAccessibilityEvent(sentEvent); 252 253 // verify if all expected methods have been called 254 assertMockServiceVerifiedWithinTimeout(service); 255 } 256 257 @LargeTest 258 public void testSendAccessibilityEvent_OneService_NotifivationAfterTimeout() throws Exception { 259 // set the accessibility setting value 260 ensureAccessibilityEnabled(mContext, true); 261 262 // enable the mock accessibility service 263 ensureOnlyMockServicesEnabled(mContext, true, false); 264 265 // configure the mock service 266 MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; 267 AccessibilityServiceInfo info = MockAccessibilityService.createDefaultInfo(); 268 info.notificationTimeout = TIMEOUT_TEST_NOTIFICATION_TIMEOUT; 269 service.setServiceInfo(info); 270 271 // wait for the binder call to #setService to complete 272 Thread.sleep(TIMEOUT_BINDER_CALL); 273 274 // create and populate the first event to be sent 275 AccessibilityEvent firstEvent = AccessibilityEvent.obtain(); 276 fullyPopulateDefaultAccessibilityEvent(firstEvent); 277 278 // create and populate the second event to be sent 279 AccessibilityEvent secondEvent = AccessibilityEvent.obtain(); 280 fullyPopulateDefaultAccessibilityEvent(secondEvent); 281 282 // set expectations 283 service.expectEvent(secondEvent); 284 service.replay(); 285 286 // send the events 287 mManagerService.sendAccessibilityEvent(firstEvent); 288 mManagerService.sendAccessibilityEvent(secondEvent); 289 290 // wait for #sendAccessibilityEvent to reach the backing service 291 Thread.sleep(TIMEOUT_BINDER_CALL); 292 293 try { 294 service.verify(); 295 fail("No events must be dispatched before the expiration of the notification timeout."); 296 } catch (IllegalStateException ise) { 297 /* expected */ 298 } 299 300 // wait for the configured notification timeout to expire 301 Thread.sleep(TIMEOUT_TEST_NOTIFICATION_TIMEOUT); 302 303 // verify if all expected methods have been called 304 assertMockServiceVerifiedWithinTimeout(service); 305 } 306 307 @LargeTest 308 public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_DiffFeedback() 309 throws Exception { 310 // set the accessibility setting value 311 ensureAccessibilityEnabled(mContext, true); 312 313 // enable the mock accessibility services 314 ensureOnlyMockServicesEnabled(mContext, true, true); 315 316 // configure the first mock service 317 MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; 318 AccessibilityServiceInfo firstInfo = MockAccessibilityService.createDefaultInfo(); 319 firstInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE; 320 firstService.setServiceInfo(firstInfo); 321 322 // configure the second mock service 323 MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; 324 AccessibilityServiceInfo secondInfo = MockAccessibilityService.createDefaultInfo(); 325 secondInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_HAPTIC; 326 secondService.setServiceInfo(secondInfo); 327 328 // wait for the binder calls to #setService to complete 329 Thread.sleep(TIMEOUT_BINDER_CALL); 330 331 // create and populate an event to be sent 332 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 333 fullyPopulateDefaultAccessibilityEvent(sentEvent); 334 335 // set expectations for the first mock service 336 firstService.expectEvent(sentEvent); 337 firstService.replay(); 338 339 // set expectations for the second mock service 340 secondService.expectEvent(sentEvent); 341 secondService.replay(); 342 343 // send the event 344 mManagerService.sendAccessibilityEvent(sentEvent); 345 346 // verify if all expected methods have been called 347 assertMockServiceVerifiedWithinTimeout(firstService); 348 assertMockServiceVerifiedWithinTimeout(secondService); 349 } 350 351 @LargeTest 352 public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType() 353 throws Exception { 354 // set the accessibility setting value 355 ensureAccessibilityEnabled(mContext, true); 356 357 // enable the mock accessibility services 358 ensureOnlyMockServicesEnabled(mContext, true, true); 359 360 // configure the first mock service 361 MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; 362 firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); 363 364 // configure the second mock service 365 MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; 366 secondService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); 367 368 // wait for the binder calls to #setService to complete 369 Thread.sleep(TIMEOUT_BINDER_CALL); 370 371 // create and populate an event to be sent 372 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 373 fullyPopulateDefaultAccessibilityEvent(sentEvent); 374 375 // set expectations for the first mock service 376 firstService.expectEvent(sentEvent); 377 firstService.replay(); 378 379 // set expectations for the second mock service 380 secondService.replay(); 381 382 // send the event 383 mManagerService.sendAccessibilityEvent(sentEvent); 384 385 // verify if all expected methods have been called 386 assertMockServiceVerifiedWithinTimeout(firstService); 387 assertMockServiceVerifiedWithinTimeout(secondService); 388 } 389 390 @LargeTest 391 public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_OneDefault() 392 throws Exception { 393 // set the accessibility setting value 394 ensureAccessibilityEnabled(mContext, true); 395 396 // enable the mock accessibility services 397 ensureOnlyMockServicesEnabled(mContext, true, true); 398 399 // configure the first mock service 400 MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; 401 AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo(); 402 firstInfo.flags = AccessibilityServiceInfo.DEFAULT; 403 firstService.setServiceInfo(firstInfo); 404 405 // configure the second mock service 406 MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; 407 secondService.setServiceInfo(MySecondMockAccessibilityService.createDefaultInfo()); 408 409 // wait for the binder calls to #setService to complete 410 Thread.sleep(TIMEOUT_BINDER_CALL); 411 412 // create and populate an event to be sent 413 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 414 fullyPopulateDefaultAccessibilityEvent(sentEvent); 415 416 // set expectations for the first mock service 417 firstService.replay(); 418 419 // set expectations for the second mock service 420 secondService.expectEvent(sentEvent); 421 secondService.replay(); 422 423 // send the event 424 mManagerService.sendAccessibilityEvent(sentEvent); 425 426 // verify if all expected methods have been called 427 assertMockServiceVerifiedWithinTimeout(firstService); 428 assertMockServiceVerifiedWithinTimeout(secondService); 429 } 430 431 @LargeTest 432 public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_TwoDefault() 433 throws Exception { 434 // set the accessibility setting value 435 ensureAccessibilityEnabled(mContext, true); 436 437 // enable the mock accessibility services 438 ensureOnlyMockServicesEnabled(mContext, true, true); 439 440 // configure the first mock service 441 MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; 442 AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo(); 443 firstInfo.flags = AccessibilityServiceInfo.DEFAULT; 444 firstService.setServiceInfo(firstInfo); 445 446 // configure the second mock service 447 MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; 448 AccessibilityServiceInfo secondInfo = MyFirstMockAccessibilityService.createDefaultInfo(); 449 secondInfo.flags = AccessibilityServiceInfo.DEFAULT; 450 secondService.setServiceInfo(firstInfo); 451 452 // wait for the binder calls to #setService to complete 453 Thread.sleep(TIMEOUT_BINDER_CALL); 454 455 // create and populate an event to be sent 456 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 457 fullyPopulateDefaultAccessibilityEvent(sentEvent); 458 459 // set expectations for the first mock service 460 firstService.expectEvent(sentEvent); 461 firstService.replay(); 462 463 // set expectations for the second mock service 464 secondService.replay(); 465 466 // send the event 467 mManagerService.sendAccessibilityEvent(sentEvent); 468 469 // verify if all expected methods have been called 470 assertMockServiceVerifiedWithinTimeout(firstService); 471 assertMockServiceVerifiedWithinTimeout(secondService); 472 } 473 474 @LargeTest 475 public void testInterrupt() throws Exception { 476 // set the accessibility setting value 477 ensureAccessibilityEnabled(mContext, true); 478 479 // enable the mock accessibility services 480 ensureOnlyMockServicesEnabled(mContext, true, true); 481 482 // configure the first mock service 483 MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; 484 firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); 485 486 // configure the second mock service 487 MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; 488 secondService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); 489 490 // wait for the binder calls to #setService to complete 491 Thread.sleep(TIMEOUT_BINDER_CALL); 492 493 // set expectations for the first mock service 494 firstService.expectInterrupt(); 495 firstService.replay(); 496 497 // set expectations for the second mock service 498 secondService.expectInterrupt(); 499 secondService.replay(); 500 501 // call the method under test 502 mManagerService.interrupt(); 503 504 // verify if all expected methods have been called 505 assertMockServiceVerifiedWithinTimeout(firstService); 506 assertMockServiceVerifiedWithinTimeout(secondService); 507 } 508 509 /** 510 * Fully populates the {@link AccessibilityEvent} to marshal. 511 * 512 * @param sentEvent The event to populate. 513 */ 514 private void fullyPopulateDefaultAccessibilityEvent(AccessibilityEvent sentEvent) { 515 sentEvent.setAddedCount(1); 516 sentEvent.setBeforeText("BeforeText"); 517 sentEvent.setChecked(true); 518 sentEvent.setClassName("foo.bar.baz.Class"); 519 sentEvent.setContentDescription("ContentDescription"); 520 sentEvent.setCurrentItemIndex(1); 521 sentEvent.setEnabled(true); 522 sentEvent.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED); 523 sentEvent.setEventTime(1000); 524 sentEvent.setFromIndex(1); 525 sentEvent.setFullScreen(true); 526 sentEvent.setItemCount(1); 527 sentEvent.setPackageName("foo.bar.baz"); 528 sentEvent.setParcelableData(Message.obtain(null, 1, null)); 529 sentEvent.setPassword(true); 530 sentEvent.setRemovedCount(1); 531 } 532 533 /** 534 * This class is a mock {@link IAccessibilityManagerClient}. 535 */ 536 public class MyMockAccessibilityManagerClient extends IAccessibilityManagerClient.Stub { 537 boolean mIsEnabled; 538 539 public void setEnabled(boolean enabled) { 540 mIsEnabled = enabled; 541 } 542 } 543 544 /** 545 * Ensures accessibility is in a given state by writing the state to the 546 * settings and waiting until the accessibility manager service pick it up. 547 * 548 * @param context A context handle to access the settings. 549 * @param enabled The accessibility state to write to the settings. 550 * @throws Exception If any error occurs. 551 */ 552 private void ensureAccessibilityEnabled(Context context, boolean enabled) throws Exception { 553 boolean isEnabled = (Settings.Secure.getInt(context.getContentResolver(), 554 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1 ? true : false); 555 556 if (isEnabled == enabled) { 557 return; 558 } 559 560 Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 561 enabled ? 1 : 0); 562 563 // wait the accessibility manager service to pick the change up 564 Thread.sleep(TIMEOUT_BINDER_CALL); 565 } 566 567 /** 568 * Ensures the only {@link MockAccessibilityService}s with given component 569 * names are enabled by writing to the system settings and waiting until the 570 * accessibility manager service picks that up or the 571 * {@link #TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES} is exceeded. 572 * 573 * @param context A context handle to access the settings. 574 * @param firstMockServiceEnabled If the first mock accessibility service is enabled. 575 * @param secondMockServiceEnabled If the second mock accessibility service is enabled. 576 * @throws IllegalStateException If some of the requested for enabling mock services 577 * is not properly started. 578 * @throws Exception Exception If any error occurs. 579 */ 580 private void ensureOnlyMockServicesEnabled(Context context, boolean firstMockServiceEnabled, 581 boolean secondMockServiceEnabled) throws Exception { 582 String enabledServices = Settings.Secure.getString(context.getContentResolver(), 583 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 584 585 StringBuilder servicesToEnable = new StringBuilder(); 586 if (firstMockServiceEnabled) { 587 servicesToEnable.append(MyFirstMockAccessibilityService.sComponentName).append(":"); 588 } 589 if (secondMockServiceEnabled) { 590 servicesToEnable.append(MySecondMockAccessibilityService.sComponentName).append(":"); 591 } 592 593 if (servicesToEnable.equals(enabledServices)) { 594 return; 595 } 596 597 Settings.Secure.putString(context.getContentResolver(), 598 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, servicesToEnable.toString()); 599 600 // we have enabled the services of interest and need to wait until they 601 // are instantiated and started (if needed) and the system binds to them 602 boolean firstMockServiceOK = false; 603 boolean secondMockServiceOK = false; 604 long start = SystemClock.uptimeMillis(); 605 long pollingInterval = TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES / 6; 606 607 while (SystemClock.uptimeMillis() - start < TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES) { 608 firstMockServiceOK = !firstMockServiceEnabled 609 || (MyFirstMockAccessibilityService.sInstance != null 610 && MyFirstMockAccessibilityService.sInstance.isSystemBoundAsClient()); 611 612 secondMockServiceOK = !secondMockServiceEnabled 613 || (MySecondMockAccessibilityService.sInstance != null 614 && MySecondMockAccessibilityService.sInstance.isSystemBoundAsClient()); 615 616 if (firstMockServiceOK && secondMockServiceOK) { 617 return; 618 } 619 620 Thread.sleep(pollingInterval); 621 } 622 623 StringBuilder message = new StringBuilder(); 624 message.append("Mock accessibility services not started or system not bound as a client: "); 625 if (!firstMockServiceOK) { 626 message.append(MyFirstMockAccessibilityService.sComponentName); 627 message.append(" "); 628 } 629 if (!secondMockServiceOK) { 630 message.append(MySecondMockAccessibilityService.sComponentName); 631 } 632 throw new IllegalStateException(message.toString()); 633 } 634 635 /** 636 * Asserts the the mock accessibility service has been successfully verified 637 * (which is it has received the expected method calls with expected 638 * arguments) within the {@link #TIMEOUT_BINDER_CALL}. The verified state is 639 * checked by polling upon small intervals. 640 * 641 * @param service The service to verify. 642 * @throws Exception If the verification has failed with exception after the 643 * {@link #TIMEOUT_BINDER_CALL}. 644 */ 645 private void assertMockServiceVerifiedWithinTimeout(MockAccessibilityService service) 646 throws Exception { 647 Exception lastVerifyException = null; 648 long beginTime = SystemClock.uptimeMillis(); 649 long pollTmeout = TIMEOUT_BINDER_CALL / 5; 650 651 // poll until the timeout has elapsed 652 while (SystemClock.uptimeMillis() - beginTime < TIMEOUT_BINDER_CALL) { 653 // sleep first since immediate call will always fail 654 try { 655 Thread.sleep(pollTmeout); 656 } catch (InterruptedException ie) { 657 /* ignore */ 658 } 659 // poll for verification and if this fails save the exception and 660 // keep polling 661 try { 662 service.verify(); 663 // reset so it does not accept more events 664 service.reset(); 665 return; 666 } catch (Exception e) { 667 lastVerifyException = e; 668 } 669 } 670 671 // reset, we have already failed 672 service.reset(); 673 674 // always not null 675 throw lastVerifyException; 676 } 677 678 /** 679 * This class is the first mock {@link AccessibilityService}. 680 */ 681 public static class MyFirstMockAccessibilityService extends MockAccessibilityService { 682 683 /** 684 * The service {@link ComponentName} flattened as a string. 685 */ 686 static final String sComponentName = new ComponentName( 687 sPackageName, 688 MyFirstMockAccessibilityService.class.getName() 689 ).flattenToShortString(); 690 691 /** 692 * Handle to the service instance. 693 */ 694 static MyFirstMockAccessibilityService sInstance; 695 696 /** 697 * Creates a new instance. 698 */ 699 public MyFirstMockAccessibilityService() { 700 sInstance = this; 701 } 702 } 703 704 /** 705 * This class is the first mock {@link AccessibilityService}. 706 */ 707 public static class MySecondMockAccessibilityService extends MockAccessibilityService { 708 709 /** 710 * The service {@link ComponentName} flattened as a string. 711 */ 712 static final String sComponentName = new ComponentName( 713 sPackageName, 714 MySecondMockAccessibilityService.class.getName() 715 ).flattenToShortString(); 716 717 /** 718 * Handle to the service instance. 719 */ 720 static MySecondMockAccessibilityService sInstance; 721 722 /** 723 * Creates a new instance. 724 */ 725 public MySecondMockAccessibilityService() { 726 sInstance = this; 727 } 728 } 729} 730