Use protected VM if possible
If the system is capable of running a protected VM, then request one.
On userdebug/eng builds only, fall back to unprotected VM if that is
all that is available. (This is useful for testing.)
A protected VM doesn't support full debug, so use app only debug in
that case. That change requires relaxing the constraint on running
compilation in test mode to match.
I've also increases the VM start timeout to avoid spurious timeouts.
Bug: 217687661
Test: composd_cmd staged-apex-compile
Test: composd_cmd test-compile
Change-Id: Ic7be2c5260982c3c69421c01d10c1537864b87be
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index 6a35fb0..72d2b76 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -37,6 +37,7 @@
};
use compos_aidl_interface::aidl::com::android::compos::ICompOsService::ICompOsService;
use log::{info, warn};
+use rustutils::system_properties;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::num::NonZeroU32;
@@ -86,6 +87,8 @@
idsig_manifest_apk: &Path,
parameters: &VmParameters,
) -> Result<VmInstance> {
+ let protected_vm = want_protected_vm()?;
+
let instance_fd = ParcelFileDescriptor::new(instance_image);
let apex_dir = Path::new(COMPOS_APEX_ROOT);
@@ -109,7 +112,9 @@
.context("Failed to create system log file")?;
let console_fd = ParcelFileDescriptor::new(console_fd);
let log_fd = ParcelFileDescriptor::new(log_fd);
- (Some(console_fd), Some(log_fd), DebugLevel::FULL)
+ // Full debug is not available in a protected VM
+ let debug_level = if protected_vm { DebugLevel::APP_ONLY } else { DebugLevel::FULL };
+ (Some(console_fd), Some(log_fd), debug_level)
} else {
(None, None, DebugLevel::NONE)
};
@@ -122,7 +127,7 @@
configPath: config_path.to_owned(),
debugLevel: debug_level,
extraIdsigs: vec![idsig_manifest_apk_fd],
- protectedVm: false,
+ protectedVm: protected_vm,
memoryMib: VM_MEMORY_MIB,
numCpus: parameters.cpus.map_or(1, NonZeroU32::get) as i32,
cpuAffinity: parameters.cpu_set.clone(),
@@ -193,6 +198,31 @@
Ok(idsig_fd)
}
+fn want_protected_vm() -> Result<bool> {
+ let have_protected_vm =
+ system_properties::read_bool("ro.boot.hypervisor.protected_vm.supported", false)
+ .unwrap_or(false);
+ if have_protected_vm {
+ info!("Starting protected VM");
+ return Ok(true);
+ }
+
+ let build_type = system_properties::read("ro.build.type")?;
+ let is_debug_build = matches!(build_type.as_str(), "userdebug" | "eng");
+ if !is_debug_build {
+ bail!("Protected VM not supported, unable to start VM");
+ }
+
+ let have_unprotected_vm =
+ system_properties::read_bool("ro.boot.hypervisor.vm.supported", false).unwrap_or(false);
+ if have_unprotected_vm {
+ warn!("Protected VM not supported, falling back to unprotected on {} build", build_type);
+ return Ok(false);
+ }
+
+ bail!("No VM support available")
+}
+
struct VsockFactory<'a> {
vm: &'a dyn IVirtualMachine,
}
diff --git a/compos/common/timeouts.rs b/compos/common/timeouts.rs
index 42cfe69..c86ae34 100644
--- a/compos/common/timeouts.rs
+++ b/compos/common/timeouts.rs
@@ -53,7 +53,7 @@
// Note: the source of truth for these odrefresh timeouts is art/odrefresh/odr_config.h.
odrefresh_max_execution_time: Duration::from_secs(300),
odrefresh_max_child_process_time: Duration::from_secs(90),
- vm_max_time_to_ready: Duration::from_secs(10),
+ vm_max_time_to_ready: Duration::from_secs(15),
};
/// The timeouts that we use when need_extra_time() returns true.
diff --git a/compos/src/compilation.rs b/compos/src/compilation.rs
index 48ba4a6..ae4a29d 100644
--- a/compos/src/compilation.rs
+++ b/compos/src/compilation.rs
@@ -62,7 +62,9 @@
system_server_compiler_filter: &'a str,
) -> Result<Self> {
if compilation_mode != CompilationMode::NORMAL_COMPILE {
- let debuggable = system_properties::read_bool("ro.boot.microdroid.debuggable", false)?;
+ let debuggable = is_property_set("ro.boot.microdroid.debuggable")
+ || is_property_set("ro.boot.logd.enabled")
+ || is_property_set("ro.boot.adb.enabled");
if !debuggable {
bail!("Requested compilation mode only available in debuggable VMs");
}
@@ -97,6 +99,12 @@
}
}
+// Return whether the named property is definitely enabled. Deliberately conservative; returns
+// false if the property does not exist or cannot be read or is malformed.
+fn is_property_set(name: &str) -> bool {
+ system_properties::read_bool(name, false).unwrap_or(false)
+}
+
pub fn odrefresh(
odrefresh_path: &Path,
context: OdrefreshContext,