Add InputDevice in VirtualMachineRawConfig
Starts with single touch, evdev.
Bug: 331191129
Test: build
Change-Id: I68639dec230f2979e145e261d8584813ee1645d7
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
index a8f318c..d267763 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -40,6 +40,7 @@
import android.sysprop.HypervisorProperties;
import android.system.virtualizationservice.DiskImage;
import android.system.virtualizationservice.Partition;
+import android.system.virtualizationservice.InputDevice;
import android.system.virtualizationservice.VirtualMachineAppConfig;
import android.system.virtualizationservice.VirtualMachinePayloadConfig;
import android.system.virtualizationservice.VirtualMachineRawConfig;
@@ -650,6 +651,7 @@
config.cpuTopology = (byte) this.mCpuTopology;
config.devices = EMPTY_STRING_ARRAY;
config.platformVersion = "~1.0";
+ config.inputDevices = new InputDevice[0];
return config;
}
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index fa43faf..1f3fb4a 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, DisplayConfig, PayloadState, VmContext, VmInstance, VmState};
+use crate::crosvm::{CrosvmConfig, DiskFile, DisplayConfig, InputDeviceOption, 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};
@@ -32,6 +32,7 @@
AssignableDevice::AssignableDevice,
CpuTopology::CpuTopology,
DiskImage::DiskImage,
+ InputDevice::InputDevice,
IVirtualMachine::{BnVirtualMachine, IVirtualMachine},
IVirtualMachineCallback::IVirtualMachineCallback,
IVirtualizationService::IVirtualizationService,
@@ -592,6 +593,17 @@
None
};
+ let input_device_options = if cfg!(paravirtualized_devices) {
+ config
+ .inputDevices
+ .iter()
+ .map(to_input_device_option_from)
+ .collect::<Result<Vec<InputDeviceOption>, _>>()
+ .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT)?
+ } else {
+ vec![]
+ };
+
// Actually start the VM.
let crosvm_config = CrosvmConfig {
cid,
@@ -618,6 +630,7 @@
dtbo,
device_tree_overlay,
display_config,
+ input_device_options,
};
let instance = Arc::new(
VmInstance::new(
@@ -723,6 +736,23 @@
(result / granularity) * granularity
}
+fn to_input_device_option_from(input_device: &InputDevice) -> Result<InputDeviceOption> {
+ Ok(match input_device {
+ InputDevice::SingleTouch(single_touch) => InputDeviceOption::SingleTouch {
+ file: clone_file(single_touch.pfd.as_ref().ok_or(anyhow!("pfd should have value"))?)?,
+ height: u32::try_from(single_touch.height)?,
+ width: u32::try_from(single_touch.width)?,
+ name: if !single_touch.name.is_empty() {
+ Some(single_touch.name.clone())
+ } else {
+ None
+ },
+ },
+ InputDevice::EvDev(evdev) => InputDeviceOption::EvDev(clone_file(
+ evdev.pfd.as_ref().ok_or(anyhow!("pfd should have value"))?,
+ )?),
+ })
+}
/// Given the configuration for a disk image, assembles the `DiskFile` to pass to crosvm.
///
/// This may involve assembling a composite disk from a set of partition images.
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index 99ad65e..2e4c517 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -120,6 +120,7 @@
pub dtbo: Option<File>,
pub device_tree_overlay: Option<File>,
pub display_config: Option<DisplayConfig>,
+ pub input_device_options: Vec<InputDeviceOption>,
}
#[derive(Debug)]
@@ -154,6 +155,14 @@
pub writable: bool,
}
+/// virtio-input device configuration from `external/crosvm/src/crosvm/config.rs`
+#[derive(Debug)]
+#[allow(dead_code)]
+pub enum InputDeviceOption {
+ EvDev(File),
+ SingleTouch { file: File, width: u32, height: u32, name: Option<String> },
+}
+
type VfioDevice = Strong<dyn IBoundDevice>;
/// The lifecycle state which the payload in the VM has reported itself to be in.
@@ -966,6 +975,23 @@
}
}
+ if cfg!(paravirtualized_devices) {
+ for input_device_option in config.input_device_options.iter() {
+ command.arg("--input");
+ command.arg(match input_device_option {
+ InputDeviceOption::EvDev(file) => {
+ format!("evdev[path={}]", add_preserved_fd(&mut preserved_fds, file))
+ }
+ InputDeviceOption::SingleTouch { file, width, height, name } => format!(
+ "single-touch[path={},width={},height={}{}]",
+ add_preserved_fd(&mut preserved_fds, file),
+ width,
+ height,
+ name.as_ref().map_or("".into(), |n| format!(",name={}", n))
+ ),
+ });
+ }
+ }
append_platform_devices(&mut command, &mut preserved_fds, &config)?;
debug!("Preserving FDs {:?}", preserved_fds);
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/InputDevice.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/InputDevice.aidl
new file mode 100644
index 0000000..fe12291
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/InputDevice.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.system.virtualizationservice;
+
+// Refer to https://crosvm.dev/book/devices/input.html
+union InputDevice {
+ // Add a single-touch touchscreen virtio-input device.
+ parcelable SingleTouch {
+ ParcelFileDescriptor pfd;
+ // Default values come from https://crosvm.dev/book/devices/input.html#single-touch
+ int width = 1280;
+ int height = 1080;
+ @utf8InCpp String name = "";
+ }
+ // Passes an event device node into the VM. The device will be grabbed (unusable from the host)
+ // and made available to the guest with the same configuration it shows on the host.
+ parcelable EvDev {
+ ParcelFileDescriptor pfd;
+ }
+
+ SingleTouch singleTouch;
+ EvDev evDev;
+}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
index 1a18bf8..86e26da 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
@@ -18,6 +18,7 @@
import android.system.virtualizationservice.CpuTopology;
import android.system.virtualizationservice.DiskImage;
import android.system.virtualizationservice.DisplayConfig;
+import android.system.virtualizationservice.InputDevice;
/** Raw configuration for running a VM. */
parcelable VirtualMachineRawConfig {
@@ -73,4 +74,7 @@
String[] devices;
@nullable DisplayConfig displayConfig;
+
+ /** List of input devices to the VM */
+ InputDevice[] inputDevices;
}