Add option to disable usb for AVF
Bug: 356447468
Test: boot microdroid, suspend/snapshot/resume, validate no usb.
Change-Id: Ica93d74774f0aa0bd4c80bd0da166d7d3c62e745
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index fb3d353..0acf4be 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -17,7 +17,7 @@
use crate::{get_calling_pid, get_calling_uid, get_this_pid};
use crate::atom::{write_vm_booted_stats, write_vm_creation_stats};
use crate::composite::make_composite_image;
-use crate::crosvm::{AudioConfig, CrosvmConfig, DiskFile, DisplayConfig, GpuConfig, InputDeviceOption, PayloadState, VmContext, VmInstance, VmState};
+use crate::crosvm::{AudioConfig, CrosvmConfig, DiskFile, DisplayConfig, GpuConfig, InputDeviceOption, PayloadState, UsbConfig, 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};
@@ -584,6 +584,13 @@
None
};
+ let usb_config = config
+ .usbConfig
+ .as_ref()
+ .map(UsbConfig::new)
+ .unwrap_or(Ok(UsbConfig { controller: false }))
+ .or_binder_exception(ExceptionCode::BAD_PARCELABLE)?;
+
// Actually start the VM.
let crosvm_config = CrosvmConfig {
cid,
@@ -623,6 +630,7 @@
gpu_config,
audio_config,
no_balloon: config.noBalloon,
+ usb_config,
};
let instance = Arc::new(
VmInstance::new(
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 9d688a2..5886535 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -47,6 +47,7 @@
AudioConfig::AudioConfig as AudioConfigParcelable,
DisplayConfig::DisplayConfig as DisplayConfigParcelable,
GpuConfig::GpuConfig as GpuConfigParcelable,
+ UsbConfig::UsbConfig as UsbConfigParcelable,
};
use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::IGlobalVmContext::IGlobalVmContext;
use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::IBoundDevice::IBoundDevice;
@@ -134,6 +135,7 @@
pub gpu_config: Option<GpuConfig>,
pub audio_config: Option<AudioConfig>,
pub no_balloon: bool,
+ pub usb_config: UsbConfig,
}
#[derive(Debug)]
@@ -149,6 +151,17 @@
}
#[derive(Debug)]
+pub struct UsbConfig {
+ pub controller: bool,
+}
+
+impl UsbConfig {
+ pub fn new(raw_config: &UsbConfigParcelable) -> Result<UsbConfig> {
+ Ok(UsbConfig { controller: raw_config.controller })
+ }
+}
+
+#[derive(Debug)]
pub struct DisplayConfig {
pub width: NonZeroU32,
pub height: NonZeroU32,
@@ -900,6 +913,10 @@
command.arg("--no-balloon");
}
+ if !config.usb_config.controller {
+ command.arg("--no-usb");
+ }
+
let mut memory_mib = config.memory_mib;
if config.protected {
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/UsbConfig.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/UsbConfig.aidl
new file mode 100644
index 0000000..1889d2c
--- /dev/null
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/UsbConfig.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+parcelable UsbConfig {
+ /** Enable the USB controller */
+ boolean controller;
+}
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
index 4ac401d..f559a71 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
@@ -21,6 +21,7 @@
import android.system.virtualizationservice.DisplayConfig;
import android.system.virtualizationservice.GpuConfig;
import android.system.virtualizationservice.InputDevice;
+import android.system.virtualizationservice.UsbConfig;
/** Raw configuration for running a VM. */
parcelable VirtualMachineRawConfig {
@@ -102,4 +103,7 @@
@nullable AudioConfig audioConfig;
boolean noBalloon;
+
+ /** Enable or disable USB passthrough support */
+ @nullable UsbConfig usbConfig;
}
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
index 644a85a..cb21ccf 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/libs/framework-virtualization/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.UsbConfig;
import android.system.virtualizationservice.VirtualMachineAppConfig;
import android.system.virtualizationservice.VirtualMachinePayloadConfig;
import android.system.virtualizationservice.VirtualMachineRawConfig;
@@ -725,6 +726,15 @@
.map(ac -> ac.toParcelable())
.orElse(null);
config.noBalloon = !customImageConfig.useAutoMemoryBalloon();
+ config.usbConfig =
+ Optional.ofNullable(customImageConfig.getUsbConfig())
+ .map(
+ uc -> {
+ UsbConfig usbConfig = new UsbConfig();
+ usbConfig.controller = uc.getUsbController();
+ return usbConfig;
+ })
+ .orElse(null);
return config;
}
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
index a38ee7f..9774585 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
@@ -46,6 +46,7 @@
private static final String KEY_AUDIO_CONFIG = "audio_config";
private static final String KEY_TRACKPAD = "trackpad";
private static final String KEY_AUTO_MEMORY_BALLOON = "auto_memory_balloon";
+ private static final String KEY_USB_CONFIG = "usb_config";
@Nullable private final String name;
@Nullable private final String kernelPath;
@@ -63,6 +64,7 @@
@Nullable private final GpuConfig gpuConfig;
private final boolean trackpad;
private final boolean autoMemoryBalloon;
+ @Nullable private final UsbConfig usbConfig;
@Nullable
public Disk[] getDisks() {
@@ -139,7 +141,8 @@
GpuConfig gpuConfig,
AudioConfig audioConfig,
boolean trackpad,
- boolean autoMemoryBalloon) {
+ boolean autoMemoryBalloon,
+ UsbConfig usbConfig) {
this.name = name;
this.kernelPath = kernelPath;
this.initrdPath = initrdPath;
@@ -156,6 +159,7 @@
this.audioConfig = audioConfig;
this.trackpad = trackpad;
this.autoMemoryBalloon = autoMemoryBalloon;
+ this.usbConfig = usbConfig;
}
static VirtualMachineCustomImageConfig from(PersistableBundle customImageConfigBundle) {
@@ -208,6 +212,9 @@
builder.setAudioConfig(AudioConfig.from(audioConfigPb));
builder.useTrackpad(customImageConfigBundle.getBoolean(KEY_TRACKPAD));
builder.useAutoMemoryBalloon(customImageConfigBundle.getBoolean(KEY_AUTO_MEMORY_BALLOON));
+ PersistableBundle usbConfigPb =
+ customImageConfigBundle.getPersistableBundle(KEY_USB_CONFIG);
+ builder.setUsbConfig(UsbConfig.from(usbConfigPb));
return builder.build();
}
@@ -266,6 +273,9 @@
Optional.ofNullable(audioConfig).map(ac -> ac.toPersistableBundle()).orElse(null));
pb.putBoolean(KEY_TRACKPAD, trackpad);
pb.putBoolean(KEY_AUTO_MEMORY_BALLOON, autoMemoryBalloon);
+ pb.putPersistableBundle(
+ KEY_USB_CONFIG,
+ Optional.ofNullable(usbConfig).map(uc -> uc.toPersistableBundle()).orElse(null));
return pb;
}
@@ -284,6 +294,11 @@
return gpuConfig;
}
+ @Nullable
+ public UsbConfig getUsbConfig() {
+ return usbConfig;
+ }
+
/** @hide */
public static final class Disk {
private final boolean writable;
@@ -362,6 +377,7 @@
private boolean trackpad;
// TODO(b/363985291): balloon breaks Linux VM behavior
private boolean autoMemoryBalloon = false;
+ private UsbConfig usbConfig;
/** @hide */
public Builder() {}
@@ -463,6 +479,12 @@
}
/** @hide */
+ public Builder setUsbConfig(UsbConfig usbConfig) {
+ this.usbConfig = usbConfig;
+ return this;
+ }
+
+ /** @hide */
public VirtualMachineCustomImageConfig build() {
return new VirtualMachineCustomImageConfig(
this.name,
@@ -480,7 +502,63 @@
gpuConfig,
audioConfig,
trackpad,
- autoMemoryBalloon);
+ autoMemoryBalloon,
+ usbConfig);
+ }
+ }
+
+ /** @hide */
+ public static final class UsbConfig {
+ private static final String KEY_USE_CONTROLLER = "use_controller";
+ public final boolean controller;
+
+ public UsbConfig(boolean controller) {
+ this.controller = controller;
+ }
+
+ public boolean getUsbController() {
+ return this.controller;
+ }
+
+ android.system.virtualizationservice.UsbConfig toParceclable() {
+ android.system.virtualizationservice.UsbConfig parcelable =
+ new android.system.virtualizationservice.UsbConfig();
+ parcelable.controller = this.controller;
+ return parcelable;
+ }
+
+ private static UsbConfig from(PersistableBundle pb) {
+ if (pb == null) {
+ return null;
+ }
+ Builder builder = new Builder();
+ builder.setController(pb.getBoolean(KEY_USE_CONTROLLER));
+ return builder.build();
+ }
+
+ private PersistableBundle toPersistableBundle() {
+ PersistableBundle pb = new PersistableBundle();
+ pb.putBoolean(KEY_USE_CONTROLLER, this.controller);
+ return pb;
+ }
+
+ /** @hide */
+ public static class Builder {
+ private boolean useController = false;
+
+ /** @hide */
+ public Builder() {}
+
+ /** @hide */
+ public Builder setController(boolean useController) {
+ this.useController = useController;
+ return this;
+ }
+
+ /** @hide */
+ public UsbConfig build() {
+ return new UsbConfig(useController);
+ }
}
}
diff --git a/libs/vmconfig/src/lib.rs b/libs/vmconfig/src/lib.rs
index ff115f3..ef932c2 100644
--- a/libs/vmconfig/src/lib.rs
+++ b/libs/vmconfig/src/lib.rs
@@ -18,6 +18,7 @@
aidl::android::system::virtualizationservice::CpuTopology::CpuTopology,
aidl::android::system::virtualizationservice::DiskImage::DiskImage as AidlDiskImage,
aidl::android::system::virtualizationservice::Partition::Partition as AidlPartition,
+ aidl::android::system::virtualizationservice::UsbConfig::UsbConfig as AidlUsbConfig,
aidl::android::system::virtualizationservice::VirtualMachineAppConfig::DebugLevel::DebugLevel,
aidl::android::system::virtualizationservice::VirtualMachineConfig::VirtualMachineConfig,
aidl::android::system::virtualizationservice::VirtualMachineRawConfig::VirtualMachineRawConfig,
@@ -68,6 +69,8 @@
pub devices: Vec<PathBuf>,
/// The serial device for VM console input.
pub console_input_device: Option<String>,
+ /// The USB config of the VM.
+ pub usb_config: Option<UsbConfig>,
}
impl VmConfig {
@@ -110,6 +113,7 @@
Some("match_host") => CpuTopology::MATCH_HOST,
Some(cpu_topology) => bail!("Invalid cpu topology {}", cpu_topology),
};
+ let usb_config = self.usb_config.clone().map(|x| x.to_parcelable()).transpose()?;
Ok(VirtualMachineRawConfig {
kernel: maybe_open_parcel_file(&self.kernel, false)?,
initrd: maybe_open_parcel_file(&self.initrd, false)?,
@@ -128,6 +132,7 @@
})
.collect::<Result<_>>()?,
consoleInputDevice: self.console_input_device.clone(),
+ usbConfig: usb_config,
..Default::default()
})
}
@@ -193,6 +198,19 @@
}
}
+/// USB controller and available USB devices
+#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
+pub struct UsbConfig {
+ /// Enable USB controller
+ pub controller: bool,
+}
+
+impl UsbConfig {
+ fn to_parcelable(&self) -> Result<AidlUsbConfig> {
+ Ok(AidlUsbConfig { controller: self.controller })
+ }
+}
+
/// Try to open the given file and wrap it in a [`ParcelFileDescriptor`].
pub fn open_parcel_file(filename: &Path, writable: bool) -> Result<ParcelFileDescriptor> {
Ok(ParcelFileDescriptor::new(