Skip priv app full apk verification if has verify

When ro.apk_verity.mode is on, full apk verification is only skipped if
the apk already has verity enabled in the file system, and if the apk
contains the Merkle tree root hash we need.

Since the configuration in the file system is duplicated from the apk
(including the offset and size of Signing Block and the Merkle tree),
in order to prevent offline attacker from changing it, we need to
measure the observed configuration and make sure it matches the kernel's
view.

Test: observed package manager's requeset to installd (only) for updated
      priv apps.
Bug: 30972906

Change-Id: I33531a3f6148232b777ea8bfd02f13700649e317
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index 1b04eb2..ee6fc07 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -523,6 +523,20 @@
         }
     }
 
+    static byte[] generateFsverityRootHash(String apkPath)
+            throws NoSuchAlgorithmException, DigestException, IOException,
+                   SignatureNotFoundException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            VerifiedSigner vSigner = verify(apk, false);
+            if (vSigner.verityRootHash == null) {
+                return null;
+            }
+            return ApkVerityBuilder.generateFsverityRootHash(
+                    apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
+        }
+    }
+
     private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) {
         switch (sigAlgorithm) {
             case SIGNATURE_RSA_PSS_WITH_SHA256: