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