1 /*
2  * Copyright (C) 2020 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 android.content.pm.cts;
18 
19 import static android.Manifest.permission.INSTALL_PACKAGES;
20 import static android.Manifest.permission.USE_INSTALLER_V2;
21 import static android.Manifest.permission.USE_SYSTEM_DATA_LOADERS;
22 import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256;
23 import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
24 import static android.content.pm.Checksum.TYPE_WHOLE_MD5;
25 import static android.content.pm.Checksum.TYPE_WHOLE_MERKLE_ROOT_4K_SHA256;
26 import static android.content.pm.Checksum.TYPE_WHOLE_SHA1;
27 import static android.content.pm.Checksum.TYPE_WHOLE_SHA256;
28 import static android.content.pm.Checksum.TYPE_WHOLE_SHA512;
29 import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
30 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES;
31 import static android.content.pm.PackageManager.TRUST_ALL;
32 import static android.content.pm.PackageManager.TRUST_NONE;
33 
34 import static com.google.common.truth.Truth.assertThat;
35 
36 import static org.junit.Assert.assertNull;
37 import static org.junit.Assert.assertTrue;
38 import static org.junit.Assume.assumeTrue;
39 import static org.testng.Assert.assertEquals;
40 import static org.testng.Assert.assertNotNull;
41 import static org.testng.Assert.assertThrows;
42 
43 import android.app.UiAutomation;
44 import android.content.ComponentName;
45 import android.content.Context;
46 import android.content.IIntentReceiver;
47 import android.content.IIntentSender;
48 import android.content.Intent;
49 import android.content.IntentSender;
50 import android.content.pm.ApkChecksum;
51 import android.content.pm.Checksum;
52 import android.content.pm.DataLoaderParams;
53 import android.content.pm.PackageInfo;
54 import android.content.pm.PackageInstaller;
55 import android.content.pm.PackageInstaller.Session;
56 import android.content.pm.PackageInstaller.SessionParams;
57 import android.content.pm.PackageManager;
58 import android.content.pm.Signature;
59 import android.content.pm.cts.util.AbandonAllPackageSessionsRule;
60 import android.os.Build;
61 import android.os.Bundle;
62 import android.os.Environment;
63 import android.os.IBinder;
64 import android.os.ParcelFileDescriptor;
65 import android.os.SystemProperties;
66 import android.platform.test.annotations.AppModeFull;
67 import android.platform.test.annotations.RequiresFlagsDisabled;
68 import android.platform.test.annotations.RequiresFlagsEnabled;
69 import android.platform.test.flag.junit.CheckFlagsRule;
70 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
71 import android.util.ExceptionUtils;
72 
73 import androidx.annotation.NonNull;
74 import androidx.test.InstrumentationRegistry;
75 import androidx.test.filters.LargeTest;
76 import androidx.test.runner.AndroidJUnit4;
77 
78 import com.android.compatibility.common.util.CpuFeatures;
79 import com.android.compatibility.common.util.FileUtils;
80 import com.android.compatibility.common.util.SystemUtil;
81 import com.android.internal.util.HexDump;
82 import com.android.server.pm.ApkChecksums;
83 import com.android.server.pm.PackageManagerShellCommandDataLoader;
84 import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
85 
86 import org.junit.AfterClass;
87 import org.junit.Assert;
88 import org.junit.Rule;
89 import org.junit.Test;
90 import org.junit.runner.RunWith;
91 
92 import java.io.ByteArrayInputStream;
93 import java.io.ByteArrayOutputStream;
94 import java.io.DataInputStream;
95 import java.io.DataOutputStream;
96 import java.io.EOFException;
97 import java.io.File;
98 import java.io.FileInputStream;
99 import java.io.FileOutputStream;
100 import java.io.IOException;
101 import java.io.InputStream;
102 import java.io.OutputStream;
103 import java.nio.file.Files;
104 import java.nio.file.Paths;
105 import java.security.SecureRandom;
106 import java.security.cert.Certificate;
107 import java.security.cert.CertificateException;
108 import java.security.cert.CertificateFactory;
109 import java.security.cert.X509Certificate;
110 import java.util.ArrayList;
111 import java.util.Arrays;
112 import java.util.List;
113 import java.util.Objects;
114 import java.util.concurrent.LinkedBlockingQueue;
115 import java.util.concurrent.TimeUnit;
116 
117 import javax.annotation.Nonnull;
118 
119 @RunWith(AndroidJUnit4.class)
120 @AppModeFull
121 public class ChecksumsTest {
122     private static final String CTS_PACKAGE_NAME = "android.content.cts";
123     private static final String V2V3_PACKAGE_NAME = "android.content.cts";
124     private static final String V4_PACKAGE_NAME = "com.example.helloworld";
125     private static final String FIXED_PACKAGE_NAME = "android.appsecurity.cts.tinyapp";
126     private static final String FIXED_FSVERITY_PACKAGE_NAME =
127             "android.appsecurity.cts.apkveritytestapp";
128 
129     private static final String TEST_APK_PATH = "/data/local/tmp/cts/content/";
130 
131     private static final String TEST_V4_APK = "HelloWorld5.apk";
132     private static final String TEST_V4_SPLIT0 = "HelloWorld5_hdpi-v4.apk";
133     private static final String TEST_V4_SPLIT1 = "HelloWorld5_mdpi-v4.apk";
134     private static final String TEST_V4_SPLIT2 = "HelloWorld5_xhdpi-v4.apk";
135     private static final String TEST_V4_SPLIT3 = "HelloWorld5_xxhdpi-v4.apk";
136     private static final String TEST_V4_SPLIT4 = "HelloWorld5_xxxhdpi-v4.apk";
137 
138     private static final String TEST_FIXED_APK = "CtsPkgInstallTinyAppV2V3V4.apk";
139     private static final String TEST_FIXED_APK_DIGESTS_FILE =
140             "CtsPkgInstallTinyAppV2V3V4.digests";
141     private static final String TEST_FIXED_APK_DIGESTS_SIGNATURE =
142             "CtsPkgInstallTinyAppV2V3V4.digests.signature";
143     private static final String TEST_CERTIFICATE = "test-cert.x509.pem";
144     private static final String TEST_FIXED_APK_V1 = "CtsPkgInstallTinyAppV1.apk";
145     private static final String TEST_FIXED_APK_SHA512 =
146             "CtsPkgInstallTinyAppV2V3V4-Sha512withEC.apk";
147     private static final String TEST_FIXED_APK_VERITY = "CtsPkgInstallTinyAppV2V3V4-Verity.apk";
148 
149     private static final String TEST_FIXED_APK_FSVERITY = "CtsApkVerityTestAppPrebuilt.apk";
150     private static final String TEST_FIXED_APK_FSVERITY_FSVSIG =
151             "CtsApkVerityTestAppPrebuilt.apk.fsv_sig";
152     private static final String TEST_FIXED_APK_FSVERITY_SHA256_ARM64 =
153             "84c9974e74258a9c5abbc8a797358fe8ebf8918edf62383ea621e9e9e6461864";
154     private static final String TEST_FIXED_APK_FSVERITY_SHA256_X86_64 =
155             "5073070ee9e9a7821b4044b457d95a2bb81f349ba32d31acd0952e4a2617075a";
156 
157     private static final String TEST_FIXED_APK_V2_SHA256 =
158             "1eec9e86e322b8d7e48e255fc3f2df2dbc91036e63982ff9850597c6a37bbeb3";
159     private static final String TEST_FIXED_APK_SHA256 =
160             "91aa30c1ce8d0474052f71cb8210691d41f534989c5521e27e794ec4f754c5ef";
161     private static final String TEST_FIXED_APK_MD5 = "c19868da017dc01467169f8ea7c5bc57";
162     private static final Checksum[] TEST_FIXED_APK_DIGESTS = new Checksum[]{
163             new Checksum(TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
164                     hexStringToBytes(TEST_FIXED_APK_V2_SHA256)),
165             new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(TEST_FIXED_APK_SHA256)),
166             new Checksum(TYPE_WHOLE_MD5, hexStringToBytes(TEST_FIXED_APK_MD5))};
167     private static final Checksum[] TEST_FIXED_APK_WRONG_DIGESTS = new Checksum[]{
168             new Checksum(TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256, hexStringToBytes("850597c6a37bbeb3")),
169             new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(TEST_FIXED_APK_SHA256)),
170             new Checksum(TYPE_WHOLE_MD5, hexStringToBytes(TEST_FIXED_APK_MD5))};
171 
172     /** Default is to not use fs-verity since it depends on kernel support. */
173     private static final int FSVERITY_DISABLED = 0;
174 
175     /** Standard fs-verity. */
176     private static final int FSVERITY_ENABLED = 2;
177 
178     private static final byte[] NO_SIGNATURE = null;
179 
180     private static final int ALL_CHECKSUMS =
181             TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 | TYPE_WHOLE_MD5 | TYPE_WHOLE_SHA1 | TYPE_WHOLE_SHA256
182                     | TYPE_WHOLE_SHA512
183                     | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256 | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
184 
getUiAutomation()185     private static UiAutomation getUiAutomation() {
186         return InstrumentationRegistry.getInstrumentation().getUiAutomation();
187     }
188 
getContext()189     private static Context getContext() {
190         return InstrumentationRegistry.getContext();
191     }
192 
getPackageManager()193     private static PackageManager getPackageManager() {
194         return getContext().getPackageManager();
195     }
196 
getPackageInstaller()197     private static PackageInstaller getPackageInstaller() {
198         return getPackageManager().getPackageInstaller();
199     }
200 
201     @Rule
202     public AbandonAllPackageSessionsRule mAbandonSessionsRule = new AbandonAllPackageSessionsRule();
203 
204     @Rule
205     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
206 
207     @AfterClass
onAfterClass()208     public static void onAfterClass() throws Exception {
209         uninstallPackageSilently(V4_PACKAGE_NAME);
210         uninstallPackageSilently(FIXED_PACKAGE_NAME);
211         uninstallPackageSilently(FIXED_FSVERITY_PACKAGE_NAME);
212     }
213 
214     @Test
testNameNotFound()215     public void testNameNotFound() throws Exception {
216         uninstallPackageSilently(V4_PACKAGE_NAME);
217         LocalListener receiver = new LocalListener();
218         PackageManager pm = getPackageManager();
219         assertThrows(PackageManager.NameNotFoundException.class,
220                 () -> pm.requestChecksums(V4_PACKAGE_NAME, true, 0, TRUST_NONE, receiver));
221     }
222 
223     @Test
testReadWriteChecksums()224     public void testReadWriteChecksums() throws Exception {
225         // Read checksums from file and confirm they are the same as hardcoded.
226         checkStoredChecksums(TEST_FIXED_APK_DIGESTS, TEST_FIXED_APK_DIGESTS_FILE);
227 
228         // Write checksums and confirm that the file stays the same.
229         try (ByteArrayOutputStream os = new ByteArrayOutputStream();
230              DataOutputStream dos = new DataOutputStream(os)) {
231             for (Checksum checksum : TEST_FIXED_APK_DIGESTS) {
232                 Checksum.writeToStream(dos, checksum);
233             }
234             final byte[] fileBytes = Files.readAllBytes(
235                     Paths.get(createApkPath(TEST_FIXED_APK_DIGESTS_FILE)));
236             final byte[] localBytes = os.toByteArray();
237             Assert.assertArrayEquals(fileBytes, localBytes);
238         }
239     }
240 
241     @Test
testDefaultChecksums()242     public void testDefaultChecksums() throws Exception {
243         LocalListener receiver = new LocalListener();
244         PackageManager pm = getPackageManager();
245         pm.requestChecksums(V2V3_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
246         ApkChecksum[] checksums = receiver.getResult();
247         assertNotNull(checksums);
248         assertEquals(checksums.length, 1, Arrays.toString(checksums));
249         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
250     }
251 
252     @Test
testSplitsDefaultChecksums()253     public void testSplitsDefaultChecksums() throws Exception {
254         uninstallPackageSilently(V4_PACKAGE_NAME);
255         installSplits(new String[]{TEST_V4_APK, TEST_V4_SPLIT0, TEST_V4_SPLIT1, TEST_V4_SPLIT2,
256                 TEST_V4_SPLIT3, TEST_V4_SPLIT4});
257         assertTrue(isAppInstalled(V4_PACKAGE_NAME));
258 
259         LocalListener receiver = new LocalListener();
260         PackageManager pm = getPackageManager();
261         pm.requestChecksums(V4_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
262         ApkChecksum[] checksums = receiver.getResult();
263         assertNotNull(checksums);
264         assertEquals(checksums.length, 6, Arrays.toString(checksums));
265         // v2/v3 signature use 1M merkle tree.
266         assertEquals(checksums[0].getSplitName(), null);
267         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
268         assertEquals(checksums[1].getSplitName(), "config.hdpi");
269         assertEquals(checksums[1].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
270         assertEquals(checksums[2].getSplitName(), "config.mdpi");
271         assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
272         assertEquals(checksums[3].getSplitName(), "config.xhdpi");
273         assertEquals(checksums[3].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
274         assertEquals(checksums[4].getSplitName(), "config.xxhdpi");
275         assertEquals(checksums[4].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
276         assertEquals(checksums[5].getSplitName(), "config.xxxhdpi");
277         assertEquals(checksums[5].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
278     }
279 
280     @Test
testFixedDefaultChecksums()281     public void testFixedDefaultChecksums() throws Exception {
282         uninstallPackageSilently(FIXED_PACKAGE_NAME);
283         installPackage(TEST_FIXED_APK);
284         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
285 
286         LocalListener receiver = new LocalListener();
287         PackageManager pm = getPackageManager();
288         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
289         ApkChecksum[] checksums = receiver.getResult();
290         assertNotNull(checksums);
291         assertEquals(checksums.length, 1, Arrays.toString(checksums));
292         // v2/v3 signature use 1M merkle tree.
293         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
294         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_V2_SHA256);
295         assertNull(checksums[0].getInstallerCertificate());
296     }
297 
298     @Test
testFixedV1DefaultChecksums()299     public void testFixedV1DefaultChecksums() throws Exception {
300         uninstallPackageSilently(FIXED_PACKAGE_NAME);
301         installPackage(TEST_FIXED_APK_V1);
302         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
303 
304         LocalListener receiver = new LocalListener();
305         PackageManager pm = getPackageManager();
306         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
307         ApkChecksum[] checksums = receiver.getResult();
308         assertNotNull(checksums);
309         assertEquals(checksums.length, 0, Arrays.toString(checksums));
310     }
311 
312     @Test
testFixedSha512DefaultChecksums()313     public void testFixedSha512DefaultChecksums() throws Exception {
314         uninstallPackageSilently(FIXED_PACKAGE_NAME);
315         installPackage(TEST_FIXED_APK_SHA512);
316         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
317 
318         LocalListener receiver = new LocalListener();
319         PackageManager pm = getPackageManager();
320         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
321         ApkChecksum[] checksums = receiver.getResult();
322         assertNotNull(checksums);
323         assertEquals(checksums.length, 1, Arrays.toString(checksums));
324         // v2/v3 signature use 1M merkle tree.
325         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512);
326         assertEquals(bytesToHexString(checksums[0].getValue()),
327                 "6b866e8a54a3e358dfc20007960fb96123845f6c6d6c45f5fddf88150d71677f"
328                         + "4c3081a58921c88651f7376118aca312cf764b391cdfb8a18c6710f9f27916a0");
329         assertNull(checksums[0].getInstallerCertificate());
330     }
331 
332     @LargeTest
333     @Test
334     @RequiresFlagsDisabled(android.security.Flags.FLAG_DEPRECATE_FSV_SIG)
testFixedFSVerityDefaultChecksums()335     public void testFixedFSVerityDefaultChecksums() throws Exception {
336         assumeTrue(isApkVerityEnabled());
337         uninstallPackageSilently(FIXED_FSVERITY_PACKAGE_NAME);
338         installApkWithFSVerity(TEST_FIXED_APK_FSVERITY, TEST_FIXED_APK_FSVERITY_FSVSIG);
339         assertTrue(isAppInstalled(FIXED_FSVERITY_PACKAGE_NAME));
340 
341         LocalListener receiver = new LocalListener();
342         PackageManager pm = getPackageManager();
343         pm.requestChecksums(FIXED_FSVERITY_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
344         ApkChecksum[] checksums = receiver.getResult();
345         assertNotNull(checksums);
346         assertEquals(checksums.length, 2, Arrays.toString(checksums));
347         assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
348         if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArmCpu()) {
349             assertEquals(bytesToHexString(checksums[0].getValue()),
350                     TEST_FIXED_APK_FSVERITY_SHA256_ARM64);
351             assertEquals(bytesToHexString(checksums[1].getValue()),
352                     "8c61bc2548521aa0005276af68e42253957e1e24c122f7d8bf10f1832d4014e5");
353         } else if (CpuFeatures.isX86_64Cpu() || CpuFeatures.isX86Cpu()) {
354             assertEquals(bytesToHexString(checksums[0].getValue()),
355                     TEST_FIXED_APK_FSVERITY_SHA256_X86_64);
356             assertEquals(bytesToHexString(checksums[1].getValue()),
357                     "6f7cfa569c4a25d7241e26c1c8ff274badbdefd7854d91b842b1a97a985d5917");
358         } else {
359             Assert.fail("Unsupported CPU ABI");
360         }
361         assertEquals(checksums[1].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
362     }
363 
364     @LargeTest
365     @Test
366     @RequiresFlagsDisabled(android.security.Flags.FLAG_DEPRECATE_FSV_SIG)
testFixedFSVerityDefaultChecksumsIncremental()367     public void testFixedFSVerityDefaultChecksumsIncremental() throws Exception {
368         assumeTrue(checkIncrementalDeliveryFeature());
369 
370         uninstallPackageSilently(FIXED_FSVERITY_PACKAGE_NAME);
371         installFilesIncrementally(
372                 new String[]{TEST_FIXED_APK_FSVERITY, TEST_FIXED_APK_FSVERITY_FSVSIG});
373         assertTrue(isAppInstalled(FIXED_FSVERITY_PACKAGE_NAME));
374 
375         LocalListener receiver = new LocalListener();
376         PackageManager pm = getPackageManager();
377         pm.requestChecksums(FIXED_FSVERITY_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
378         ApkChecksum[] checksums = receiver.getResult();
379         assertNotNull(checksums);
380         assertEquals(checksums.length, 1, Arrays.toString(checksums));
381         assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
382         if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArmCpu()) {
383             assertEquals(bytesToHexString(checksums[0].getValue()),
384                     TEST_FIXED_APK_FSVERITY_SHA256_ARM64);
385         } else if (CpuFeatures.isX86_64Cpu() || CpuFeatures.isX86Cpu()) {
386             assertEquals(bytesToHexString(checksums[0].getValue()),
387                     TEST_FIXED_APK_FSVERITY_SHA256_X86_64);
388         } else {
389             Assert.fail("Unsupported CPU ABI");
390         }
391     }
392 
393     @Test
testFixedVerityDefaultChecksums()394     public void testFixedVerityDefaultChecksums() throws Exception {
395         uninstallPackageSilently(FIXED_PACKAGE_NAME);
396         installPackage(TEST_FIXED_APK_VERITY);
397         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
398 
399         LocalListener receiver = new LocalListener();
400         PackageManager pm = getPackageManager();
401         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
402         ApkChecksum[] checksums = receiver.getResult();
403         assertNotNull(checksums);
404         // No usable hashes as verity-in-v2-signature does not cover the whole file.
405         assertEquals(checksums.length, 0, Arrays.toString(checksums));
406     }
407 
408     @Test
409     @RequiresFlagsEnabled(android.content.pm.Flags.FLAG_ARCHIVING)
testArchivedDefaultChecksums()410     public void testArchivedDefaultChecksums() throws Exception {
411         uninstallPackageSilently(FIXED_PACKAGE_NAME);
412         installPackage(TEST_FIXED_APK);
413         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
414 
415         byte[] archivedPackage = SystemUtil.runShellCommandByteOutput(
416                 getUiAutomation(),
417                 "pm get-archived-package-metadata " + FIXED_PACKAGE_NAME);
418         uninstallPackageSilently(FIXED_PACKAGE_NAME);
419 
420         // Install as archived.
421         Assert.assertEquals("Success\n", executeShellCommand(
422                 String.format("pm install-archived --bypass-low-target-sdk-block -r -i %s -t -S %s",
423                         getContext().getPackageName(), archivedPackage.length), archivedPackage));
424         assertTrue(isPackagePresent(FIXED_PACKAGE_NAME));
425 
426         LocalListener receiver = new LocalListener();
427         PackageManager pm = getPackageManager();
428         assertThrows(PackageManager.NameNotFoundException.class, () ->
429                 pm.requestChecksums(
430                         FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver));
431     }
432 
433     @LargeTest
434     @Test
testFixedAllChecksums()435     public void testFixedAllChecksums() throws Exception {
436         uninstallPackageSilently(FIXED_PACKAGE_NAME);
437         installPackage(TEST_FIXED_APK);
438         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
439 
440         LocalListener receiver = new LocalListener();
441         PackageManager pm = getPackageManager();
442         pm.requestChecksums(FIXED_PACKAGE_NAME, true, ALL_CHECKSUMS, TRUST_NONE,
443                 receiver);
444         ApkChecksum[] checksums = receiver.getResult();
445         assertNotNull(checksums);
446         assertEquals(checksums.length, 7, Arrays.toString(checksums));
447         assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
448         assertEquals(bytesToHexString(checksums[0].getValue()),
449                 "759626c33083fbf43215cb5b17156977d963d4c6850c0cb4e73162a665db560b");
450         assertEquals(checksums[1].getType(), TYPE_WHOLE_MD5);
451         assertEquals(bytesToHexString(checksums[1].getValue()), TEST_FIXED_APK_MD5);
452         assertEquals(checksums[2].getType(), TYPE_WHOLE_SHA1);
453         assertEquals(bytesToHexString(checksums[2].getValue()),
454                 "331eef6bc57671de28cbd7e32089d047285ade6a");
455         assertEquals(checksums[3].getType(), TYPE_WHOLE_SHA256);
456         assertEquals(bytesToHexString(checksums[3].getValue()), TEST_FIXED_APK_SHA256);
457         assertEquals(checksums[4].getType(), TYPE_WHOLE_SHA512);
458         assertEquals(bytesToHexString(checksums[4].getValue()),
459                 "b59467fe578ebc81974ab3aaa1e0d2a76fef3e4ea7212a6f2885cec1af5253571"
460                         + "1e2e94496224cae3eba8dc992144ade321540ebd458ec5b9e6a4cc51170e018");
461         assertEquals(checksums[5].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
462         assertEquals(bytesToHexString(checksums[5].getValue()), TEST_FIXED_APK_V2_SHA256);
463         assertEquals(checksums[6].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512);
464         assertEquals(bytesToHexString(checksums[6].getValue()),
465                 "ef80a8630283f60108e8557c924307d0ccdfb6bbbf2c0176bd49af342f43bc84"
466                         + "5f2888afcb71524196dda0d6dd16a6a3292bb75b431b8ff74fb60d796e882f80");
467     }
468 
469     @LargeTest
470     @Test
testFixedV1AllChecksums()471     public void testFixedV1AllChecksums() throws Exception {
472         uninstallPackageSilently(FIXED_PACKAGE_NAME);
473         installPackage(TEST_FIXED_APK_V1);
474         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
475 
476         LocalListener receiver = new LocalListener();
477         PackageManager pm = getPackageManager();
478         pm.requestChecksums(FIXED_PACKAGE_NAME, true, ALL_CHECKSUMS, TRUST_NONE,
479                 receiver);
480         ApkChecksum[] checksums = receiver.getResult();
481         assertNotNull(checksums);
482         assertEquals(checksums.length, 5, Arrays.toString(checksums));
483         assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
484         assertEquals(bytesToHexString(checksums[0].getValue()),
485                 "0b9bd6ef683e0c4e8940aba6460382b33e607c0fcf487f3dc6a44b715615d166");
486         assertEquals(checksums[1].getType(), TYPE_WHOLE_MD5);
487         assertEquals(bytesToHexString(checksums[1].getValue()), "78e51e8c51e4adc6870cd71389e0f3db");
488         assertEquals(checksums[2].getType(), TYPE_WHOLE_SHA1);
489         assertEquals(bytesToHexString(checksums[2].getValue()),
490                 "f6654505f2274fd9bfc098b660cdfdc2e4da6d53");
491         assertEquals(checksums[3].getType(), TYPE_WHOLE_SHA256);
492         assertEquals(bytesToHexString(checksums[3].getValue()),
493                 "43755d36ec944494f6275ee92662aca95079b3aa6639f2d35208c5af15adff78");
494         assertEquals(checksums[4].getType(), TYPE_WHOLE_SHA512);
495         assertEquals(bytesToHexString(checksums[4].getValue()),
496                 "030fc815a4957c163af2bc6f30dd5b48ac09c94c25a824a514609e1476f91421"
497                         + "e2c8b6baa16ef54014ad6c5b90c37b26b0f5c8aeb01b63a1db2eca133091c8d1");
498     }
499 
500     @Test
testDefaultIncrementalChecksums()501     public void testDefaultIncrementalChecksums() throws Exception {
502         assumeTrue(checkIncrementalDeliveryFeature());
503         uninstallPackageSilently(V4_PACKAGE_NAME);
504 
505         installPackageIncrementally(TEST_V4_APK);
506         assertTrue(isAppInstalled(V4_PACKAGE_NAME));
507 
508         LocalListener receiver = new LocalListener();
509         PackageManager pm = getPackageManager();
510         pm.requestChecksums(V4_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
511         ApkChecksum[] checksums = receiver.getResult();
512         assertNotNull(checksums);
513         assertEquals(checksums.length, 1, Arrays.toString(checksums));
514         assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
515     }
516 
517     @Test
testFixedDefaultIncrementalChecksums()518     public void testFixedDefaultIncrementalChecksums() throws Exception {
519         assumeTrue(checkIncrementalDeliveryFeature());
520         uninstallPackageSilently(FIXED_PACKAGE_NAME);
521 
522         installPackageIncrementally(TEST_FIXED_APK);
523         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
524 
525         LocalListener receiver = new LocalListener();
526         PackageManager pm = getPackageManager();
527         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
528         ApkChecksum[] checksums = receiver.getResult();
529         assertNotNull(checksums);
530         assertEquals(checksums.length, 1, Arrays.toString(checksums));
531         assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
532         assertEquals(bytesToHexString(checksums[0].getValue()),
533                 "759626c33083fbf43215cb5b17156977d963d4c6850c0cb4e73162a665db560b");
534     }
535 
536     @LargeTest
537     @Test
testFixedAllIncrementalChecksums()538     public void testFixedAllIncrementalChecksums() throws Exception {
539         assumeTrue(checkIncrementalDeliveryFeature());
540         uninstallPackageSilently(FIXED_PACKAGE_NAME);
541 
542         installPackageIncrementally(TEST_FIXED_APK);
543         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
544 
545         LocalListener receiver = new LocalListener();
546         PackageManager pm = getPackageManager();
547         pm.requestChecksums(FIXED_PACKAGE_NAME, true, ALL_CHECKSUMS, TRUST_NONE,
548                 receiver);
549         ApkChecksum[] checksums = receiver.getResult();
550         assertNotNull(checksums);
551         assertEquals(checksums.length, 7, Arrays.toString(checksums));
552         assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
553         assertEquals(bytesToHexString(checksums[0].getValue()),
554                 "759626c33083fbf43215cb5b17156977d963d4c6850c0cb4e73162a665db560b");
555         assertEquals(checksums[1].getType(), TYPE_WHOLE_MD5);
556         assertEquals(bytesToHexString(checksums[1].getValue()), TEST_FIXED_APK_MD5);
557         assertEquals(checksums[2].getType(), TYPE_WHOLE_SHA1);
558         assertEquals(bytesToHexString(checksums[2].getValue()),
559                 "331eef6bc57671de28cbd7e32089d047285ade6a");
560         assertEquals(checksums[3].getType(), TYPE_WHOLE_SHA256);
561         assertEquals(bytesToHexString(checksums[3].getValue()), TEST_FIXED_APK_SHA256);
562         assertEquals(checksums[4].getType(), TYPE_WHOLE_SHA512);
563         assertEquals(bytesToHexString(checksums[4].getValue()),
564                 "b59467fe578ebc81974ab3aaa1e0d2a76fef3e4ea7212a6f2885cec1af5253571"
565                         + "1e2e94496224cae3eba8dc992144ade321540ebd458ec5b9e6a4cc51170e018");
566         assertEquals(checksums[5].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
567         assertEquals(bytesToHexString(checksums[5].getValue()), TEST_FIXED_APK_V2_SHA256);
568         assertEquals(checksums[6].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512);
569         assertEquals(bytesToHexString(checksums[6].getValue()),
570                 "ef80a8630283f60108e8557c924307d0ccdfb6bbbf2c0176bd49af342f43bc84"
571                         + "5f2888afcb71524196dda0d6dd16a6a3292bb75b431b8ff74fb60d796e882f80");
572     }
573 
574 
575     @Test
testInstallerChecksumsTrustNone()576     public void testInstallerChecksumsTrustNone() throws Exception {
577         uninstallPackageSilently(FIXED_PACKAGE_NAME);
578         installApkWithChecksums(TEST_FIXED_APK_DIGESTS);
579 
580         LocalListener receiver = new LocalListener();
581         PackageManager pm = getPackageManager();
582         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
583         ApkChecksum[] checksums = receiver.getResult();
584         assertNotNull(checksums);
585         assertEquals(checksums.length, 1, Arrays.toString(checksums));
586         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
587         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_V2_SHA256);
588         assertNull(checksums[0].getInstallerPackageName());
589         assertNull(checksums[0].getInstallerCertificate());
590     }
591 
592     @Test
testInstallerWrongChecksumsTrustAll()593     public void testInstallerWrongChecksumsTrustAll() throws Exception {
594         uninstallPackageSilently(FIXED_PACKAGE_NAME);
595         installApkWithChecksums(TEST_FIXED_APK_WRONG_DIGESTS);
596 
597         LocalListener receiver = new LocalListener();
598         PackageManager pm = getPackageManager();
599         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_ALL, receiver);
600         ApkChecksum[] checksums = receiver.getResult();
601         assertNotNull(checksums);
602         assertEquals(checksums.length, 1, Arrays.toString(checksums));
603         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
604         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_V2_SHA256);
605         assertNull(checksums[0].getInstallerPackageName());
606         assertNull(checksums[0].getInstallerCertificate());
607     }
608 
609     @Test
testInstallerSignedChecksumsInvalidSignature()610     public void testInstallerSignedChecksumsInvalidSignature() throws Exception {
611         uninstallPackageSilently(FIXED_PACKAGE_NAME);
612         adoptShellPermissionIdentity();
613         try {
614             final PackageInstaller installer = getPackageInstaller();
615             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
616             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
617             params.installFlags |= PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
618 
619             final int sessionId = installer.createSession(params);
620             Session session = installer.openSession(sessionId);
621             writeFileToSession(session, "file", TEST_FIXED_APK);
622 
623             assertThrows(IllegalArgumentException.class, () -> session.setChecksums("file",
624                     Arrays.asList(TEST_FIXED_APK_DIGESTS), hexStringToBytes("1eec9e86")));
625         } finally {
626             dropShellPermissionIdentity();
627         }
628     }
629 
createRandomArray(int size)630     private static byte[] createRandomArray(int size) {
631         byte[] array = new byte[size];
632         (new SecureRandom()).nextBytes(array);
633         return array;
634     }
635 
636     @Test
testInstallerSignedChecksumsSignatureTooBig()637     public void testInstallerSignedChecksumsSignatureTooBig() throws Exception {
638         uninstallPackageSilently(FIXED_PACKAGE_NAME);
639         adoptShellPermissionIdentity();
640         try {
641             final PackageInstaller installer = getPackageInstaller();
642             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
643             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
644 
645             final int sessionId = installer.createSession(params);
646             Session session = installer.openSession(sessionId);
647             writeFileToSession(session, "file", TEST_FIXED_APK);
648 
649             try {
650                 session.setChecksums("file",
651                         Arrays.asList(TEST_FIXED_APK_DIGESTS), createRandomArray(50000));
652                 Assert.fail("setChecksums should throw exception.");
653             } catch (IllegalArgumentException e) {
654                 assertThat(e.getMessage()).contains("Invalid signature");
655             }
656         } finally {
657             dropShellPermissionIdentity();
658         }
659     }
660 
661     @Test
testInstallerSignedChecksumsInvalidChecksum()662     public void testInstallerSignedChecksumsInvalidChecksum() throws Exception {
663         final Checksum[] invalidChecksums = new Checksum[]{new Checksum(
664                 TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256, hexStringToBytes(
665                 "6b866e8a54a3e358dfc20007960fb96123845f6c6d6c45f5fddf8"
666                         + "8150d71677f4c3081a58921c88651f7376118aca312cf764"
667                         + "b391cdfb8a18c6710f9f27916a0a0"))};
668 
669         uninstallPackageSilently(FIXED_PACKAGE_NAME);
670         adoptShellPermissionIdentity();
671         try {
672             final PackageInstaller installer = getPackageInstaller();
673             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
674             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
675             params.installFlags |= PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
676 
677             final int sessionId = installer.createSession(params);
678             Session session = installer.openSession(sessionId);
679             writeFileToSession(session, "file", TEST_FIXED_APK);
680             assertThrows(IllegalArgumentException.class, () -> session.setChecksums("file",
681                     Arrays.asList(invalidChecksums), NO_SIGNATURE));
682         } finally {
683             dropShellPermissionIdentity();
684         }
685     }
686 
687     @Test
testInstallerSignedChecksumsTrustNone()688     public void testInstallerSignedChecksumsTrustNone() throws Exception {
689         uninstallPackageSilently(FIXED_PACKAGE_NAME);
690         final byte[] signature = readSignature();
691 
692         CommitIntentReceiver.checkSuccess(
693                 installApkWithChecksums(TEST_FIXED_APK, "file", "file", TEST_FIXED_APK_DIGESTS,
694                         signature));
695 
696         LocalListener receiver = new LocalListener();
697         PackageManager pm = getPackageManager();
698         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE, receiver);
699         ApkChecksum[] checksums = receiver.getResult();
700         assertNotNull(checksums);
701         assertEquals(checksums.length, 1, Arrays.toString(checksums));
702         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
703         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_V2_SHA256);
704         assertNull(checksums[0].getInstallerPackageName());
705         assertNull(checksums[0].getInstallerCertificate());
706     }
707 
708     @Test
testInstallerSignedChecksumsTrustAll()709     public void testInstallerSignedChecksumsTrustAll() throws Exception {
710         uninstallPackageSilently(FIXED_PACKAGE_NAME);
711         final byte[] signature = readSignature();
712         final Certificate certificate = readCertificate();
713 
714         CommitIntentReceiver.checkSuccess(
715                 installApkWithChecksums(TEST_FIXED_APK, "file", "file", TEST_FIXED_APK_DIGESTS,
716                         signature));
717 
718         LocalListener receiver = new LocalListener();
719         PackageManager pm = getPackageManager();
720         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_ALL, receiver);
721         ApkChecksum[] checksums = receiver.getResult();
722         assertNotNull(checksums);
723         // v2/v3+installer provided.
724         assertEquals(checksums.length, 3, Arrays.toString(checksums));
725 
726         assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
727         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_MD5);
728         assertEquals(checksums[0].getSplitName(), null);
729         assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
730         assertEquals(checksums[0].getInstallerCertificate(), certificate);
731         assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
732         assertEquals(bytesToHexString(checksums[1].getValue()), TEST_FIXED_APK_SHA256);
733         assertEquals(checksums[1].getSplitName(), null);
734         assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
735         assertEquals(checksums[1].getInstallerCertificate(), certificate);
736         assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
737         assertEquals(bytesToHexString(checksums[2].getValue()), TEST_FIXED_APK_V2_SHA256);
738         assertEquals(checksums[2].getSplitName(), null);
739         assertNull(checksums[2].getInstallerPackageName());
740         assertNull(checksums[2].getInstallerCertificate());
741     }
742 
743     @Test
testInstallerChecksumsTrustAll()744     public void testInstallerChecksumsTrustAll() throws Exception {
745         uninstallPackageSilently(FIXED_PACKAGE_NAME);
746         installApkWithChecksums(TEST_FIXED_APK_DIGESTS);
747 
748         final Certificate installerCertificate = getInstallerCertificate();
749 
750         LocalListener receiver = new LocalListener();
751         getPackageManager().requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_ALL,
752                 receiver);
753         ApkChecksum[] checksums = receiver.getResult();
754         assertNotNull(checksums);
755         // v2/v3+installer provided.
756         assertEquals(checksums.length, 3, Arrays.toString(checksums));
757 
758         assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
759         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_MD5);
760         assertEquals(checksums[0].getSplitName(), null);
761         assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
762         assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
763         assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
764         assertEquals(bytesToHexString(checksums[1].getValue()), TEST_FIXED_APK_SHA256);
765         assertEquals(checksums[1].getSplitName(), null);
766         assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
767         assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
768         assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
769         assertEquals(bytesToHexString(checksums[2].getValue()), TEST_FIXED_APK_V2_SHA256);
770         assertEquals(checksums[2].getSplitName(), null);
771         assertNull(checksums[2].getInstallerPackageName());
772         assertNull(checksums[2].getInstallerCertificate());
773     }
774 
775     @Test
testInstallerChecksumsTrustInstaller()776     public void testInstallerChecksumsTrustInstaller() throws Exception {
777         uninstallPackageSilently(FIXED_PACKAGE_NAME);
778         installApkWithChecksums(TEST_FIXED_APK_DIGESTS);
779 
780         // Using the installer's certificate(s).
781         PackageManager pm = getPackageManager();
782         PackageInfo packageInfo = pm.getPackageInfo(CTS_PACKAGE_NAME,
783                 PackageManager.PackageInfoFlags.of(GET_SIGNING_CERTIFICATES));
784         final List<Certificate> signatures = convertSignaturesToCertificates(
785                 packageInfo.signingInfo.getApkContentsSigners());
786 
787         LocalListener receiver = new LocalListener();
788         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, signatures, receiver);
789         ApkChecksum[] checksums = receiver.getResult();
790         assertNotNull(checksums);
791         assertEquals(checksums.length, 3, Arrays.toString(checksums));
792         assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
793         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_MD5);
794         assertEquals(checksums[0].getSplitName(), null);
795         assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
796         assertEquals(checksums[0].getInstallerCertificate(), signatures.get(0));
797         assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
798         assertEquals(bytesToHexString(checksums[1].getValue()), TEST_FIXED_APK_SHA256);
799         assertEquals(checksums[1].getSplitName(), null);
800         assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
801         assertEquals(checksums[1].getInstallerCertificate(), signatures.get(0));
802         assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
803         assertEquals(bytesToHexString(checksums[2].getValue()), TEST_FIXED_APK_V2_SHA256);
804         assertEquals(checksums[2].getSplitName(), null);
805         assertNull(checksums[2].getInstallerPackageName());
806         assertNull(checksums[2].getInstallerCertificate());
807     }
808 
809     @LargeTest
810     @Test
testInstallerFileChecksumsDuringInstall()811     public void testInstallerFileChecksumsDuringInstall() throws Exception {
812         uninstallPackageSilently(V4_PACKAGE_NAME);
813         Checksum[] digestsBase = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
814                 "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e")),
815                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("dd93e23bb8cdab0382fdca0d21a4f1cb"))};
816         Checksum[] digestsSplit0 = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
817                 "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e")),
818                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("f6430e1b795ce2658c49e68d15316b2d"))};
819 
820         final Certificate installerCertificate = getInstallerCertificate();
821 
822         adoptShellPermissionIdentity();
823         PackageInstaller installer = null;
824         int sessionId = -1;
825         try {
826             installer = getPackageInstaller();
827             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
828             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
829 
830             sessionId = installer.createSession(params);
831             final Session session = installer.openSession(sessionId);
832 
833             writeFileToSession(session, "hw5.apk", TEST_V4_APK);
834             session.setChecksums("hw5.apk", Arrays.asList(digestsBase), NO_SIGNATURE);
835 
836             writeFileToSession(session, "hw5_split0.apk", TEST_V4_SPLIT0);
837             session.setChecksums("hw5_split0.apk", Arrays.asList(digestsSplit0), NO_SIGNATURE);
838 
839             // Workaround to emulate .digests file present in installation.
840             writeChecksumsToSession(session, "hw5.digests", digestsBase);
841             writeChecksumsToSession(session, "hw5_split0.digests", digestsSplit0);
842 
843             File dataApp = Environment.getDataAppDirectory(null);
844 
845             {
846                 LocalListener receiver = new LocalListener();
847 
848                 session.requestChecksums("hw5.apk", 0, TRUST_ALL, getContext().getMainExecutor(),
849                         receiver);
850                 ApkChecksum[] checksums = receiver.getResult();
851                 assertNotNull(checksums);
852                 assertEquals(checksums.length, 3, Arrays.toString(checksums));
853                 // base
854                 assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
855                 assertEquals(checksums[0].getSplitName(), null);
856                 assertEquals(bytesToHexString(checksums[0].getValue()),
857                         "dd93e23bb8cdab0382fdca0d21a4f1cb");
858                 assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
859                 assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
860                 assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
861                 assertEquals(checksums[1].getSplitName(), null);
862                 assertEquals(bytesToHexString(checksums[1].getValue()),
863                         "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e");
864                 assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
865                 assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
866                 assertEquals(checksums[2].getSplitName(), null);
867                 assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
868                 assertNull(checksums[2].getInstallerPackageName());
869                 assertNull(checksums[2].getInstallerCertificate());
870             }
871             {
872                 LocalListener receiver = new LocalListener();
873 
874                 session.requestChecksums("hw5_split0.apk", 0, TRUST_ALL,
875                         getContext().getMainExecutor(), receiver);
876                 ApkChecksum[] checksums = receiver.getResult();
877                 assertNotNull(checksums);
878                 assertEquals(checksums.length, 3, Arrays.toString(checksums));
879                 // split0
880                 assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
881                 assertEquals(checksums[0].getSplitName(), null);
882                 assertEquals(bytesToHexString(checksums[0].getValue()),
883                         "f6430e1b795ce2658c49e68d15316b2d");
884                 assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
885                 assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
886                 assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
887                 assertEquals(checksums[1].getSplitName(), null);
888                 assertEquals(bytesToHexString(checksums[1].getValue()),
889                         "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e");
890                 assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
891                 assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
892                 assertEquals(checksums[2].getSplitName(), null);
893                 assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
894                 assertNull(checksums[2].getInstallerPackageName());
895                 assertNull(checksums[2].getInstallerCertificate());
896             }
897         } finally {
898             installer.abandonSession(sessionId);
899             dropShellPermissionIdentity();
900         }
901     }
902 
903     @Test
testInstallerChecksumsTrustWrongInstaller()904     public void testInstallerChecksumsTrustWrongInstaller() throws Exception {
905         uninstallPackageSilently(FIXED_PACKAGE_NAME);
906         installApkWithChecksums(TEST_FIXED_APK_DIGESTS);
907 
908         // Using certificates from a security app, not the installer (us).
909         PackageManager pm = getPackageManager();
910         PackageInfo packageInfo = pm.getPackageInfo(FIXED_PACKAGE_NAME,
911                 PackageManager.PackageInfoFlags.of(GET_SIGNING_CERTIFICATES));
912         final List<Certificate> signatures = convertSignaturesToCertificates(
913                 packageInfo.signingInfo.getApkContentsSigners());
914 
915         LocalListener receiver = new LocalListener();
916         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, signatures, receiver);
917         ApkChecksum[] checksums = receiver.getResult();
918         assertNotNull(checksums);
919         assertEquals(checksums.length, 1, Arrays.toString(checksums));
920         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
921         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_V2_SHA256);
922         assertNull(checksums[0].getInstallerPackageName());
923         assertNull(checksums[0].getInstallerCertificate());
924     }
925 
926     @Test
testInstallerChecksumsTrustAllWrongName()927     public void testInstallerChecksumsTrustAllWrongName() throws Exception {
928         uninstallPackageSilently(FIXED_PACKAGE_NAME);
929         // NB: "Invalid checksum name(s):" is used in Play to report checksum related failures.
930         // Please consult with them before changing.
931         CommitIntentReceiver.checkFailure(
932                 installApkWithChecksums(TEST_FIXED_APK, "apk", "wrong_name",
933                         TEST_FIXED_APK_DIGESTS),
934                 "INSTALL_FAILED_SESSION_INVALID: Invalid checksum name(s): wrong_name");
935     }
936 
937     @Test
testInstallerChecksumsUpdate()938     public void testInstallerChecksumsUpdate() throws Exception {
939         uninstallPackageSilently(V4_PACKAGE_NAME);
940 
941         Checksum[] digestsBase = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
942                 "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e")),
943                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("dd93e23bb8cdab0382fdca0d21a4f1cb"))};
944         Checksum[] digestsSplit0 = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
945                 "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e")),
946                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("f6430e1b795ce2658c49e68d15316b2d"))};
947         Checksum[] digestsSplit1 = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
948                 "f16898f43990c14585a900eda345c3a236c6224f63920d69cfe8a7afbc0c0ccf")),
949                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("d1f4b00d034994663e84f907fe4bb664"))};
950 
951         final Certificate installerCertificate = getInstallerCertificate();
952 
953         // Original package checksums: base + split0.
954         adoptShellPermissionIdentity();
955         try {
956             final PackageInstaller installer = getPackageInstaller();
957             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
958 
959             final int sessionId = installer.createSession(params);
960             Session session = installer.openSession(sessionId);
961 
962             writeFileToSession(session, "hw5", TEST_V4_APK);
963             session.setChecksums("hw5", Arrays.asList(digestsBase), NO_SIGNATURE);
964 
965             writeFileToSession(session, "hw5_split0", TEST_V4_SPLIT0);
966             session.setChecksums("hw5_split0", Arrays.asList(digestsSplit0), NO_SIGNATURE);
967 
968             CommitIntentReceiver receiver = new CommitIntentReceiver();
969             session.commit(receiver.getIntentSender());
970             CommitIntentReceiver.checkSuccess(receiver.getResult());
971         } finally {
972             dropShellPermissionIdentity();
973         }
974 
975         {
976             LocalListener receiver = new LocalListener();
977             PackageManager pm = getPackageManager();
978             pm.requestChecksums(V4_PACKAGE_NAME, true, 0, TRUST_ALL, receiver);
979             ApkChecksum[] checksums = receiver.getResult();
980             assertNotNull(checksums);
981             assertEquals(checksums.length, 6, Arrays.toString(checksums));
982             // base
983             assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
984             assertEquals(checksums[0].getSplitName(), null);
985             assertEquals(bytesToHexString(checksums[0].getValue()),
986                     "dd93e23bb8cdab0382fdca0d21a4f1cb");
987             assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
988             assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
989             assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
990             assertEquals(checksums[1].getSplitName(), null);
991             assertEquals(bytesToHexString(checksums[1].getValue()),
992                     "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e");
993             assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
994             assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
995             assertEquals(checksums[2].getSplitName(), null);
996             assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
997             assertNull(checksums[2].getInstallerPackageName());
998             assertNull(checksums[2].getInstallerCertificate());
999             // split0
1000             assertEquals(checksums[3].getType(), TYPE_WHOLE_MD5);
1001             assertEquals(checksums[3].getSplitName(), "config.hdpi");
1002             assertEquals(bytesToHexString(checksums[3].getValue()),
1003                     "f6430e1b795ce2658c49e68d15316b2d");
1004             assertEquals(checksums[3].getInstallerPackageName(), CTS_PACKAGE_NAME);
1005             assertEquals(checksums[3].getInstallerCertificate(), installerCertificate);
1006             assertEquals(checksums[4].getType(), TYPE_WHOLE_SHA256);
1007             assertEquals(checksums[4].getSplitName(), "config.hdpi");
1008             assertEquals(bytesToHexString(checksums[4].getValue()),
1009                     "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e");
1010             assertEquals(checksums[4].getInstallerPackageName(), CTS_PACKAGE_NAME);
1011             assertEquals(checksums[4].getInstallerCertificate(), installerCertificate);
1012             assertEquals(checksums[5].getSplitName(), "config.hdpi");
1013             assertEquals(checksums[5].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1014             assertNull(checksums[5].getInstallerPackageName());
1015             assertNull(checksums[5].getInstallerCertificate());
1016         }
1017 
1018         // Update the package with one split+checksums and another split without checksums.
1019         adoptShellPermissionIdentity();
1020         try {
1021             final PackageInstaller installer = getPackageInstaller();
1022             final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1023             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1024             params.setAppPackageName(V4_PACKAGE_NAME);
1025 
1026             final int sessionId = installer.createSession(params);
1027             Session session = installer.openSession(sessionId);
1028 
1029             writeFileToSession(session, "hw5_split1", TEST_V4_SPLIT1);
1030             session.setChecksums("hw5_split1", Arrays.asList(digestsSplit1), NO_SIGNATURE);
1031 
1032             writeFileToSession(session, "hw5_split2", TEST_V4_SPLIT2);
1033 
1034             CommitIntentReceiver receiver = new CommitIntentReceiver();
1035             session.commit(receiver.getIntentSender());
1036             CommitIntentReceiver.checkSuccess(receiver.getResult());
1037         } finally {
1038             dropShellPermissionIdentity();
1039         }
1040 
1041         {
1042             LocalListener receiver = new LocalListener();
1043             PackageManager pm = getPackageManager();
1044             pm.requestChecksums(V4_PACKAGE_NAME, true, 0, TRUST_ALL, receiver);
1045             ApkChecksum[] checksums = receiver.getResult();
1046             assertNotNull(checksums);
1047             assertEquals(checksums.length, 10, Arrays.toString(checksums));
1048             // base
1049             assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
1050             assertEquals(checksums[0].getSplitName(), null);
1051             assertEquals(bytesToHexString(checksums[0].getValue()),
1052                     "dd93e23bb8cdab0382fdca0d21a4f1cb");
1053             assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
1054             assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
1055             assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
1056             assertEquals(checksums[1].getSplitName(), null);
1057             assertEquals(bytesToHexString(checksums[1].getValue()),
1058                     "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e");
1059             assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
1060             assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
1061             assertEquals(checksums[2].getSplitName(), null);
1062             assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1063             assertNull(checksums[2].getInstallerPackageName());
1064             assertNull(checksums[2].getInstallerCertificate());
1065             // split0
1066             assertEquals(checksums[3].getType(), TYPE_WHOLE_MD5);
1067             assertEquals(checksums[3].getSplitName(), "config.hdpi");
1068             assertEquals(bytesToHexString(checksums[3].getValue()),
1069                     "f6430e1b795ce2658c49e68d15316b2d");
1070             assertEquals(checksums[3].getInstallerPackageName(), CTS_PACKAGE_NAME);
1071             assertEquals(checksums[3].getInstallerCertificate(), installerCertificate);
1072             assertEquals(checksums[4].getType(), TYPE_WHOLE_SHA256);
1073             assertEquals(checksums[4].getSplitName(), "config.hdpi");
1074             assertEquals(bytesToHexString(checksums[4].getValue()),
1075                     "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e");
1076             assertEquals(checksums[4].getInstallerPackageName(), CTS_PACKAGE_NAME);
1077             assertEquals(checksums[4].getInstallerCertificate(), installerCertificate);
1078             assertEquals(checksums[5].getSplitName(), "config.hdpi");
1079             assertEquals(checksums[5].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1080             assertNull(checksums[5].getInstallerPackageName());
1081             assertNull(checksums[5].getInstallerCertificate());
1082             // split1
1083             assertEquals(checksums[6].getType(), TYPE_WHOLE_MD5);
1084             assertEquals(checksums[6].getSplitName(), "config.mdpi");
1085             assertEquals(bytesToHexString(checksums[6].getValue()),
1086                     "d1f4b00d034994663e84f907fe4bb664");
1087             assertEquals(checksums[6].getInstallerPackageName(), CTS_PACKAGE_NAME);
1088             assertEquals(checksums[6].getInstallerCertificate(), installerCertificate);
1089             assertEquals(checksums[7].getType(), TYPE_WHOLE_SHA256);
1090             assertEquals(checksums[7].getSplitName(), "config.mdpi");
1091             assertEquals(bytesToHexString(checksums[7].getValue()),
1092                     "f16898f43990c14585a900eda345c3a236c6224f63920d69cfe8a7afbc0c0ccf");
1093             assertEquals(checksums[7].getInstallerPackageName(), CTS_PACKAGE_NAME);
1094             assertEquals(checksums[7].getInstallerCertificate(), installerCertificate);
1095             assertEquals(checksums[8].getSplitName(), "config.mdpi");
1096             assertEquals(checksums[8].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1097             assertNull(checksums[8].getInstallerPackageName());
1098             assertNull(checksums[8].getInstallerCertificate());
1099             // split2
1100             assertEquals(checksums[9].getSplitName(), "config.xhdpi");
1101             assertEquals(checksums[9].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1102             assertNull(checksums[9].getInstallerPackageName());
1103             assertNull(checksums[9].getInstallerCertificate());
1104         }
1105     }
1106 
1107     @Test
testInstallerSignedChecksumsUpdate()1108     public void testInstallerSignedChecksumsUpdate() throws Exception {
1109         uninstallPackageSilently(V4_PACKAGE_NAME);
1110         Checksum[] digestsBase = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
1111                 "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e")),
1112                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("dd93e23bb8cdab0382fdca0d21a4f1cb"))};
1113         Checksum[] digestsSplit0 = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
1114                 "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e")),
1115                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("f6430e1b795ce2658c49e68d15316b2d"))};
1116         Checksum[] digestsSplit1 = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
1117                 "f16898f43990c14585a900eda345c3a236c6224f63920d69cfe8a7afbc0c0ccf")),
1118                 new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("d1f4b00d034994663e84f907fe4bb664"))};
1119 
1120         String digestBaseFile = ApkChecksums.buildDigestsPathForApk(TEST_V4_APK);
1121         String digestSplit0File = ApkChecksums.buildDigestsPathForApk(TEST_V4_SPLIT0);
1122         String digestSplit1File = ApkChecksums.buildDigestsPathForApk(TEST_V4_SPLIT1);
1123 
1124         checkStoredChecksums(digestsBase, digestBaseFile);
1125         checkStoredChecksums(digestsSplit0, digestSplit0File);
1126         checkStoredChecksums(digestsSplit1, digestSplit1File);
1127 
1128         byte[] digestBaseSignature = readSignature(
1129                 ApkChecksums.buildSignaturePathForDigests(digestBaseFile));
1130         byte[] digestSplit0Signature = readSignature(
1131                 ApkChecksums.buildSignaturePathForDigests(digestSplit0File));
1132         byte[] digestSplit1Signature = readSignature(
1133                 ApkChecksums.buildSignaturePathForDigests(digestSplit1File));
1134 
1135         final Certificate certificate = readCertificate();
1136 
1137         // Original package checksums: base + split0.
1138         adoptShellPermissionIdentity();
1139         try {
1140             final PackageInstaller installer = getPackageInstaller();
1141             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1142 
1143             final int sessionId = installer.createSession(params);
1144             Session session = installer.openSession(sessionId);
1145 
1146             writeFileToSession(session, "hw5", TEST_V4_APK);
1147             session.setChecksums("hw5", Arrays.asList(digestsBase), digestBaseSignature);
1148 
1149             writeFileToSession(session, "hw5_split0", TEST_V4_SPLIT0);
1150             session.setChecksums("hw5_split0", Arrays.asList(digestsSplit0), digestSplit0Signature);
1151 
1152             CommitIntentReceiver receiver = new CommitIntentReceiver();
1153             session.commit(receiver.getIntentSender());
1154             CommitIntentReceiver.checkSuccess(receiver.getResult());
1155         } finally {
1156             dropShellPermissionIdentity();
1157         }
1158 
1159         {
1160             LocalListener receiver = new LocalListener();
1161             PackageManager pm = getPackageManager();
1162             pm.requestChecksums(V4_PACKAGE_NAME, true, 0, TRUST_ALL, receiver);
1163             ApkChecksum[] checksums = receiver.getResult();
1164             assertNotNull(checksums);
1165             assertEquals(checksums.length, 6, Arrays.toString(checksums));
1166             // base
1167             assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
1168             assertEquals(checksums[0].getSplitName(), null);
1169             assertEquals(bytesToHexString(checksums[0].getValue()),
1170                     "dd93e23bb8cdab0382fdca0d21a4f1cb");
1171             assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
1172             assertEquals(checksums[0].getInstallerCertificate(), certificate);
1173             assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
1174             assertEquals(checksums[1].getSplitName(), null);
1175             assertEquals(bytesToHexString(checksums[1].getValue()),
1176                     "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e");
1177             assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
1178             assertEquals(checksums[1].getInstallerCertificate(), certificate);
1179             assertEquals(checksums[2].getSplitName(), null);
1180             assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1181             assertNull(checksums[2].getInstallerPackageName());
1182             assertNull(checksums[2].getInstallerCertificate());
1183             // split0
1184             assertEquals(checksums[3].getType(), TYPE_WHOLE_MD5);
1185             assertEquals(checksums[3].getSplitName(), "config.hdpi");
1186             assertEquals(bytesToHexString(checksums[3].getValue()),
1187                     "f6430e1b795ce2658c49e68d15316b2d");
1188             assertEquals(checksums[3].getInstallerPackageName(), CTS_PACKAGE_NAME);
1189             assertEquals(checksums[3].getInstallerCertificate(), certificate);
1190             assertEquals(checksums[4].getType(), TYPE_WHOLE_SHA256);
1191             assertEquals(checksums[4].getSplitName(), "config.hdpi");
1192             assertEquals(bytesToHexString(checksums[4].getValue()),
1193                     "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e");
1194             assertEquals(checksums[4].getInstallerPackageName(), CTS_PACKAGE_NAME);
1195             assertEquals(checksums[4].getInstallerCertificate(), certificate);
1196             assertEquals(checksums[5].getSplitName(), "config.hdpi");
1197             assertEquals(checksums[5].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1198             assertNull(checksums[5].getInstallerPackageName());
1199             assertNull(checksums[5].getInstallerCertificate());
1200         }
1201 
1202         // Update the package with one split+checksums and another split without checksums.
1203         adoptShellPermissionIdentity();
1204         try {
1205             final PackageInstaller installer = getPackageInstaller();
1206             final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1207             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1208             params.setAppPackageName(V4_PACKAGE_NAME);
1209 
1210             final int sessionId = installer.createSession(params);
1211             Session session = installer.openSession(sessionId);
1212 
1213             writeFileToSession(session, "hw5_split1", TEST_V4_SPLIT1);
1214             session.setChecksums("hw5_split1", Arrays.asList(digestsSplit1), digestSplit1Signature);
1215 
1216             writeFileToSession(session, "hw5_split2", TEST_V4_SPLIT2);
1217 
1218             CommitIntentReceiver receiver = new CommitIntentReceiver();
1219             session.commit(receiver.getIntentSender());
1220             CommitIntentReceiver.checkSuccess(receiver.getResult());
1221         } finally {
1222             dropShellPermissionIdentity();
1223         }
1224 
1225         {
1226             LocalListener receiver = new LocalListener();
1227             PackageManager pm = getPackageManager();
1228             pm.requestChecksums(V4_PACKAGE_NAME, true, 0, TRUST_ALL, receiver);
1229             ApkChecksum[] checksums = receiver.getResult();
1230             assertNotNull(checksums);
1231             assertEquals(checksums.length, 10, Arrays.toString(checksums));
1232             // base
1233             assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
1234             assertEquals(checksums[0].getSplitName(), null);
1235             assertEquals(bytesToHexString(checksums[0].getValue()),
1236                     "dd93e23bb8cdab0382fdca0d21a4f1cb");
1237             assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
1238             assertEquals(checksums[0].getInstallerCertificate(), certificate);
1239             assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
1240             assertEquals(checksums[1].getSplitName(), null);
1241             assertEquals(bytesToHexString(checksums[1].getValue()),
1242                     "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e");
1243             assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
1244             assertEquals(checksums[1].getInstallerCertificate(), certificate);
1245             assertEquals(checksums[2].getSplitName(), null);
1246             assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1247             assertNull(checksums[2].getInstallerPackageName());
1248             assertNull(checksums[2].getInstallerCertificate());
1249             // split0
1250             assertEquals(checksums[3].getType(), TYPE_WHOLE_MD5);
1251             assertEquals(checksums[3].getSplitName(), "config.hdpi");
1252             assertEquals(bytesToHexString(checksums[3].getValue()),
1253                     "f6430e1b795ce2658c49e68d15316b2d");
1254             assertEquals(checksums[3].getInstallerPackageName(), CTS_PACKAGE_NAME);
1255             assertEquals(checksums[3].getInstallerCertificate(), certificate);
1256             assertEquals(checksums[4].getType(), TYPE_WHOLE_SHA256);
1257             assertEquals(checksums[4].getSplitName(), "config.hdpi");
1258             assertEquals(bytesToHexString(checksums[4].getValue()),
1259                     "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e");
1260             assertEquals(checksums[4].getInstallerPackageName(), CTS_PACKAGE_NAME);
1261             assertEquals(checksums[4].getInstallerCertificate(), certificate);
1262             assertEquals(checksums[5].getSplitName(), "config.hdpi");
1263             assertEquals(checksums[5].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1264             assertNull(checksums[5].getInstallerPackageName());
1265             assertNull(checksums[5].getInstallerCertificate());
1266             // split1
1267             assertEquals(checksums[6].getType(), TYPE_WHOLE_MD5);
1268             assertEquals(checksums[6].getSplitName(), "config.mdpi");
1269             assertEquals(bytesToHexString(checksums[6].getValue()),
1270                     "d1f4b00d034994663e84f907fe4bb664");
1271             assertEquals(checksums[6].getInstallerPackageName(), CTS_PACKAGE_NAME);
1272             assertEquals(checksums[6].getInstallerCertificate(), certificate);
1273             assertEquals(checksums[7].getType(), TYPE_WHOLE_SHA256);
1274             assertEquals(checksums[7].getSplitName(), "config.mdpi");
1275             assertEquals(bytesToHexString(checksums[7].getValue()),
1276                     "f16898f43990c14585a900eda345c3a236c6224f63920d69cfe8a7afbc0c0ccf");
1277             assertEquals(checksums[7].getInstallerPackageName(), CTS_PACKAGE_NAME);
1278             assertEquals(checksums[7].getInstallerCertificate(), certificate);
1279             assertEquals(checksums[8].getSplitName(), "config.mdpi");
1280             assertEquals(checksums[8].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1281             assertNull(checksums[8].getInstallerPackageName());
1282             assertNull(checksums[8].getInstallerCertificate());
1283             // split2
1284             assertEquals(checksums[9].getSplitName(), "config.xhdpi");
1285             assertEquals(checksums[9].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1286             assertNull(checksums[9].getInstallerPackageName());
1287             assertNull(checksums[9].getInstallerCertificate());
1288         }
1289     }
1290 
1291     @Test
testInstallerChecksumsIncremental()1292     public void testInstallerChecksumsIncremental() throws Exception {
1293         assumeTrue(checkIncrementalDeliveryFeature());
1294 
1295         final Certificate installerCertificate = getInstallerCertificate();
1296 
1297         uninstallPackageSilently(FIXED_PACKAGE_NAME);
1298         installPackageIncrementally(TEST_FIXED_APK);
1299 
1300         PackageManager pm = getPackageManager();
1301         PackageInfo packageInfo = pm.getPackageInfo(FIXED_PACKAGE_NAME,
1302                 PackageManager.PackageInfoFlags.of(0));
1303         final String inPath = packageInfo.applicationInfo.getBaseCodePath();
1304 
1305         installApkWithChecksumsIncrementally(inPath);
1306         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
1307 
1308         LocalListener receiver = new LocalListener();
1309         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_ALL,
1310                 receiver);
1311         ApkChecksum[] checksums = receiver.getResult();
1312         assertNotNull(checksums);
1313         assertEquals(checksums.length, 3, Arrays.toString(checksums));
1314         assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
1315         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_MD5);
1316         assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
1317         assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
1318         assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
1319         assertEquals(bytesToHexString(checksums[1].getValue()), TEST_FIXED_APK_SHA256);
1320         assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
1321         assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
1322         assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1323         assertEquals(bytesToHexString(checksums[2].getValue()), TEST_FIXED_APK_V2_SHA256);
1324         assertNull(checksums[2].getInstallerPackageName());
1325         assertNull(checksums[2].getInstallerCertificate());
1326     }
1327 
1328     @Test
testInstallerSignedChecksumsIncremental()1329     public void testInstallerSignedChecksumsIncremental() throws Exception {
1330         assumeTrue(checkIncrementalDeliveryFeature());
1331 
1332         uninstallPackageSilently(FIXED_PACKAGE_NAME);
1333         installPackageIncrementally(TEST_FIXED_APK);
1334 
1335         PackageInfo packageInfo = getPackageManager().getPackageInfo(FIXED_PACKAGE_NAME,
1336                 PackageManager.PackageInfoFlags.of(0));
1337         final String inPath = packageInfo.applicationInfo.getBaseCodePath();
1338 
1339         final byte[] signature = readSignature();
1340         final Certificate certificate = readCertificate();
1341 
1342         installApkWithChecksumsIncrementally(inPath, TEST_FIXED_APK, TEST_FIXED_APK_DIGESTS,
1343                 signature);
1344         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
1345 
1346         LocalListener receiver = new LocalListener();
1347         PackageManager pm = getPackageManager();
1348         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_ALL,
1349                 receiver);
1350         ApkChecksum[] checksums = receiver.getResult();
1351         assertNotNull(checksums);
1352         assertEquals(checksums.length, 3, Arrays.toString(checksums));
1353         assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
1354         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_MD5);
1355         assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
1356         assertEquals(checksums[0].getInstallerCertificate(), certificate);
1357         assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
1358         assertEquals(bytesToHexString(checksums[1].getValue()), TEST_FIXED_APK_SHA256);
1359         assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
1360         assertEquals(checksums[1].getInstallerCertificate(), certificate);
1361         assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1362         assertEquals(bytesToHexString(checksums[2].getValue()), TEST_FIXED_APK_V2_SHA256);
1363         assertNull(checksums[2].getInstallerPackageName());
1364         assertNull(checksums[2].getInstallerCertificate());
1365     }
1366 
1367     @Test
testInstallerChecksumsIncrementalTrustNone()1368     public void testInstallerChecksumsIncrementalTrustNone() throws Exception {
1369         assumeTrue(checkIncrementalDeliveryFeature());
1370 
1371         uninstallPackageSilently(FIXED_PACKAGE_NAME);
1372         installPackageIncrementally(TEST_FIXED_APK);
1373 
1374         PackageInfo packageInfo = getPackageManager().getPackageInfo(FIXED_PACKAGE_NAME,
1375                 PackageManager.PackageInfoFlags.of(0));
1376         final String inPath = packageInfo.applicationInfo.getBaseCodePath();
1377 
1378         installApkWithChecksumsIncrementally(inPath);
1379         assertTrue(isAppInstalled(FIXED_PACKAGE_NAME));
1380 
1381         LocalListener receiver = new LocalListener();
1382         PackageManager pm = getPackageManager();
1383         pm.requestChecksums(FIXED_PACKAGE_NAME, true, 0, TRUST_NONE,
1384                 receiver);
1385         ApkChecksum[] checksums = receiver.getResult();
1386         assertNotNull(checksums);
1387         assertEquals(checksums.length, 1, Arrays.toString(checksums));
1388         assertEquals(checksums[0].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
1389         assertEquals(bytesToHexString(checksums[0].getValue()), TEST_FIXED_APK_V2_SHA256);
1390         assertNull(checksums[0].getInstallerPackageName());
1391         assertNull(checksums[0].getInstallerCertificate());
1392     }
1393 
1394     @Test
testInstallerChecksumsDuplicate()1395     public void testInstallerChecksumsDuplicate() throws Exception {
1396         uninstallPackageSilently(FIXED_PACKAGE_NAME);
1397         adoptShellPermissionIdentity();
1398         try {
1399             final PackageInstaller installer = getPackageInstaller();
1400             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1401 
1402             final int sessionId = installer.createSession(params);
1403             Session session = installer.openSession(sessionId);
1404             writeFileToSession(session, "file", TEST_FIXED_APK);
1405             session.setChecksums("file", Arrays.asList(TEST_FIXED_APK_DIGESTS), NO_SIGNATURE);
1406             try {
1407                 session.setChecksums("file", Arrays.asList(TEST_FIXED_APK_DIGESTS), NO_SIGNATURE);
1408                 Assert.fail("setChecksums should throw exception.");
1409             } catch (IllegalStateException e) {
1410                 // expected
1411             }
1412         } finally {
1413             dropShellPermissionIdentity();
1414         }
1415     }
1416 
convertSignaturesToCertificates(Signature[] signatures)1417     private List<Certificate> convertSignaturesToCertificates(Signature[] signatures) {
1418         try {
1419             final CertificateFactory cf = CertificateFactory.getInstance("X.509");
1420             ArrayList<Certificate> certs = new ArrayList<>(signatures.length);
1421             for (Signature signature : signatures) {
1422                 final InputStream is = new ByteArrayInputStream(signature.toByteArray());
1423                 final X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
1424                 certs.add(cert);
1425             }
1426             return certs;
1427         } catch (CertificateException e) {
1428             throw ExceptionUtils.propagate(e);
1429         }
1430     }
1431 
installApkWithChecksums(Checksum[] checksums)1432     private void installApkWithChecksums(Checksum[] checksums) throws Exception {
1433         installApkWithChecksums("file", "file", checksums);
1434     }
1435 
installApkWithChecksums(String apkName, String checksumsName, Checksum[] checksums)1436     private void installApkWithChecksums(String apkName, String checksumsName, Checksum[] checksums)
1437             throws Exception {
1438         CommitIntentReceiver.checkSuccess(
1439                 installApkWithChecksums(TEST_FIXED_APK, apkName, checksumsName, checksums));
1440     }
1441 
installApkWithChecksums(String apk, String apkName, String checksumsName, Checksum[] checksums)1442     private Intent installApkWithChecksums(String apk, String apkName,
1443             String checksumsName, Checksum[] checksums) throws Exception {
1444         return installApkWithChecksums(apk, apkName, checksumsName, checksums, NO_SIGNATURE);
1445     }
1446 
installApkWithChecksums(String apk, String apkName, String checksumsName, Checksum[] checksums, byte[] signature)1447     private Intent installApkWithChecksums(String apk, String apkName,
1448             String checksumsName, Checksum[] checksums, byte[] signature) throws Exception {
1449         adoptShellPermissionIdentity();
1450         try {
1451             final PackageInstaller installer = getPackageInstaller();
1452             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1453             params.installFlags |= PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
1454 
1455             final int sessionId = installer.createSession(params);
1456             Session session = installer.openSession(sessionId);
1457             writeFileToSession(session, apkName, apk);
1458             session.setChecksums(checksumsName, Arrays.asList(checksums), signature);
1459 
1460             CommitIntentReceiver receiver = new CommitIntentReceiver();
1461             session.commit(receiver.getIntentSender());
1462             return receiver.getResult();
1463         } finally {
1464             dropShellPermissionIdentity();
1465         }
1466     }
1467 
installApkWithFSVerity(String apk, String fsv)1468     private void installApkWithFSVerity(String apk, String fsv) throws Exception {
1469         adoptShellPermissionIdentity();
1470         try {
1471             final PackageInstaller installer = getPackageInstaller();
1472             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1473             params.installFlags |= PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
1474 
1475             final int sessionId = installer.createSession(params);
1476             Session session = installer.openSession(sessionId);
1477             writeFileToSession(session, "file", apk);
1478             writeFileToSession(session, "file.fsv_sig", fsv);
1479 
1480             CommitIntentReceiver receiver = new CommitIntentReceiver();
1481             session.commit(receiver.getIntentSender());
1482             CommitIntentReceiver.checkSuccess(receiver.getResult());
1483         } finally {
1484             dropShellPermissionIdentity();
1485         }
1486     }
1487 
installApkWithChecksumsIncrementally(final String inPath)1488     private void installApkWithChecksumsIncrementally(final String inPath) throws Exception {
1489         installApkWithChecksumsIncrementally(inPath, TEST_FIXED_APK, TEST_FIXED_APK_DIGESTS,
1490                 NO_SIGNATURE);
1491     }
1492 
installApkWithChecksumsIncrementally(final String inPath, final String apk, final Checksum[] checksums, final byte[] signature)1493     private void installApkWithChecksumsIncrementally(final String inPath, final String apk,
1494             final Checksum[] checksums, final byte[] signature) throws Exception {
1495         adoptShellPermissionIdentity();
1496         try {
1497             final PackageInstaller installer = getPackageInstaller();
1498             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1499             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1500             params.installFlags |= PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
1501             params.setDataLoaderParams(DataLoaderParams.forIncremental(new ComponentName("android",
1502                     PackageManagerShellCommandDataLoader.class.getName()), ""));
1503 
1504             final int sessionId = installer.createSession(params);
1505             Session session = installer.openSession(sessionId);
1506 
1507             final File file = new File(inPath);
1508             final String name = file.getName();
1509             final long size = file.length();
1510             final Metadata metadata = Metadata.forLocalFile(inPath);
1511 
1512             session.addFile(LOCATION_DATA_APP, name, size, metadata.toByteArray(), null);
1513             session.setChecksums(name, Arrays.asList(checksums), signature);
1514 
1515             CommitIntentReceiver receiver = new CommitIntentReceiver();
1516             session.commit(receiver.getIntentSender());
1517             CommitIntentReceiver.checkSuccess(receiver.getResult());
1518         } finally {
1519             dropShellPermissionIdentity();
1520         }
1521     }
1522 
readFullStream(InputStream inputStream)1523     private static String readFullStream(InputStream inputStream) throws IOException {
1524         ByteArrayOutputStream result = new ByteArrayOutputStream();
1525         writeFullStream(inputStream, result, -1);
1526         return result.toString("UTF-8");
1527     }
1528 
writeFullStream(InputStream inputStream, OutputStream outputStream, long expected)1529     private static void writeFullStream(InputStream inputStream, OutputStream outputStream,
1530             long expected)
1531             throws IOException {
1532         byte[] buffer = new byte[1024];
1533         long total = 0;
1534         int length;
1535         while ((length = inputStream.read(buffer)) != -1) {
1536             outputStream.write(buffer, 0, length);
1537             total += length;
1538         }
1539         if (expected > 0) {
1540             Assert.assertEquals(expected, total);
1541         }
1542     }
1543 
executeShellCommand(String command)1544     private static String executeShellCommand(String command) throws IOException {
1545         final ParcelFileDescriptor stdout = getUiAutomation().executeShellCommand(command);
1546         try (InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(stdout)) {
1547             return readFullStream(inputStream);
1548         }
1549     }
1550 
executeShellCommand(String command, byte[] input)1551     private String executeShellCommand(String command, byte[] input) throws IOException {
1552         final ParcelFileDescriptor[] pfds =
1553                 getUiAutomation().executeShellCommandRw(command);
1554         ParcelFileDescriptor stdout = pfds[0];
1555         ParcelFileDescriptor stdin = pfds[1];
1556         try (FileOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(
1557                 stdin)) {
1558             outputStream.write(input);
1559         }
1560         try (InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(stdout)) {
1561             return new String(FileUtils.readInputStreamFully(inputStream));
1562         }
1563     }
1564 
createApkPath(String baseName)1565     private static String createApkPath(String baseName) {
1566         return TEST_APK_PATH + baseName;
1567     }
1568 
installPackage(String baseName)1569     private void installPackage(String baseName) throws IOException {
1570         File file = new File(createApkPath(baseName));
1571         Assert.assertEquals("Success\n", executeShellCommand(
1572                 "pm install -t -g --bypass-low-target-sdk-block " + file.getPath()));
1573     }
1574 
installPackageIncrementally(String baseName)1575     private void installPackageIncrementally(String baseName) throws IOException {
1576         File file = new File(createApkPath(baseName));
1577         Assert.assertEquals("Success\n", executeShellCommand(
1578                 "pm install-incremental -t -g --bypass-low-target-sdk-block " + file.getPath()));
1579     }
1580 
installSplits(String[] baseNames)1581     private void installSplits(String[] baseNames) throws IOException {
1582         String[] splits = Arrays.stream(baseNames).map(
1583                 baseName -> createApkPath(baseName)).toArray(String[]::new);
1584         Assert.assertEquals("Success\n",
1585                 executeShellCommand(
1586                         "pm install -t -g --bypass-low-target-sdk-block " + String.join(" ",
1587                                 splits)));
1588     }
1589 
installFilesIncrementally(String[] baseNames)1590     private void installFilesIncrementally(String[] baseNames) throws IOException {
1591         String[] splits = Arrays.stream(baseNames).map(
1592                 baseName -> createApkPath(baseName)).toArray(String[]::new);
1593         Assert.assertEquals("Success\n",
1594                 executeShellCommand(
1595                         "pm install-incremental -t -g --bypass-low-target-sdk-block " + String.join(
1596                                 " ", splits)));
1597     }
1598 
writeFileToSession(PackageInstaller.Session session, String name, String apk)1599     private static void writeFileToSession(PackageInstaller.Session session, String name,
1600             String apk) throws IOException {
1601         File file = new File(createApkPath(apk));
1602         try (OutputStream os = session.openWrite(name, 0, file.length());
1603              InputStream is = new FileInputStream(file)) {
1604             writeFullStream(is, os, file.length());
1605         }
1606     }
1607 
writeChecksumsToSession(PackageInstaller.Session session, String name, Checksum[] checksums)1608     private static void writeChecksumsToSession(PackageInstaller.Session session, String name,
1609             Checksum[] checksums) throws IOException {
1610         try (DataOutputStream dos = new DataOutputStream(session.openWrite(name, 0, -1))) {
1611             for (Checksum checksum : checksums) {
1612                 Checksum.writeToStream(dos, checksum);
1613             }
1614         }
1615     }
1616 
uninstallPackageSilently(String packageName)1617     private static String uninstallPackageSilently(String packageName) throws IOException {
1618         return executeShellCommand("pm uninstall " + packageName);
1619     }
1620 
isAppInstalled(String packageName)1621     private static boolean isAppInstalled(String packageName) throws IOException {
1622         return isPackagePresent(packageName, /*matchAllPackages=*/false);
1623     }
1624 
isPackagePresent(String packageName)1625     private static boolean isPackagePresent(String packageName) throws IOException {
1626         return isPackagePresent(packageName, /*matchAllPackages=*/true);
1627     }
1628 
isPackagePresent(String packageName, boolean matchAllPackages)1629     private static boolean isPackagePresent(String packageName, boolean matchAllPackages)
1630             throws IOException {
1631         final String commandResult =
1632                 executeShellCommand("pm list packages" + (matchAllPackages ? " -a" : ""));
1633         final int prefixLength = "package:".length();
1634         return Arrays.stream(commandResult.split("\\r?\\n"))
1635                 .anyMatch(line -> line.substring(prefixLength).equals(packageName));
1636     }
1637 
getAppCodePath(String packageName)1638     private String getAppCodePath(String packageName) throws IOException {
1639         final String commandResult = executeShellCommand("pm dump " + packageName);
1640         final String prefix = "    codePath=";
1641         final int prefixLength = prefix.length();
1642         return Arrays.stream(commandResult.split("\\r?\\n"))
1643                 .filter(line -> line.startsWith(prefix))
1644                 .map(line -> line.substring(prefixLength))
1645                 .findFirst().get();
1646     }
1647 
1648     @Nonnull
bytesToHexString(byte[] bytes)1649     private static String bytesToHexString(byte[] bytes) {
1650         return HexDump.toHexString(bytes, 0, bytes.length, /*upperCase=*/ false);
1651     }
1652 
1653     @Nonnull
hexStringToBytes(String hexString)1654     private static byte[] hexStringToBytes(String hexString) {
1655         return HexDump.hexStringToByteArray(hexString);
1656     }
1657 
checkIncrementalDeliveryFeature()1658     private boolean checkIncrementalDeliveryFeature() {
1659         return getPackageManager().hasSystemFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY);
1660     }
1661 
1662     // From PackageManagerServiceUtils.
isApkVerityEnabled()1663     private static boolean isApkVerityEnabled() {
1664         return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R
1665                 || SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED)
1666                 == FSVERITY_ENABLED;
1667     }
1668 
readSignature()1669     private byte[] readSignature() throws IOException {
1670         return readSignature(TEST_FIXED_APK_DIGESTS_SIGNATURE);
1671     }
1672 
readSignature(String file)1673     private byte[] readSignature(String file) throws IOException {
1674         return Files.readAllBytes(Paths.get(createApkPath(file)));
1675     }
1676 
readCertificate()1677     private Certificate readCertificate() throws Exception {
1678         try (InputStream is = new FileInputStream(createApkPath(TEST_CERTIFICATE))) {
1679             CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
1680             return certFactory.generateCertificate(is);
1681         }
1682     }
1683 
getInstallerCertificate()1684     private Certificate getInstallerCertificate() throws Exception {
1685         PackageManager pm = getPackageManager();
1686         PackageInfo installerPackageInfo = pm.getPackageInfo(CTS_PACKAGE_NAME,
1687                 PackageManager.PackageInfoFlags.of(GET_SIGNING_CERTIFICATES));
1688         final List<Certificate> signatures = convertSignaturesToCertificates(
1689                 installerPackageInfo.signingInfo.getApkContentsSigners());
1690         return signatures.get(0);
1691     }
1692 
checkStoredChecksums(Checksum[] checksums, String fileName)1693     private void checkStoredChecksums(Checksum[] checksums, String fileName) throws Exception {
1694         ArrayList<Checksum> storedChecksumsList = new ArrayList<>();
1695         try (InputStream is = new FileInputStream(createApkPath(fileName));
1696              DataInputStream dis = new DataInputStream(is)) {
1697             for (int i = 0; i < 100; ++i) {
1698                 try {
1699                     storedChecksumsList.add(Checksum.readFromStream(dis));
1700                 } catch (EOFException e) {
1701                     break;
1702                 }
1703             }
1704         }
1705         final Checksum[] storedChecksums = storedChecksumsList.toArray(
1706                 new Checksum[storedChecksumsList.size()]);
1707 
1708         final String message = fileName + " needs to be updated: ";
1709         Assert.assertEquals(message, storedChecksums.length, checksums.length);
1710         for (int i = 0, size = storedChecksums.length; i < size; ++i) {
1711             Assert.assertEquals(message, storedChecksums[i].getType(), checksums[i].getType());
1712             Assert.assertArrayEquals(message, storedChecksums[i].getValue(),
1713                     checksums[i].getValue());
1714         }
1715     }
1716 
adoptShellPermissionIdentity()1717     private void adoptShellPermissionIdentity() {
1718         // For non-shell/non-root/non-system uids, USE_SYSTEM_DATA_LOADERS means
1719         // "install-related test adapted shell identity".
1720         getUiAutomation().adoptShellPermissionIdentity(INSTALL_PACKAGES, USE_SYSTEM_DATA_LOADERS,
1721                 USE_INSTALLER_V2);
1722     }
1723 
dropShellPermissionIdentity()1724     private void dropShellPermissionIdentity() {
1725         getUiAutomation().dropShellPermissionIdentity();
1726     }
1727 
1728     private static class LocalListener implements PackageManager.OnChecksumsReadyListener {
1729         private final LinkedBlockingQueue<ApkChecksum[]> mResult = new LinkedBlockingQueue<>();
1730 
1731         @Override
onChecksumsReady(@onNull List<ApkChecksum> checksumsList)1732         public void onChecksumsReady(@NonNull List<ApkChecksum> checksumsList) {
1733             if (checksumsList == null) {
1734                 mResult.offer(null);
1735                 return;
1736             }
1737             ApkChecksum[] checksums = checksumsList.toArray(new ApkChecksum[checksumsList.size()]);
1738             Arrays.sort(checksums, (ApkChecksum lhs, ApkChecksum rhs) ->  {
1739                 final String lhsSplit = lhs.getSplitName();
1740                 final String rhsSplit = rhs.getSplitName();
1741                 if (Objects.equals(lhsSplit, rhsSplit)) {
1742                     return Integer.signum(lhs.getType() - rhs.getType());
1743                 }
1744                 if (lhsSplit == null) {
1745                     return -1;
1746                 }
1747                 if (rhsSplit == null) {
1748                     return +1;
1749                 }
1750                 return lhsSplit.compareTo(rhsSplit);
1751             });
1752             mResult.offer(checksums);
1753         }
1754 
getResult()1755         public ApkChecksum[] getResult() {
1756             try {
1757                 return mResult.poll(6, TimeUnit.SECONDS);
1758             } catch (InterruptedException e) {
1759                 throw new RuntimeException(e);
1760             }
1761         }
1762     }
1763 
1764     private static class CommitIntentReceiver {
1765         private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
1766 
1767         private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1768             @Override
1769             public void send(int code, Intent intent, String resolvedType, IBinder allowlistToken,
1770                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1771                 try {
1772                     mResult.offer(intent, 5, TimeUnit.SECONDS);
1773                 } catch (InterruptedException e) {
1774                     throw new RuntimeException(e);
1775                 }
1776             }
1777         };
1778 
getIntentSender()1779         public IntentSender getIntentSender() {
1780             return new IntentSender((IIntentSender) mLocalSender);
1781         }
1782 
getResult()1783         public Intent getResult() {
1784             try {
1785                 return mResult.take();
1786             } catch (InterruptedException e) {
1787                 throw new RuntimeException(e);
1788             }
1789         }
1790 
checkSuccess(Intent result)1791         public static void checkSuccess(Intent result) {
1792             final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1793                     PackageInstaller.STATUS_FAILURE);
1794             assertEquals(status, PackageInstaller.STATUS_SUCCESS,
1795                     result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + " OR "
1796                             + result.getExtras().get(Intent.EXTRA_INTENT));
1797         }
1798 
checkFailure(Intent result, int expectedStatus, String expectedStatusMessage)1799         public static void checkFailure(Intent result, int expectedStatus,
1800                 String expectedStatusMessage) {
1801             final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1802                     PackageInstaller.STATUS_FAILURE);
1803             assertEquals(status, expectedStatus);
1804             assertEquals(result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE),
1805                     expectedStatusMessage);
1806         }
1807 
checkFailure(Intent result, String expectedStatusMessage)1808         public static void checkFailure(Intent result, String expectedStatusMessage) {
1809             checkFailure(result, PackageInstaller.STATUS_FAILURE, expectedStatusMessage);
1810         }
1811     }
1812 }
1813