1 /*
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 
17 package com.android.server.rollback;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.ArgumentMatchers.argThat;
24 import static org.mockito.ArgumentMatchers.eq;
25 import static org.mockito.Mockito.never;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.content.pm.PackageManagerInternal;
30 import android.content.pm.VersionedPackage;
31 import android.content.rollback.PackageRollbackInfo;
32 import android.util.SparseArray;
33 import android.util.SparseIntArray;
34 
35 import com.android.server.pm.PackageList;
36 import com.android.server.pm.parsing.pkg.PackageImpl;
37 import com.google.common.collect.Range;
38 
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.junit.runners.JUnit4;
43 import org.mockito.ArgumentMatcher;
44 import org.mockito.Mock;
45 import org.mockito.MockitoAnnotations;
46 
47 import java.io.File;
48 import java.time.Instant;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.List;
52 
53 @RunWith(JUnit4.class)
54 public class RollbackUnitTest {
55 
56     private static final String PKG_1 = "test.testpackage.pkg1";
57     private static final String PKG_2 = "test.testpackage.pkg2";
58     private static final String PKG_3 = "com.blah.hello.three";
59     private static final String PKG_4 = "com.something.4pack";
60     private static final int USER = 0;
61     private static final String INSTALLER = "some.installer";
62 
63     @Mock private AppDataRollbackHelper mMockDataHelper;
64     @Mock private PackageManagerInternal mMockPmi;
65 
66     private List<String> mPackages;
67     private PackageList mPackageList;
68 
69     @Before
setUp()70     public void setUp() {
71         MockitoAnnotations.initMocks(this);
72         mPackages = new ArrayList<>();
73         mPackageList = new PackageList(mPackages, null);
74         when(mMockPmi.getPackageList()).thenReturn(mPackageList);
75     }
76 
createStagedRollback(int rollbackId, File backupDir, int originalSessionId)77     private Rollback createStagedRollback(int rollbackId, File backupDir, int originalSessionId) {
78         return new Rollback(rollbackId, backupDir, originalSessionId, /* isStaged */ true, USER,
79                 INSTALLER, null, new SparseIntArray(0));
80     }
81 
createNonStagedRollback(int rollbackId, File backupDir)82     private Rollback createNonStagedRollback(int rollbackId, File backupDir) {
83         return new Rollback(rollbackId, backupDir, -1, /* isStaged */ false, USER,
84                 INSTALLER, null, new SparseIntArray(0));
85     }
86 
87     @Test
newEmptyStagedRollbackDefaults()88     public void newEmptyStagedRollbackDefaults() {
89         int rollbackId = 123;
90         int sessionId = 567;
91         File file = new File("/test/testing");
92 
93         Rollback rollback = createStagedRollback(rollbackId, file, sessionId);
94 
95         assertThat(rollback.isEnabling()).isTrue();
96         assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
97         assertThat(rollback.isStaged()).isTrue();
98         assertThat(rollback.getOriginalSessionId()).isEqualTo(567);
99     }
100 
101     @Test
newEmptyNonStagedRollbackDefaults()102     public void newEmptyNonStagedRollbackDefaults() {
103         int rollbackId = 123;
104         File file = new File("/test/testing");
105 
106         Rollback rollback = createNonStagedRollback(rollbackId, file);
107 
108         assertThat(rollback.isEnabling()).isTrue();
109         assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
110         assertThat(rollback.isStaged()).isFalse();
111     }
112 
113     @Test
rollbackMadeAvailable()114     public void rollbackMadeAvailable() {
115         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
116 
117         assertThat(rollback.isEnabling()).isTrue();
118         assertThat(rollback.isAvailable()).isFalse();
119         assertThat(rollback.isCommitted()).isFalse();
120 
121         Instant availableTime = Instant.now();
122         rollback.makeAvailable();
123 
124         assertThat(rollback.isEnabling()).isFalse();
125         assertThat(rollback.isAvailable()).isTrue();
126         assertThat(rollback.isCommitted()).isFalse();
127 
128         assertThat(rollback.getTimestamp()).isIn(Range.closed(availableTime, Instant.now()));
129     }
130 
131     @Test
deletedRollbackCannotBeMadeAvailable()132     public void deletedRollbackCannotBeMadeAvailable() {
133         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
134 
135         rollback.delete(mMockDataHelper, "test");
136 
137         assertThat(rollback.isDeleted()).isTrue();
138 
139         rollback.makeAvailable();
140 
141         assertThat(rollback.isAvailable()).isFalse();
142         assertThat(rollback.isDeleted()).isTrue();
143     }
144 
145     @Test
getPackageNamesAllAndJustApex()146     public void getPackageNamesAllAndJustApex() {
147         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
148         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
149         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 11, true);
150         PackageRollbackInfo pkgInfo3 = newPkgInfoFor(PKG_3, 19, 1, false);
151         PackageRollbackInfo pkgInfo4 = newPkgInfoFor(PKG_4, 12, 1, true);
152 
153         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2, pkgInfo3, pkgInfo4));
154 
155         assertThat(rollback.getPackageNames()).containsExactly(PKG_1, PKG_2, PKG_3, PKG_4);
156         assertThat(rollback.getApexPackageNames()).containsExactly(PKG_2, PKG_4);
157     }
158 
159     @Test
includesPackagesAfterEnable()160     public void includesPackagesAfterEnable() {
161         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
162         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
163         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
164         PackageRollbackInfo pkgInfo3 = newPkgInfoFor(PKG_3, 157, 156, false);
165         PackageRollbackInfo pkgInfo4 = newPkgInfoFor(PKG_4, 99, 1, true);
166 
167         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2, pkgInfo3, pkgInfo4));
168 
169         assertThat(rollback.includesPackage(PKG_2)).isTrue();
170         assertThat(rollback.includesPackage(PKG_3)).isTrue();
171         assertThat(rollback.includesPackage("com.something.else")).isFalse();
172 
173         assertThat(rollback.includesPackageWithDifferentVersion(PKG_1, 12)).isFalse();
174         assertThat(rollback.includesPackageWithDifferentVersion(PKG_1, 1)).isTrue();
175 
176         assertThat(rollback.includesPackageWithDifferentVersion(PKG_2, 18)).isFalse();
177         assertThat(rollback.includesPackageWithDifferentVersion(PKG_2, 12)).isTrue();
178 
179         assertThat(rollback.includesPackageWithDifferentVersion(PKG_3, 157)).isFalse();
180         assertThat(rollback.includesPackageWithDifferentVersion(PKG_3, 156)).isTrue();
181         assertThat(rollback.includesPackageWithDifferentVersion(PKG_3, 15)).isTrue();
182 
183         assertThat(rollback.includesPackageWithDifferentVersion(PKG_4, 99)).isFalse();
184         assertThat(rollback.includesPackageWithDifferentVersion(PKG_4, 100)).isTrue();
185     }
186 
187     @Test
snapshotWhenEnabling()188     public void snapshotWhenEnabling() {
189         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
190         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
191         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
192         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
193 
194         assertThat(rollback.isEnabling()).isTrue();
195 
196         int[] userIds = {4, 77};
197         rollback.snapshotUserData(PKG_2, userIds, mMockDataHelper);
198 
199         // Data is snapshotted for the specified package.
200         verify(mMockDataHelper).snapshotAppData(eq(123), pkgRollbackInfoFor(PKG_2), eq(userIds));
201         verify(mMockDataHelper, never())
202                 .snapshotAppData(anyInt(), pkgRollbackInfoFor(PKG_1), any());
203     }
204 
205     @Test
snapshotWhenAvailable()206     public void snapshotWhenAvailable() {
207         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
208         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
209         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
210         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
211 
212         rollback.makeAvailable();
213 
214         assertThat(rollback.isAvailable()).isTrue();
215 
216         int[] userIds = {4, 77};
217         rollback.snapshotUserData(PKG_2, userIds, mMockDataHelper);
218 
219         // No data is snapshotted as rollback was not in the enabling state.
220         verify(mMockDataHelper, never())
221                 .snapshotAppData(anyInt(), pkgRollbackInfoFor(PKG_1), any());
222         verify(mMockDataHelper, never())
223                 .snapshotAppData(anyInt(), pkgRollbackInfoFor(PKG_2), any());
224     }
225 
226     @Test
snapshotWhenDeleted()227     public void snapshotWhenDeleted() {
228         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
229         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
230         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
231         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
232 
233         rollback.delete(mMockDataHelper, "test");
234 
235         assertThat(rollback.isDeleted()).isTrue();
236 
237         int[] userIds = {4, 77};
238         rollback.snapshotUserData(PKG_2, userIds, mMockDataHelper);
239 
240         // No data is snapshotted as rollback was not in the enabling state.
241         verify(mMockDataHelper, never())
242                 .snapshotAppData(anyInt(), pkgRollbackInfoFor(PKG_1), any());
243         verify(mMockDataHelper, never())
244                 .snapshotAppData(anyInt(), pkgRollbackInfoFor(PKG_2), any());
245     }
246 
247     @Test
snapshotThenDeleteNoApex()248     public void snapshotThenDeleteNoApex() {
249         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
250         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
251         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, false);
252         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
253 
254         int[] userIds = {111, 222};
255         rollback.snapshotUserData(PKG_2, userIds, mMockDataHelper);
256 
257         verify(mMockDataHelper).snapshotAppData(eq(123), pkgRollbackInfoFor(PKG_2), eq(userIds));
258 
259         rollback.delete(mMockDataHelper, "test");
260 
261         verify(mMockDataHelper).destroyAppDataSnapshot(eq(123), pkgRollbackInfoFor(PKG_2), eq(111));
262         verify(mMockDataHelper).destroyAppDataSnapshot(eq(123), pkgRollbackInfoFor(PKG_2), eq(222));
263         verify(mMockDataHelper, never()).destroyApexDeSnapshots(anyInt());
264         verify(mMockDataHelper, never()).destroyApexCeSnapshots(anyInt(), anyInt());
265 
266         assertThat(rollback.isDeleted()).isTrue();
267     }
268 
269     @Test
snapshotThenDeleteWithApex()270     public void snapshotThenDeleteWithApex() {
271         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
272         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
273         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
274         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
275 
276         int[] userIds = {111, 222};
277         rollback.snapshotUserData(PKG_2, userIds, mMockDataHelper);
278 
279         verify(mMockDataHelper).snapshotAppData(eq(123), pkgRollbackInfoFor(PKG_2), eq(userIds));
280 
281         rollback.delete(mMockDataHelper, "test");
282 
283         verify(mMockDataHelper, never())
284                 .destroyAppDataSnapshot(anyInt(), pkgRollbackInfoFor(PKG_2), anyInt());
285         verify(mMockDataHelper).destroyApexDeSnapshots(123);
286         verify(mMockDataHelper).destroyApexCeSnapshots(111, 123);
287         verify(mMockDataHelper).destroyApexCeSnapshots(222, 123);
288 
289         assertThat(rollback.isDeleted()).isTrue();
290     }
291 
292     @Test
restoreUserDataDoesNothingIfNotInProgress()293     public void restoreUserDataDoesNothingIfNotInProgress() {
294         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
295         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
296         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
297         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
298 
299         assertThat(rollback.isRestoreUserDataInProgress()).isFalse();
300 
301         assertThat(rollback.restoreUserDataForPackageIfInProgress(
302                 PKG_1, new int[] { 5 }, 333, "", mMockDataHelper)).isFalse();
303 
304         verify(mMockDataHelper, never()).restoreAppData(anyInt(), any(), anyInt(), anyInt(), any());
305     }
306 
307     @Test
restoreUserDataDoesNothingIfPackageNotFound()308     public void restoreUserDataDoesNothingIfPackageNotFound() {
309         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
310         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
311         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
312         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
313 
314         rollback.setRestoreUserDataInProgress(true);
315         assertThat(rollback.isRestoreUserDataInProgress()).isTrue();
316 
317         assertThat(rollback.restoreUserDataForPackageIfInProgress(
318                 PKG_3, new int[] { 5 }, 333, "", mMockDataHelper)).isFalse();
319 
320         verify(mMockDataHelper, never()).restoreAppData(anyInt(), any(), anyInt(), anyInt(), any());
321     }
322 
323     @Test
restoreUserDataRestoresIfInProgressAndPackageFound()324     public void restoreUserDataRestoresIfInProgressAndPackageFound() {
325         Rollback rollback = createNonStagedRollback(123, new File("/test/testing"));
326         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
327         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
328         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
329 
330         rollback.setRestoreUserDataInProgress(true);
331         assertThat(rollback.isRestoreUserDataInProgress()).isTrue();
332 
333         assertThat(rollback.restoreUserDataForPackageIfInProgress(
334                 PKG_1, new int[] { 5, 7 }, 333, "blah", mMockDataHelper)).isTrue();
335 
336         verify(mMockDataHelper).restoreAppData(123, pkgInfo1, 5, 333, "blah");
337         verify(mMockDataHelper).restoreAppData(123, pkgInfo1, 7, 333, "blah");
338     }
339 
340     @Test
allPackagesEnabled()341     public void allPackagesEnabled() {
342         int[] sessionIds = new int[]{ 7777, 8888 };
343         Rollback rollback = new Rollback(123, new File("/test/testing"), -1, false, USER, INSTALLER,
344                 sessionIds, new SparseIntArray(0));
345         // #allPackagesEnabled returns false when 1 out of 2 packages is enabled.
346         rollback.info.getPackages().add(newPkgInfoFor(PKG_1, 12, 10, false));
347         assertThat(rollback.allPackagesEnabled()).isFalse();
348         // #allPackagesEnabled returns false for ApkInApex doesn't count.
349         rollback.info.getPackages().add(newPkgInfoForApkInApex(PKG_3, 157, 156));
350         assertThat(rollback.allPackagesEnabled()).isFalse();
351         // #allPackagesEnabled returns true when 2 out of 2 packages are enabled.
352         rollback.info.getPackages().add(newPkgInfoFor(PKG_2, 18, 12, true));
353         assertThat(rollback.allPackagesEnabled()).isTrue();
354     }
355 
356     @Test
minExtVerConstraintNotViolated()357     public void minExtVerConstraintNotViolated() {
358         addPkgWithMinExtVersions("pkg0", new int[][] {{30, 4}});
359         addPkgWithMinExtVersions("pkg1", new int[][] {});
360         addPkgWithMinExtVersions("pkg2", new int[][] {{30, 5}, {31, 1}});
361         addPkgWithMinExtVersions("pkg3", new int[][] {{31, 7}, {32, 15}});
362 
363         assertThat(Rollback.extensionVersionReductionWouldViolateConstraint(
364                 sparseArrayFrom(new int[][] {{30, 5}}), mMockPmi)).isFalse();
365     }
366 
367     @Test
minExtVerConstraintExists()368     public void minExtVerConstraintExists() {
369         addPkgWithMinExtVersions("pkg0", null);
370         addPkgWithMinExtVersions("pkg1", new int[][] {{30, 5}, {31, 1}});
371 
372         assertThat(Rollback.extensionVersionReductionWouldViolateConstraint(
373                 sparseArrayFrom(new int[][] {{30, 4}}), mMockPmi)).isTrue();
374     }
375 
376     @Test
minExtVerConstraintExistsOnOnePackage()377     public void minExtVerConstraintExistsOnOnePackage() {
378         addPkgWithMinExtVersions("pkg0", new int[][] {{30, 4}});
379         addPkgWithMinExtVersions("pkg1", new int[][] {});
380         addPkgWithMinExtVersions("pkg2", new int[][] {{30, 5}, {31, 1}});
381         addPkgWithMinExtVersions("pkg3", new int[][] {{31, 7}, {32, 15}});
382 
383         assertThat(Rollback.extensionVersionReductionWouldViolateConstraint(
384                 sparseArrayFrom(new int[][] {{30, 4}}), mMockPmi)).isTrue();
385     }
386 
387     @Test
minExtVerConstraintDifferentSdk()388     public void minExtVerConstraintDifferentSdk() {
389         addPkgWithMinExtVersions("pkg0", null);
390         addPkgWithMinExtVersions("pkg1", new int[][] {{30, 5}, {31, 1}});
391 
392         assertThat(Rollback.extensionVersionReductionWouldViolateConstraint(
393                 sparseArrayFrom(new int[][] {{32, 4}}), mMockPmi)).isFalse();
394     }
395 
396     @Test
minExtVerConstraintNoneRecordedOnRollback()397     public void minExtVerConstraintNoneRecordedOnRollback() {
398         addPkgWithMinExtVersions("pkg0", new int[][] {{30, 4}});
399         addPkgWithMinExtVersions("pkg1", new int[][] {});
400         addPkgWithMinExtVersions("pkg2", new int[][] {{30, 5}, {31, 1}});
401         addPkgWithMinExtVersions("pkg3", new int[][] {{31, 7}, {32, 15}});
402 
403         assertThat(Rollback.extensionVersionReductionWouldViolateConstraint(
404                 new SparseIntArray(0), mMockPmi)).isFalse();
405     }
406 
407     @Test
minExtVerConstraintNoMinsRecorded()408     public void minExtVerConstraintNoMinsRecorded() {
409         addPkgWithMinExtVersions("pkg0", null);
410         addPkgWithMinExtVersions("pkg1", null);
411 
412         assertThat(Rollback.extensionVersionReductionWouldViolateConstraint(
413                 sparseArrayFrom(new int[][] {{32, 4}}), mMockPmi)).isFalse();
414     }
415 
addPkgWithMinExtVersions(String pkg, int[][] minExtVersions)416     private void addPkgWithMinExtVersions(String pkg, int[][] minExtVersions) {
417         mPackages.add(pkg);
418         PackageImpl pkgImpl = new PackageImpl(pkg, "baseCodePath", "codePath", null, false);
419         pkgImpl.setMinExtensionVersions(sparseArrayFrom(minExtVersions));
420 
421         when(mMockPmi.getPackage(pkg)).thenReturn(pkgImpl);
422     }
423 
sparseArrayFrom(int[][] arr)424     private static SparseIntArray sparseArrayFrom(int[][] arr) {
425         if (arr == null) {
426             return null;
427         }
428         SparseIntArray result = new SparseIntArray(arr.length);
429         for (int[] pair : arr) {
430             result.put(pair[0], pair[1]);
431         }
432         return result;
433     }
434 
435     @Test
readAndWriteStagedRollbackIdsFile()436     public void readAndWriteStagedRollbackIdsFile() throws Exception {
437         File testFile = File.createTempFile("test", ".txt");
438         RollbackPackageHealthObserver.writeStagedRollbackId(testFile, 2468, null);
439         RollbackPackageHealthObserver.writeStagedRollbackId(testFile, 12345,
440                 new VersionedPackage("com.test.package", 1));
441         RollbackPackageHealthObserver.writeStagedRollbackId(testFile, 13579,
442                 new VersionedPackage("com.test.package2", 2));
443         SparseArray<String> readInfo =
444                 RollbackPackageHealthObserver.readStagedRollbackIds(testFile);
445         assertThat(readInfo.size()).isEqualTo(3);
446 
447         assertThat(readInfo.keyAt(0)).isEqualTo(2468);
448         assertThat(readInfo.valueAt(0)).isEqualTo("");
449         assertThat(readInfo.keyAt(1)).isEqualTo(12345);
450         assertThat(readInfo.valueAt(1)).isEqualTo("com.test.package");
451         assertThat(readInfo.keyAt(2)).isEqualTo(13579);
452         assertThat(readInfo.valueAt(2)).isEqualTo("com.test.package2");
453     }
454 
newPkgInfoFor( String packageName, long fromVersion, long toVersion, boolean isApex)455     private static PackageRollbackInfo newPkgInfoFor(
456             String packageName, long fromVersion, long toVersion, boolean isApex) {
457         return new PackageRollbackInfo(new VersionedPackage(packageName, fromVersion),
458                 new VersionedPackage(packageName, toVersion),
459                 new ArrayList<>(), new ArrayList<>(), isApex, false, new ArrayList<>());
460     }
461 
462     /**
463      * TODO: merge newPkgInfoFor and newPkgInfoForApkInApex by using enums to specify
464      * 1. IS_APK
465      * 2. IS_APEX
466      * 3. IS_APK_IN_APEX
467      */
newPkgInfoForApkInApex( String packageName, long fromVersion, long toVersion)468     private static PackageRollbackInfo newPkgInfoForApkInApex(
469             String packageName, long fromVersion, long toVersion) {
470         return new PackageRollbackInfo(new VersionedPackage(packageName, fromVersion),
471                 new VersionedPackage(packageName, toVersion),
472                 new ArrayList<>(), new ArrayList<>(), false, true, new ArrayList<>());
473     }
474 
475     private static class PackageRollbackInfoForPackage implements
476             ArgumentMatcher<PackageRollbackInfo> {
477         private final String mPkg;
478 
PackageRollbackInfoForPackage(String pkg)479         PackageRollbackInfoForPackage(String pkg) {
480             mPkg = pkg;
481         }
482 
483         @Override
matches(PackageRollbackInfo pkgRollbackInfo)484         public boolean matches(PackageRollbackInfo pkgRollbackInfo) {
485             return pkgRollbackInfo.getPackageName().equals(mPkg);
486         }
487     }
488 
pkgRollbackInfoFor(String pkg)489     private static PackageRollbackInfo pkgRollbackInfoFor(String pkg) {
490         return argThat(new PackageRollbackInfoForPackage(pkg));
491     }
492 }
493