Add option to use GKI kernel for microdroid

With either payload config's osName field or config file's os field, a
GKI kernel can be used to run microdroid instead of microdroid kernel.
This also adds a new option --gki to the VM tool.

Bug: 305118971
Test: run VM with --gki
Change-Id: I87eb445c84bd208df549712aea7f55ab148c7f8a
diff --git a/apex/Android.bp b/apex/Android.bp
index 96540aa..e04dbd2 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -146,6 +146,7 @@
                 "microdroid_gki_initrd_debuggable",
                 "microdroid_gki_initrd_normal",
                 "microdroid_gki_kernel",
+                "microdroid_gki.json",
             ],
         },
     },
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index a1ce594..23eadcf 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -416,6 +416,11 @@
 }
 
 prebuilt_etc {
+    name: "microdroid_gki.json",
+    src: "microdroid_gki.json",
+}
+
+prebuilt_etc {
     name: "microdroid_manifest",
     src: "microdroid_manifest.xml",
     filename: "manifest.xml",
diff --git a/microdroid/microdroid_gki.json b/microdroid/microdroid_gki.json
new file mode 100644
index 0000000..d7ba53e
--- /dev/null
+++ b/microdroid/microdroid_gki.json
@@ -0,0 +1,20 @@
+{
+  "kernel": "/apex/com.android.virt/etc/fs/microdroid_gki_kernel",
+  "disks": [
+    {
+      "partitions": [
+        {
+          "label": "vbmeta_a",
+          "path": "/apex/com.android.virt/etc/fs/microdroid_vbmeta.img"
+        },
+        {
+          "label": "super",
+          "path": "/apex/com.android.virt/etc/fs/microdroid_super.img"
+        }
+      ],
+      "writable": false
+    }
+  ],
+  "memory_mib": 256,
+  "platform_version": "~1.0"
+}
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 19768b5..24e5ed6 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -101,6 +101,8 @@
 
 const MICRODROID_OS_NAME: &str = "microdroid";
 
+const MICRODROID_GKI_OS_NAME: &str = "microdroid_gki";
+
 const UNFORMATTED_STORAGE_MAGIC: &str = "UNFORMATTED-STORAGE";
 
 /// Roughly estimated sufficient size for storing vendor public key into DTBO.
@@ -694,6 +696,16 @@
     }
 }
 
+fn is_valid_os(os_name: &str) -> bool {
+    if os_name == MICRODROID_OS_NAME {
+        return true;
+    }
+    if cfg!(vendor_modules) && os_name == MICRODROID_GKI_OS_NAME {
+        return true;
+    }
+    false
+}
+
 fn load_app_config(
     config: &VirtualMachineAppConfig,
     debug_config: &DebugConfig,
@@ -717,9 +729,9 @@
         Payload::PayloadConfig(payload_config) => create_vm_payload_config(payload_config)?,
     };
 
-    // For now, the only supported OS is Microdroid
+    // For now, the only supported OS is Microdroid and Microdroid GKI
     let os_name = vm_payload_config.os.name.as_str();
-    if os_name != MICRODROID_OS_NAME {
+    if !is_valid_os(os_name) {
         bail!("Unknown OS \"{}\"", os_name);
     }
 
@@ -753,7 +765,7 @@
     vm_config.cpuTopology = config.cpuTopology;
 
     // Microdroid takes additional init ramdisk & (optionally) storage image
-    add_microdroid_system_images(config, instance_file, storage_image, &mut vm_config)?;
+    add_microdroid_system_images(config, instance_file, storage_image, os_name, &mut vm_config)?;
 
     // Include Microdroid payload disk (contains apks, idsigs) in vm config
     add_microdroid_payload_images(
@@ -788,8 +800,9 @@
     }
 
     let task = Task { type_: TaskType::MicrodroidLauncher, command: payload_binary_name.clone() };
+    let name = payload_config.osName.clone();
     Ok(VmPayloadConfig {
-        os: OsConfig { name: MICRODROID_OS_NAME.to_owned() },
+        os: OsConfig { name },
         task: Some(task),
         apexes: vec![],
         extra_apks: vec![],
diff --git a/virtualizationmanager/src/payload.rs b/virtualizationmanager/src/payload.rs
index 3bfad33..c19c103 100644
--- a/virtualizationmanager/src/payload.rs
+++ b/virtualizationmanager/src/payload.rs
@@ -425,6 +425,7 @@
     config: &VirtualMachineAppConfig,
     instance_file: File,
     storage_image: Option<File>,
+    os_name: &str,
     vm_config: &mut VirtualMachineRawConfig,
 ) -> Result<()> {
     let debug_suffix = match config.debugLevel {
@@ -432,7 +433,7 @@
         DebugLevel::FULL => "debuggable",
         _ => return Err(anyhow!("unsupported debug level: {:?}", config.debugLevel)),
     };
-    let initrd = format!("/apex/com.android.virt/etc/microdroid_initrd_{}.img", debug_suffix);
+    let initrd = format!("/apex/com.android.virt/etc/{os_name}_initrd_{debug_suffix}.img");
     vm_config.initrd = Some(open_parcel_file(Path::new(&initrd), false)?);
 
     let mut writable_partitions = vec![Partition {
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
index 55c2f5d..f3f54f3 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
@@ -23,4 +23,9 @@
      * function invoked.
      */
     @utf8InCpp String payloadBinaryName;
+
+    /**
+     * Name of the OS to run the payload. Currently "microdroid" and "microdroid_gki" is supported.
+     */
+    @utf8InCpp String osName = "microdroid";
 }
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 14db27c..87278bc 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -97,11 +97,6 @@
     #[arg(long)]
     storage_size: Option<u64>,
 
-    /// Path to custom kernel image to use when booting Microdroid.
-    #[cfg(vendor_modules)]
-    #[arg(long)]
-    kernel: Option<PathBuf>,
-
     /// Path to disk image containing vendor-specific modules.
     #[cfg(vendor_modules)]
     #[arg(long)]
@@ -111,20 +106,15 @@
     #[cfg(device_assignment)]
     #[arg(long)]
     devices: Vec<PathBuf>,
+
+    /// If set, use GKI instead of microdroid kernel
+    #[cfg(vendor_modules)]
+    #[arg(long)]
+    gki: bool,
 }
 
 impl MicrodroidConfig {
     #[cfg(vendor_modules)]
-    fn kernel(&self) -> &Option<PathBuf> {
-        &self.kernel
-    }
-
-    #[cfg(not(vendor_modules))]
-    fn kernel(&self) -> Option<PathBuf> {
-        None
-    }
-
-    #[cfg(vendor_modules)]
     fn vendor(&self) -> &Option<PathBuf> {
         &self.vendor
     }
@@ -134,6 +124,16 @@
         None
     }
 
+    #[cfg(vendor_modules)]
+    fn gki(&self) -> bool {
+        self.gki
+    }
+
+    #[cfg(not(vendor_modules))]
+    fn gki(&self) -> bool {
+        false
+    }
+
     #[cfg(device_assignment)]
     fn devices(&self) -> &Vec<PathBuf> {
         &self.devices
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 84c3af6..44ba9af 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -98,9 +98,6 @@
         None
     };
 
-    let kernel =
-        config.microdroid.kernel().as_ref().map(|p| open_parcel_file(p, false)).transpose()?;
-
     let vendor =
         config.microdroid.vendor().as_ref().map(|p| open_parcel_file(p, false)).transpose()?;
 
@@ -114,8 +111,11 @@
         }
         Payload::ConfigPath(config_path)
     } else if let Some(payload_binary_name) = config.payload_binary_name {
+        let os_name =
+            if config.microdroid.gki() { "microdroid_gki" } else { "microdroid" }.to_owned();
         Payload::PayloadConfig(VirtualMachinePayloadConfig {
             payloadBinaryName: payload_binary_name,
+            osName: os_name,
         })
     } else {
         bail!("Either --config-path or --payload-binary-name must be defined")
@@ -124,7 +124,7 @@
     let payload_config_str = format!("{:?}!{:?}", config.apk, payload);
 
     let custom_config = CustomConfig {
-        customKernelImage: kernel,
+        customKernelImage: None,
         gdbPort: config.debug.gdb.map(u16::from).unwrap_or(0) as i32, // 0 means no gdb
         taskProfiles: config.common.task_profiles,
         vendorImage: vendor,