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