Merge "[avmd] Verify apk_digest when generating avmd file"
diff --git a/apkdmverity/Android.bp b/apkdmverity/Android.bp
index 97a6174..51ef4dd 100644
--- a/apkdmverity/Android.bp
+++ b/apkdmverity/Android.bp
@@ -43,4 +43,8 @@
     rustlibs: [
         "libtempfile",
     ],
+    data: [
+        "testdata/*.apk",
+        "testdata/*.idsig",
+    ],
 }
diff --git a/apkdmverity/src/main.rs b/apkdmverity/src/main.rs
index de7f5bb..b99ed1c 100644
--- a/apkdmverity/src/main.rs
+++ b/apkdmverity/src/main.rs
@@ -31,7 +31,6 @@
 use itertools::Itertools;
 use std::fmt::Debug;
 use std::fs;
-use std::fs::File;
 use std::os::unix::fs::FileTypeExt;
 use std::path::{Path, PathBuf};
 
@@ -104,9 +103,7 @@
     // Parse the idsig file to locate the merkle tree in it, then attach the file to a loop device
     // with the offset so that the start of the merkle tree becomes the beginning of the loop
     // device.
-    let sig = V4Signature::from(
-        File::open(&idsig).context(format!("Failed to open idsig file {:?}", &idsig))?,
-    )?;
+    let sig = V4Signature::from_idsig_path(&idsig)?;
     let offset = sig.merkle_tree_offset;
     let size = sig.merkle_tree_size as u64;
     // Due to unknown reason(b/191344832), we can't enable "direct IO" for the IDSIG file (backing
@@ -143,8 +140,8 @@
 #[cfg(test)]
 mod tests {
     use crate::*;
-    use std::fs::OpenOptions;
-    use std::io::{Cursor, Write};
+    use std::fs::{File, OpenOptions};
+    use std::io::Write;
     use std::os::unix::fs::FileExt;
 
     struct TestContext<'a> {
@@ -251,7 +248,9 @@
         let idsig = include_bytes!("../testdata/test.apk.idsig");
 
         // Make a single-byte change to the merkle tree
-        let offset = V4Signature::from(Cursor::new(&idsig)).unwrap().merkle_tree_offset as usize;
+        let offset = V4Signature::from_idsig_path("testdata/test.apk.idsig")
+            .unwrap()
+            .merkle_tree_offset as usize;
 
         let mut modified_idsig = Vec::new();
         modified_idsig.extend_from_slice(idsig);
@@ -354,7 +353,10 @@
     fn correct_custom_roothash() {
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
-        let roothash = V4Signature::from(Cursor::new(&idsig)).unwrap().hashing_info.raw_root_hash;
+        let roothash = V4Signature::from_idsig_path("testdata/test.apk.idsig")
+            .unwrap()
+            .hashing_info
+            .raw_root_hash;
         run_test_with_hash(
             apk.as_ref(),
             idsig.as_ref(),
diff --git a/compos/aidl/com/android/compos/ICompOsService.aidl b/compos/aidl/com/android/compos/ICompOsService.aidl
index 9b45e13..bfde6b6 100644
--- a/compos/aidl/com/android/compos/ICompOsService.aidl
+++ b/compos/aidl/com/android/compos/ICompOsService.aidl
@@ -17,6 +17,7 @@
 package com.android.compos;
 
 /** {@hide} */
+@SuppressWarnings(value={"mixed-oneway"})
 interface ICompOsService {
     /**
      * Initializes system properties. ART expects interesting properties that have to be passed from
diff --git a/compos/apk/assets/vm_config.json b/compos/apk/assets/vm_config.json
index c4abfd9..1f5cdba 100644
--- a/compos/apk/assets/vm_config.json
+++ b/compos/apk/assets/vm_config.json
@@ -26,5 +26,6 @@
       "name": "{CLASSPATH}"
     }
   ],
-  "export_tombstones": true
+  "export_tombstones": true,
+  "enable_authfs": true
 }
diff --git a/compos/apk/assets/vm_config_staged.json b/compos/apk/assets/vm_config_staged.json
index 0be6e78..37b1d7a 100644
--- a/compos/apk/assets/vm_config_staged.json
+++ b/compos/apk/assets/vm_config_staged.json
@@ -27,5 +27,6 @@
       "name": "{CLASSPATH}"
     }
   ],
-  "export_tombstones": true
+  "export_tombstones": true,
+  "enable_authfs": true
 }
diff --git a/compos/apk/assets/vm_config_system_ext.json b/compos/apk/assets/vm_config_system_ext.json
index e60dee7..1ef43f0 100644
--- a/compos/apk/assets/vm_config_system_ext.json
+++ b/compos/apk/assets/vm_config_system_ext.json
@@ -29,5 +29,6 @@
       "name": "{CLASSPATH}"
     }
   ],
-  "export_tombstones": true
+  "export_tombstones": true,
+  "enable_authfs": true
 }
diff --git a/compos/apk/assets/vm_config_system_ext_staged.json b/compos/apk/assets/vm_config_system_ext_staged.json
index 99a4160..9103a9e 100644
--- a/compos/apk/assets/vm_config_system_ext_staged.json
+++ b/compos/apk/assets/vm_config_system_ext_staged.json
@@ -30,5 +30,6 @@
       "name": "{CLASSPATH}"
     }
   ],
-  "export_tombstones": true
+  "export_tombstones": true,
+  "enable_authfs": true
 }
diff --git a/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java b/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java
index dd113a6..c25de71 100644
--- a/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java
+++ b/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java
@@ -55,7 +55,7 @@
     private static final int BUFFER_SIZE = 1024;
     private static final int ROUND_COUNT = 5;
     private static final double NANOS_IN_SEC = 1_000_000_000.0;
-    private static final String METRIC_PREFIX = "avf_perf/compos/";
+    private static final String METRIC_PREFIX = getMetricPrefix() + "compos/";
 
     private final MetricsProcessor mMetricsProcessor = new MetricsProcessor(METRIC_PREFIX);
 
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index 7ce60cd..3dbb4da 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -117,7 +117,7 @@
             ));
         }
 
-        let context = to_binder_result(OdrefreshContext::new(
+        let context = OdrefreshContext::new(
             compilation_mode,
             system_dir_fd,
             if system_ext_dir_fd >= 0 { Some(system_ext_dir_fd) } else { None },
@@ -126,21 +126,9 @@
             target_dir_name,
             zygote_arch,
             system_server_compiler_filter,
-        ))?;
+        );
 
-        let authfs_service = binder::get_interface(AUTHFS_SERVICE_NAME)?;
-        let exit_code = to_binder_result(
-            odrefresh(&self.odrefresh_path, context, authfs_service, |output_dir| {
-                // authfs only shows us the files we created, so it's ok to just sign everything
-                // under the output directory.
-                let mut artifact_signer = ArtifactSigner::new(&output_dir);
-                add_artifacts(&output_dir, &mut artifact_signer)?;
-
-                artifact_signer.write_info_and_signature(&output_dir.join("compos.info"))
-            })
-            .context("odrefresh failed"),
-        )?;
-        Ok(exit_code as i8)
+        to_binder_result(context.and_then(|c| self.do_odrefresh(c)))
     }
 
     fn getPublicKey(&self) -> BinderResult<Vec<u8>> {
@@ -158,6 +146,23 @@
     }
 }
 
+impl CompOsService {
+    fn do_odrefresh(&self, context: OdrefreshContext) -> Result<i8> {
+        let authfs_service = binder::get_interface(AUTHFS_SERVICE_NAME)
+            .context("Unable to connect to AuthFS service")?;
+        let exit_code = odrefresh(&self.odrefresh_path, context, authfs_service, |output_dir| {
+            // authfs only shows us the files we created, so it's ok to just sign everything
+            // under the output directory.
+            let mut artifact_signer = ArtifactSigner::new(&output_dir);
+            add_artifacts(&output_dir, &mut artifact_signer)?;
+
+            artifact_signer.write_info_and_signature(&output_dir.join("compos.info"))
+        })
+        .context("odrefresh failed")?;
+        Ok(exit_code as i8)
+    }
+}
+
 fn add_artifacts(target_dir: &Path, artifact_signer: &mut ArtifactSigner) -> Result<()> {
     for entry in
         read_dir(&target_dir).with_context(|| format!("Traversing {}", target_dir.display()))?
diff --git a/libs/apexutil/src/lib.rs b/libs/apexutil/src/lib.rs
index 1183aea..999f16d 100644
--- a/libs/apexutil/src/lib.rs
+++ b/libs/apexutil/src/lib.rs
@@ -145,8 +145,9 @@
     use super::*;
 
     #[test]
-    fn test_open_apex() {
+    fn apex_verification_returns_valid_result() {
         let res = verify("tests/data/test.apex").unwrap();
+        // The expected hex is generated when we ran the method the first time.
         assert_eq!(
             to_hex_string(&res.root_digest),
             "fe11ab17da0a3a738b54bdc3a13f6139cbdf91ec32f001f8d4bbbf8938e04e39"
@@ -154,7 +155,7 @@
     }
 
     #[test]
-    fn test_payload_vbmeta_image_hash() {
+    fn payload_vbmeta_has_valid_image_hash() {
         let result = get_payload_vbmeta_image_hash("tests/data/test.apex").unwrap();
         assert_eq!(
             to_hex_string(&result),
diff --git a/libs/idsig/Android.bp b/libs/idsig/Android.bp
index 9f7d377..615d70e 100644
--- a/libs/idsig/Android.bp
+++ b/libs/idsig/Android.bp
@@ -31,5 +31,7 @@
     compile_multilib: "first",
     data: [
         "testdata/input.*",
+        "testdata/*.apk",
+        "testdata/*.idsig",
     ],
 }
diff --git a/libs/idsig/src/apksigv4.rs b/libs/idsig/src/apksigv4.rs
index 29def3b..3f73df3 100644
--- a/libs/idsig/src/apksigv4.rs
+++ b/libs/idsig/src/apksigv4.rs
@@ -19,7 +19,9 @@
 use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 use num_derive::{FromPrimitive, ToPrimitive};
 use num_traits::{FromPrimitive, ToPrimitive};
+use std::fs;
 use std::io::{copy, Cursor, Read, Seek, SeekFrom, Write};
+use std::path::Path;
 
 use crate::hashtree::*;
 
@@ -114,9 +116,17 @@
     }
 }
 
+impl V4Signature<fs::File> {
+    /// Creates a `V4Signature` struct from the given idsig path.
+    pub fn from_idsig_path<P: AsRef<Path>>(idsig_path: P) -> Result<Self> {
+        let idsig = fs::File::open(idsig_path).context("Cannot find idsig file")?;
+        Self::from_idsig(idsig)
+    }
+}
+
 impl<R: Read + Seek> V4Signature<R> {
     /// Consumes a stream for an idsig file into a `V4Signature` struct.
-    pub fn from(mut r: R) -> Result<V4Signature<R>> {
+    pub fn from_idsig(mut r: R) -> Result<V4Signature<R>> {
         Ok(V4Signature {
             version: Version::from(r.read_u32::<LittleEndian>()?)?,
             hashing_info: HashingInfo::from(&mut r)?,
@@ -293,14 +303,15 @@
     use super::*;
     use std::io::Cursor;
 
+    const TEST_APK_PATH: &str = "testdata/v4-digest-v3-Sha256withEC.apk";
+
     fn hexstring_from(s: &[u8]) -> String {
         s.iter().map(|byte| format!("{:02x}", byte)).reduce(|i, j| i + &j).unwrap_or_default()
     }
 
     #[test]
     fn parse_idsig_file() {
-        let idsig = Cursor::new(include_bytes!("../testdata/v4-digest-v3-Sha256withEC.apk.idsig"));
-        let parsed = V4Signature::from(idsig).unwrap();
+        let parsed = V4Signature::from_idsig_path(format!("{}.idsig", TEST_APK_PATH)).unwrap();
 
         assert_eq!(Version::V2, parsed.version);
 
@@ -334,13 +345,13 @@
     /// the input file.
     #[test]
     fn parse_and_compose() {
-        let input = Cursor::new(include_bytes!("../testdata/v4-digest-v3-Sha256withEC.apk.idsig"));
-        let mut parsed = V4Signature::from(input.clone()).unwrap();
+        let idsig_path = format!("{}.idsig", TEST_APK_PATH);
+        let mut v4_signature = V4Signature::from_idsig_path(&idsig_path).unwrap();
 
         let mut output = Cursor::new(Vec::new());
-        parsed.write_into(&mut output).unwrap();
+        v4_signature.write_into(&mut output).unwrap();
 
-        assert_eq!(input.get_ref().as_ref(), output.get_ref().as_slice());
+        assert_eq!(fs::read(&idsig_path).unwrap(), output.get_ref().as_slice());
     }
 
     /// Create V4Signature by hashing an APK. Merkle tree and the root hash should be the same
@@ -351,8 +362,7 @@
         let mut created =
             V4Signature::create(&mut input, 4096, &[], HashAlgorithm::SHA256).unwrap();
 
-        let golden = Cursor::new(include_bytes!("../testdata/v4-digest-v3-Sha256withEC.apk.idsig"));
-        let mut golden = V4Signature::from(golden).unwrap();
+        let mut golden = V4Signature::from_idsig_path(format!("{}.idsig", TEST_APK_PATH)).unwrap();
 
         // Compare the root hash
         assert_eq!(
diff --git a/microdroid/init.rc b/microdroid/init.rc
index cd7332b..4e36726 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -149,7 +149,6 @@
     restorecon /data/misc
 
     mkdir /data/misc/authfs 0700 root root
-    start authfs_service
 
 on late-fs && property:ro.debuggable=1
     # Ensure that tracefs has the correct permissions.
diff --git a/microdroid/payload/config/src/lib.rs b/microdroid/payload/config/src/lib.rs
index b82544f..54b745e 100644
--- a/microdroid/payload/config/src/lib.rs
+++ b/microdroid/payload/config/src/lib.rs
@@ -42,6 +42,11 @@
     /// Whether to export the tomsbtones (VM crashes) out of VM to host
     /// This does not have a default & the value is expected to be in json for deserialization
     pub export_tombstones: bool,
+
+    /// Whether the authfs service should be started in the VM. This enables read or write of host
+    /// files with integrity checking, but not confidentiality.
+    #[serde(default)]
+    pub enable_authfs: bool,
 }
 
 /// OS config
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index e3ad495..c50bcbe 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -323,6 +323,11 @@
 
     let config = load_config(Path::new(&metadata.payload_config_path))?;
 
+    let task = config
+        .task
+        .as_ref()
+        .ok_or_else(|| MicrodroidError::InvalidConfig("No task in VM config".to_string()))?;
+
     if config.extra_apks.len() != verified_data.extra_apks_data.len() {
         return Err(anyhow!(
             "config expects {} extra apks, but found only {}",
@@ -338,18 +343,23 @@
 
     // Start tombstone_transmit if enabled
     if config.export_tombstones {
-        system_properties::write("ctl.start", "tombstone_transmit")
-            .context("Failed to start tombstone_transmit")?;
+        control_service("start", "tombstone_transmit")?;
     } else {
-        system_properties::write("ctl.stop", "tombstoned").context("Failed to stop tombstoned")?;
+        control_service("stop", "tombstoned")?;
     }
 
-    ensure!(
-        config.task.is_some(),
-        MicrodroidError::InvalidConfig("No task in VM config".to_string())
-    );
+    // Start authfs if enabled
+    if config.enable_authfs {
+        control_service("start", "authfs_service")?;
+    }
+
     system_properties::write("dev.bootcomplete", "1").context("set dev.bootcomplete")?;
-    exec_task(&config.task.unwrap(), service)
+    exec_task(task, service)
+}
+
+fn control_service(action: &str, service: &str) -> Result<()> {
+    system_properties::write(&format!("ctl.{}", action), service)
+        .with_context(|| format!("Failed to {} {}", action, service))
 }
 
 struct ApkDmverityArgument<'a> {
@@ -471,7 +481,7 @@
         .map(|(i, extra_idsig)| {
             (
                 format!("extra-apk-{}", i),
-                get_apk_root_hash_from_idsig(extra_idsig.to_str().unwrap())
+                get_apk_root_hash_from_idsig(extra_idsig)
                     .expect("Can't find root hash from extra idsig"),
             )
         })
@@ -591,10 +601,8 @@
     Ok(())
 }
 
-fn get_apk_root_hash_from_idsig(path: &str) -> Result<Box<RootHash>> {
-    let mut idsig = File::open(path)?;
-    let idsig = V4Signature::from(&mut idsig)?;
-    Ok(idsig.hashing_info.raw_root_hash)
+fn get_apk_root_hash_from_idsig<P: AsRef<Path>>(idsig_path: P) -> Result<Box<RootHash>> {
+    Ok(V4Signature::from_idsig_path(idsig_path)?.hashing_info.raw_root_hash)
 }
 
 fn get_public_key_from_apk(apk: &str, root_hash_trustful: bool) -> Result<Box<[u8]>> {
diff --git a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
index 41661e9..d73eb9c 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -53,7 +53,7 @@
 @RunWith(Parameterized.class)
 public class MicrodroidBenchmarks extends MicrodroidDeviceTestBase {
     private static final String TAG = "MicrodroidBenchmarks";
-    private static final String METRIC_NAME_PREFIX = "avf_perf/microdroid/";
+    private static final String METRIC_NAME_PREFIX = getMetricPrefix() + "microdroid/";
     private static final int IO_TEST_TRIAL_COUNT = 5;
 
     @Rule public Timeout globalTimeout = Timeout.seconds(300);
@@ -76,7 +76,6 @@
 
     @Before
     public void setup() {
-        assume().that(shouldSkipBenchmarks()).isFalse();
         prepareTestSetup(mProtectedVm);
         mInstrumentation = getInstrumentation();
     }
diff --git a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
index e5eee27..efba60b 100644
--- a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
+++ b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
@@ -70,14 +70,14 @@
     private static final int BOOT_COMPLETE_TIMEOUT_MS = 10 * 60 * 1000;
     private static final double NANOS_IN_SEC = 1_000_000_000.0;
     private static final int ROUND_COUNT = 5;
-    private static final String METRIC_PREFIX = "avf_perf/hostside/";
 
-    private final MetricsProcessor mMetricsProcessor = new MetricsProcessor(METRIC_PREFIX);
+    private MetricsProcessor mMetricsProcessor;
     @Rule public TestMetrics mMetrics = new TestMetrics();
 
     @Before
     public void setUp() throws Exception {
         testIfDeviceIsCapable(getDevice());
+        mMetricsProcessor = new MetricsProcessor(getMetricPrefix() + "hostside/");
     }
 
     @After
diff --git a/tests/helper/Android.bp b/tests/helper/Android.bp
index f77dae5..60d4be1 100644
--- a/tests/helper/Android.bp
+++ b/tests/helper/Android.bp
@@ -20,6 +20,7 @@
     static_libs: [
         "androidx.test.runner",
         "androidx.test.ext.junit",
+        "MicrodroidTestHelper",
         "VirtualizationTestHelper",
         "truth-prebuilt",
     ],
diff --git a/tests/helper/src/java/com/android/microdroid/test/common/MetricsProcessor.java b/tests/helper/src/java/com/android/microdroid/test/common/MetricsProcessor.java
index 41534f1..b6bc479 100644
--- a/tests/helper/src/java/com/android/microdroid/test/common/MetricsProcessor.java
+++ b/tests/helper/src/java/com/android/microdroid/test/common/MetricsProcessor.java
@@ -24,6 +24,12 @@
 public final class MetricsProcessor {
     private final String mPrefix;
 
+    public static String getMetricPrefix(String debugTag) {
+        return "avf_perf"
+            + ((debugTag != null && !debugTag.isEmpty()) ? "[" + debugTag + "]" : "")
+            + "/";
+    }
+
     public MetricsProcessor(String prefix) {
         mPrefix = prefix;
     }
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index c0b76da..5dcd77b 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -33,6 +33,7 @@
 import androidx.annotation.CallSuper;
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.microdroid.test.common.MetricsProcessor;
 import com.android.virt.VirtualizationTestHelper;
 
 import java.io.BufferedReader;
@@ -51,8 +52,9 @@
         return VirtualizationTestHelper.isCuttlefish(SystemProperties.get("ro.product.name"));
     }
 
-    public static boolean shouldSkipBenchmarks() {
-        return SystemProperties.getBoolean("debug.avf.benchmark.skip", false);
+    public static String getMetricPrefix() {
+        return MetricsProcessor.getMetricPrefix(
+                SystemProperties.get("debug.hypervisor.metrics_tag"));
     }
 
     // TODO(b/220920264): remove Inner class; this is a hack to hide virt APEX types
diff --git a/tests/hostside/helper/Android.bp b/tests/hostside/helper/Android.bp
index af88bb6..b2333ab 100644
--- a/tests/hostside/helper/Android.bp
+++ b/tests/hostside/helper/Android.bp
@@ -11,6 +11,7 @@
         "truth-prebuilt",
     ],
     static_libs: [
+        "MicrodroidTestHelper",
         "VirtualizationTestHelper",
     ],
 }
diff --git a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
index 875d89f..0417123 100644
--- a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
+++ b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
@@ -27,6 +27,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.microdroid.test.common.MetricsProcessor;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
@@ -97,6 +98,11 @@
         return VirtualizationTestHelper.isCuttlefish(getDevice().getProperty("ro.product.name"));
     }
 
+    protected String getMetricPrefix() throws Exception {
+        return MetricsProcessor.getMetricPrefix(
+                getDevice().getProperty("debug.hypervisor.metrics_tag"));
+    }
+
     public static void testIfDeviceIsCapable(ITestDevice androidDevice) throws Exception {
         assumeTrue("Need an actual TestDevice", androidDevice instanceof TestDevice);
         TestDevice testDevice = (TestDevice) androidDevice;
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidTestCase.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidTestCase.java
index 69218a8..48dd1e0 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidTestCase.java
@@ -93,6 +93,8 @@
     @Rule public TestName mTestName = new TestName();
     @Rule public TestMetrics mMetrics = new TestMetrics();
 
+    private String mMetricPrefix;
+
     private int minMemorySize() throws DeviceNotAvailableException {
         CommandRunner android = new CommandRunner(getDevice());
         String abi = android.run("getprop", "ro.product.cpu.abi");
@@ -792,7 +794,7 @@
 
         for (Map.Entry<String, Long> stat : getProcMemInfo().entrySet()) {
             mMetrics.addTestMetric(
-                    "avf_perf/microdroid/meminfo/" + stat.getKey().toLowerCase(),
+                    mMetricPrefix + "meminfo/" + stat.getKey().toLowerCase(),
                     stat.getValue().toString());
         }
 
@@ -800,7 +802,7 @@
             for (Map.Entry<String, Long> stat : getProcSmapsRollup(proc.mPid).entrySet()) {
                 String name = stat.getKey().toLowerCase();
                 mMetrics.addTestMetric(
-                        "avf_perf/microdroid/smaps/" + name + "/" + proc.mName,
+                        mMetricPrefix + "smaps/" + name + "/" + proc.mName,
                         stat.getValue().toString());
             }
         }
@@ -845,6 +847,7 @@
     @Before
     public void setUp() throws Exception {
         testIfDeviceIsCapable(getDevice());
+        mMetricPrefix = getMetricPrefix() + "microdroid/";
 
         prepareVirtualizationTestSetup(getDevice());