Support console input to VM
createVm accepts a new ParcelFileDescriptor which when set is used as
the console input in the VM. The `vm` tool sets this to stdin unless
explicitly specified via `--console-in`. This will be useful for
bringing up custom OSes.
Note that Java APIs for this is not added in this CL.
Bug: 263360203
Test: Start a vm using the `vm` tool. Type something. Then do `cat
/dev/console` in the VM. It shows the typed characters.
Change-Id: I5d0dfcc4852387ec50897a8dcae2935dd4a2dd9a
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 54c1de4..27fd903 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -51,7 +51,8 @@
storage_size: Option<u64>,
config_path: Option<String>,
payload_binary_name: Option<String>,
- console_path: Option<&Path>,
+ console_out_path: Option<&Path>,
+ console_in_path: Option<&Path>,
log_path: Option<&Path>,
debug_level: DebugLevel,
protected: bool,
@@ -152,7 +153,7 @@
gdbPort: gdb.map(u16::from).unwrap_or(0) as i32, // 0 means no gdb
customKernelImage: kernel,
});
- run(service, &config, &payload_config_str, console_path, log_path)
+ run(service, &config, &payload_config_str, console_out_path, console_in_path, log_path)
}
fn find_empty_payload_apk_path() -> Result<PathBuf, Error> {
@@ -185,7 +186,8 @@
work_dir: Option<PathBuf>,
storage: Option<&Path>,
storage_size: Option<u64>,
- console_path: Option<&Path>,
+ console_out_path: Option<&Path>,
+ console_in_path: Option<&Path>,
log_path: Option<&Path>,
debug_level: DebugLevel,
protected: bool,
@@ -216,7 +218,8 @@
storage_size,
/* config_path= */ None,
Some(payload_binary_name.to_owned()),
- console_path,
+ console_out_path,
+ console_in_path,
log_path,
debug_level,
protected,
@@ -235,7 +238,8 @@
name: Option<String>,
service: &dyn IVirtualizationService,
config_path: &Path,
- console_path: Option<&Path>,
+ console_out_path: Option<&Path>,
+ console_in_path: Option<&Path>,
log_path: Option<&Path>,
mem: Option<u32>,
cpu_topology: CpuTopology,
@@ -262,7 +266,8 @@
service,
&VirtualMachineConfig::RawConfig(config),
&format!("{:?}", config_path),
- console_path,
+ console_out_path,
+ console_in_path,
log_path,
)
}
@@ -283,28 +288,35 @@
service: &dyn IVirtualizationService,
config: &VirtualMachineConfig,
payload_config: &str,
- console_path: Option<&Path>,
+ console_out_path: Option<&Path>,
+ console_in_path: Option<&Path>,
log_path: Option<&Path>,
) -> Result<(), Error> {
- let console = if let Some(console_path) = console_path {
- Some(
- File::create(console_path)
- .with_context(|| format!("Failed to open console file {:?}", console_path))?,
- )
+ let console_out = if let Some(console_out_path) = console_out_path {
+ Some(File::create(console_out_path).with_context(|| {
+ format!("Failed to open console output file {:?}", console_out_path)
+ })?)
} else {
- Some(duplicate_stdout()?)
+ Some(duplicate_fd(io::stdout())?)
};
+ let console_in =
+ if let Some(console_in_path) = console_in_path {
+ Some(File::create(console_in_path).with_context(|| {
+ format!("Failed to open console input file {:?}", console_in_path)
+ })?)
+ } else {
+ Some(duplicate_fd(io::stdin())?)
+ };
let log = if let Some(log_path) = log_path {
Some(
File::create(log_path)
.with_context(|| format!("Failed to open log file {:?}", log_path))?,
)
} else {
- Some(duplicate_stdout()?)
+ Some(duplicate_fd(io::stdout())?)
};
-
let callback = Box::new(Callback {});
- let vm = VmInstance::create(service, config, console, log, Some(callback))
+ let vm = VmInstance::create(service, config, console_out, console_in, log, Some(callback))
.context("Failed to create VM")?;
vm.start().context("Failed to start VM")?;
@@ -349,12 +361,12 @@
}
}
-/// Safely duplicate the standard output file descriptor.
-fn duplicate_stdout() -> io::Result<File> {
- let stdout_fd = io::stdout().as_raw_fd();
+/// Safely duplicate the file descriptor.
+fn duplicate_fd<T: AsRawFd>(file: T) -> io::Result<File> {
+ let fd = file.as_raw_fd();
// Safe because this just duplicates a file descriptor which we know to be valid, and we check
// for an error.
- let dup_fd = unsafe { libc::dup(stdout_fd) };
+ let dup_fd = unsafe { libc::dup(fd) };
if dup_fd < 0 {
Err(io::Error::last_os_error())
} else {