Add extra apk mount test

system/etc/fsverity/security/BuildManifest.apk contains a protobuf file
as an asset. This test tries to parse the protobuf file, thus verifying
the extra APK mount.

Bug: 203483081
Test: atest MicrodroidTests
Change-Id: I2ca0bf337fcee0c2df3c32d43685c4cdadcbac91
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 541e93f..6cd16c2 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -30,6 +30,11 @@
         "libbinder_rpc_unstable",
         "MicrodroidTestNativeLibSub",
     ],
+    static_libs: [
+        "libfsverity_digests_proto_cc",
+        "liblog",
+        "libprotobuf-cpp-lite-ndk",
+    ],
 }
 
 cc_library_shared {
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 4736f19..032ecfd 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -140,7 +140,8 @@
     @Test
     public void connectToVmService() throws VirtualMachineException, InterruptedException {
         VirtualMachineConfig.Builder builder =
-                new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config.json");
+                new VirtualMachineConfig.Builder(mInner.mContext,
+                        "assets/vm_config_extra_apk.json");
         if (Build.SUPPORTED_ABIS.length > 0) {
             String primaryAbi = Build.SUPPORTED_ABIS[0];
             switch(primaryAbi) {
@@ -154,7 +155,7 @@
         }
         VirtualMachineConfig config = builder.build();
 
-        mInner.mVm = mInner.mVmm.getOrCreate("test_vm", config);
+        mInner.mVm = mInner.mVmm.getOrCreate("test_vm_extra_apk", config);
         VmEventListener listener =
                 new VmEventListener() {
                     private boolean mPayloadReadyCalled = false;
@@ -177,6 +178,9 @@
                             assertEquals(
                                     testService.readProperty("debug.microdroid.test.keystore"),
                                     "PASS");
+                            assertEquals(
+                                    testService.readProperty("debug.microdroid.test.extra_apk"),
+                                    "PASS");
                         } catch (Exception e) {
                             fail("Exception while testing service: " + e.toString());
                         }
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 5435547..c748b2a 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -16,12 +16,14 @@
 #include <aidl/android/system/keystore2/IKeystoreService.h>
 #include <aidl/android/system/virtualmachineservice/IVirtualMachineService.h>
 #include <aidl/com/android/microdroid/testservice/BnTestService.h>
+#include <android-base/file.h>
 #include <android-base/properties.h>
 #include <android-base/result.h>
 #include <android-base/unique_fd.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
 #include <fcntl.h>
+#include <fsverity_digests.pb.h>
 #include <linux/vm_sockets.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -193,8 +195,8 @@
         outcome << "PASS";
     } else {
         outcome << "FAIL: " << result.error();
-        // Pollute stdout with the error in case the property is truncated.
-        std::cout << "[" << name << "] test failed: " << result.error() << "\n";
+        // Pollute stderr with the error in case the property is truncated.
+        std::cerr << "[" << name << "] test failed: " << result.error() << "\n";
     }
     __system_property_set(property.c_str(), outcome.str().c_str());
     return result;
@@ -243,6 +245,21 @@
     return {};
 }
 
+Result<void> verify_apk() {
+    const char* path = "/mnt/extra-apk/0/assets/build_manifest.pb";
+
+    std::string str;
+    if (!android::base::ReadFileToString(path, &str)) {
+        return ErrnoError() << "failed to read build_manifest.pb";
+    }
+
+    if (!android::security::fsverity::FSVerityDigests().ParseFromString(str)) {
+        return Error() << "invalid build_manifest.pb";
+    }
+
+    return {};
+}
+
 } // Anonymous namespace
 
 extern "C" int android_native_main(int argc, char* argv[]) {
@@ -262,6 +279,9 @@
     testlib_sub();
     printf("\n");
 
+    // Extra apks may be missing; this is not a fatal error
+    report_test("extra_apk", verify_apk());
+
     __system_property_set("debug.microdroid.app.run", "true");
     if (!report_test("keystore", test_keystore()).ok()) return 1;