blob: d0c261279c9d23ab75b34c637790ce95ae0cf6d6 [file] [log] [blame]
Zimuzo3eee4382019-01-08 20:42:39 +00001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import static com.android.server.PackageWatchdog.TRIGGER_FAILURE_COUNT;
20
21import static org.junit.Assert.assertEquals;
22import static org.junit.Assert.assertNull;
23import static org.junit.Assert.assertTrue;
24
Zimuzo972e1cd2019-01-28 16:30:01 +000025import android.content.pm.VersionedPackage;
Zimuzo3eee4382019-01-08 20:42:39 +000026import android.os.test.TestLooper;
Brett Chabot502ec7a2019-03-01 14:43:20 -080027
28import androidx.test.InstrumentationRegistry;
Zimuzo3eee4382019-01-08 20:42:39 +000029
30import com.android.server.PackageWatchdog.PackageHealthObserver;
Zimuzoe5009cd2019-01-23 18:11:58 +000031import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
Zimuzo3eee4382019-01-08 20:42:39 +000032
Zimuzo3eee4382019-01-08 20:42:39 +000033import org.junit.Before;
34import org.junit.Test;
35
36import java.io.File;
37import java.util.ArrayList;
38import java.util.Arrays;
39import java.util.List;
40import java.util.concurrent.TimeUnit;
41
42// TODO(zezeozue): Write test without using PackageWatchdog#getPackages. Just rely on
43// behavior of observers receiving crash notifications or not to determine if it's registered
44/**
45 * Test PackageWatchdog.
46 */
47public class PackageWatchdogTest {
48 private static final String APP_A = "com.package.a";
49 private static final String APP_B = "com.package.b";
Zimuzoe5009cd2019-01-23 18:11:58 +000050 private static final String APP_C = "com.package.c";
51 private static final String APP_D = "com.package.d";
Zimuzo972e1cd2019-01-28 16:30:01 +000052 private static final long VERSION_CODE = 1L;
Zimuzo3eee4382019-01-08 20:42:39 +000053 private static final String OBSERVER_NAME_1 = "observer1";
54 private static final String OBSERVER_NAME_2 = "observer2";
55 private static final String OBSERVER_NAME_3 = "observer3";
Zimuzoe5009cd2019-01-23 18:11:58 +000056 private static final String OBSERVER_NAME_4 = "observer4";
Zimuzo3eee4382019-01-08 20:42:39 +000057 private static final long SHORT_DURATION = TimeUnit.SECONDS.toMillis(1);
58 private static final long LONG_DURATION = TimeUnit.SECONDS.toMillis(5);
59 private TestLooper mTestLooper;
60
61 @Before
62 public void setUp() throws Exception {
Zimuzo3eee4382019-01-08 20:42:39 +000063 new File(InstrumentationRegistry.getContext().getFilesDir(),
64 "package-watchdog.xml").delete();
Zimuzoe5009cd2019-01-23 18:11:58 +000065 mTestLooper = new TestLooper();
66 mTestLooper.startAutoDispatch();
Zimuzo3eee4382019-01-08 20:42:39 +000067 }
68
69 /**
70 * Test registration, unregistration, package expiry and duration reduction
71 */
72 @Test
73 public void testRegistration() throws Exception {
74 PackageWatchdog watchdog = createWatchdog();
75 TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
76 TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
77 TestObserver observer3 = new TestObserver(OBSERVER_NAME_3);
78
79 // Start observing for observer1 which will be unregistered
Zimuzo9284e742019-02-22 12:09:28 +000080 watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
Zimuzo3eee4382019-01-08 20:42:39 +000081 // Start observing for observer2 which will expire
Zimuzo9284e742019-02-22 12:09:28 +000082 watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION,
83 false);
Zimuzo3eee4382019-01-08 20:42:39 +000084 // Start observing for observer3 which will have expiry duration reduced
Zimuzo9284e742019-02-22 12:09:28 +000085 watchdog.startObservingHealth(observer3, Arrays.asList(APP_A), LONG_DURATION, false);
Zimuzo3eee4382019-01-08 20:42:39 +000086
87 // Verify packages observed at start
88 // 1
89 assertEquals(1, watchdog.getPackages(observer1).size());
90 assertTrue(watchdog.getPackages(observer1).contains(APP_A));
91 // 2
92 assertEquals(2, watchdog.getPackages(observer2).size());
93 assertTrue(watchdog.getPackages(observer2).contains(APP_A));
94 assertTrue(watchdog.getPackages(observer2).contains(APP_B));
95 // 3
96 assertEquals(1, watchdog.getPackages(observer3).size());
97 assertTrue(watchdog.getPackages(observer3).contains(APP_A));
98
99 // Then unregister observer1
100 watchdog.unregisterHealthObserver(observer1);
101
102 // Verify observer2 and observer3 left
103 // 1
104 assertNull(watchdog.getPackages(observer1));
105 // 2
106 assertEquals(2, watchdog.getPackages(observer2).size());
107 assertTrue(watchdog.getPackages(observer2).contains(APP_A));
108 assertTrue(watchdog.getPackages(observer2).contains(APP_B));
109 // 3
110 assertEquals(1, watchdog.getPackages(observer3).size());
111 assertTrue(watchdog.getPackages(observer3).contains(APP_A));
112
113 // Then advance time a little and run messages in Handlers so observer2 expires
114 Thread.sleep(SHORT_DURATION);
115 mTestLooper.dispatchAll();
116
117 // Verify observer3 left with reduced expiry duration
118 // 1
119 assertNull(watchdog.getPackages(observer1));
120 // 2
121 assertNull(watchdog.getPackages(observer2));
122 // 3
123 assertEquals(1, watchdog.getPackages(observer3).size());
124 assertTrue(watchdog.getPackages(observer3).contains(APP_A));
125
126 // Then advance time some more and run messages in Handlers so observer3 expires
127 Thread.sleep(LONG_DURATION);
128 mTestLooper.dispatchAll();
129
130 // Verify observer3 expired
131 // 1
132 assertNull(watchdog.getPackages(observer1));
133 // 2
134 assertNull(watchdog.getPackages(observer2));
135 // 3
136 assertNull(watchdog.getPackages(observer3));
137 }
138
139 /**
140 * Test package observers are persisted and loaded on startup
141 */
142 @Test
143 public void testPersistence() throws Exception {
144 PackageWatchdog watchdog1 = createWatchdog();
145 TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
146 TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
147
Zimuzo9284e742019-02-22 12:09:28 +0000148 watchdog1.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
149 watchdog1.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION,
150 false);
Zimuzo3eee4382019-01-08 20:42:39 +0000151
152 // Verify 2 observers are registered and saved internally
153 // 1
154 assertEquals(1, watchdog1.getPackages(observer1).size());
155 assertTrue(watchdog1.getPackages(observer1).contains(APP_A));
156 // 2
157 assertEquals(2, watchdog1.getPackages(observer2).size());
158 assertTrue(watchdog1.getPackages(observer2).contains(APP_A));
159 assertTrue(watchdog1.getPackages(observer2).contains(APP_B));
160
Zimuzo3eee4382019-01-08 20:42:39 +0000161 // Then advance time and run IO Handler so file is saved
162 mTestLooper.dispatchAll();
163
164 // Then start a new watchdog
165 PackageWatchdog watchdog2 = createWatchdog();
166
167 // Verify the new watchdog loads observers on startup but nothing registered
168 assertEquals(0, watchdog2.getPackages(observer1).size());
169 assertEquals(0, watchdog2.getPackages(observer2).size());
170 // Verify random observer not saved returns null
171 assertNull(watchdog2.getPackages(new TestObserver(OBSERVER_NAME_3)));
172
173 // Then regiser observer1
174 watchdog2.registerHealthObserver(observer1);
175 watchdog2.registerHealthObserver(observer2);
176
177 // Verify 2 observers are registered after reload
178 // 1
179 assertEquals(1, watchdog1.getPackages(observer1).size());
180 assertTrue(watchdog1.getPackages(observer1).contains(APP_A));
181 // 2
182 assertEquals(2, watchdog1.getPackages(observer2).size());
183 assertTrue(watchdog1.getPackages(observer2).contains(APP_A));
184 assertTrue(watchdog1.getPackages(observer2).contains(APP_B));
185 }
186
187 /**
188 * Test package failure under threshold does not notify observers
189 */
190 @Test
191 public void testNoPackageFailureBeforeThreshold() throws Exception {
192 PackageWatchdog watchdog = createWatchdog();
193 TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
194 TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
195
Zimuzo9284e742019-02-22 12:09:28 +0000196 watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION, false);
197 watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
Zimuzo3eee4382019-01-08 20:42:39 +0000198
199 // Then fail APP_A below the threshold
200 for (int i = 0; i < TRIGGER_FAILURE_COUNT - 1; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000201 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
Zimuzo3eee4382019-01-08 20:42:39 +0000202 }
203
Zimuzoe5009cd2019-01-23 18:11:58 +0000204 // Run handler so package failures are dispatched to observers
205 mTestLooper.dispatchAll();
206
Zimuzo3eee4382019-01-08 20:42:39 +0000207 // Verify that observers are not notified
208 assertEquals(0, observer1.mFailedPackages.size());
209 assertEquals(0, observer2.mFailedPackages.size());
210 }
211
212 /**
Zimuzoe5009cd2019-01-23 18:11:58 +0000213 * Test package failure and does not notify any observer because they are not observing
214 * the failed packages.
Zimuzo3eee4382019-01-08 20:42:39 +0000215 */
216 @Test
Zimuzo972e1cd2019-01-28 16:30:01 +0000217 public void testPackageFailureDifferentPackageNotifyNone() throws Exception {
Zimuzo3eee4382019-01-08 20:42:39 +0000218 PackageWatchdog watchdog = createWatchdog();
Zimuzo972e1cd2019-01-28 16:30:01 +0000219 TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
220 TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
Zimuzo3eee4382019-01-08 20:42:39 +0000221
Zimuzoe5009cd2019-01-23 18:11:58 +0000222
Zimuzo9284e742019-02-22 12:09:28 +0000223 watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION, false);
224 watchdog.startObservingHealth(observer1, Arrays.asList(APP_B), SHORT_DURATION, false);
Zimuzo3eee4382019-01-08 20:42:39 +0000225
Zimuzoe5009cd2019-01-23 18:11:58 +0000226 // Then fail APP_C (not observed) above the threshold
Zimuzo3eee4382019-01-08 20:42:39 +0000227 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000228 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
Zimuzo3eee4382019-01-08 20:42:39 +0000229 }
230
Zimuzoe5009cd2019-01-23 18:11:58 +0000231 // Run handler so package failures are dispatched to observers
232 mTestLooper.dispatchAll();
233
234 // Verify that observers are not notified
235 assertEquals(0, observer1.mFailedPackages.size());
236 assertEquals(0, observer2.mFailedPackages.size());
Zimuzo3eee4382019-01-08 20:42:39 +0000237 }
238
239 /**
Zimuzo972e1cd2019-01-28 16:30:01 +0000240 * Test package failure and does not notify any observer because the failed package version
241 * does not match the available rollback-from-version.
242 */
243 @Test
244 public void testPackageFailureDifferentVersionNotifyNone() throws Exception {
245 PackageWatchdog watchdog = createWatchdog();
246 long differentVersionCode = 2L;
247 TestObserver observer = new TestObserver(OBSERVER_NAME_1) {
Zimuzo71d931e2019-02-01 13:08:16 +0000248 @Override
249 public int onHealthCheckFailed(VersionedPackage versionedPackage) {
250 if (versionedPackage.getVersionCode() == VERSION_CODE) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000251 // Only rollback for specific versionCode
252 return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
253 }
254 return PackageHealthObserverImpact.USER_IMPACT_NONE;
255 }
256 };
257
Zimuzo9284e742019-02-22 12:09:28 +0000258 watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION, false);
Zimuzo972e1cd2019-01-28 16:30:01 +0000259
260 // Then fail APP_A (different version) above the threshold
261 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
262 watchdog.onPackageFailure(Arrays.asList(
263 new VersionedPackage(APP_A, differentVersionCode)));
264 }
265
266 // Run handler so package failures are dispatched to observers
267 mTestLooper.dispatchAll();
268
269 // Verify that observers are not notified
270 assertEquals(0, observer.mFailedPackages.size());
271 }
272
273
274 /**
Zimuzoe5009cd2019-01-23 18:11:58 +0000275 * Test package failure and notifies only least impact observers.
Zimuzo3eee4382019-01-08 20:42:39 +0000276 */
277 @Test
Zimuzoe5009cd2019-01-23 18:11:58 +0000278 public void testPackageFailureNotifyAllDifferentImpacts() throws Exception {
Zimuzo3eee4382019-01-08 20:42:39 +0000279 PackageWatchdog watchdog = createWatchdog();
Zimuzoe5009cd2019-01-23 18:11:58 +0000280 TestObserver observerNone = new TestObserver(OBSERVER_NAME_1,
281 PackageHealthObserverImpact.USER_IMPACT_NONE);
282 TestObserver observerHigh = new TestObserver(OBSERVER_NAME_2,
283 PackageHealthObserverImpact.USER_IMPACT_HIGH);
284 TestObserver observerMid = new TestObserver(OBSERVER_NAME_3,
285 PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
286 TestObserver observerLow = new TestObserver(OBSERVER_NAME_4,
287 PackageHealthObserverImpact.USER_IMPACT_LOW);
288
289 // Start observing for all impact observers
290 watchdog.startObservingHealth(observerNone, Arrays.asList(APP_A, APP_B, APP_C, APP_D),
Zimuzo9284e742019-02-22 12:09:28 +0000291 SHORT_DURATION, false);
Zimuzoe5009cd2019-01-23 18:11:58 +0000292 watchdog.startObservingHealth(observerHigh, Arrays.asList(APP_A, APP_B, APP_C),
Zimuzo9284e742019-02-22 12:09:28 +0000293 SHORT_DURATION, false);
Zimuzoe5009cd2019-01-23 18:11:58 +0000294 watchdog.startObservingHealth(observerMid, Arrays.asList(APP_A, APP_B),
Zimuzo9284e742019-02-22 12:09:28 +0000295 SHORT_DURATION, false);
Zimuzoe5009cd2019-01-23 18:11:58 +0000296 watchdog.startObservingHealth(observerLow, Arrays.asList(APP_A),
Zimuzo9284e742019-02-22 12:09:28 +0000297 SHORT_DURATION, false);
Zimuzoe5009cd2019-01-23 18:11:58 +0000298
299 // Then fail all apps above the threshold
300 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000301 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
302 new VersionedPackage(APP_B, VERSION_CODE),
303 new VersionedPackage(APP_C, VERSION_CODE),
304 new VersionedPackage(APP_D, VERSION_CODE)));
Zimuzoe5009cd2019-01-23 18:11:58 +0000305 }
306
307 // Run handler so package failures are dispatched to observers
308 mTestLooper.dispatchAll();
309
310 // Verify least impact observers are notifed of package failures
311 List<String> observerNonePackages = observerNone.mFailedPackages;
312 List<String> observerHighPackages = observerHigh.mFailedPackages;
313 List<String> observerMidPackages = observerMid.mFailedPackages;
314 List<String> observerLowPackages = observerLow.mFailedPackages;
315
316 // APP_D failure observed by only observerNone is not caught cos its impact is none
317 assertEquals(0, observerNonePackages.size());
318 // APP_C failure is caught by observerHigh cos it's the lowest impact observer
319 assertEquals(1, observerHighPackages.size());
320 assertEquals(APP_C, observerHighPackages.get(0));
321 // APP_B failure is caught by observerMid cos it's the lowest impact observer
322 assertEquals(1, observerMidPackages.size());
323 assertEquals(APP_B, observerMidPackages.get(0));
324 // APP_A failure is caught by observerLow cos it's the lowest impact observer
325 assertEquals(1, observerLowPackages.size());
326 assertEquals(APP_A, observerLowPackages.get(0));
327 }
328
329 /**
330 * Test package failure and least impact observers are notified successively.
331 * State transistions:
332 *
333 * <ul>
334 * <li>(observer1:low, observer2:mid) -> {observer1}
335 * <li>(observer1:high, observer2:mid) -> {observer2}
336 * <li>(observer1:high, observer2:none) -> {observer1}
337 * <li>(observer1:none, observer2:none) -> {}
338 * <ul>
339 */
340 @Test
Zimuzo972e1cd2019-01-28 16:30:01 +0000341 public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception {
Zimuzoe5009cd2019-01-23 18:11:58 +0000342 PackageWatchdog watchdog = createWatchdog();
343 TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1,
344 PackageHealthObserverImpact.USER_IMPACT_LOW);
345 TestObserver observerSecond = new TestObserver(OBSERVER_NAME_2,
346 PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
347
348 // Start observing for observerFirst and observerSecond with failure handling
Zimuzo9284e742019-02-22 12:09:28 +0000349 watchdog.startObservingHealth(observerFirst, Arrays.asList(APP_A), LONG_DURATION, false);
350 watchdog.startObservingHealth(observerSecond, Arrays.asList(APP_A), LONG_DURATION, false);
Zimuzoe5009cd2019-01-23 18:11:58 +0000351
352 // Then fail APP_A above the threshold
353 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000354 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
Zimuzoe5009cd2019-01-23 18:11:58 +0000355 }
356 // Run handler so package failures are dispatched to observers
357 mTestLooper.dispatchAll();
358
359 // Verify only observerFirst is notifed
360 assertEquals(1, observerFirst.mFailedPackages.size());
361 assertEquals(APP_A, observerFirst.mFailedPackages.get(0));
362 assertEquals(0, observerSecond.mFailedPackages.size());
363
364 // After observerFirst handles failure, next action it has is high impact
365 observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_HIGH;
366 observerFirst.mFailedPackages.clear();
367 observerSecond.mFailedPackages.clear();
368
369 // Then fail APP_A again above the threshold
370 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000371 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
Zimuzoe5009cd2019-01-23 18:11:58 +0000372 }
373 // Run handler so package failures are dispatched to observers
374 mTestLooper.dispatchAll();
375
376 // Verify only observerSecond is notifed cos it has least impact
377 assertEquals(1, observerSecond.mFailedPackages.size());
378 assertEquals(APP_A, observerSecond.mFailedPackages.get(0));
379 assertEquals(0, observerFirst.mFailedPackages.size());
380
381 // After observerSecond handles failure, it has no further actions
382 observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE;
383 observerFirst.mFailedPackages.clear();
384 observerSecond.mFailedPackages.clear();
385
386 // Then fail APP_A again above the threshold
387 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000388 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
Zimuzoe5009cd2019-01-23 18:11:58 +0000389 }
390 // Run handler so package failures are dispatched to observers
391 mTestLooper.dispatchAll();
392
393 // Verify only observerFirst is notifed cos it has the only action
394 assertEquals(1, observerFirst.mFailedPackages.size());
395 assertEquals(APP_A, observerFirst.mFailedPackages.get(0));
396 assertEquals(0, observerSecond.mFailedPackages.size());
397
398 // After observerFirst handles failure, it too has no further actions
399 observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE;
400 observerFirst.mFailedPackages.clear();
401 observerSecond.mFailedPackages.clear();
402
403 // Then fail APP_A again above the threshold
404 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000405 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
Zimuzoe5009cd2019-01-23 18:11:58 +0000406 }
407 // Run handler so package failures are dispatched to observers
408 mTestLooper.dispatchAll();
409
410 // Verify no observer is notified cos no actions left
411 assertEquals(0, observerFirst.mFailedPackages.size());
412 assertEquals(0, observerSecond.mFailedPackages.size());
413 }
414
415 /**
416 * Test package failure and notifies only one observer even with observer impact tie.
417 */
418 @Test
419 public void testPackageFailureNotifyOneSameImpact() throws Exception {
420 PackageWatchdog watchdog = createWatchdog();
421 TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
422 PackageHealthObserverImpact.USER_IMPACT_HIGH);
423 TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
424 PackageHealthObserverImpact.USER_IMPACT_HIGH);
Zimuzo3eee4382019-01-08 20:42:39 +0000425
426 // Start observing for observer1 and observer2 with failure handling
Zimuzo9284e742019-02-22 12:09:28 +0000427 watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION, false);
428 watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
Zimuzo3eee4382019-01-08 20:42:39 +0000429
430 // Then fail APP_A above the threshold
431 for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
Zimuzo972e1cd2019-01-28 16:30:01 +0000432 watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
Zimuzo3eee4382019-01-08 20:42:39 +0000433 }
434
Zimuzoe5009cd2019-01-23 18:11:58 +0000435 // Run handler so package failures are dispatched to observers
436 mTestLooper.dispatchAll();
437
Zimuzo3eee4382019-01-08 20:42:39 +0000438 // Verify only one observer is notifed
439 assertEquals(1, observer1.mFailedPackages.size());
440 assertEquals(APP_A, observer1.mFailedPackages.get(0));
441 assertEquals(0, observer2.mFailedPackages.size());
442 }
443
Zimuzo9284e742019-02-22 12:09:28 +0000444 /**
445 * Test explicit health check status determines package failure or success on expiry
446 */
Zimuzo9284e742019-02-22 12:09:28 +0000447 @Test
448 public void testPackageFailureExplicitHealthCheck() throws Exception {
449 PackageWatchdog watchdog = createWatchdog();
450 TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
451 PackageHealthObserverImpact.USER_IMPACT_HIGH);
452 TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
453 PackageHealthObserverImpact.USER_IMPACT_HIGH);
454 TestObserver observer3 = new TestObserver(OBSERVER_NAME_3,
455 PackageHealthObserverImpact.USER_IMPACT_HIGH);
456
457
458 // Start observing with explicit health checks for APP_A and APP_B respectively
459 // with observer1 and observer2
460 watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, true);
461 watchdog.startObservingHealth(observer2, Arrays.asList(APP_B), SHORT_DURATION, true);
462 // Explicit health check passed for APP_A (observer1 is aware)
463 watchdog.onExplicitHealthCheckPassed(APP_A);
464 // Start observing APP_A with explicit health checks for observer3.
465 // Observer3 didn't exist when we got the explicit health check above, so
466 // it starts out with a non-passing explicit health check and has to wait for a pass
467 // otherwise it would be notified of APP_A failure on expiry
468 watchdog.startObservingHealth(observer3, Arrays.asList(APP_A), SHORT_DURATION, true);
469
470 // Then expire observers
471 Thread.sleep(SHORT_DURATION);
472 // Run handler so package failures are dispatched to observers
473 mTestLooper.dispatchAll();
474
475 // Verify observer1 is not notified
476 assertEquals(0, observer1.mFailedPackages.size());
477
478 // Verify observer2 is notifed because health checks for APP_B never passed
479 assertEquals(1, observer2.mFailedPackages.size());
480 assertEquals(APP_B, observer2.mFailedPackages.get(0));
481
482 // Verify observer3 is notifed because health checks for APP_A did not pass before expiry
483 assertEquals(1, observer3.mFailedPackages.size());
484 assertEquals(APP_A, observer3.mFailedPackages.get(0));
485 }
486
Zimuzo3eee4382019-01-08 20:42:39 +0000487 private PackageWatchdog createWatchdog() {
488 return new PackageWatchdog(InstrumentationRegistry.getContext(),
489 mTestLooper.getLooper());
490 }
491
492 private static class TestObserver implements PackageHealthObserver {
493 private final String mName;
Zimuzoe5009cd2019-01-23 18:11:58 +0000494 private int mImpact;
Zimuzo3eee4382019-01-08 20:42:39 +0000495 final List<String> mFailedPackages = new ArrayList<>();
496
497 TestObserver(String name) {
498 mName = name;
Zimuzoe5009cd2019-01-23 18:11:58 +0000499 mImpact = PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
Zimuzo3eee4382019-01-08 20:42:39 +0000500 }
501
Zimuzoe5009cd2019-01-23 18:11:58 +0000502 TestObserver(String name, int impact) {
Zimuzo3eee4382019-01-08 20:42:39 +0000503 mName = name;
Zimuzoe5009cd2019-01-23 18:11:58 +0000504 mImpact = impact;
Zimuzo3eee4382019-01-08 20:42:39 +0000505 }
506
Zimuzo71d931e2019-02-01 13:08:16 +0000507 public int onHealthCheckFailed(VersionedPackage versionedPackage) {
Zimuzoe5009cd2019-01-23 18:11:58 +0000508 return mImpact;
509 }
510
Zimuzo71d931e2019-02-01 13:08:16 +0000511 public boolean execute(VersionedPackage versionedPackage) {
512 mFailedPackages.add(versionedPackage.getPackageName());
Zimuzoe5009cd2019-01-23 18:11:58 +0000513 return true;
Zimuzo3eee4382019-01-08 20:42:39 +0000514 }
515
516 public String getName() {
517 return mName;
518 }
519 }
520}