Merge "Unify OS APIs into one API" into main
diff --git a/authfs/tests/common/src/java/com/android/fs/common/AuthFsTestRule.java b/authfs/tests/common/src/java/com/android/fs/common/AuthFsTestRule.java
index 9c0fd72..7c85797 100644
--- a/authfs/tests/common/src/java/com/android/fs/common/AuthFsTestRule.java
+++ b/authfs/tests/common/src/java/com/android/fs/common/AuthFsTestRule.java
@@ -52,7 +52,7 @@
     public static final String FUSE_SUPER_MAGIC_HEX = "65735546";
 
     /** VM config entry path in the test APK */
-    private static final String VM_CONFIG_PATH_IN_APK = "assets/microdroid/vm_config.json";
+    private static final String VM_CONFIG_PATH_IN_APK = "assets/vm_config.json";
 
     /** Test directory on Android where data are located */
     public static final String TEST_DIR = "/data/local/tmp/authfs";
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index ffdd0ea..d0ca026 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -24,10 +24,7 @@
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
     CpuTopology::CpuTopology,
     IVirtualizationService::IVirtualizationService,
-    VirtualMachineAppConfig::{
-        CustomConfig::CustomConfig, DebugLevel::DebugLevel, Payload::Payload,
-        VirtualMachineAppConfig,
-    },
+    VirtualMachineAppConfig::{DebugLevel::DebugLevel, Payload::Payload, VirtualMachineAppConfig},
     VirtualMachineConfig::VirtualMachineConfig,
 };
 use anyhow::{anyhow, bail, Context, Result};
@@ -125,14 +122,13 @@
             idsig: Some(idsig_fd),
             instanceId: instance_id,
             instanceImage: Some(instance_fd),
-            encryptedStorageImage: None,
             payload: Payload::ConfigPath(config_path),
             debugLevel: debug_level,
             extraIdsigs: extra_idsigs,
             protectedVm: protected_vm,
             memoryMib: parameters.memory_mib.unwrap_or(0), // 0 means use the default
             cpuTopology: cpu_topology,
-            customConfig: Some(CustomConfig { ..Default::default() }),
+            ..Default::default()
         });
 
         // Let logs go to logcat.
diff --git a/java/framework/api/test-current.txt b/java/framework/api/test-current.txt
index 3cd8e42..a8b2088 100644
--- a/java/framework/api/test-current.txt
+++ b/java/framework/api/test-current.txt
@@ -9,9 +9,10 @@
 
   public final class VirtualMachineConfig {
     method @FlaggedApi("com.android.system.virtualmachine.flags.avf_v_test_apis") @NonNull public java.util.List<java.lang.String> getExtraApks();
-    method @FlaggedApi("com.android.system.virtualmachine.flags.avf_v_test_apis") @Nullable public String getOs();
+    method @FlaggedApi("com.android.system.virtualmachine.flags.avf_v_test_apis") @NonNull public String getOs();
     method @Nullable public String getPayloadConfigPath();
     method public boolean isVmConsoleInputSupported();
+    field @FlaggedApi("com.android.system.virtualmachine.flags.avf_v_test_apis") public static final String MICRODROID = "microdroid";
   }
 
   public static final class VirtualMachineConfig.Builder {
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
index 12aeac8..054d73c 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -27,6 +27,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.content.Context;
@@ -183,8 +184,25 @@
 
     @Nullable private final File mVendorDiskImage;
 
-    /** OS name of the VM using payload binaries. null if the VM uses a payload config file. */
-    @Nullable private final String mOs;
+    /** OS name of the VM using payload binaries. */
+    @NonNull @OsName private final String mOs;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @StringDef(
+            prefix = "MICRODROID",
+            value = {MICRODROID})
+    private @interface OsName {}
+
+    /**
+     * OS name of microdroid using microdroid kernel.
+     *
+     * @see Builder#setOs
+     * @hide
+     */
+    @TestApi
+    @FlaggedApi(Flags.FLAG_AVF_V_TEST_APIS)
+    @OsName
+    public static final String MICRODROID = "microdroid";
 
     private VirtualMachineConfig(
             @Nullable String packageName,
@@ -200,7 +218,7 @@
             boolean vmOutputCaptured,
             boolean vmConsoleInputSupported,
             @Nullable File vendorDiskImage,
-            @Nullable String os) {
+            @NonNull @OsName String os) {
         // This is only called from Builder.build(); the builder handles parameter validation.
         mPackageName = packageName;
         mApkPath = apkPath;
@@ -301,10 +319,7 @@
             builder.setVendorDiskImage(new File(vendorDiskImagePath));
         }
 
-        String os = b.getString(KEY_OS);
-        if (os != null) {
-            builder.setOs(os);
-        }
+        builder.setOs(b.getString(KEY_OS));
 
         String[] extraApks = b.getStringArray(KEY_EXTRA_APKS);
         if (extraApks != null) {
@@ -498,14 +513,15 @@
     }
 
     /**
-     * Returns the OS of the VM using a payload binary. Returns null if the VM uses payload config.
+     * Returns the OS of the VM.
      *
      * @see Builder#setOs
      * @hide
      */
     @TestApi
     @FlaggedApi(Flags.FLAG_AVF_V_TEST_APIS)
-    @Nullable
+    @NonNull
+    @OsName
     public String getOs() {
         return mOs;
     }
@@ -559,7 +575,6 @@
         if (mPayloadBinaryName != null) {
             VirtualMachinePayloadConfig payloadConfig = new VirtualMachinePayloadConfig();
             payloadConfig.payloadBinaryName = mPayloadBinaryName;
-            payloadConfig.osName = mOs;
             payloadConfig.extraApks = Collections.emptyList();
             vsConfig.payload =
                     VirtualMachineAppConfig.Payload.payloadConfig(payloadConfig);
@@ -567,6 +582,7 @@
             vsConfig.payload =
                     VirtualMachineAppConfig.Payload.configPath(mPayloadConfigPath);
         }
+        vsConfig.osName = mOs;
         switch (mDebugLevel) {
             case DEBUG_LEVEL_FULL:
                 vsConfig.debugLevel = VirtualMachineAppConfig.DebugLevel.FULL;
@@ -658,7 +674,7 @@
      */
     @SystemApi
     public static final class Builder {
-        private final String DEFAULT_OS = "microdroid";
+        @OsName private final String DEFAULT_OS = MICRODROID;
 
         @Nullable private final String mPackageName;
         @Nullable private String mApkPath;
@@ -674,7 +690,7 @@
         private boolean mVmOutputCaptured = false;
         private boolean mVmConsoleInputSupported = false;
         @Nullable private File mVendorDiskImage;
-        @Nullable private String mOs;
+        @NonNull @OsName private String mOs = DEFAULT_OS;
 
         /**
          * Creates a builder for the given context.
@@ -714,15 +730,10 @@
                 throw new IllegalStateException("apkPath or packageName must be specified");
             }
 
-            String os = null;
             if (mPayloadBinaryName == null) {
                 if (mPayloadConfigPath == null) {
                     throw new IllegalStateException("setPayloadBinaryName must be called");
                 }
-                if (mOs != null) {
-                    throw new IllegalStateException(
-                            "setPayloadConfigPath and setOs may not both be called");
-                }
                 if (!mExtraApks.isEmpty()) {
                     throw new IllegalStateException(
                             "setPayloadConfigPath and addExtraApk may not both be called");
@@ -732,11 +743,6 @@
                     throw new IllegalStateException(
                             "setPayloadBinaryName and setPayloadConfigPath may not both be called");
                 }
-                if (mOs != null) {
-                    os = mOs;
-                } else {
-                    os = DEFAULT_OS;
-                }
             }
 
             if (!mProtectedVmSet) {
@@ -765,7 +771,7 @@
                     mVmOutputCaptured,
                     mVmConsoleInputSupported,
                     mVendorDiskImage,
-                    os);
+                    mOs);
         }
 
         /**
@@ -1025,7 +1031,7 @@
         @FlaggedApi(Flags.FLAG_AVF_V_TEST_APIS)
         @RequiresPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION)
         @NonNull
-        public Builder setOs(@NonNull String os) {
+        public Builder setOs(@NonNull @OsName String os) {
             mOs = requireNonNull(os, "os must not be null");
             return this;
         }
diff --git a/microdroid/payload/config/src/lib.rs b/microdroid/payload/config/src/lib.rs
index cdef3e4..d6f65bd 100644
--- a/microdroid/payload/config/src/lib.rs
+++ b/microdroid/payload/config/src/lib.rs
@@ -17,10 +17,12 @@
 use serde::{Deserialize, Serialize};
 
 /// VM payload config
-#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
+#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
 pub struct VmPayloadConfig {
-    /// OS config. Default: "microdroid"
+    /// OS config.
+    /// Deprecated: don't use. Error if not "" or "microdroid".
     #[serde(default)]
+    #[deprecated]
     pub os: OsConfig,
 
     /// Task to run in a VM
@@ -58,7 +60,7 @@
 
 impl Default for OsConfig {
     fn default() -> Self {
-        Self { name: "microdroid".to_owned() }
+        Self { name: "".to_owned() }
     }
 }
 
diff --git a/tests/benchmark/assets/microdroid_gki-android14-6.1/vm_config.json b/tests/benchmark/assets/microdroid_gki-android14-6.1/vm_config.json
deleted file mode 100644
index c4fdc6e..0000000
--- a/tests/benchmark/assets/microdroid_gki-android14-6.1/vm_config.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "task": {
-    "type": "microdroid_launcher",
-    "command": "MicrodroidIdleNativeLib.so"
-  },
-  "export_tombstones": true
-}
diff --git a/tests/benchmark/assets/microdroid_gki-android14-6.1/vm_config_io.json b/tests/benchmark/assets/microdroid_gki-android14-6.1/vm_config_io.json
deleted file mode 100644
index 34c204e..0000000
--- a/tests/benchmark/assets/microdroid_gki-android14-6.1/vm_config_io.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "task": {
-    "type": "microdroid_launcher",
-    "command": "MicrodroidBenchmarkNativeLib.so"
-  },
-  "apexes": [
-    {
-      "name": "com.android.virt"
-    }
-  ],
-  "export_tombstones": true
-}
diff --git a/tests/benchmark/assets/microdroid/vm_config.json b/tests/benchmark/assets/vm_config.json
similarity index 76%
rename from tests/benchmark/assets/microdroid/vm_config.json
rename to tests/benchmark/assets/vm_config.json
index 5a604a9..d4c66d7 100644
--- a/tests/benchmark/assets/microdroid/vm_config.json
+++ b/tests/benchmark/assets/vm_config.json
@@ -1,7 +1,4 @@
 {
-  "os": {
-    "name": "microdroid"
-  },
   "task": {
     "type": "microdroid_launcher",
     "command": "MicrodroidIdleNativeLib.so"
diff --git a/tests/benchmark/assets/microdroid/vm_config_io.json b/tests/benchmark/assets/vm_config_io.json
similarity index 82%
rename from tests/benchmark/assets/microdroid/vm_config_io.json
rename to tests/benchmark/assets/vm_config_io.json
index 66046ba..f982d41 100644
--- a/tests/benchmark/assets/microdroid/vm_config_io.json
+++ b/tests/benchmark/assets/vm_config_io.json
@@ -1,7 +1,4 @@
 {
-  "os": {
-    "name": "microdroid"
-  },
   "task": {
     "type": "microdroid_launcher",
     "command": "MicrodroidBenchmarkNativeLib.so"
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 acd6f2c..9cc1b7b 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -222,7 +222,6 @@
 
     private void runBootTimeTest(
             String name,
-            String payloadConfig,
             boolean fullDebug,
             Function<VirtualMachineConfig.Builder, VirtualMachineConfig.Builder> fnConfig)
             throws VirtualMachineException, InterruptedException, IOException {
@@ -261,7 +260,6 @@
             throws VirtualMachineException, InterruptedException, IOException {
         runBootTimeTest(
                 "test_vm_boot_time",
-                "assets/" + os() + "/vm_config.json",
                 /* fullDebug */ false,
                 (builder) -> builder.setCpuTopology(CPU_TOPOLOGY_ONE_CPU));
     }
@@ -270,7 +268,6 @@
             throws VirtualMachineException, InterruptedException, IOException {
         runBootTimeTest(
                 "test_vm_boot_time_host_topology",
-                "assets/" + os() + "/vm_config.json",
                 /* fullDebug */ false,
                 (builder) -> builder.setCpuTopology(CPU_TOPOLOGY_MATCH_HOST));
     }
@@ -280,7 +277,6 @@
             throws VirtualMachineException, InterruptedException, IOException {
         runBootTimeTest(
                 "test_vm_boot_time_debug",
-                "assets/" + os() + "/vm_config.json",
                 /* fullDebug */ true,
                 (builder) -> builder);
     }
@@ -298,7 +294,6 @@
         assumeFeatureEnabled(VirtualMachineManager.FEATURE_VENDOR_MODULES);
         runBootTimeTest(
                 "test_vm_boot_time_debug_with_vendor_partition",
-                "assets/" + os() + "/vm_config.json",
                 /* fullDebug */ true,
                 (builder) -> builder.setVendorDiskImage(vendorDiskImage));
     }
@@ -348,7 +343,7 @@
     @Test
     public void testVsockTransferFromHostToVM() throws Exception {
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config_io.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config_io.json")
                         .setDebugLevel(DEBUG_LEVEL_NONE)
                         .build();
         List<Double> transferRates = new ArrayList<>(IO_TEST_TRIAL_COUNT);
@@ -374,7 +369,7 @@
 
     private void testVirtioBlkReadRate(boolean isRand) throws Exception {
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config_io.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config_io.json")
                         .setDebugLevel(DEBUG_LEVEL_NONE)
                         .build();
         List<Double> readRates = new ArrayList<>(IO_TEST_TRIAL_COUNT);
@@ -525,7 +520,7 @@
     public void testMemoryUsage() throws Exception {
         final String vmName = "test_vm_mem_usage";
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config_io.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config_io.json")
                         .setDebugLevel(DEBUG_LEVEL_NONE)
                         .setMemoryBytes(256 * ONE_MEBI)
                         .build();
@@ -611,7 +606,7 @@
     public void testMemoryReclaim() throws Exception {
         final String vmName = "test_vm_mem_reclaim";
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config_io.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config_io.json")
                         .setDebugLevel(DEBUG_LEVEL_NONE)
                         .setMemoryBytes(256 * ONE_MEBI)
                         .build();
@@ -836,7 +831,7 @@
     @Test
     public void testVmKillTime() throws Exception {
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config_io.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config_io.json")
                         .setDebugLevel(DEBUG_LEVEL_NONE)
                         .build();
         List<Double> vmKillTime = new ArrayList<>(TEST_TRIAL_COUNT);
diff --git a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
index f01a76b..b176cfc 100644
--- a/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
+++ b/tests/benchmark_hostside/java/android/avf/test/AVFHostTestCase.java
@@ -231,7 +231,7 @@
         android.tryRun("rm", "-rf", MicrodroidHostTestCaseBase.TEST_ROOT);
 
         // Donate 80% of the available device memory to the VM
-        final String configPath = "assets/microdroid/vm_config.json";
+        final String configPath = "assets/vm_config.json";
         final int vm_mem_mb = getFreeMemoryInfoMb(android) * 80 / 100;
         ITestDevice microdroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
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 2c92f04..70ac944 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
@@ -127,6 +127,7 @@
     public VirtualMachineConfig.Builder newVmConfigBuilderWithPayloadConfig(String configPath) {
         return new VirtualMachineConfig.Builder(mCtx)
                 .setProtectedVm(mProtectedVm)
+                .setOs(os())
                 .setPayloadConfigPath(configPath);
     }
 
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 6dd3afe..a51bebe 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -153,7 +153,7 @@
             throws Exception {
         PayloadMetadata.write(
                 PayloadMetadata.metadata(
-                        "/mnt/apk/assets/" + mOs + "/vm_config.json",
+                        "/mnt/apk/assets/vm_config.json",
                         PayloadMetadata.apk("microdroid-apk"),
                         apexes.stream()
                                 .map(apex -> PayloadMetadata.apex(apex.name))
@@ -412,7 +412,7 @@
     public void protectedVmRunsPvmfw() throws Exception {
         // Arrange
         assumeProtectedVm();
-        final String configPath = "assets/" + mOs + "/vm_config_apex.json";
+        final String configPath = "assets/vm_config_apex.json";
 
         // Act
         mMicrodroidDevice =
@@ -421,6 +421,7 @@
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(true)
+                        .gki(mGki)
                         .build(getAndroidDevice());
 
         // Assert
@@ -548,6 +549,7 @@
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(protectedVm)
+                        .gki(mGki)
                         .build(getAndroidDevice());
         mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
         mMicrodroidDevice.enableAdbRoot();
@@ -569,7 +571,7 @@
         assertThat(
                         isTombstoneGeneratedWithCmd(
                                 mProtectedVm,
-                                "assets/" + mOs + "/vm_config.json",
+                                "assets/vm_config.json",
                                 "kill",
                                 "-SIGSEGV",
                                 "$(pidof microdroid_launcher)"))
@@ -583,7 +585,7 @@
         assertThat(
                         isTombstoneGeneratedWithCmd(
                                 mProtectedVm,
-                                "assets/" + mOs + "/vm_config_no_tombstone.json",
+                                "assets/vm_config_no_tombstone.json",
                                 "kill",
                                 "-SIGSEGV",
                                 "$(pidof microdroid_launcher)"))
@@ -597,7 +599,7 @@
         assertThat(
                         isTombstoneGeneratedWithCmd(
                                 mProtectedVm,
-                                "assets/" + mOs + "/vm_config.json",
+                                "assets/vm_config.json",
                                 "echo",
                                 "c",
                                 ">",
@@ -636,6 +638,10 @@
         if (protectedVm) {
             cmd.add("--protected");
         }
+        if (mGki != null) {
+            cmd.add("--gki");
+            cmd.add(mGki);
+        }
         Collections.addAll(cmd, additionalArgs);
 
         android.run(cmd.toArray(new String[0]));
@@ -667,10 +673,7 @@
     private boolean isTombstoneGeneratedWithCrashConfig(boolean protectedVm, boolean debuggable)
             throws Exception {
         return isTombstoneGeneratedWithVmRunApp(
-                protectedVm,
-                debuggable,
-                "--config-path",
-                "assets/" + mOs + "/vm_config_crash.json");
+                protectedVm, debuggable, "--config-path", "assets/vm_config_crash.json");
     }
 
     @Test
@@ -705,13 +708,14 @@
 
         // Create VM with microdroid
         TestDevice device = getAndroidDevice();
-        final String configPath = "assets/" + mOs + "/vm_config_apex.json"; // path inside the APK
+        final String configPath = "assets/vm_config_apex.json"; // path inside the APK
         ITestDevice microdroid =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(mProtectedVm)
+                        .gki(mGki)
                         .build(device);
         microdroid.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
         device.shutdownMicrodroid(microdroid);
@@ -797,7 +801,7 @@
                 getDevice().pullFileContents(CONSOLE_PATH) + getDevice().pullFileContents(LOG_PATH);
         assertWithMessage("Unexpected denials during VM boot")
                 .that(logText)
-                .doesNotContainMatch("avc:\s+denied");
+                .doesNotContainMatch("avc:\\s+denied");
 
         assertThat(getDeviceNumCpus(microdroid)).isEqualTo(getDeviceNumCpus(android));
 
@@ -833,24 +837,26 @@
     @Test
     @CddTest(requirements = {"9.17/C-1-1", "9.17/C-1-2", "9.17/C/1-3"})
     public void testMicrodroidBoots() throws Exception {
-        final String configPath = "assets/" + mOs + "/vm_config.json"; // path inside the APK
+        final String configPath = "assets/vm_config.json"; // path inside the APK
         testMicrodroidBootsWithBuilder(
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
-                        .protectedVm(mProtectedVm));
+                        .protectedVm(mProtectedVm)
+                        .gki(mGki));
     }
 
     @Test
     public void testMicrodroidRamUsage() throws Exception {
-        final String configPath = "assets/" + mOs + "/vm_config.json";
+        final String configPath = "assets/vm_config.json";
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(mProtectedVm)
+                        .gki(mGki)
                         .build(getAndroidDevice());
         mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
         mMicrodroidDevice.enableAdbRoot();
@@ -1082,14 +1088,15 @@
     }
 
     private void launchWithDeviceAssignment(String device) throws Exception {
-        final String configPath = "assets/" + mOs + "/vm_config.json";
+        final String configPath = "assets/vm_config.json";
 
         MicrodroidBuilder builder =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
                         .debugLevel("full")
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
-                        .protectedVm(mProtectedVm);
+                        .protectedVm(mProtectedVm)
+                        .gki(mGki);
         if (device != null) {
             builder.addAssignableDevice(device);
         }
diff --git a/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java b/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
index a3216c2..541f5ec 100644
--- a/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
+++ b/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
@@ -50,8 +50,7 @@
     @NonNull public static final String MICRODROID_DEBUG_FULL = "full";
     @NonNull public static final String MICRODROID_DEBUG_NONE = "none";
 
-    @NonNull
-    public static final String MICRODROID_CONFIG_PATH = "assets/microdroid/vm_config_apex.json";
+    @NonNull public static final String MICRODROID_CONFIG_PATH = "assets/vm_config_apex.json";
 
     @NonNull
     public static final String VM_REFERENCE_DT_PATH = "/data/local/tmp/pvmfw/reference_dt.dtb";
diff --git a/tests/testapk/assets/microdroid/vm_config_no_task.json b/tests/testapk/assets/microdroid/vm_config_no_task.json
deleted file mode 100644
index 3162bd0..0000000
--- a/tests/testapk/assets/microdroid/vm_config_no_task.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "os": {
-    "name": "microdroid"
-  },
-  "export_tombstones": true
-}
diff --git a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config.json b/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config.json
deleted file mode 100644
index 2022127..0000000
--- a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "task": {
-    "type": "microdroid_launcher",
-    "command": "MicrodroidTestNativeLib.so"
-  },
-  "export_tombstones": true
-}
diff --git a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_apex.json b/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_apex.json
deleted file mode 100644
index bd3998d..0000000
--- a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_apex.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "task": {
-    "type": "microdroid_launcher",
-    "command": "MicrodroidTestNativeLib.so"
-  },
-  "apexes": [
-    {
-      "name": "com.android.art"
-    },
-    {
-      "name": "com.android.compos"
-    },
-    {
-      "name": "com.android.sdkext"
-    }
-  ],
-  "export_tombstones": true
-}
diff --git a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_crash.json b/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_crash.json
deleted file mode 100644
index 4692258..0000000
--- a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_crash.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "task": {
-    "type": "microdroid_launcher",
-    "command": "MicrodroidCrashNativeLib.so"
-  }
-}
diff --git a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_extra_apk.json b/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_extra_apk.json
deleted file mode 100644
index 1602294..0000000
--- a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_extra_apk.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "task": {
-    "type": "microdroid_launcher",
-    "command": "MicrodroidTestNativeLib.so"
-  },
-  "extra_apks": [
-    {
-      "path": "/system/etc/security/fsverity/BuildManifest.apk"
-    }
-  ],
-  "export_tombstones": true
-}
diff --git a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_no_task.json b/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_no_task.json
deleted file mode 100644
index 8282f99..0000000
--- a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_no_task.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "export_tombstones": true
-}
diff --git a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_no_tombstone.json b/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_no_tombstone.json
deleted file mode 100644
index 6e8a136..0000000
--- a/tests/testapk/assets/microdroid_gki-android14-6.1/vm_config_no_tombstone.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "os": {
-    "name": "microdroid_gki-android14-6.1"
-  },
-  "task": {
-    "type": "microdroid_launcher",
-    "command": "MicrodroidTestNativeLib.so"
-  },
-  "export_tombstones": false
-}
diff --git a/tests/testapk/assets/microdroid/vm_config.json b/tests/testapk/assets/vm_config.json
similarity index 76%
rename from tests/testapk/assets/microdroid/vm_config.json
rename to tests/testapk/assets/vm_config.json
index d12eb5c..90945a5 100644
--- a/tests/testapk/assets/microdroid/vm_config.json
+++ b/tests/testapk/assets/vm_config.json
@@ -1,7 +1,4 @@
 {
-  "os": {
-    "name": "microdroid"
-  },
   "task": {
     "type": "microdroid_launcher",
     "command": "MicrodroidTestNativeLib.so"
diff --git a/tests/testapk/assets/microdroid/vm_config_apex.json b/tests/testapk/assets/vm_config_apex.json
similarity index 87%
rename from tests/testapk/assets/microdroid/vm_config_apex.json
rename to tests/testapk/assets/vm_config_apex.json
index c00787f..591bfea 100644
--- a/tests/testapk/assets/microdroid/vm_config_apex.json
+++ b/tests/testapk/assets/vm_config_apex.json
@@ -1,7 +1,4 @@
 {
-  "os": {
-    "name": "microdroid"
-  },
   "task": {
     "type": "microdroid_launcher",
     "command": "MicrodroidTestNativeLib.so"
diff --git a/tests/testapk/assets/microdroid/vm_config_crash.json b/tests/testapk/assets/vm_config_crash.json
similarity index 71%
rename from tests/testapk/assets/microdroid/vm_config_crash.json
rename to tests/testapk/assets/vm_config_crash.json
index ce6af80..ef2a383 100644
--- a/tests/testapk/assets/microdroid/vm_config_crash.json
+++ b/tests/testapk/assets/vm_config_crash.json
@@ -1,7 +1,4 @@
 {
-  "os": {
-    "name": "microdroid"
-  },
   "task": {
     "type": "microdroid_launcher",
     "command": "MicrodroidCrashNativeLib.so"
diff --git a/tests/testapk/assets/microdroid/vm_config_extra_apk.json b/tests/testapk/assets/vm_config_extra_apk.json
similarity index 84%
rename from tests/testapk/assets/microdroid/vm_config_extra_apk.json
rename to tests/testapk/assets/vm_config_extra_apk.json
index b45e57d..3e4bf2d 100644
--- a/tests/testapk/assets/microdroid/vm_config_extra_apk.json
+++ b/tests/testapk/assets/vm_config_extra_apk.json
@@ -1,7 +1,4 @@
 {
-  "os": {
-    "name": "microdroid"
-  },
   "task": {
     "type": "microdroid_launcher",
     "command": "MicrodroidTestNativeLib.so"
diff --git a/tests/testapk/assets/vm_config_no_task.json b/tests/testapk/assets/vm_config_no_task.json
new file mode 100644
index 0000000..b71140e
--- /dev/null
+++ b/tests/testapk/assets/vm_config_no_task.json
@@ -0,0 +1,3 @@
+{
+  "export_tombstones": true
+}
diff --git a/tests/testapk/assets/microdroid/vm_config_no_tombstone.json b/tests/testapk/assets/vm_config_no_tombstone.json
similarity index 76%
rename from tests/testapk/assets/microdroid/vm_config_no_tombstone.json
rename to tests/testapk/assets/vm_config_no_tombstone.json
index 97e764d..a07ec89 100644
--- a/tests/testapk/assets/microdroid/vm_config_no_tombstone.json
+++ b/tests/testapk/assets/vm_config_no_tombstone.json
@@ -1,7 +1,4 @@
 {
-  "os": {
-    "name": "microdroid"
-  },
   "task": {
     "type": "microdroid_launcher",
     "command": "MicrodroidTestNativeLib.so"
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 51aace4..efacf8f 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -469,7 +469,7 @@
         assertThat(minimal.isEncryptedStorageEnabled()).isFalse();
         assertThat(minimal.getEncryptedStorageBytes()).isEqualTo(0);
         assertThat(minimal.isVmOutputCaptured()).isEqualTo(false);
-        assertThat(minimal.getOs()).isNull();
+        assertThat(minimal.getOs()).isEqualTo("microdroid");
 
         // Maximal has everything that can be set to some non-default value. (And has different
         // values than minimal for the required fields.)
@@ -484,7 +484,8 @@
                         .setMemoryBytes(42)
                         .setCpuTopology(CPU_TOPOLOGY_MATCH_HOST)
                         .setEncryptedStorageBytes(1_000_000)
-                        .setVmOutputCaptured(true);
+                        .setVmOutputCaptured(true)
+                        .setOs("microdroid_gki-android14-6.1");
         VirtualMachineConfig maximal = maximalBuilder.build();
 
         assertThat(maximal.getApkPath()).isEqualTo("/apk/path");
@@ -500,16 +501,11 @@
         assertThat(maximal.isEncryptedStorageEnabled()).isTrue();
         assertThat(maximal.getEncryptedStorageBytes()).isEqualTo(1_000_000);
         assertThat(maximal.isVmOutputCaptured()).isEqualTo(true);
-        assertThat(maximal.getOs()).isEqualTo("microdroid");
+        assertThat(maximal.getOs()).isEqualTo("microdroid_gki-android14-6.1");
 
         assertThat(minimal.isCompatibleWith(maximal)).isFalse();
         assertThat(minimal.isCompatibleWith(minimal)).isTrue();
         assertThat(maximal.isCompatibleWith(maximal)).isTrue();
-
-        VirtualMachineConfig os = maximalBuilder.setOs("microdroid_gki-android14-6.1").build();
-        assertThat(os.getPayloadBinaryName()).isEqualTo("binary.so");
-        assertThat(os.getOs()).isEqualTo("microdroid_gki-android14-6.1");
-        assertThat(os.isCompatibleWith(maximal)).isFalse();
     }
 
     @Test
@@ -560,16 +556,6 @@
                         .setVmConsoleInputSupported(true);
         e = assertThrows(IllegalStateException.class, () -> captureInputOnNonDebuggable.build());
         assertThat(e).hasMessageThat().contains("debug level must be FULL to use console input");
-
-        VirtualMachineConfig.Builder specifyBothOsAndConfig =
-                new VirtualMachineConfig.Builder(getContext())
-                        .setPayloadConfigPath("config/path")
-                        .setProtectedVm(mProtectedVm)
-                        .setOs("microdroid");
-        e = assertThrows(IllegalStateException.class, () -> specifyBothOsAndConfig.build());
-        assertThat(e)
-                .hasMessageThat()
-                .contains("setPayloadConfigPath and setOs may not both be called");
     }
 
     @Test
@@ -787,7 +773,7 @@
         revokePermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
 
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config.json")
                         .setMemoryBytes(minMemoryRequired())
                         .build();
 
@@ -905,7 +891,7 @@
 
         grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config_extra_apk.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config_extra_apk.json")
                         .setMemoryBytes(minMemoryRequired())
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .build();
@@ -1077,7 +1063,7 @@
 
         grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
         VirtualMachineConfig normalConfig =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config.json")
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .build();
         forceCreateNewVirtualMachine("test_vm_a", normalConfig);
@@ -1103,7 +1089,7 @@
 
         grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
         VirtualMachineConfig normalConfig =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config.json")
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .build();
         forceCreateNewVirtualMachine("test_vm", normalConfig);
@@ -1123,7 +1109,7 @@
 
         grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
         VirtualMachineConfig normalConfig =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config.json")
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .build();
         VirtualMachine vm = forceCreateNewVirtualMachine("bcc_vm", normalConfig);
@@ -1266,7 +1252,7 @@
     public void bootFailsWhenConfigIsInvalid() throws Exception {
         grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config_no_task.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config_no_task.json")
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .build();
 
@@ -1391,7 +1377,7 @@
         // Arrange
         grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
         VirtualMachineConfig config =
-                newVmConfigBuilderWithPayloadConfig("assets/" + os() + "/vm_config.json")
+                newVmConfigBuilderWithPayloadConfig("assets/vm_config.json")
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .build();
         String vmNameOrig = "test_vm_orig";
@@ -1680,9 +1666,7 @@
         assumeSupportedDevice();
 
         final VirtualMachineConfig vmConfig =
-                new VirtualMachineConfig.Builder(getContext())
-                        .setProtectedVm(mProtectedVm)
-                        .setPayloadBinaryName("MicrodroidTestNativeLib.so")
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .setVmConsoleInputSupported(true) // even if console input is supported
                         .build();
@@ -1704,9 +1688,7 @@
         assumeSupportedDevice();
 
         final VirtualMachineConfig vmConfig =
-                new VirtualMachineConfig.Builder(getContext())
-                        .setProtectedVm(mProtectedVm)
-                        .setPayloadBinaryName("MicrodroidTestNativeLib.so")
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .setVmOutputCaptured(true) // even if output is captured
                         .build();
@@ -1730,6 +1712,7 @@
                         .setPayloadBinaryName("MicrodroidTestNativeLib.so")
                         .setDebugLevel(debuggable ? DEBUG_LEVEL_FULL : DEBUG_LEVEL_NONE)
                         .setVmOutputCaptured(false)
+                        .setOs(os())
                         .build();
         final VirtualMachine vm = forceCreateNewVirtualMachine("test_vm_logcat", vmConfig);
 
@@ -1824,6 +1807,7 @@
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .setProtectedVm(isProtectedVm())
                         .setPayloadBinaryName("MicrodroidPayloadInOtherAppNativeLib.so")
+                        .setOs(os())
                         .build();
 
         try (VirtualMachine vm = forceCreateNewVirtualMachine("vm_from_another_app", config)) {
@@ -1938,6 +1922,7 @@
                         .setDebugLevel(DEBUG_LEVEL_FULL)
                         .setProtectedVm(isProtectedVm())
                         .setPayloadBinaryName("MicrodroidPayloadInOtherAppNativeLib.so")
+                        .setOs(os())
                         .build();
 
         VirtualMachine vm = forceCreateNewVirtualMachine("vm_to_share", config);
@@ -1987,6 +1972,7 @@
                         .setProtectedVm(isProtectedVm())
                         .setEncryptedStorageBytes(3_000_000)
                         .setPayloadBinaryName("MicrodroidPayloadInOtherAppNativeLib.so")
+                        .setOs(os())
                         .build();
 
         VirtualMachine vm = forceCreateNewVirtualMachine("vm_to_share", config);
diff --git a/tests/vmshareapp/AndroidManifest.xml b/tests/vmshareapp/AndroidManifest.xml
index b623f7f..9626599 100644
--- a/tests/vmshareapp/AndroidManifest.xml
+++ b/tests/vmshareapp/AndroidManifest.xml
@@ -16,6 +16,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.microdroid.vmshare_app">
     <uses-permission android:name="android.permission.MANAGE_VIRTUAL_MACHINE" />
+    <uses-permission android:name="android.permission.USE_CUSTOM_VIRTUAL_MACHINE" />
 
     <uses-feature android:name="android.software.virtualization_framework"
                   android:required="false" />
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 6be219e..ea05bdb 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -70,7 +70,7 @@
 use glob::glob;
 use lazy_static::lazy_static;
 use log::{debug, error, info, warn};
-use microdroid_payload_config::{ApkConfig, OsConfig, Task, TaskType, VmPayloadConfig};
+use microdroid_payload_config::{ApkConfig, Task, TaskType, VmPayloadConfig};
 use nix::unistd::pipe;
 use rpcbinder::RpcServer;
 use rustutils::system_properties;
@@ -622,13 +622,10 @@
                 // - specifying a config file;
                 // - specifying extra APKs;
                 // - specifying an OS other than Microdroid.
-                match &config.payload {
+                (match &config.payload {
                     Payload::ConfigPath(_) => true,
-                    Payload::PayloadConfig(payload_config) => {
-                        !payload_config.extraApks.is_empty()
-                            || payload_config.osName != MICRODROID_OS_NAME
-                    }
-                }
+                    Payload::PayloadConfig(payload_config) => !payload_config.extraApks.is_empty(),
+                }) || config.osName != MICRODROID_OS_NAME
             }
         }
     }
@@ -813,8 +810,13 @@
         }
     };
 
+    let payload_config_os = vm_payload_config.os.name.as_str();
+    if !payload_config_os.is_empty() && payload_config_os != "microdroid" {
+        bail!("'os' in payload config is deprecated");
+    }
+
     // For now, the only supported OS is Microdroid and Microdroid GKI
-    let os_name = vm_payload_config.os.name.as_str();
+    let os_name = config.osName.as_str();
     if !is_valid_os(os_name) {
         bail!("Unknown OS \"{}\"", os_name);
     }
@@ -916,22 +918,13 @@
     }
 
     let task = Task { type_: TaskType::MicrodroidLauncher, command: payload_binary_name.clone() };
-    let name = payload_config.osName.clone();
 
     // The VM only cares about how many there are, these names are actually ignored.
     let extra_apk_count = payload_config.extraApks.len();
     let extra_apks =
         (0..extra_apk_count).map(|i| ApkConfig { path: format!("extra-apk-{i}") }).collect();
 
-    Ok(VmPayloadConfig {
-        os: OsConfig { name },
-        task: Some(task),
-        apexes: vec![],
-        extra_apks,
-        prefer_staged: false,
-        export_tombstones: None,
-        enable_authfs: false,
-    })
+    Ok(VmPayloadConfig { task: Some(task), extra_apks, ..Default::default() })
 }
 
 /// Generates a unique filename to use for a composite disk image.
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index 29232ff..890535b 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -62,6 +62,15 @@
     /** Detailed configuration for the VM, specifying how the payload will be run. */
     Payload payload;
 
+    /**
+     * Name of the OS to run the payload. Currently "microdroid" and
+     * "microdroid_gki-android14-6.1" is supported.
+     *
+     * <p>Setting this field to a value other than "microdroid" requires
+     * android.permission.USE_CUSTOM_VIRTUAL_MACHINE
+     */
+    @utf8InCpp String osName = "microdroid";
+
     enum DebugLevel {
         /** Not debuggable at all */
         NONE,
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
index 7ca5b62..efd363c 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
@@ -24,11 +24,6 @@
      */
     @utf8InCpp String payloadBinaryName;
 
-    /**
-     * Name of the OS to run the payload. Currently "microdroid" and "microdroid_gki" is supported.
-     */
-    @utf8InCpp String osName = "microdroid";
-
     /** Any extra APKs. */
     List<ParcelFileDescriptor> extraApks;
 }
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 57b7641..07e0276 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -127,29 +127,25 @@
         if config.payload_binary_name.is_some() {
             bail!("Only one of --config-path or --payload-binary-name can be defined")
         }
-        if config.microdroid.gki().is_some() {
-            bail!("--gki cannot be defined with --config-path. Use 'os' field in the config file")
-        }
         Payload::ConfigPath(config_path)
     } else if let Some(payload_binary_name) = config.payload_binary_name {
-        let os_name = if let Some(ver) = config.microdroid.gki() {
-            format!("microdroid_gki-{ver}")
-        } else {
-            "microdroid".to_owned()
-        };
-
         let extra_apk_files: Result<Vec<_>, _> = extra_apks.iter().map(File::open).collect();
         let extra_apk_fds = extra_apk_files?.into_iter().map(ParcelFileDescriptor::new).collect();
 
         Payload::PayloadConfig(VirtualMachinePayloadConfig {
             payloadBinaryName: payload_binary_name,
-            osName: os_name,
             extraApks: extra_apk_fds,
         })
     } else {
         bail!("Either --config-path or --payload-binary-name must be defined")
     };
 
+    let os_name = if let Some(ver) = config.microdroid.gki() {
+        format!("microdroid_gki-{ver}")
+    } else {
+        "microdroid".to_owned()
+    };
+
     let payload_config_str = format!("{:?}!{:?}", config.apk, payload);
 
     let custom_config = CustomConfig {
@@ -180,6 +176,7 @@
         memoryMib: config.common.mem.unwrap_or(0) as i32, // 0 means use the VM default
         cpuTopology: config.common.cpu_topology,
         customConfig: Some(custom_config),
+        osName: os_name,
     });
     run(
         service.as_ref(),