1/* 2 * Copyright (C) 2017 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.timezone; 18 19import org.hamcrest.BaseMatcher; 20import org.hamcrest.Description; 21import org.hamcrest.Matcher; 22import org.junit.After; 23import org.junit.Before; 24import org.junit.Test; 25 26import android.app.timezone.RulesUpdaterContract; 27import android.content.Context; 28import android.content.Intent; 29import android.provider.TimeZoneRulesDataContract; 30import android.support.test.InstrumentationRegistry; 31import android.support.test.filters.SmallTest; 32 33import java.io.File; 34import java.io.PrintWriter; 35import java.io.StringWriter; 36import java.time.Clock; 37import java.time.Instant; 38import java.time.ZoneId; 39 40import static org.junit.Assert.assertEquals; 41import static org.junit.Assert.assertFalse; 42import static org.junit.Assert.assertNotNull; 43import static org.junit.Assert.assertNull; 44import static org.junit.Assert.assertTrue; 45import static org.junit.Assert.fail; 46import static org.mockito.Mockito.eq; 47import static org.mockito.Mockito.mock; 48import static org.mockito.Mockito.when; 49import static org.mockito.hamcrest.MockitoHamcrest.argThat; 50 51/** 52 * White box interaction / unit testing of the {@link PackageTracker}. 53 */ 54@SmallTest 55public class PackageTrackerTest { 56 private static final String UPDATE_APP_PACKAGE_NAME = "updateAppPackageName"; 57 private static final String DATA_APP_PACKAGE_NAME = "dataAppPackageName"; 58 private static final PackageVersions INITIAL_APP_PACKAGE_VERSIONS = 59 new PackageVersions(2 /* updateAppVersion */, 2 /* dataAppVersion */); 60 61 private ConfigHelper mMockConfigHelper; 62 private PackageManagerHelper mMockPackageManagerHelper; 63 64 private FakeClock mFakeClock; 65 private FakeIntentHelper mFakeIntentHelper; 66 private PackageStatusStorage mPackageStatusStorage; 67 private PackageTracker mPackageTracker; 68 69 @Before 70 public void setUp() throws Exception { 71 Context context = InstrumentationRegistry.getContext(); 72 73 mFakeClock = new FakeClock(); 74 75 // Read-only interfaces so are easy to mock. 76 mMockConfigHelper = mock(ConfigHelper.class); 77 mMockPackageManagerHelper = mock(PackageManagerHelper.class); 78 79 // Using the instrumentation context means the database is created in a test app-specific 80 // directory. We can use the real thing for this test. 81 mPackageStatusStorage = new PackageStatusStorage(context.getFilesDir()); 82 83 // For other interactions with the Android framework we create a fake object. 84 mFakeIntentHelper = new FakeIntentHelper(); 85 86 // Create the PackageTracker to use in tests. 87 mPackageTracker = new PackageTracker( 88 mFakeClock, 89 mMockConfigHelper, 90 mMockPackageManagerHelper, 91 mPackageStatusStorage, 92 mFakeIntentHelper); 93 } 94 95 @After 96 public void tearDown() throws Exception { 97 if (mPackageStatusStorage != null) { 98 mPackageStatusStorage.deleteFileForTests(); 99 } 100 } 101 102 @Test 103 public void trackingDisabled_intentHelperNotUsed() { 104 // Set up device configuration. 105 configureTrackingDisabled(); 106 107 // Initialize the tracker. 108 assertFalse(mPackageTracker.start()); 109 110 // Check the IntentHelper was not initialized. 111 mFakeIntentHelper.assertNotInitialized(); 112 113 // Check reliability triggering state. 114 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 115 } 116 117 @Test 118 public void trackingDisabled_triggerUpdateIfNeededNotAllowed() { 119 // Set up device configuration. 120 configureTrackingDisabled(); 121 122 // Initialize the tracker. 123 assertFalse(mPackageTracker.start()); 124 125 // Check reliability triggering state. 126 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 127 128 try { 129 // This call should also not be allowed and will throw an exception if tracking is 130 // disabled. 131 mPackageTracker.triggerUpdateIfNeeded(true); 132 fail(); 133 } catch (IllegalStateException expected) {} 134 135 // Check reliability triggering state. 136 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 137 } 138 139 @Test 140 public void trackingDisabled_unsolicitedResultsIgnored_withoutToken() { 141 // Set up device configuration. 142 configureTrackingDisabled(); 143 144 // Initialize the tracker. 145 assertFalse(mPackageTracker.start()); 146 147 // Check reliability triggering state. 148 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 149 150 // Receiving a check result when tracking is disabled should cause the storage to be 151 // reset. 152 mPackageTracker.recordCheckResult(null /* checkToken */, true /* success */); 153 154 // Check reliability triggering state. 155 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 156 157 // Assert the storage was reset. 158 checkPackageStorageStatusIsInitialOrReset(); 159 } 160 161 @Test 162 public void trackingDisabled_unsolicitedResultsIgnored_withToken() { 163 // Set up device configuration. 164 configureTrackingDisabled(); 165 166 // Set the storage into an arbitrary state so we can detect a reset. 167 mPackageStatusStorage.generateCheckToken(INITIAL_APP_PACKAGE_VERSIONS); 168 169 // Initialize the tracker. 170 assertFalse(mPackageTracker.start()); 171 172 // Check reliability triggering state. 173 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 174 175 // Receiving a check result when tracking is disabled should cause the storage to be reset. 176 mPackageTracker.recordCheckResult(createArbitraryCheckToken(), true /* success */); 177 178 // Check reliability triggering state. 179 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 180 181 // Assert the storage was reset. 182 checkPackageStorageStatusIsInitialOrReset(); 183 } 184 185 @Test 186 public void trackingEnabled_updateAppConfigMissing() throws Exception { 187 // Set up device configuration. 188 configureTrackingEnabled(); 189 configureReliabilityConfigSettingsOk(); 190 configureUpdateAppPackageNameMissing(); 191 configureDataAppPackageOk(DATA_APP_PACKAGE_NAME); 192 193 try { 194 // Initialize the tracker. 195 mPackageTracker.start(); 196 fail(); 197 } catch (RuntimeException expected) {} 198 199 mFakeIntentHelper.assertNotInitialized(); 200 201 // Check reliability triggering state. 202 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 203 } 204 205 @Test 206 public void trackingEnabled_updateAppNotPrivileged() throws Exception { 207 // Set up device configuration. 208 configureTrackingEnabled(); 209 configureReliabilityConfigSettingsOk(); 210 configureUpdateAppPackageNotPrivileged(UPDATE_APP_PACKAGE_NAME); 211 configureDataAppPackageOk(DATA_APP_PACKAGE_NAME); 212 213 try { 214 // Initialize the tracker. 215 mPackageTracker.start(); 216 fail(); 217 } catch (RuntimeException expected) {} 218 219 mFakeIntentHelper.assertNotInitialized(); 220 221 // Check reliability triggering state. 222 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 223 } 224 225 @Test 226 public void trackingEnabled_dataAppConfigMissing() throws Exception { 227 // Set up device configuration. 228 configureTrackingEnabled(); 229 configureReliabilityConfigSettingsOk(); 230 configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME); 231 configureDataAppPackageNameMissing(); 232 233 try { 234 // Initialize the tracker. 235 mPackageTracker.start(); 236 fail(); 237 } catch (RuntimeException expected) {} 238 239 mFakeIntentHelper.assertNotInitialized(); 240 241 // Check reliability triggering state. 242 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 243 } 244 245 @Test 246 public void trackingEnabled_dataAppNotPrivileged() throws Exception { 247 // Set up device configuration. 248 configureTrackingEnabled(); 249 configureReliabilityConfigSettingsOk(); 250 configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME); 251 configureDataAppPackageNotPrivileged(DATA_APP_PACKAGE_NAME); 252 253 try { 254 // Initialize the tracker. 255 mPackageTracker.start(); 256 fail(); 257 } catch (RuntimeException expected) {} 258 259 mFakeIntentHelper.assertNotInitialized(); 260 261 // Check reliability triggering state. 262 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 263 } 264 265 @Test 266 public void trackingEnabled_storageInitializationFails() throws Exception { 267 // Create a PackageStateStorage that will fail to initialize. 268 PackageStatusStorage packageStatusStorage = 269 new PackageStatusStorage(new File("/system/does/not/exist")); 270 271 // Create a new PackageTracker to use the bad storage. 272 mPackageTracker = new PackageTracker( 273 mFakeClock, 274 mMockConfigHelper, 275 mMockPackageManagerHelper, 276 packageStatusStorage, 277 mFakeIntentHelper); 278 279 // Set up device configuration. 280 configureTrackingEnabled(); 281 configureReliabilityConfigSettingsOk(); 282 configureValidApplications(); 283 284 // Initialize the tracker. 285 assertFalse(mPackageTracker.start()); 286 287 // Check the IntentHelper was not initialized. 288 mFakeIntentHelper.assertNotInitialized(); 289 290 // Check reliability triggering state. 291 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 292 } 293 294 @Test 295 public void trackingEnabled_packageUpdate_badUpdateAppManifestEntry() throws Exception { 296 // Set up device configuration. 297 configureTrackingEnabled(); 298 configureReliabilityConfigSettingsOk(); 299 configureValidApplications(); 300 301 // Initialize the tracker. 302 assertTrue(mPackageTracker.start()); 303 304 // Check the intent helper is properly configured. 305 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 306 307 // Check the initial storage state. 308 checkPackageStorageStatusIsInitialOrReset(); 309 310 // Configure a bad manifest for the update app. Should effectively turn off tracking. 311 PackageVersions packageVersions = 312 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 313 configureUpdateAppManifestBad(UPDATE_APP_PACKAGE_NAME); 314 configureDataAppManifestOk(DATA_APP_PACKAGE_NAME); 315 configureUpdateAppPackageVersion( 316 UPDATE_APP_PACKAGE_NAME, packageVersions.mUpdateAppVersion); 317 configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, packageVersions.mDataAppVersion); 318 // Simulate a tracked package being updated. 319 mFakeIntentHelper.simulatePackageUpdatedEvent(); 320 321 // Assert the PackageTracker did not attempt to trigger an update. 322 mFakeIntentHelper.assertUpdateNotTriggered(); 323 324 // Check reliability triggering state. 325 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 326 327 // Assert the storage was not touched. 328 checkPackageStorageStatusIsInitialOrReset(); 329 } 330 331 @Test 332 public void trackingEnabled_packageUpdate_badDataAppManifestEntry() throws Exception { 333 // Set up device configuration. 334 configureTrackingEnabled(); 335 configureReliabilityConfigSettingsOk(); 336 configureValidApplications(); 337 338 // Initialize the tracker. 339 assertTrue(mPackageTracker.start()); 340 341 // Check the intent helper is properly configured. 342 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 343 344 // Check the initial storage state. 345 checkPackageStorageStatusIsInitialOrReset(); 346 347 // Configure a bad manifest for the data app. Should effectively turn off tracking. 348 PackageVersions packageVersions = 349 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 350 configureUpdateAppManifestOk(UPDATE_APP_PACKAGE_NAME); 351 configureDataAppManifestBad(DATA_APP_PACKAGE_NAME); 352 configureUpdateAppPackageVersion( 353 UPDATE_APP_PACKAGE_NAME, packageVersions.mUpdateAppVersion); 354 configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, packageVersions.mDataAppVersion); 355 mFakeIntentHelper.simulatePackageUpdatedEvent(); 356 357 // Assert the PackageTracker did not attempt to trigger an update. 358 mFakeIntentHelper.assertUpdateNotTriggered(); 359 360 // Check reliability triggering state. 361 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 362 363 // Assert the storage was not touched. 364 checkPackageStorageStatusIsInitialOrReset(); 365 } 366 367 @Test 368 public void trackingEnabled_packageUpdate_responseWithToken_success() throws Exception { 369 trackingEnabled_packageUpdate_responseWithToken(true); 370 } 371 372 @Test 373 public void trackingEnabled_packageUpdate_responseWithToken_failed() throws Exception { 374 trackingEnabled_packageUpdate_responseWithToken(false); 375 } 376 377 private void trackingEnabled_packageUpdate_responseWithToken(boolean success) throws Exception { 378 // Set up device configuration. 379 configureTrackingEnabled(); 380 configureReliabilityConfigSettingsOk(); 381 configureValidApplications(); 382 383 // Initialize the tracker. 384 assertTrue(mPackageTracker.start()); 385 386 // Check the intent helper is properly configured. 387 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 388 389 // Check the initial storage state. 390 checkPackageStorageStatusIsInitialOrReset(); 391 392 // Simulate a tracked package being updated. 393 PackageVersions packageVersions = 394 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 395 simulatePackageInstallation(packageVersions); 396 397 // Confirm an update was triggered. 398 checkUpdateCheckTriggered(packageVersions); 399 400 // Get the token that was passed to the intent helper, and pass it back. 401 CheckToken token = mFakeIntentHelper.captureAndResetLastToken(); 402 mPackageTracker.recordCheckResult(token, success); 403 404 // Check storage and reliability triggering state. 405 if (success) { 406 checkUpdateCheckSuccessful(packageVersions); 407 } else { 408 checkUpdateCheckFailed(packageVersions); 409 } 410 } 411 412 @Test 413 public void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset_success() 414 throws Exception { 415 trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(true); 416 } 417 418 @Test 419 public void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset_failed() 420 throws Exception { 421 trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(false); 422 } 423 424 private void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset( 425 boolean success) throws Exception { 426 // Set up device configuration. 427 configureTrackingEnabled(); 428 configureReliabilityConfigSettingsOk(); 429 configureValidApplications(); 430 431 // Initialize the tracker. 432 assertTrue(mPackageTracker.start()); 433 434 // Check the intent helper is properly configured. 435 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 436 437 // Check the initial storage state. 438 checkPackageStorageStatusIsInitialOrReset(); 439 440 // Set up installed app versions / manifests. 441 PackageVersions packageVersions = 442 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 443 simulatePackageInstallation(packageVersions); 444 445 // Confirm an update was triggered. 446 checkUpdateCheckTriggered(packageVersions); 447 448 // Ignore the token that was given to the intent helper, just pass null. 449 mPackageTracker.recordCheckResult(null /* checkToken */, success); 450 451 // Check reliability triggering state. 452 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 453 454 // Assert the storage was reset. 455 checkPackageStorageStatusIsInitialOrReset(); 456 } 457 458 /** 459 * Two package updates triggered for the same package versions. The second is triggered while 460 * the first is still happening. 461 */ 462 @Test 463 public void trackingEnabled_packageUpdate_twoChecksNoPackageChange_secondWhileFirstInProgress() 464 throws Exception { 465 // Set up device configuration. 466 configureTrackingEnabled(); 467 configureReliabilityConfigSettingsOk(); 468 configureValidApplications(); 469 470 // Initialize the tracker. 471 assertTrue(mPackageTracker.start()); 472 473 // Check the intent helper is properly configured. 474 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 475 476 // Check the initial storage state. 477 checkPackageStorageStatusIsInitialOrReset(); 478 479 // Simulate package installation. 480 PackageVersions packageVersions = 481 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 482 simulatePackageInstallation(packageVersions); 483 484 // Confirm an update was triggered. 485 checkUpdateCheckTriggered(packageVersions); 486 487 // Get the first token. 488 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 489 assertEquals(packageVersions, token1.mPackageVersions); 490 491 // Now attempt to generate another check while the first is in progress and without having 492 // updated the package versions. The PackageTracker should trigger again for safety. 493 simulatePackageInstallation(packageVersions); 494 495 // Confirm an update was triggered. 496 checkUpdateCheckTriggered(packageVersions); 497 498 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken(); 499 assertEquals(packageVersions, token2.mPackageVersions); 500 assertEquals(token1.mPackageVersions, token2.mPackageVersions); 501 assertTrue(token1.mOptimisticLockId != token2.mOptimisticLockId); 502 } 503 504 /** 505 * Two package updates triggered for the same package versions. The second happens after 506 * the first has succeeded. 507 */ 508 @Test 509 public void trackingEnabled_packageUpdate_twoChecksNoPackageChange_sequential() 510 throws Exception { 511 // Set up device configuration. 512 configureTrackingEnabled(); 513 configureReliabilityConfigSettingsOk(); 514 configureValidApplications(); 515 516 // Initialize the tracker. 517 assertTrue(mPackageTracker.start()); 518 519 // Check the intent helper is properly configured. 520 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 521 522 // Check the initial storage state. 523 checkPackageStorageStatusIsInitialOrReset(); 524 525 // Simulate package installation. 526 PackageVersions packageVersions = 527 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 528 simulatePackageInstallation(packageVersions); 529 530 // Confirm an update was triggered. 531 checkUpdateCheckTriggered(packageVersions); 532 533 // Get the token. 534 CheckToken token = mFakeIntentHelper.captureAndResetLastToken(); 535 assertEquals(packageVersions, token.mPackageVersions); 536 537 // Simulate a successful check. 538 mPackageTracker.recordCheckResult(token, true /* success */); 539 540 // Check storage and reliability triggering state. 541 checkUpdateCheckSuccessful(packageVersions); 542 543 // Now attempt to generate another check, but without having updated the package. The 544 // PackageTracker should be smart enough to recognize there's nothing to do here. 545 simulatePackageInstallation(packageVersions); 546 547 // Assert the PackageTracker did not attempt to trigger an update. 548 mFakeIntentHelper.assertUpdateNotTriggered(); 549 550 // Check storage and reliability triggering state. 551 checkUpdateCheckSuccessful(packageVersions); 552 } 553 554 /** 555 * Two package updates triggered for the same package versions. The second is triggered after 556 * the first has failed. 557 */ 558 @Test 559 public void trackingEnabled_packageUpdate_afterFailure() throws Exception { 560 // Set up device configuration. 561 configureTrackingEnabled(); 562 configureReliabilityConfigSettingsOk(); 563 configureValidApplications(); 564 565 // Initialize the tracker. 566 assertTrue(mPackageTracker.start()); 567 568 // Check the intent helper is properly configured. 569 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 570 571 // Check the initial storage state. 572 checkPackageStorageStatusIsInitialOrReset(); 573 574 // Simulate package installation. 575 PackageVersions packageVersions = 576 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 577 simulatePackageInstallation(packageVersions); 578 579 // Confirm an update was triggered. 580 checkUpdateCheckTriggered(packageVersions); 581 582 // Get the first token. 583 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 584 assertEquals(packageVersions, token1.mPackageVersions); 585 586 // Simulate an *unsuccessful* check. 587 mPackageTracker.recordCheckResult(token1, false /* success */); 588 589 // Check storage and reliability triggering state. 590 checkUpdateCheckFailed(packageVersions); 591 592 // Now generate another check, but without having updated the package. The 593 // PackageTracker should recognize the last check failed and trigger again. 594 simulatePackageInstallation(packageVersions); 595 596 // Confirm an update was triggered. 597 checkUpdateCheckTriggered(packageVersions); 598 599 // Get the second token. 600 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken(); 601 602 // Assert some things about the tokens. 603 assertEquals(packageVersions, token2.mPackageVersions); 604 assertTrue(token1.mOptimisticLockId != token2.mOptimisticLockId); 605 606 // For completeness, now simulate this check was successful. 607 mPackageTracker.recordCheckResult(token2, true /* success */); 608 609 // Check storage and reliability triggering state. 610 checkUpdateCheckSuccessful(packageVersions); 611 } 612 613 /** 614 * Two package updates triggered for different package versions. The second is triggered while 615 * the first is still happening. 616 */ 617 @Test 618 public void trackingEnabled_packageUpdate_twoChecksWithPackageChange_firstCheckInProcess() 619 throws Exception { 620 // Set up device configuration. 621 configureTrackingEnabled(); 622 configureReliabilityConfigSettingsOk(); 623 configureValidApplications(); 624 625 // Initialize the package tracker. 626 assertTrue(mPackageTracker.start()); 627 628 // Check the intent helper is properly configured. 629 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 630 631 // Check the initial storage state. 632 checkPackageStorageStatusIsInitialOrReset(); 633 634 // Simulate package installation. 635 PackageVersions packageVersions1 = 636 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 637 simulatePackageInstallation(packageVersions1); 638 639 // Confirm an update was triggered. 640 checkUpdateCheckTriggered(packageVersions1); 641 642 // Get the first token. 643 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 644 assertEquals(packageVersions1, token1.mPackageVersions); 645 646 // Simulate a tracked package being updated a second time (before the response for the 647 // first has been received). 648 PackageVersions packageVersions2 = 649 new PackageVersions(3 /* updateAppPackageVersion */, 4 /* dataAppPackageVersion */); 650 simulatePackageInstallation(packageVersions2); 651 652 // Confirm an update was triggered. 653 checkUpdateCheckTriggered(packageVersions2); 654 655 // Get the second token. 656 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken(); 657 assertEquals(packageVersions2, token2.mPackageVersions); 658 659 // token1 should be invalid because the token2 was generated. 660 mPackageTracker.recordCheckResult(token1, true /* success */); 661 662 // Reliability triggering should still be enabled. 663 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 664 665 // Check the expected storage state. 666 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions2); 667 668 // token2 should still be accepted. 669 mPackageTracker.recordCheckResult(token2, true /* success */); 670 671 // Check storage and reliability triggering state. 672 checkUpdateCheckSuccessful(packageVersions2); 673 } 674 675 /** 676 * Two package updates triggered for different package versions. The second is triggered after 677 * the first has completed successfully. 678 */ 679 @Test 680 public void trackingEnabled_packageUpdate_twoChecksWithPackageChange_sequential() 681 throws Exception { 682 // Set up device configuration. 683 configureTrackingEnabled(); 684 configureReliabilityConfigSettingsOk(); 685 configureValidApplications(); 686 687 // Initialize the package tracker. 688 assertTrue(mPackageTracker.start()); 689 690 // Check the intent helper is properly configured. 691 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 692 693 // Check the initial storage state. 694 checkPackageStorageStatusIsInitialOrReset(); 695 696 // Simulate package installation. 697 PackageVersions packageVersions1 = 698 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 699 simulatePackageInstallation(packageVersions1); 700 701 // Confirm an update was triggered. 702 checkUpdateCheckTriggered(packageVersions1); 703 704 // Get the first token. 705 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 706 assertEquals(packageVersions1, token1.mPackageVersions); 707 708 // token1 should be accepted. 709 mPackageTracker.recordCheckResult(token1, true /* success */); 710 711 // Check storage and reliability triggering state. 712 checkUpdateCheckSuccessful(packageVersions1); 713 714 // Simulate a tracked package being updated a second time. 715 PackageVersions packageVersions2 = 716 new PackageVersions(3 /* updateAppPackageVersion */, 4 /* dataAppPackageVersion */); 717 simulatePackageInstallation(packageVersions2); 718 719 // Confirm an update was triggered. 720 checkUpdateCheckTriggered(packageVersions2); 721 722 // Get the second token. 723 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken(); 724 assertEquals(packageVersions2, token2.mPackageVersions); 725 726 // token2 should still be accepted. 727 mPackageTracker.recordCheckResult(token2, true /* success */); 728 729 // Check storage and reliability triggering state. 730 checkUpdateCheckSuccessful(packageVersions2); 731 } 732 733 /** 734 * Replaying the same token twice. 735 */ 736 @Test 737 public void trackingEnabled_packageUpdate_sameTokenReplayFails() throws Exception { 738 // Set up device configuration. 739 configureTrackingEnabled(); 740 configureReliabilityConfigSettingsOk(); 741 configureValidApplications(); 742 743 // Initialize the package tracker. 744 assertTrue(mPackageTracker.start()); 745 746 // Check the intent helper is properly configured. 747 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 748 749 // Check the initial storage state. 750 checkPackageStorageStatusIsInitialOrReset(); 751 752 // Simulate package installation. 753 PackageVersions packageVersions1 = 754 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */); 755 simulatePackageInstallation(packageVersions1); 756 757 // Confirm an update was triggered. 758 checkUpdateCheckTriggered(packageVersions1); 759 760 // Get the first token. 761 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 762 assertEquals(packageVersions1, token1.mPackageVersions); 763 764 // token1 should be accepted. 765 mPackageTracker.recordCheckResult(token1, true /* success */); 766 767 // Check storage and reliability triggering state. 768 checkUpdateCheckSuccessful(packageVersions1); 769 770 // Apply token1 again. 771 mPackageTracker.recordCheckResult(token1, true /* success */); 772 773 // Check the expected storage state. No real way to tell if it has been updated, but 774 // we can check the final state is still what it should be. 775 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions1); 776 777 // Under the covers we expect it to fail to update because the storage should recognize that 778 // the token is no longer valid. 779 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 780 781 // Peek inside the package tracker to make sure it is tracking failure counts properly. 782 assertEquals(1, mPackageTracker.getCheckFailureCountForTests()); 783 } 784 785 @Test 786 public void trackingEnabled_reliabilityTrigger_firstTime_initialStorage() throws Exception { 787 // Set up device configuration. 788 configureTrackingEnabled(); 789 configureReliabilityConfigSettingsOk(); 790 PackageVersions packageVersions = configureValidApplications(); 791 792 // Initialize the package tracker. 793 assertTrue(mPackageTracker.start()); 794 795 // Check the intent helper is properly configured. 796 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 797 798 // Check the initial storage state. 799 checkPackageStorageStatusIsInitialOrReset(); 800 801 // Simulate a reliability trigger. 802 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 803 804 // Assert the PackageTracker did trigger an update. 805 checkUpdateCheckTriggered(packageVersions); 806 807 // Confirm the token was correct. 808 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 809 assertEquals(packageVersions, token1.mPackageVersions); 810 811 // token1 should be accepted. 812 mPackageTracker.recordCheckResult(token1, true /* success */); 813 814 // Check storage and reliability triggering state. 815 checkUpdateCheckSuccessful(packageVersions); 816 } 817 818 @Test 819 public void trackingEnabled_reliabilityTrigger_afterRebootNoTriggerNeeded() throws Exception { 820 // Set up device configuration. 821 configureTrackingEnabled(); 822 configureReliabilityConfigSettingsOk(); 823 PackageVersions packageVersions = configureValidApplications(); 824 825 // Force the storage into a state we want. 826 mPackageStatusStorage.forceCheckStateForTests( 827 PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); 828 829 // Initialize the package tracker. 830 assertTrue(mPackageTracker.start()); 831 832 // Check the intent helper is properly configured. 833 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 834 835 // Check the initial storage state. 836 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); 837 838 // Simulate a reliability trigger. 839 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 840 841 // Assert the PackageTracker did not attempt to trigger an update. 842 mFakeIntentHelper.assertUpdateNotTriggered(); 843 844 // Check storage and reliability triggering state. 845 checkUpdateCheckSuccessful(packageVersions); 846 } 847 848 /** 849 * Simulates the device starting where the storage records do not match the installed app 850 * versions. The reliability trigger should cause the package tracker to perform a check. 851 */ 852 @Test 853 public void trackingEnabled_reliabilityTrigger_afterRebootTriggerNeededBecausePreviousFailed() 854 throws Exception { 855 // Set up device configuration. 856 configureTrackingEnabled(); 857 configureReliabilityConfigSettingsOk(); 858 859 PackageVersions oldPackageVersions = new PackageVersions(1, 1); 860 PackageVersions currentPackageVersions = new PackageVersions(2, 2); 861 862 // Simulate there being a newer version installed than the one recorded in storage. 863 configureValidApplications(currentPackageVersions); 864 865 // Force the storage into a state we want. 866 mPackageStatusStorage.forceCheckStateForTests( 867 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 868 869 // Initialize the package tracker. 870 assertTrue(mPackageTracker.start()); 871 872 // Check the intent helper is properly configured. 873 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 874 875 // Check the initial storage state. 876 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 877 878 // Simulate a reliability trigger. 879 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 880 881 // Assert the PackageTracker did trigger an update. 882 checkUpdateCheckTriggered(currentPackageVersions); 883 884 // Simulate the update check completing successfully. 885 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken(); 886 mPackageTracker.recordCheckResult(checkToken, true /* success */); 887 888 // Check storage and reliability triggering state. 889 checkUpdateCheckSuccessful(currentPackageVersions); 890 } 891 892 /** 893 * Simulates persistent failures of the reliability check. It should stop after the configured 894 * number of checks. 895 */ 896 @Test 897 public void trackingEnabled_reliabilityTrigger_repeatedFailures() throws Exception { 898 // Set up device configuration. 899 configureTrackingEnabled(); 900 901 int retriesAllowed = 3; 902 int checkDelayMillis = 5 * 60 * 1000; 903 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis); 904 905 PackageVersions oldPackageVersions = new PackageVersions(1, 1); 906 PackageVersions currentPackageVersions = new PackageVersions(2, 2); 907 908 // Simulate there being a newer version installed than the one recorded in storage. 909 configureValidApplications(currentPackageVersions); 910 911 // Force the storage into a state we want. 912 mPackageStatusStorage.forceCheckStateForTests( 913 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 914 915 // Initialize the package tracker. 916 assertTrue(mPackageTracker.start()); 917 918 // Check the intent helper is properly configured. 919 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 920 921 // Check the initial storage state. 922 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 923 924 for (int i = 0; i < retriesAllowed + 1; i++) { 925 // Simulate a reliability trigger. 926 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 927 928 // Assert the PackageTracker did trigger an update. 929 checkUpdateCheckTriggered(currentPackageVersions); 930 931 // Check the PackageTracker failure count before calling recordCheckResult. 932 assertEquals(i, mPackageTracker.getCheckFailureCountForTests()); 933 934 // Simulate a check failure. 935 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken(); 936 mPackageTracker.recordCheckResult(checkToken, false /* success */); 937 938 // Peek inside the package tracker to make sure it is tracking failure counts properly. 939 assertEquals(i + 1, mPackageTracker.getCheckFailureCountForTests()); 940 941 // Confirm nothing has changed. 942 mFakeIntentHelper.assertUpdateNotTriggered(); 943 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, 944 currentPackageVersions); 945 946 // Check reliability triggering is in the correct state. 947 if (i <= retriesAllowed) { 948 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 949 } else { 950 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 951 } 952 } 953 } 954 955 @Test 956 public void trackingEnabled_reliabilityTrigger_failureCountIsReset() throws Exception { 957 // Set up device configuration. 958 configureTrackingEnabled(); 959 960 int retriesAllowed = 3; 961 int checkDelayMillis = 5 * 60 * 1000; 962 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis); 963 964 PackageVersions oldPackageVersions = new PackageVersions(1, 1); 965 PackageVersions currentPackageVersions = new PackageVersions(2, 2); 966 967 // Simulate there being a newer version installed than the one recorded in storage. 968 configureValidApplications(currentPackageVersions); 969 970 // Force the storage into a state we want. 971 mPackageStatusStorage.forceCheckStateForTests( 972 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 973 974 // Initialize the package tracker. 975 assertTrue(mPackageTracker.start()); 976 977 // Check the intent helper is properly configured. 978 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 979 980 // Check the initial storage state. 981 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 982 983 // Fail (retries - 1) times. 984 for (int i = 0; i < retriesAllowed - 1; i++) { 985 // Simulate a reliability trigger. 986 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 987 988 // Assert the PackageTracker did trigger an update. 989 checkUpdateCheckTriggered(currentPackageVersions); 990 991 // Check the PackageTracker failure count before calling recordCheckResult. 992 assertEquals(i, mPackageTracker.getCheckFailureCountForTests()); 993 994 // Simulate a check failure. 995 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken(); 996 mPackageTracker.recordCheckResult(checkToken, false /* success */); 997 998 // Peek inside the package tracker to make sure it is tracking failure counts properly. 999 assertEquals(i + 1, mPackageTracker.getCheckFailureCountForTests()); 1000 1001 // Confirm nothing has changed. 1002 mFakeIntentHelper.assertUpdateNotTriggered(); 1003 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, 1004 currentPackageVersions); 1005 1006 // Check reliability triggering is still enabled. 1007 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 1008 } 1009 1010 // Simulate a reliability trigger. 1011 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 1012 1013 // Assert the PackageTracker did trigger an update. 1014 checkUpdateCheckTriggered(currentPackageVersions); 1015 1016 // Check the PackageTracker failure count before calling recordCheckResult. 1017 assertEquals(retriesAllowed - 1, mPackageTracker.getCheckFailureCountForTests()); 1018 1019 // On the last possible try, succeed. 1020 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken(); 1021 mPackageTracker.recordCheckResult(checkToken, true /* success */); 1022 1023 checkUpdateCheckSuccessful(currentPackageVersions); 1024 } 1025 1026 /** 1027 * Simulates reliability triggers happening too close together. Package tracker should ignore 1028 * the ones it doesn't need. 1029 */ 1030 @Test 1031 public void trackingEnabled_reliabilityTrigger_tooSoon() throws Exception { 1032 // Set up device configuration. 1033 configureTrackingEnabled(); 1034 1035 int retriesAllowed = 5; 1036 int checkDelayMillis = 5 * 60 * 1000; 1037 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis); 1038 1039 PackageVersions oldPackageVersions = new PackageVersions(1, 1); 1040 PackageVersions currentPackageVersions = new PackageVersions(2, 2); 1041 1042 // Simulate there being a newer version installed than the one recorded in storage. 1043 configureValidApplications(currentPackageVersions); 1044 1045 // Force the storage into a state we want. 1046 mPackageStatusStorage.forceCheckStateForTests( 1047 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 1048 1049 // Initialize the package tracker. 1050 assertTrue(mPackageTracker.start()); 1051 1052 // Check the intent helper is properly configured. 1053 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 1054 1055 // Check the initial storage state. 1056 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); 1057 1058 // Simulate a reliability trigger. 1059 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 1060 1061 // Assert the PackageTracker did trigger an update. 1062 checkUpdateCheckTriggered(currentPackageVersions); 1063 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 1064 1065 // Increment the clock, but not enough. 1066 mFakeClock.incrementClock(checkDelayMillis - 1); 1067 1068 // Simulate a reliability trigger. 1069 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 1070 1071 // Assert the PackageTracker did not trigger an update. 1072 mFakeIntentHelper.assertUpdateNotTriggered(); 1073 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, currentPackageVersions); 1074 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 1075 1076 // Increment the clock slightly more. Should now consider the response overdue. 1077 mFakeClock.incrementClock(2); 1078 1079 // Simulate a reliability trigger. 1080 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 1081 1082 // Triggering should have happened. 1083 checkUpdateCheckTriggered(currentPackageVersions); 1084 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken(); 1085 1086 // Check a new token was generated. 1087 assertFalse(token1.equals(token2)); 1088 } 1089 1090 /** 1091 * Tests what happens when a package update doesn't complete and a reliability trigger cleans 1092 * up for it. 1093 */ 1094 @Test 1095 public void trackingEnabled_reliabilityTrigger_afterPackageUpdateDidNotComplete() 1096 throws Exception { 1097 1098 // Set up device configuration. 1099 configureTrackingEnabled(); 1100 1101 int retriesAllowed = 5; 1102 int checkDelayMillis = 5 * 60 * 1000; 1103 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis); 1104 1105 PackageVersions currentPackageVersions = new PackageVersions(1, 1); 1106 PackageVersions newPackageVersions = new PackageVersions(2, 2); 1107 1108 // Simulate there being a newer version installed than the one recorded in storage. 1109 configureValidApplications(currentPackageVersions); 1110 1111 // Force the storage into a state we want. 1112 mPackageStatusStorage.forceCheckStateForTests( 1113 PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions); 1114 1115 // Initialize the package tracker. 1116 assertTrue(mPackageTracker.start()); 1117 1118 // Check the intent helper is properly configured. 1119 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 1120 1121 // Simulate a reliability trigger. 1122 simulatePackageInstallation(newPackageVersions); 1123 1124 // Assert the PackageTracker did trigger an update. 1125 checkUpdateCheckTriggered(newPackageVersions); 1126 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 1127 1128 // Increment the clock, but not enough. 1129 mFakeClock.incrementClock(checkDelayMillis + 1); 1130 1131 // Simulate a reliability trigger. 1132 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 1133 1134 // Assert the PackageTracker triggered an update. 1135 checkUpdateCheckTriggered(newPackageVersions); 1136 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken(); 1137 1138 // Check a new token was generated. 1139 assertFalse(token1.equals(token2)); 1140 1141 // Simulate the reliability check completing. 1142 mPackageTracker.recordCheckResult(token2, true /* success */); 1143 1144 // Check everything is now as it should be. 1145 checkUpdateCheckSuccessful(newPackageVersions); 1146 } 1147 1148 /** 1149 * Simulates a reliability trigger happening too soon after a package update trigger occurred. 1150 */ 1151 @Test 1152 public void trackingEnabled_reliabilityTriggerAfterUpdate_tooSoon() throws Exception { 1153 // Set up device configuration. 1154 configureTrackingEnabled(); 1155 1156 int retriesAllowed = 5; 1157 int checkDelayMillis = 5 * 60 * 1000; 1158 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis); 1159 1160 PackageVersions currentPackageVersions = new PackageVersions(1, 1); 1161 PackageVersions newPackageVersions = new PackageVersions(2, 2); 1162 1163 // Simulate there being a newer version installed than the one recorded in storage. 1164 configureValidApplications(currentPackageVersions); 1165 1166 // Force the storage into a state we want. 1167 mPackageStatusStorage.forceCheckStateForTests( 1168 PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions); 1169 1170 // Initialize the package tracker. 1171 assertTrue(mPackageTracker.start()); 1172 1173 // Check the intent helper is properly configured. 1174 checkIntentHelperInitializedAndReliabilityTrackingEnabled(); 1175 1176 // Check the initial storage state. 1177 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions); 1178 1179 // Simulate a package update trigger. 1180 simulatePackageInstallation(newPackageVersions); 1181 1182 // Assert the PackageTracker did trigger an update. 1183 checkUpdateCheckTriggered(newPackageVersions); 1184 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken(); 1185 1186 // Increment the clock, but not enough. 1187 mFakeClock.incrementClock(checkDelayMillis - 1); 1188 1189 // Simulate a reliability trigger. 1190 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 1191 1192 // Assert the PackageTracker did not trigger an update. 1193 mFakeIntentHelper.assertUpdateNotTriggered(); 1194 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, newPackageVersions); 1195 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 1196 1197 // Increment the clock slightly more. Should now consider the response overdue. 1198 mFakeClock.incrementClock(2); 1199 1200 // Simulate a reliability trigger. 1201 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); 1202 1203 // Triggering should have happened. 1204 checkUpdateCheckTriggered(newPackageVersions); 1205 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken(); 1206 1207 // Check a new token was generated. 1208 assertFalse(token1.equals(token2)); 1209 } 1210 1211 @Test 1212 public void dump() { 1213 StringWriter stringWriter = new StringWriter(); 1214 PrintWriter printWriter = new PrintWriter(stringWriter); 1215 1216 mPackageTracker.dump(printWriter); 1217 1218 assertFalse(stringWriter.toString().isEmpty()); 1219 } 1220 1221 private void simulatePackageInstallation(PackageVersions packageVersions) throws Exception { 1222 configureApplicationsValidManifests(packageVersions); 1223 1224 // Simulate a tracked package being updated. 1225 mFakeIntentHelper.simulatePackageUpdatedEvent(); 1226 } 1227 1228 /** 1229 * Checks an update check was triggered, reliability triggering is therefore enabled and the 1230 * storage state reflects that there is a check in progress. 1231 */ 1232 private void checkUpdateCheckTriggered(PackageVersions packageVersions) { 1233 // Assert the PackageTracker attempted to trigger an update. 1234 mFakeIntentHelper.assertUpdateTriggered(); 1235 1236 // If an update check was triggered reliability triggering should always be enabled to 1237 // ensure that it can be completed if it fails. 1238 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 1239 1240 // Check the expected storage state. 1241 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions); 1242 } 1243 1244 private void checkUpdateCheckFailed(PackageVersions packageVersions) { 1245 // Check reliability triggering state. 1246 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 1247 1248 // Assert the storage was updated. 1249 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, packageVersions); 1250 } 1251 1252 private void checkUpdateCheckSuccessful(PackageVersions packageVersions) { 1253 // Check reliability triggering state. 1254 mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); 1255 1256 // Assert the storage was updated. 1257 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); 1258 1259 // Peek inside the package tracker to make sure it is tracking failure counts properly. 1260 assertEquals(0, mPackageTracker.getCheckFailureCountForTests()); 1261 } 1262 1263 private PackageVersions configureValidApplications() throws Exception { 1264 configureValidApplications(INITIAL_APP_PACKAGE_VERSIONS); 1265 return INITIAL_APP_PACKAGE_VERSIONS; 1266 } 1267 1268 private void configureValidApplications(PackageVersions versions) throws Exception { 1269 configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME); 1270 configureDataAppPackageOk(DATA_APP_PACKAGE_NAME); 1271 configureApplicationsValidManifests(versions); 1272 } 1273 1274 private void configureApplicationsValidManifests(PackageVersions versions) throws Exception { 1275 configureUpdateAppManifestOk(UPDATE_APP_PACKAGE_NAME); 1276 configureDataAppManifestOk(DATA_APP_PACKAGE_NAME); 1277 configureUpdateAppPackageVersion(UPDATE_APP_PACKAGE_NAME, versions.mUpdateAppVersion); 1278 configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, versions.mDataAppVersion); 1279 } 1280 1281 private void configureUpdateAppPackageVersion(String updateAppPackageName, 1282 long updataAppPackageVersion) throws Exception { 1283 when(mMockPackageManagerHelper.getInstalledPackageVersion(updateAppPackageName)) 1284 .thenReturn(updataAppPackageVersion); 1285 } 1286 1287 private void configureDataAppPackageVersion(String dataAppPackageName, 1288 long dataAppPackageVersion) throws Exception { 1289 when(mMockPackageManagerHelper.getInstalledPackageVersion(dataAppPackageName)) 1290 .thenReturn(dataAppPackageVersion); 1291 } 1292 1293 private void configureUpdateAppManifestOk(String updateAppPackageName) throws Exception { 1294 Intent expectedIntent = RulesUpdaterContract.createUpdaterIntent(updateAppPackageName); 1295 when(mMockPackageManagerHelper.receiverRegistered( 1296 filterEquals(expectedIntent), 1297 eq(RulesUpdaterContract.TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION))) 1298 .thenReturn(true); 1299 when(mMockPackageManagerHelper.usesPermission( 1300 updateAppPackageName, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION)) 1301 .thenReturn(true); 1302 } 1303 1304 private void configureUpdateAppManifestBad(String updateAppPackageName) throws Exception { 1305 Intent expectedIntent = RulesUpdaterContract.createUpdaterIntent(updateAppPackageName); 1306 when(mMockPackageManagerHelper.receiverRegistered( 1307 filterEquals(expectedIntent), 1308 eq(RulesUpdaterContract.TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION))) 1309 .thenReturn(false); 1310 // Has permission, but that shouldn't matter if the check above is false. 1311 when(mMockPackageManagerHelper.usesPermission( 1312 updateAppPackageName, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION)) 1313 .thenReturn(true); 1314 } 1315 1316 private void configureDataAppManifestOk(String dataAppPackageName) throws Exception { 1317 when(mMockPackageManagerHelper.contentProviderRegistered( 1318 TimeZoneRulesDataContract.AUTHORITY, dataAppPackageName)) 1319 .thenReturn(true); 1320 } 1321 1322 private void configureDataAppManifestBad(String dataAppPackageName) throws Exception { 1323 // Simulate the data app not exposing the content provider we require. 1324 when(mMockPackageManagerHelper.contentProviderRegistered( 1325 TimeZoneRulesDataContract.AUTHORITY, dataAppPackageName)) 1326 .thenReturn(false); 1327 } 1328 1329 private void configureTrackingEnabled() { 1330 when(mMockConfigHelper.isTrackingEnabled()).thenReturn(true); 1331 } 1332 1333 private void configureTrackingDisabled() { 1334 when(mMockConfigHelper.isTrackingEnabled()).thenReturn(false); 1335 } 1336 1337 private void configureReliabilityConfigSettings(int retriesAllowed, int checkDelayMillis) { 1338 when(mMockConfigHelper.getFailedCheckRetryCount()).thenReturn(retriesAllowed); 1339 when(mMockConfigHelper.getCheckTimeAllowedMillis()).thenReturn(checkDelayMillis); 1340 } 1341 1342 private void configureReliabilityConfigSettingsOk() { 1343 configureReliabilityConfigSettings(5, 5 * 60 * 1000); 1344 } 1345 1346 private void configureUpdateAppPackageOk(String updateAppPackageName) throws Exception { 1347 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(updateAppPackageName); 1348 when(mMockPackageManagerHelper.isPrivilegedApp(updateAppPackageName)).thenReturn(true); 1349 } 1350 1351 private void configureUpdateAppPackageNotPrivileged(String updateAppPackageName) 1352 throws Exception { 1353 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(updateAppPackageName); 1354 when(mMockPackageManagerHelper.isPrivilegedApp(updateAppPackageName)).thenReturn(false); 1355 } 1356 1357 private void configureUpdateAppPackageNameMissing() { 1358 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(null); 1359 } 1360 1361 private void configureDataAppPackageOk(String dataAppPackageName) throws Exception { 1362 when(mMockConfigHelper.getDataAppPackageName()).thenReturn(dataAppPackageName); 1363 when(mMockPackageManagerHelper.isPrivilegedApp(dataAppPackageName)).thenReturn(true); 1364 } 1365 1366 private void configureDataAppPackageNotPrivileged(String dataAppPackageName) 1367 throws Exception { 1368 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(dataAppPackageName); 1369 when(mMockPackageManagerHelper.isPrivilegedApp(dataAppPackageName)).thenReturn(false); 1370 } 1371 1372 private void configureDataAppPackageNameMissing() { 1373 when(mMockConfigHelper.getDataAppPackageName()).thenThrow(new RuntimeException()); 1374 } 1375 1376 private void checkIntentHelperInitializedAndReliabilityTrackingEnabled() { 1377 // Verify that calling start initialized the IntentHelper as well. 1378 mFakeIntentHelper.assertInitialized(UPDATE_APP_PACKAGE_NAME, DATA_APP_PACKAGE_NAME); 1379 1380 // Assert that reliability tracking is always enabled after initialization. 1381 mFakeIntentHelper.assertReliabilityTriggerScheduled(); 1382 } 1383 1384 private void checkPackageStorageStatus( 1385 int expectedCheckStatus, PackageVersions expectedPackageVersions) { 1386 PackageStatus packageStatus = mPackageStatusStorage.getPackageStatus(); 1387 assertEquals(expectedCheckStatus, packageStatus.mCheckStatus); 1388 assertEquals(expectedPackageVersions, packageStatus.mVersions); 1389 } 1390 1391 private void checkPackageStorageStatusIsInitialOrReset() { 1392 assertNull(mPackageStatusStorage.getPackageStatus()); 1393 } 1394 1395 private static CheckToken createArbitraryCheckToken() { 1396 return new CheckToken(1, INITIAL_APP_PACKAGE_VERSIONS); 1397 } 1398 1399 /** 1400 * A fake IntentHelper implementation for use in tests. 1401 */ 1402 private static class FakeIntentHelper implements PackageTrackerIntentHelper { 1403 1404 private PackageTracker mPackageTracker; 1405 private String mUpdateAppPackageName; 1406 private String mDataAppPackageName; 1407 1408 private CheckToken mLastToken; 1409 1410 private boolean mReliabilityTriggerScheduled; 1411 1412 @Override 1413 public void initialize(String updateAppPackageName, String dataAppPackageName, 1414 PackageTracker packageTracker) { 1415 assertNotNull(updateAppPackageName); 1416 assertNotNull(dataAppPackageName); 1417 assertNotNull(packageTracker); 1418 mPackageTracker = packageTracker; 1419 mUpdateAppPackageName = updateAppPackageName; 1420 mDataAppPackageName = dataAppPackageName; 1421 } 1422 1423 public void assertInitialized( 1424 String expectedUpdateAppPackageName, String expectedDataAppPackageName) { 1425 assertNotNull(mPackageTracker); 1426 assertEquals(expectedUpdateAppPackageName, mUpdateAppPackageName); 1427 assertEquals(expectedDataAppPackageName, mDataAppPackageName); 1428 } 1429 1430 public void assertNotInitialized() { 1431 assertNull(mPackageTracker); 1432 } 1433 1434 @Override 1435 public void sendTriggerUpdateCheck(CheckToken checkToken) { 1436 if (mLastToken != null) { 1437 fail("lastToken already set"); 1438 } 1439 mLastToken = checkToken; 1440 } 1441 1442 @Override 1443 public void scheduleReliabilityTrigger(long minimumDelayMillis) { 1444 mReliabilityTriggerScheduled = true; 1445 } 1446 1447 @Override 1448 public void unscheduleReliabilityTrigger() { 1449 mReliabilityTriggerScheduled = false; 1450 } 1451 1452 public void assertReliabilityTriggerScheduled() { 1453 assertTrue(mReliabilityTriggerScheduled); 1454 } 1455 1456 public void assertReliabilityTriggerNotScheduled() { 1457 assertFalse(mReliabilityTriggerScheduled); 1458 } 1459 1460 public void assertUpdateTriggered() { 1461 assertNotNull(mLastToken); 1462 } 1463 1464 public void assertUpdateNotTriggered() { 1465 assertNull(mLastToken); 1466 } 1467 1468 public CheckToken captureAndResetLastToken() { 1469 CheckToken toReturn = mLastToken; 1470 assertNotNull("No update triggered", toReturn); 1471 mLastToken = null; 1472 return toReturn; 1473 } 1474 1475 public void simulatePackageUpdatedEvent() { 1476 mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */); 1477 } 1478 } 1479 1480 private static class FakeClock extends Clock { 1481 1482 private long currentTime = 1000; 1483 1484 @Override 1485 public long millis() { 1486 return currentTime; 1487 } 1488 1489 public void incrementClock(long millis) { 1490 currentTime += millis; 1491 } 1492 1493 @Override 1494 public ZoneId getZone() { 1495 throw new UnsupportedOperationException(); 1496 } 1497 1498 @Override 1499 public Clock withZone(ZoneId zone) { 1500 throw new UnsupportedOperationException(); 1501 } 1502 1503 @Override 1504 public Instant instant() { 1505 throw new UnsupportedOperationException(); 1506 } 1507 } 1508 1509 /** 1510 * Registers a mockito parameter matcher that uses {@link Intent#filterEquals(Intent)}. to 1511 * check the parameter against the intent supplied. 1512 */ 1513 private static Intent filterEquals(final Intent expected) { 1514 final Matcher<Intent> m = new BaseMatcher<Intent>() { 1515 @Override 1516 public boolean matches(Object actual) { 1517 return actual != null && expected.filterEquals((Intent) actual); 1518 } 1519 @Override 1520 public void describeTo(Description description) { 1521 description.appendText(expected.toString()); 1522 } 1523 }; 1524 return argThat(m); 1525 } 1526} 1527