Add display config for CustomImageConfig

For now, display config include display size info and refresh rate

Bug: 331708504
Test: check if the screen shows
Change-Id: I0f41822c756b56d17efa6150f0c3ec28628371d4
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index b8c6315..d65df34 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -17,7 +17,7 @@
 use crate::{get_calling_pid, get_calling_uid};
 use crate::atom::{write_vm_booted_stats, write_vm_creation_stats};
 use crate::composite::make_composite_image;
-use crate::crosvm::{CrosvmConfig, DiskFile, PayloadState, VmContext, VmInstance, VmState};
+use crate::crosvm::{CrosvmConfig, DiskFile, DisplayConfig, PayloadState, VmContext, VmInstance, VmState};
 use crate::debug_config::DebugConfig;
 use crate::dt_overlay::{create_device_tree_overlay, VM_DT_OVERLAY_MAX_SIZE, VM_DT_OVERLAY_PATH};
 use crate::payload::{add_microdroid_payload_images, add_microdroid_system_images, add_microdroid_vendor_image};
@@ -571,6 +571,13 @@
             (vec![], None)
         };
 
+        let display_config = config
+            .displayConfig
+            .as_ref()
+            .map(DisplayConfig::new)
+            .transpose()
+            .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT)?;
+
         // Actually start the VM.
         let crosvm_config = CrosvmConfig {
             cid,
@@ -596,6 +603,7 @@
             vfio_devices,
             dtbo,
             device_tree_overlay,
+            display_config,
         };
         let instance = Arc::new(
             VmInstance::new(
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index 97a27e0..d5e2e67 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -44,7 +44,8 @@
 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason;
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
     MemoryTrimLevel::MemoryTrimLevel,
-    VirtualMachineAppConfig::DebugLevel::DebugLevel
+    VirtualMachineAppConfig::DebugLevel::DebugLevel,
+    DisplayConfig::DisplayConfig as DisplayConfigParcelable,
 };
 use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::IGlobalVmContext::IGlobalVmContext;
 use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::IBoundDevice::IBoundDevice;
@@ -118,6 +119,32 @@
     pub vfio_devices: Vec<VfioDevice>,
     pub dtbo: Option<File>,
     pub device_tree_overlay: Option<File>,
+    pub display_config: Option<DisplayConfig>,
+}
+
+#[derive(Debug)]
+pub struct DisplayConfig {
+    pub width: NonZeroU32,
+    pub height: NonZeroU32,
+    pub horizontal_dpi: NonZeroU32,
+    pub vertical_dpi: NonZeroU32,
+    pub refresh_rate: NonZeroU32,
+}
+
+impl DisplayConfig {
+    pub fn new(raw_config: &DisplayConfigParcelable) -> Result<DisplayConfig> {
+        let width = try_into_non_zero_u32(raw_config.width)?;
+        let height = try_into_non_zero_u32(raw_config.height)?;
+        let horizontal_dpi = try_into_non_zero_u32(raw_config.horizontalDpi)?;
+        let vertical_dpi = try_into_non_zero_u32(raw_config.verticalDpi)?;
+        let refresh_rate = try_into_non_zero_u32(raw_config.refreshRate)?;
+        Ok(DisplayConfig { width, height, horizontal_dpi, vertical_dpi, refresh_rate })
+    }
+}
+
+fn try_into_non_zero_u32(value: i32) -> Result<NonZeroU32> {
+    let u32_value = value.try_into()?;
+    NonZeroU32::new(u32_value).ok_or(anyhow!("value should be greater than 0"))
 }
 
 /// A disk image to pass to crosvm for a VM.
@@ -927,6 +954,13 @@
     if let Some(dt_overlay) = &config.device_tree_overlay {
         command.arg("--device-tree-overlay").arg(add_preserved_fd(&mut preserved_fds, dt_overlay));
     }
+    if let Some(display_config) = &config.display_config {
+        command.arg("--gpu")
+        // TODO(b/331708504): support backend config as well
+        .arg("backend=virglrenderer,context-types=virgl2,egl=true,surfaceless=true,glx=false,gles=true")
+        .arg(format!("--gpu-display=mode=windowed[{},{}],dpi=[{},{}],refresh-rate={}", display_config.width, display_config.height, display_config.horizontal_dpi, display_config.vertical_dpi, display_config.refresh_rate))
+        .arg(format!("--android-display-service={}", config.name));
+    }
 
     append_platform_devices(&mut command, &mut preserved_fds, &config)?;