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