Merge "VirtualMachineCustomImageConfig.from(pb) should return value" into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 5b0c000..58dcc06 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -43,6 +43,9 @@
     },
     {
       "name": "libsecretkeeper_comm.test"
+    },
+    {
+      "name": "libdice_driver_test"
     }
   ],
   "avf-postsubmit": [
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index e19a343..169ecae 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -343,9 +343,8 @@
     },
 }
 
-// TODO(ioffe): rename to microdroid_first_stage_ramdisk
 android_filesystem {
-    name: "microdroid_fstab_ramdisk",
+    name: "microdroid_first_stage_ramdisk",
     deps: [
         "microdroid_fstab",
     ],
diff --git a/microdroid/initrd/Android.bp b/microdroid/initrd/Android.bp
index ec971fa..544a3ff 100644
--- a/microdroid/initrd/Android.bp
+++ b/microdroid/initrd/Android.bp
@@ -34,7 +34,7 @@
     name: "microdroid_initrd_gen",
     srcs: [
         ":microdroid_ramdisk",
-        ":microdroid_fstab_ramdisk",
+        ":microdroid_first_stage_ramdisk",
     ],
     out: ["microdroid_initrd.img"],
     cmd: "cat $(in) > $(out)",
@@ -44,7 +44,7 @@
     name: "microdroid_gki-android14-6.1_initrd_gen_arm64",
     srcs: [
         ":microdroid_ramdisk",
-        ":microdroid_fstab_ramdisk",
+        ":microdroid_first_stage_ramdisk",
         ":microdroid_gki_modules-6.1-arm64",
     ],
     out: ["microdroid_initrd.img"],
@@ -55,7 +55,7 @@
     name: "microdroid_gki-android14-6.1_initrd_gen_x86_64",
     srcs: [
         ":microdroid_ramdisk",
-        ":microdroid_fstab_ramdisk",
+        ":microdroid_first_stage_ramdisk",
         ":microdroid_gki_modules-6.1-x86_64",
     ],
     out: ["microdroid_initrd.img"],
diff --git a/pvmfw/avb/src/ops.rs b/pvmfw/avb/src/ops.rs
index 9711f72..62bf239 100644
--- a/pvmfw/avb/src/ops.rs
+++ b/pvmfw/avb/src/ops.rs
@@ -59,7 +59,7 @@
     pub(crate) fn verify_partition(
         &mut self,
         partition_name: &CStr,
-    ) -> SlotVerifyResult<SlotVerifyData> {
+    ) -> SlotVerifyResult<SlotVerifyData<'a>> {
         slot_verify(
             self,
             &[partition_name],
@@ -70,7 +70,7 @@
     }
 }
 
-impl<'a> avb::Ops for Ops<'a> {
+impl<'a> avb::Ops<'a> for Ops<'a> {
     fn read_from_partition(
         &mut self,
         partition: &CStr,
@@ -82,7 +82,7 @@
         Ok(buffer.len())
     }
 
-    fn get_preloaded_partition(&mut self, partition: &CStr) -> IoResult<&[u8]> {
+    fn get_preloaded_partition(&mut self, partition: &CStr) -> IoResult<&'a [u8]> {
         self.payload.get_partition(partition)
     }
 
diff --git a/pvmfw/avb/src/verify.rs b/pvmfw/avb/src/verify.rs
index 2ebe9a1..038b1d6 100644
--- a/pvmfw/avb/src/verify.rs
+++ b/pvmfw/avb/src/verify.rs
@@ -280,11 +280,10 @@
     }
 
     let initrd = initrd.unwrap();
-    let mut initrd_ops = Ops::new(&payload);
     let (debug_level, initrd_descriptor) =
-        if verify_initrd(&mut initrd_ops, PartitionName::InitrdNormal, initrd).is_ok() {
+        if verify_initrd(&mut ops, PartitionName::InitrdNormal, initrd).is_ok() {
             (DebugLevel::None, hash_descriptors.initrd_normal)
-        } else if verify_initrd(&mut initrd_ops, PartitionName::InitrdDebug, initrd).is_ok() {
+        } else if verify_initrd(&mut ops, PartitionName::InitrdDebug, initrd).is_ok() {
             (DebugLevel::Full, hash_descriptors.initrd_debug)
         } else {
             return Err(SlotVerifyError::Verification(None).into());
diff --git a/pvmfw/platform.dts b/pvmfw/platform.dts
index 8074188..e63e42f 100644
--- a/pvmfw/platform.dts
+++ b/pvmfw/platform.dts
@@ -84,7 +84,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <0>;
+			reg = <0x0>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table0>;
 			opp_table0: opp-table-0 {
@@ -116,7 +116,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <1>;
+			reg = <0x1>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table1>;
 			opp_table1: opp-table-1 {
@@ -148,7 +148,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <2>;
+			reg = <0x2>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table2>;
 			opp_table2: opp-table-2 {
@@ -180,7 +180,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <3>;
+			reg = <0x3>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table3>;
 			opp_table3: opp-table-3 {
@@ -212,7 +212,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <4>;
+			reg = <0x4>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table4>;
 			opp_table4: opp-table-4 {
@@ -244,7 +244,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <5>;
+			reg = <0x5>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table5>;
 			opp_table5: opp-table-5 {
@@ -276,7 +276,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <6>;
+			reg = <0x6>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table6>;
 			opp_table6: opp-table-6 {
@@ -308,7 +308,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <7>;
+			reg = <0x7>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table7>;
 			opp_table7: opp-table-7 {
@@ -340,7 +340,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <8>;
+			reg = <0x8>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table8>;
 			opp_table8: opp-table-8 {
@@ -372,7 +372,7 @@
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <9>;
+			reg = <0x9>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table9>;
 			opp_table9: opp-table-9 {
@@ -400,11 +400,11 @@
 				opp20 { opp-hz = <PLACEHOLDER2>; };
 			};
 		};
-		cpu10: cpu@10 {
+		cpu10: cpu@a {
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <10>;
+			reg = <0xa>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table10>;
 			opp_table10: opp-table-10 {
@@ -432,11 +432,11 @@
 				opp20 { opp-hz = <PLACEHOLDER2>; };
 			};
 		};
-		cpu11: cpu@11 {
+		cpu11: cpu@b {
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <11>;
+			reg = <0xb>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table11>;
 			opp_table11: opp-table-11 {
@@ -464,11 +464,11 @@
 				opp20 { opp-hz = <PLACEHOLDER2>; };
 			};
 		};
-		cpu12: cpu@12 {
+		cpu12: cpu@c {
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <12>;
+			reg = <0xc>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table12>;
 			opp_table12: opp-table-12 {
@@ -496,11 +496,11 @@
 				opp20 { opp-hz = <PLACEHOLDER2>; };
 			};
 		};
-		cpu13: cpu@13 {
+		cpu13: cpu@d {
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <13>;
+			reg = <0xd>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table13>;
 			opp_table13: opp-table-13 {
@@ -528,11 +528,11 @@
 				opp20 { opp-hz = <PLACEHOLDER2>; };
 			};
 		};
-		cpu14: cpu@14 {
+		cpu14: cpu@e {
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <14>;
+			reg = <0xe>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table14>;
 			opp_table14: opp-table-14 {
@@ -560,11 +560,11 @@
 				opp20 { opp-hz = <PLACEHOLDER2>; };
 			};
 		};
-		cpu15: cpu@15 {
+		cpu15: cpu@f {
 			device_type = "cpu";
 			compatible = "arm,arm-v8";
 			enable-method = "psci";
-			reg = <15>;
+			reg = <0xf>;
 			capacity-dmips-mhz = <PLACEHOLDER>;
 			operating-points-v2 = <&opp_table15>;
 			opp_table15: opp-table-15 {
diff --git a/service_vm/manager/src/lib.rs b/service_vm/manager/src/lib.rs
index c50f0b3..273b54d 100644
--- a/service_vm/manager/src/lib.rs
+++ b/service_vm/manager/src/lib.rs
@@ -277,6 +277,7 @@
     }
     let instance_img = OpenOptions::new()
         .create(true)
+        .truncate(true)
         .read(true)
         .write(true)
         .open(instance_img_path)
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index 068d8f9..2eca2fa 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -23,6 +23,7 @@
     per_testcase_directory: true,
     data: [
         ":MicrodroidTestApp",
+        ":MicrodroidTestAppUpdated",
         ":microdroid_general_sepolicy.conf",
         ":test.com.android.virt.pem",
         ":test2.com.android.virt.pem",
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 007f38c..1e81172 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
@@ -31,6 +31,7 @@
 import com.android.tradefed.device.TestDevice;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
 import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.RunUtil;
 
@@ -49,12 +50,16 @@
 
 public abstract class MicrodroidHostTestCaseBase extends BaseHostJUnit4Test {
     protected static final String TEST_ROOT = "/data/local/tmp/virt/";
+    protected static final String TRADEFED_TEST_ROOT = "/data/local/tmp/virt/tradefed/";
     protected static final String LOG_PATH = TEST_ROOT + "log.txt";
     protected static final String CONSOLE_PATH = TEST_ROOT + "console.txt";
+    protected static final String TRADEFED_CONSOLE_PATH = TRADEFED_TEST_ROOT + "console.txt";
     private static final int TEST_VM_ADB_PORT = 8000;
     private static final String MICRODROID_SERIAL = "localhost:" + TEST_VM_ADB_PORT;
     private static final String INSTANCE_IMG = "instance.img";
     protected static final String VIRT_APEX = "/apex/com.android.virt/";
+    protected static final String SECRETKEEPER_AIDL =
+            "android.hardware.security.secretkeeper.ISecretkeeper/default";
 
     private static final long MICRODROID_ADB_CONNECT_TIMEOUT_MINUTES = 5;
     protected static final long MICRODROID_COMMAND_TIMEOUT_MILLIS = 30000;
@@ -244,6 +249,17 @@
         return ret;
     }
 
+    public boolean isUpdatableVmSupported() throws DeviceNotAvailableException {
+        // Updatable VMs are possible iff device supports Secretkeeper.
+        CommandRunner android = new CommandRunner(getDevice());
+        CommandResult result = android.runForResult("service check", SECRETKEEPER_AIDL);
+        assertWithMessage("Failed to run service check. Result= " + result)
+                .that(result.getStatus() == CommandStatus.SUCCESS && result.getExitCode() == 0)
+                .isTrue();
+        boolean is_sk_supported = !result.getStdout().trim().contains("not found");
+        return is_sk_supported;
+    }
+
     public List<String> getSupportedOSList() throws Exception {
         return parseStringArrayFieldsFromVmInfo("Available OS list: ");
     }
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 06806ec..2b53571 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -19,12 +19,14 @@
 import static com.android.microdroid.test.host.CommandResultSubject.command_results;
 import static com.android.tradefed.device.TestDevice.MicrodroidBuilder;
 import static com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
+import com.android.tradefed.device.DeviceRuntimeException;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
@@ -88,9 +90,12 @@
 @UseParametersRunnerFactory(DeviceJUnit4ClassRunnerWithParameters.RunnerFactory.class)
 public class MicrodroidHostTests extends MicrodroidHostTestCaseBase {
     private static final String APK_NAME = "MicrodroidTestApp.apk";
+    private static final String APK_UPDATED_NAME = "MicrodroidTestAppUpdated.apk";
     private static final String PACKAGE_NAME = "com.android.microdroid.test";
     private static final String SHELL_PACKAGE_NAME = "com.android.shell";
     private static final String VIRT_APEX = "/apex/com.android.virt/";
+    private static final String INSTANCE_IMG = TEST_ROOT + "instance.img";
+    private static final String INSTANCE_ID_FILE = TEST_ROOT + "instance_id";
 
     private static final int MIN_MEM_ARM64 = 170;
     private static final int MIN_MEM_X86_64 = 196;
@@ -409,6 +414,67 @@
     }
 
     @Test
+    @CddTest
+    public void UpgradedPackageIsAcceptedWithSecretkeeper() throws Exception {
+        assumeUpdatableVmSupported();
+        getDevice().uninstallPackage(PACKAGE_NAME);
+        getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ true);
+        ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG);
+
+        getDevice().uninstallPackage(PACKAGE_NAME);
+        cleanUpVirtualizationTestSetup(getDevice());
+        // Install the updated version of app (versionCode 6)
+        getDevice().installPackage(findTestFile(APK_UPDATED_NAME), /* reinstall= */ true);
+        ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG);
+    }
+
+    @Test
+    @CddTest
+    public void DowngradedPackageIsRejectedProtectedVm() throws Exception {
+        assumeProtectedVm(); // Rollback protection is provided only for protected VM.
+
+        // Install the upgraded version (v6)
+        getDevice().uninstallPackage(PACKAGE_NAME);
+        getDevice().installPackage(findTestFile(APK_UPDATED_NAME), /* reinstall= */ true);
+        ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG);
+
+        getDevice().uninstallPackage(PACKAGE_NAME);
+        cleanUpVirtualizationTestSetup(getDevice());
+        // Install the older version (v5)
+        getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ true);
+
+        assertThrows(
+                "pVM must fail to boot with downgraded payload apk",
+                DeviceRuntimeException.class,
+                () -> ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG));
+    }
+
+    private void ensureMicrodroidBootsSuccessfully(String instanceIdPath, String instanceImgPath)
+            throws DeviceNotAvailableException {
+        final String configPath = "assets/vm_config.json";
+        ITestDevice microdroid = null;
+        int timeout = 30000; // 30 seconds
+        try {
+            microdroid =
+                    MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
+                            .debugLevel("full")
+                            .memoryMib(minMemorySize())
+                            .cpuTopology("match_host")
+                            .protectedVm(mProtectedVm)
+                            .instanceIdFile(instanceIdPath)
+                            .instanceImgFile(instanceImgPath)
+                            .setAdbConnectTimeoutMs(timeout)
+                            .build(getAndroidDevice());
+            assertThat(microdroid.waitForBootComplete(timeout)).isTrue();
+            assertThat(microdroid.enableAdbRoot()).isTrue();
+        } finally {
+            if (microdroid != null) {
+                getAndroidDevice().shutdownMicrodroid(microdroid);
+            }
+        }
+    }
+
+    @Test
     @CddTest(requirements = {"9.17/C-2-1", "9.17/C-2-2", "9.17/C-2-6"})
     public void protectedVmRunsPvmfw() throws Exception {
         // Arrange
@@ -427,7 +493,7 @@
 
         // Assert
         mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
-        String consoleLog = getDevice().pullFileContents(CONSOLE_PATH);
+        String consoleLog = getDevice().pullFileContents(TRADEFED_CONSOLE_PATH);
         assertWithMessage("Failed to verify that pvmfw started")
                 .that(consoleLog)
                 .contains("pVM firmware");
@@ -1106,7 +1172,7 @@
 
         prepareVirtualizationTestSetup(getDevice());
 
-        getDevice().installPackage(findTestFile(APK_NAME), /* reinstall */ false);
+        getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ false);
 
         // Skip test if given device doesn't support protected or non-protected VM.
         assumeTrue(
@@ -1159,6 +1225,12 @@
                         && device.doesFileExist("/sys/bus/platform/drivers/vfio-platform"));
     }
 
+    private void assumeUpdatableVmSupported() throws DeviceNotAvailableException {
+        assumeTrue(
+                "This test is only applicable if if Updatable VMs are supported",
+                isUpdatableVmSupported());
+    }
+
     private TestDevice getAndroidDevice() {
         TestDevice androidDevice = (TestDevice) getDevice();
         assertThat(androidDevice).isNotNull();
diff --git a/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java b/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
index 541f5ec..3116cc5 100644
--- a/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
+++ b/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
@@ -19,7 +19,6 @@
 import static com.android.tradefed.device.TestDevice.MicrodroidBuilder;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assume.assumeTrue;
 
@@ -27,12 +26,9 @@
 import androidx.annotation.Nullable;
 
 import com.android.microdroid.test.host.MicrodroidHostTestCaseBase;
-import com.android.microdroid.test.host.CommandRunner;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.TestDevice;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
 import com.android.tradefed.util.FileUtil;
 
 import org.junit.After;
@@ -62,18 +58,12 @@
 
     @NonNull public static final String CUSTOM_PVMFW_FILE_PREFIX = "pvmfw";
     @NonNull public static final String CUSTOM_PVMFW_FILE_SUFFIX = ".bin";
-    @NonNull public static final String CUSTOM_PVMFW_IMG_PATH = TEST_ROOT + PVMFW_FILE_NAME;
+
+    @NonNull
+    public static final String CUSTOM_PVMFW_IMG_PATH = TRADEFED_TEST_ROOT + PVMFW_FILE_NAME;
+
     @NonNull public static final String CUSTOM_PVMFW_IMG_PATH_PROP = "hypervisor.pvmfw.path";
 
-    @NonNull private static final String DUMPSYS = "dumpsys";
-
-    @NonNull
-    private static final String DUMPSYS_MISSING_SERVICE_MSG_PREFIX = "Can't find service: ";
-
-    @NonNull
-    private static final String SECRET_KEEPER_AIDL =
-            "android.hardware.security.secretkeeper.ISecretkeeper/default";
-
     @Nullable private File mPvmfwBinFileOnHost;
     @Nullable private File mBccFileOnHost;
     @Nullable private File mVmReferenceDtFile;
@@ -100,23 +90,7 @@
         // This is prepared by AndroidTest.xml
         mVmReferenceDtFile = mAndroidDevice.pullFile(VM_REFERENCE_DT_PATH);
 
-        CommandRunner runner = new CommandRunner(mAndroidDevice);
-        CommandResult result = runner.runForResult(DUMPSYS, SECRET_KEEPER_AIDL);
-
-        // dumpsys prints 'Can't find service: ~' to stderr if secret keeper HAL is missing,
-        // but it doesn't return any error code for it.
-        // Read stderr to know whether secret keeper is supported, and stop test for any other case.
-        assertWithMessage("Failed to run " + DUMPSYS + ", result=" + result)
-                .that(result.getStatus() == CommandStatus.SUCCESS && result.getExitCode() == 0)
-                .isTrue();
-        if (result.getStderr() != null && !result.getStderr().trim().isEmpty()) {
-            assertWithMessage(
-                            "Unexpected stderr from " + DUMPSYS + ", stderr=" + result.getStderr())
-                    .that(result.getStderr().trim().startsWith(DUMPSYS_MISSING_SERVICE_MSG_PREFIX))
-                    .isTrue();
-        } else {
-            mSecretKeeperSupported = true;
-        }
+        mSecretKeeperSupported = isUpdatableVmSupported();
 
         // Prepare for system properties for custom pvmfw.img.
         // File will be prepared later in individual test and then pushed to device
diff --git a/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java b/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
index 223f93f..2a6ab2d 100644
--- a/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
+++ b/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
@@ -50,7 +50,7 @@
 
     @NonNull
     private static final String CUSTOM_DEBUG_POLICY_PATH =
-            TEST_ROOT + CUSTOM_DEBUG_POLICY_FILE_NAME;
+            TRADEFED_TEST_ROOT + CUSTOM_DEBUG_POLICY_FILE_NAME;
 
     @NonNull
     private static final String CUSTOM_DEBUG_POLICY_PATH_PROP =
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 84bf098..471aea7 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -33,10 +33,10 @@
     compile_multilib: "both",
 }
 
-android_test {
-    name: "MicrodroidTestApp",
-    defaults: ["MicrodroidTestAppsDefaults"],
+java_defaults {
+    name: "MicrodroidVersionsTestAppDefaults",
     srcs: ["src/java/**/*.java"],
+    defaults: ["MicrodroidTestAppsDefaults"],
     static_libs: [
         "MicrodroidDeviceTestHelper",
         "VmAttestationTestUtil",
@@ -58,14 +58,27 @@
         "libvm_attestation_test_payload",
     ],
     min_sdk_version: "33",
+}
+
+android_test {
+    name: "MicrodroidTestApp",
+    defaults: ["MicrodroidVersionsTestAppDefaults"],
+    manifest: "AndroidManifestV5.xml",
     // Defined in ../vmshareapp/Android.bp
     data: [
+        ":MicrodroidTestAppUpdated",
         ":MicrodroidVmShareApp",
         ":test_microdroid_vendor_image",
         ":test_microdroid_vendor_image_unsigned",
     ],
 }
 
+android_test_helper_app {
+    name: "MicrodroidTestAppUpdated",
+    defaults: ["MicrodroidVersionsTestAppDefaults"],
+    manifest: "AndroidManifestV6.xml",
+}
+
 // Defaults shared between MicrodroidTestNativeLib and MicrodroidPayloadInOtherAppNativeLib shared
 // libs. They are expected to share everything apart from the name, so that one app
 // (MicrodroidTestApp) can start a payload defined in the another app (MicrodroidVmShareApp).
diff --git a/tests/testapk/AndroidManifest.xml b/tests/testapk/AndroidManifestV5.xml
similarity index 94%
copy from tests/testapk/AndroidManifest.xml
copy to tests/testapk/AndroidManifestV5.xml
index d6e6004..7d97680 100644
--- a/tests/testapk/AndroidManifest.xml
+++ b/tests/testapk/AndroidManifestV5.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="com.android.microdroid.test">
+      package="com.android.microdroid.test"
+      android:versionCode="5">
     <uses-permission android:name="android.permission.MANAGE_VIRTUAL_MACHINE" />
     <uses-permission android:name="android.permission.USE_CUSTOM_VIRTUAL_MACHINE" />
     <uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33" />
diff --git a/tests/testapk/AndroidManifest.xml b/tests/testapk/AndroidManifestV6.xml
similarity index 94%
rename from tests/testapk/AndroidManifest.xml
rename to tests/testapk/AndroidManifestV6.xml
index d6e6004..19d5674 100644
--- a/tests/testapk/AndroidManifest.xml
+++ b/tests/testapk/AndroidManifestV6.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="com.android.microdroid.test">
+      package="com.android.microdroid.test"
+      android:versionCode="6">
     <uses-permission android:name="android.permission.MANAGE_VIRTUAL_MACHINE" />
     <uses-permission android:name="android.permission.USE_CUSTOM_VIRTUAL_MACHINE" />
     <uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33" />
diff --git a/vmbase/Android.bp b/vmbase/Android.bp
index e797aa4..07e1b4c 100644
--- a/vmbase/Android.bp
+++ b/vmbase/Android.bp
@@ -57,8 +57,6 @@
         hwaddress: false,
     },
     native_coverage: false,
-    // Use --lto-O0 to reduce binary size.
-    lto_O0: true,
 }
 
 // Used by cc_binary when producing the ELF of a vmbase-based binary.
diff --git a/zipfuse/src/main.rs b/zipfuse/src/main.rs
index e8be42c..ef31a0c 100644
--- a/zipfuse/src/main.rs
+++ b/zipfuse/src/main.rs
@@ -320,6 +320,7 @@
         }
     }
 
+    #[allow(clippy::unused_io_amount)]
     fn read<W: io::Write + ZeroCopyWriter>(
         &self,
         _ctx: Context,