blob: d9f4adfb5e0636715c42517018e3929ec9c640a8 [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 Fuller35822592017-12-11 14:39:03 +000033import java.io.File;
Neil Fuller87b11282017-06-23 16:43:45 +010034import java.io.PrintWriter;
35import java.io.StringWriter;
Neil Fullera7d21f82017-12-05 15:09:35 +000036import java.time.Clock;
37import java.time.Instant;
38import java.time.ZoneId;
Neil Fuller87b11282017-06-23 16:43:45 +010039
Neil Fuller68f66662017-03-16 18:32:21 +000040import 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
Neil Fullera7d21f82017-12-05 15:09:35 +000064 private FakeClock mFakeClock;
Neil Fuller68f66662017-03-16 18:32:21 +000065 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
Neil Fullera7d21f82017-12-05 15:09:35 +000073 mFakeClock = new FakeClock();
Neil Fuller68f66662017-03-16 18:32:21 +000074
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.
Neil Fuller5f6750f2017-05-17 04:43:12 +010081 mPackageStatusStorage = new PackageStatusStorage(context.getFilesDir());
Neil Fuller68f66662017-03-16 18:32:21 +000082
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) {
Neil Fuller5f6750f2017-05-17 04:43:12 +010098 mPackageStatusStorage.deleteFileForTests();
Neil Fuller68f66662017-03-16 18:32:21 +000099 }
100 }
101
102 @Test
103 public void trackingDisabled_intentHelperNotUsed() {
104 // Set up device configuration.
105 configureTrackingDisabled();
106
107 // Initialize the tracker.
Neil Fuller35822592017-12-11 14:39:03 +0000108 assertFalse(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000109
110 // Check the IntentHelper was not initialized.
111 mFakeIntentHelper.assertNotInitialized();
112
113 // Check reliability triggering state.
Neil Fullercd1a1092017-09-13 21:59:59 +0100114 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000115 }
116
117 @Test
118 public void trackingDisabled_triggerUpdateIfNeededNotAllowed() {
119 // Set up device configuration.
120 configureTrackingDisabled();
121
122 // Initialize the tracker.
Neil Fuller35822592017-12-11 14:39:03 +0000123 assertFalse(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000124
125 // Check reliability triggering state.
Neil Fullercd1a1092017-09-13 21:59:59 +0100126 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000127
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100136 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000137 }
138
139 @Test
140 public void trackingDisabled_unsolicitedResultsIgnored_withoutToken() {
141 // Set up device configuration.
142 configureTrackingDisabled();
143
144 // Initialize the tracker.
Neil Fuller35822592017-12-11 14:39:03 +0000145 assertFalse(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000146
147 // Check reliability triggering state.
Neil Fullercd1a1092017-09-13 21:59:59 +0100148 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000149
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100155 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000156
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.
Neil Fuller35822592017-12-11 14:39:03 +0000170 assertFalse(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000171
172 // Check reliability triggering state.
Neil Fullercd1a1092017-09-13 21:59:59 +0100173 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000174
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100179 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000180
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100202 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000203 }
204
Neil Fuller29ff71b2017-07-18 10:30:53 +0100205 @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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100222 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller29ff71b2017-07-18 10:30:53 +0100223 }
Neil Fuller68f66662017-03-16 18:32:21 +0000224
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100242 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000243 }
244
Neil Fuller29ff71b2017-07-18 10:30:53 +0100245 @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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100262 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller29ff71b2017-07-18 10:30:53 +0100263 }
Neil Fuller68f66662017-03-16 18:32:21 +0000264
265 @Test
Neil Fuller35822592017-12-11 14:39:03 +0000266 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
Neil Fuller68f66662017-03-16 18:32:21 +0000295 public void trackingEnabled_packageUpdate_badUpdateAppManifestEntry() throws Exception {
296 // Set up device configuration.
297 configureTrackingEnabled();
298 configureReliabilityConfigSettingsOk();
299 configureValidApplications();
300
301 // Initialize the tracker.
Neil Fuller35822592017-12-11 14:39:03 +0000302 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000303
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100325 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000326
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.
Neil Fuller35822592017-12-11 14:39:03 +0000339 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000340
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100361 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000362
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.
Neil Fuller35822592017-12-11 14:39:03 +0000384 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000385
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.
Neil Fuller35822592017-12-11 14:39:03 +0000432 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000433
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100452 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000453
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.
Neil Fuller35822592017-12-11 14:39:03 +0000471 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000472
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.
Neil Fuller35822592017-12-11 14:39:03 +0000517 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000518
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.
Neil Fuller35822592017-12-11 14:39:03 +0000566 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000567
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.
Neil Fuller35822592017-12-11 14:39:03 +0000626 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000627
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100663 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000664
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.
Neil Fuller35822592017-12-11 14:39:03 +0000688 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000689
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.
Neil Fuller35822592017-12-11 14:39:03 +0000744 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000745
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100779 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000780
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.
Neil Fuller35822592017-12-11 14:39:03 +0000793 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000794
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100802 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +0000803
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.
Neil Fuller35822592017-12-11 14:39:03 +0000830 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000831
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100839 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +0000840
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.
Neil Fuller35822592017-12-11 14:39:03 +0000870 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000871
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100879 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +0000880
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.
Neil Fuller35822592017-12-11 14:39:03 +0000916 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000917
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100926 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +0000927
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) {
Neil Fullercd1a1092017-09-13 21:59:59 +0100948 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000949 } else {
Neil Fullercd1a1092017-09-13 21:59:59 +0100950 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +0000951 }
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.
Neil Fuller35822592017-12-11 14:39:03 +0000975 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +0000976
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.
Neil Fullercd1a1092017-09-13 21:59:59 +0100986 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +0000987
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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001007 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +00001008 }
1009
1010 // Simulate a reliability trigger.
Neil Fullercd1a1092017-09-13 21:59:59 +01001011 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001012
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.
Neil Fuller35822592017-12-11 14:39:03 +00001050 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +00001051
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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001059 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001060
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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001069 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001070
1071 // Assert the PackageTracker did not trigger an update.
1072 mFakeIntentHelper.assertUpdateNotTriggered();
1073 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, currentPackageVersions);
Neil Fullercd1a1092017-09-13 21:59:59 +01001074 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +00001075
1076 // Increment the clock slightly more. Should now consider the response overdue.
1077 mFakeClock.incrementClock(2);
1078
1079 // Simulate a reliability trigger.
Neil Fullercd1a1092017-09-13 21:59:59 +01001080 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001081
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.
Neil Fuller35822592017-12-11 14:39:03 +00001116 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +00001117
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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001132 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001133
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.
Neil Fuller35822592017-12-11 14:39:03 +00001171 assertTrue(mPackageTracker.start());
Neil Fuller68f66662017-03-16 18:32:21 +00001172
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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001190 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001191
1192 // Assert the PackageTracker did not trigger an update.
1193 mFakeIntentHelper.assertUpdateNotTriggered();
1194 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, newPackageVersions);
Neil Fullercd1a1092017-09-13 21:59:59 +01001195 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +00001196
1197 // Increment the clock slightly more. Should now consider the response overdue.
1198 mFakeClock.incrementClock(2);
1199
1200 // Simulate a reliability trigger.
Neil Fullercd1a1092017-09-13 21:59:59 +01001201 mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001202
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
Neil Fuller87b11282017-06-23 16:43:45 +01001211 @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
Neil Fuller68f66662017-03-16 18:32:21 +00001221 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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001238 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +00001239
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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001246 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +00001247
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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001254 mFakeIntentHelper.assertReliabilityTriggerNotScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +00001255
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,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001282 long updataAppPackageVersion) throws Exception {
Neil Fuller68f66662017-03-16 18:32:21 +00001283 when(mMockPackageManagerHelper.getInstalledPackageVersion(updateAppPackageName))
1284 .thenReturn(updataAppPackageVersion);
1285 }
1286
1287 private void configureDataAppPackageVersion(String dataAppPackageName,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001288 long dataAppPackageVersion) throws Exception {
Neil Fuller68f66662017-03-16 18:32:21 +00001289 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.
Neil Fullercd1a1092017-09-13 21:59:59 +01001381 mFakeIntentHelper.assertReliabilityTriggerScheduled();
Neil Fuller68f66662017-03-16 18:32:21 +00001382 }
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 */
Neil Fullerb1442272017-12-18 15:59:50 +00001402 private static class FakeIntentHelper implements PackageTrackerIntentHelper {
Neil Fuller68f66662017-03-16 18:32:21 +00001403
Neil Fullercd1a1092017-09-13 21:59:59 +01001404 private PackageTracker mPackageTracker;
Neil Fuller68f66662017-03-16 18:32:21 +00001405 private String mUpdateAppPackageName;
1406 private String mDataAppPackageName;
1407
1408 private CheckToken mLastToken;
1409
Neil Fullercd1a1092017-09-13 21:59:59 +01001410 private boolean mReliabilityTriggerScheduled;
Neil Fuller68f66662017-03-16 18:32:21 +00001411
1412 @Override
1413 public void initialize(String updateAppPackageName, String dataAppPackageName,
Neil Fullercd1a1092017-09-13 21:59:59 +01001414 PackageTracker packageTracker) {
Neil Fuller68f66662017-03-16 18:32:21 +00001415 assertNotNull(updateAppPackageName);
1416 assertNotNull(dataAppPackageName);
Neil Fullercd1a1092017-09-13 21:59:59 +01001417 assertNotNull(packageTracker);
1418 mPackageTracker = packageTracker;
Neil Fuller68f66662017-03-16 18:32:21 +00001419 mUpdateAppPackageName = updateAppPackageName;
1420 mDataAppPackageName = dataAppPackageName;
1421 }
1422
1423 public void assertInitialized(
1424 String expectedUpdateAppPackageName, String expectedDataAppPackageName) {
Neil Fullercd1a1092017-09-13 21:59:59 +01001425 assertNotNull(mPackageTracker);
Neil Fuller68f66662017-03-16 18:32:21 +00001426 assertEquals(expectedUpdateAppPackageName, mUpdateAppPackageName);
1427 assertEquals(expectedDataAppPackageName, mDataAppPackageName);
1428 }
1429
1430 public void assertNotInitialized() {
Neil Fullercd1a1092017-09-13 21:59:59 +01001431 assertNull(mPackageTracker);
Neil Fuller68f66662017-03-16 18:32:21 +00001432 }
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
Neil Fullercd1a1092017-09-13 21:59:59 +01001443 public void scheduleReliabilityTrigger(long minimumDelayMillis) {
1444 mReliabilityTriggerScheduled = true;
Neil Fuller68f66662017-03-16 18:32:21 +00001445 }
1446
1447 @Override
Neil Fullercd1a1092017-09-13 21:59:59 +01001448 public void unscheduleReliabilityTrigger() {
1449 mReliabilityTriggerScheduled = false;
Neil Fuller68f66662017-03-16 18:32:21 +00001450 }
1451
Neil Fullercd1a1092017-09-13 21:59:59 +01001452 public void assertReliabilityTriggerScheduled() {
1453 assertTrue(mReliabilityTriggerScheduled);
Neil Fuller68f66662017-03-16 18:32:21 +00001454 }
1455
Neil Fullercd1a1092017-09-13 21:59:59 +01001456 public void assertReliabilityTriggerNotScheduled() {
1457 assertFalse(mReliabilityTriggerScheduled);
Neil Fuller68f66662017-03-16 18:32:21 +00001458 }
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() {
Neil Fullercd1a1092017-09-13 21:59:59 +01001476 mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */);
Neil Fuller68f66662017-03-16 18:32:21 +00001477 }
1478 }
1479
Neil Fullera7d21f82017-12-05 15:09:35 +00001480 private static class FakeClock extends Clock {
Neil Fuller68f66662017-03-16 18:32:21 +00001481
1482 private long currentTime = 1000;
1483
1484 @Override
Neil Fullera7d21f82017-12-05 15:09:35 +00001485 public long millis() {
Neil Fuller68f66662017-03-16 18:32:21 +00001486 return currentTime;
1487 }
1488
1489 public void incrementClock(long millis) {
1490 currentTime += millis;
1491 }
Neil Fullera7d21f82017-12-05 15:09:35 +00001492
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 }
Neil Fuller68f66662017-03-16 18:32:21 +00001507 }
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}