Virtualizationservice makes payload disk image
with given APK, idsig, and config file.
To exercise the new execution mode, 'vm run-app' sub command is added.
$ vm <apk_path> <idsig_path> <config_path>
For example,
$ vm /data/local/tmp/MyApp.apk /data/local/tmp/MyApp.apk.idsig \
assets/config.json
Bug: 190503456
Test: MicrodroidHostTestCases, VirtualizationTestCases
Change-Id: Iceec9b34e9785a1ae36452bfc2653c3c045f4dfa
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 8f16eb5..d7bae30 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -20,7 +20,7 @@
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::IVirtualizationService;
use android_system_virtualizationservice::binder::{wait_for_interface, ProcessState, Strong, ParcelFileDescriptor};
use anyhow::{Context, Error};
-use run::command_run;
+use run::{command_run, command_run_app};
use std::convert::TryInto;
use std::fs::OpenOptions;
use std::path::{PathBuf, Path};
@@ -33,6 +33,27 @@
#[derive(StructOpt)]
#[structopt(no_version, global_settings = &[AppSettings::DisableVersion])]
enum Opt {
+ /// Run a virtual machine with a config in APK
+ RunApp {
+ /// Path to VM Payload APK
+ #[structopt(parse(from_os_str))]
+ apk: PathBuf,
+
+ /// Path to idsig of the APK
+ #[structopt(parse(from_os_str))]
+ idsig: PathBuf,
+
+ /// Path to VM config JSON within APK (e.g. assets/vm_config.json)
+ config_path: String,
+
+ /// Detach VM from the terminal and run in the background
+ #[structopt(short, long)]
+ daemonize: bool,
+
+ /// Path to file for VM log output.
+ #[structopt(short, long)]
+ log: Option<PathBuf>,
+ },
/// Run a virtual machine
Run {
/// Path to VM config JSON
@@ -76,6 +97,9 @@
.context("Failed to find VirtualizationService")?;
match opt {
+ Opt::RunApp { apk, idsig, config_path, daemonize, log } => {
+ command_run_app(service, &apk, &idsig, &config_path, daemonize, log.as_deref())
+ }
Opt::Run { config, daemonize, log } => {
command_run(service, &config, daemonize, log.as_deref())
}
diff --git a/vm/src/run.rs b/vm/src/run.rs
index fbf849b..1ae94ea 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -20,6 +20,10 @@
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualMachineCallback::{
BnVirtualMachineCallback, IVirtualMachineCallback,
};
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+ VirtualMachineAppConfig::VirtualMachineAppConfig,
+ VirtualMachineConfig::VirtualMachineConfig,
+};
use android_system_virtualizationservice::binder::{
BinderFeatures, DeathRecipient, IBinder, ParcelFileDescriptor, Strong,
};
@@ -31,6 +35,25 @@
use std::path::Path;
use vmconfig::VmConfig;
+/// Run a VM from the given APK, idsig, and config.
+pub fn command_run_app(
+ service: Strong<dyn IVirtualizationService>,
+ apk: &Path,
+ idsig: &Path,
+ config_path: &str,
+ daemonize: bool,
+ log_path: Option<&Path>,
+) -> Result<(), Error> {
+ let apk_file = File::open(apk).context("Failed to open APK file")?;
+ let idsig_file = File::open(idsig).context("Failed to open idsig file")?;
+ let config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig {
+ apk: ParcelFileDescriptor::new(apk_file).into(),
+ idsig: ParcelFileDescriptor::new(idsig_file).into(),
+ configPath: config_path.to_owned(),
+ });
+ run(service, &config, &format!("{:?}!{:?}", apk, config_path), daemonize, log_path)
+}
+
/// Run a VM from the given configuration file.
pub fn command_run(
service: Strong<dyn IVirtualizationService>,
@@ -41,6 +64,22 @@
let config_file = File::open(config_path).context("Failed to open config file")?;
let config =
VmConfig::load(&config_file).context("Failed to parse config file")?.to_parcelable()?;
+ run(
+ service,
+ &VirtualMachineConfig::RawConfig(config),
+ &format!("{:?}", config_path),
+ daemonize,
+ log_path,
+ )
+}
+
+fn run(
+ service: Strong<dyn IVirtualizationService>,
+ config: &VirtualMachineConfig,
+ config_path: &str,
+ daemonize: bool,
+ log_path: Option<&Path>,
+) -> Result<(), Error> {
let stdout = if let Some(log_path) = log_path {
Some(ParcelFileDescriptor::new(
File::create(log_path)
@@ -51,7 +90,7 @@
} else {
Some(ParcelFileDescriptor::new(duplicate_stdout()?))
};
- let vm = service.startVm(&config, stdout.as_ref()).context("Failed to start VM")?;
+ let vm = service.startVm(config, stdout.as_ref()).context("Failed to start VM")?;
let cid = vm.getCid().context("Failed to get CID")?;
println!("Started VM from {:?} with CID {}.", config_path, cid);