Test: add public API to obtain digests of a file.

Bug: 204208748
Test: atest ChecksumsTest
Change-Id: I5ade0af9a9dcecf67230ec494c469c7ed3d9ba1c
diff --git a/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java b/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java
index fa9f14e..d09ad9d 100644
--- a/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java
@@ -36,6 +36,7 @@
 
 import android.app.UiAutomation;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.IIntentSender;
 import android.content.Intent;
@@ -51,6 +52,7 @@
 import android.content.pm.Signature;
 import android.content.pm.cts.util.AbandonAllPackageSessionsRule;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.AppModeFull;
@@ -153,8 +155,12 @@
         return InstrumentationRegistry.getInstrumentation().getUiAutomation();
     }
 
+    private static Context getContext() {
+        return InstrumentationRegistry.getContext();
+    }
+
     private static PackageManager getPackageManager() {
-        return InstrumentationRegistry.getContext().getPackageManager();
+        return getContext().getPackageManager();
     }
 
     private static PackageInstaller getPackageInstaller() {
@@ -457,6 +463,7 @@
                         + "5f2888afcb71524196dda0d6dd16a6a3292bb75b431b8ff74fb60d796e882f80");
     }
 
+
     @Test
     public void testInstallerChecksumsTrustNone() throws Exception {
         installApkWithChecksums(TEST_FIXED_APK_DIGESTS);
@@ -628,6 +635,96 @@
         assertNull(checksums[2].getInstallerCertificate());
     }
 
+    @LargeTest
+    @Test
+    public void testInstallerFileChecksumsDuringInstall() throws Exception {
+        Checksum[] digestsBase = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
+                "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e")),
+                new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("dd93e23bb8cdab0382fdca0d21a4f1cb"))};
+        Checksum[] digestsSplit0 = new Checksum[]{new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(
+                "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e")),
+                new Checksum(TYPE_WHOLE_MD5, hexStringToBytes("f6430e1b795ce2658c49e68d15316b2d"))};
+
+        final Certificate installerCertificate = getInstallerCertificate();
+
+        getUiAutomation().adoptShellPermissionIdentity();
+        PackageInstaller installer = null;
+        int sessionId = -1;
+        try {
+            installer = getPackageInstaller();
+            final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
+
+            sessionId = installer.createSession(params);
+            final Session session = installer.openSession(sessionId);
+
+            writeFileToSession(session, "hw5.apk", TEST_V4_APK);
+            session.setChecksums("hw5.apk", Arrays.asList(digestsBase), NO_SIGNATURE);
+
+            writeFileToSession(session, "hw5_split0.apk", TEST_V4_SPLIT0);
+            session.setChecksums("hw5_split0.apk", Arrays.asList(digestsSplit0), NO_SIGNATURE);
+
+            // Workaround to emulate .digests file present in installation.
+            writeChecksumsToSession(session, "hw5.digests", digestsBase);
+            writeChecksumsToSession(session, "hw5_split0.digests", digestsSplit0);
+
+            File dataApp = Environment.getDataAppDirectory(null);
+
+            {
+                LocalListener receiver = new LocalListener();
+
+                session.requestChecksums("hw5.apk", 0, TRUST_ALL, receiver);
+                ApkChecksum[] checksums = receiver.getResult();
+                assertNotNull(checksums);
+                assertEquals(checksums.length, 3);
+                // base
+                assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
+                assertEquals(checksums[0].getSplitName(), null);
+                assertEquals(bytesToHexString(checksums[0].getValue()),
+                        "dd93e23bb8cdab0382fdca0d21a4f1cb");
+                assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
+                assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
+                assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
+                assertEquals(checksums[1].getSplitName(), null);
+                assertEquals(bytesToHexString(checksums[1].getValue()),
+                        "ed8c7ae1220fe16d558e00cfc37256e6f7088ab90eb04c1bfcb39922a8a5248e");
+                assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
+                assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
+                assertEquals(checksums[2].getSplitName(), null);
+                assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
+                assertNull(checksums[2].getInstallerPackageName());
+                assertNull(checksums[2].getInstallerCertificate());
+            }
+            {
+                LocalListener receiver = new LocalListener();
+
+                session.requestChecksums("hw5_split0.apk", 0, TRUST_ALL, receiver);
+                ApkChecksum[] checksums = receiver.getResult();
+                assertNotNull(checksums);
+                assertEquals(checksums.length, 3);
+                // split0
+                assertEquals(checksums[0].getType(), TYPE_WHOLE_MD5);
+                assertEquals(checksums[0].getSplitName(), null);
+                assertEquals(bytesToHexString(checksums[0].getValue()),
+                        "f6430e1b795ce2658c49e68d15316b2d");
+                assertEquals(checksums[0].getInstallerPackageName(), CTS_PACKAGE_NAME);
+                assertEquals(checksums[0].getInstallerCertificate(), installerCertificate);
+                assertEquals(checksums[1].getType(), TYPE_WHOLE_SHA256);
+                assertEquals(checksums[1].getSplitName(), null);
+                assertEquals(bytesToHexString(checksums[1].getValue()),
+                        "bd9b095a49a9068498b018ce8cb7cc18d411b13a5a5f7fb417d2ff9808ae838e");
+                assertEquals(checksums[1].getInstallerPackageName(), CTS_PACKAGE_NAME);
+                assertEquals(checksums[1].getInstallerCertificate(), installerCertificate);
+                assertEquals(checksums[2].getSplitName(), null);
+                assertEquals(checksums[2].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
+                assertNull(checksums[2].getInstallerPackageName());
+                assertNull(checksums[2].getInstallerCertificate());
+            }
+        } finally {
+            installer.abandonSession(sessionId);
+            getUiAutomation().dropShellPermissionIdentity();
+        }
+    }
+
     @Test
     public void testInstallerChecksumsTrustWrongInstaller() throws Exception {
         installApkWithChecksums(TEST_FIXED_APK_DIGESTS);
@@ -1283,6 +1380,15 @@
         }
     }
 
+    private static void writeChecksumsToSession(PackageInstaller.Session session, String name,
+            Checksum[] checksums) throws IOException {
+        try (DataOutputStream dos = new DataOutputStream(session.openWrite(name, 0, -1))) {
+            for (Checksum checksum : checksums) {
+                Checksum.writeToStream(dos, checksum);
+            }
+        }
+    }
+
     private String uninstallPackageSilently(String packageName) throws IOException {
         return executeShellCommand("pm uninstall " + packageName);
     }
@@ -1294,6 +1400,16 @@
                 .anyMatch(line -> line.substring(prefixLength).equals(packageName));
     }
 
+    private String getAppCodePath(String packageName) throws IOException {
+        final String commandResult = executeShellCommand("pm dump " + packageName);
+        final String prefix = "    codePath=";
+        final int prefixLength = prefix.length();
+        return Arrays.stream(commandResult.split("\\r?\\n"))
+                .filter(line -> line.startsWith(prefix))
+                .map(line -> line.substring(prefixLength))
+                .findFirst().get();
+    }
+
     @Nonnull
     private static String bytesToHexString(byte[] bytes) {
         return HexDump.toHexString(bytes, 0, bytes.length, /*upperCase=*/ false);