Snap for 13248265 from 78f66e0b66732695896777df0822c363d5597c1c to 25Q2-release
Change-Id: I4d96b3f0992b29446dfb99326342d08bf44ae2ed
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt
index 59be4ae..50aaa33 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt
@@ -19,6 +19,7 @@
import android.os.FileUtils
import android.system.ErrnoException
import android.system.Os
+import android.system.OsConstants
import android.util.Log
import com.android.virtualization.terminal.MainActivity.Companion.TAG
import java.io.BufferedReader
@@ -127,13 +128,36 @@
}
if (roundedUpDesiredSize > curSize) {
- allocateSpace(rootPartition, roundedUpDesiredSize)
+ if (!allocateSpace(roundedUpDesiredSize)) {
+ return curSize
+ }
}
resizeFilesystem(rootPartition, roundedUpDesiredSize)
return getApparentSize()
}
@Throws(IOException::class)
+ private fun allocateSpace(sizeInBytes: Long): Boolean {
+ val curSizeInBytes = getApparentSize()
+ try {
+ RandomAccessFile(rootPartition.toFile(), "rw").use { raf ->
+ Os.posix_fallocate(raf.fd, 0, sizeInBytes)
+ }
+ Log.d(TAG, "Allocated space to: $sizeInBytes bytes")
+ return true
+ } catch (e: ErrnoException) {
+ Log.e(TAG, "Failed to allocate space", e)
+ if (e.errno == OsConstants.ENOSPC) {
+ Log.d(TAG, "Trying to truncate disk into the original size")
+ truncate(curSizeInBytes)
+ return false
+ } else {
+ throw IOException("Failed to allocate space", e)
+ }
+ }
+ }
+
+ @Throws(IOException::class)
fun shrinkToMinimumSize(): Long {
// Fix filesystem before resizing.
runE2fsck(rootPartition)
@@ -153,8 +177,8 @@
RandomAccessFile(rootPartition.toFile(), "rw").use { raf -> Os.ftruncate(raf.fd, size) }
Log.d(TAG, "Truncated space to: $size bytes")
} catch (e: ErrnoException) {
- Log.e(TAG, "Failed to allocate space", e)
- throw IOException("Failed to allocate space", e)
+ Log.e(TAG, "Failed to truncate space", e)
+ throw IOException("Failed to truncate space", e)
}
}
@@ -175,19 +199,6 @@
}
@Throws(IOException::class)
- private fun allocateSpace(path: Path, sizeInBytes: Long) {
- try {
- RandomAccessFile(path.toFile(), "rw").use { raf ->
- Os.posix_fallocate(raf.fd, 0, sizeInBytes)
- }
- Log.d(TAG, "Allocated space to: $sizeInBytes bytes")
- } catch (e: ErrnoException) {
- Log.e(TAG, "Failed to allocate space", e)
- throw IOException("Failed to allocate space", e)
- }
- }
-
- @Throws(IOException::class)
private fun runE2fsck(path: Path) {
val p: String = path.toAbsolutePath().toString()
runCommand("/system/bin/e2fsck", "-y", "-f", p)
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
index 144db40..da07b19 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
@@ -33,6 +33,7 @@
import androidx.core.view.isVisible
import com.android.virtualization.terminal.VmLauncherService.VmLauncherServiceCallback
import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.snackbar.Snackbar
import java.util.Locale
import java.util.regex.Pattern
@@ -46,6 +47,7 @@
private lateinit var cancelButton: View
private lateinit var resizeButton: View
private lateinit var diskSizeText: TextView
+ private lateinit var diskMaxSizeText: TextView
private lateinit var diskSizeSlider: SeekBar
private fun bytesToMb(bytes: Long): Long {
@@ -56,6 +58,13 @@
return bytes shl 20
}
+ private fun getAvailableSizeMb(): Long {
+ val usableSpaceMb =
+ bytesToMb(Environment.getDataDirectory().getUsableSpace()) and
+ (diskSizeStepMb - 1).inv()
+ return diskSizeMb + usableSpaceMb
+ }
+
private fun mbToProgress(bytes: Long): Int {
return (bytes / diskSizeStepMb).toInt()
}
@@ -73,13 +82,10 @@
val image = InstalledImage.getDefault(this)
diskSizeMb = bytesToMb(image.getApparentSize())
val minDiskSizeMb = bytesToMb(image.getSmallestSizePossible()).coerceAtMost(diskSizeMb)
- val usableSpaceMb =
- bytesToMb(Environment.getDataDirectory().getUsableSpace()) and
- (diskSizeStepMb - 1).inv()
- val maxDiskSizeMb = defaultMaxDiskSizeMb.coerceAtMost(diskSizeMb + usableSpaceMb)
+ val maxDiskSizeMb = defaultMaxDiskSizeMb.coerceAtMost(getAvailableSizeMb())
diskSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_assigned)!!
- val diskMaxSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_max)
+ diskMaxSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_max)
diskMaxSizeText.text =
getString(
R.string.settings_disk_resize_resize_gb_max_format,
@@ -138,7 +144,22 @@
}
private fun resize() {
- diskSizeMb = progressToMb(diskSizeSlider.progress)
+ val desiredDiskSizeMb = progressToMb(diskSizeSlider.progress)
+ val availableSizeMb = getAvailableSizeMb()
+ if (availableSizeMb < desiredDiskSizeMb) {
+ Snackbar.make(
+ findViewById(android.R.id.content),
+ R.string.settings_disk_resize_not_enough_space_message,
+ Snackbar.LENGTH_SHORT,
+ )
+ .show()
+ diskSizeSlider.max = mbToProgress(availableSizeMb)
+ updateMaxSizeText(availableSizeMb)
+ cancel()
+ return
+ }
+
+ diskSizeMb = desiredDiskSizeMb
buttons.isVisible = false
// Note: we first stop the VM, and wait for it to fully stop. Then we (re) start the Main
@@ -186,6 +207,14 @@
)
}
+ fun updateMaxSizeText(sizeMb: Long) {
+ diskMaxSizeText.text =
+ getString(
+ R.string.settings_disk_resize_resize_gb_max_format,
+ localizedFileSize(sizeMb, /* isShort= */ true),
+ )
+ }
+
fun localizedFileSize(sizeMb: Long, isShort: Boolean): String {
val sizeGb = sizeMb / (1 shl 10).toFloat()
val measure = Measure(sizeGb, MeasureUnit.GIGABYTE)
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
index d43a8d1..84168e5 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -463,15 +463,32 @@
@WorkerThread
private fun doShutdown(resultReceiver: ResultReceiver?) {
- stopForeground(STOP_FOREGROUND_REMOVE)
+ runner?.exitStatus?.thenAcceptAsync { success: Boolean ->
+ resultReceiver?.send(if (success) RESULT_STOP else RESULT_ERROR, null)
+ stopSelf()
+ }
if (debianService != null && debianService!!.shutdownDebian()) {
// During shutdown, change the notification content to indicate that it's closing
val notification = createNotificationForTerminalClose()
getSystemService<NotificationManager?>(NotificationManager::class.java)
.notify(this.hashCode(), notification)
- runner?.exitStatus?.thenAcceptAsync { success: Boolean ->
- resultReceiver?.send(if (success) RESULT_STOP else RESULT_ERROR, null)
- stopSelf()
+
+ runner?.also { r ->
+ // For the case that shutdown from the guest agent fails.
+ // When timeout is set, the original CompletableFuture's every `thenAcceptAsync` is
+ // canceled as well. So add empty `thenAcceptAsync` to avoid interference.
+ r.exitStatus
+ .thenAcceptAsync {}
+ .orTimeout(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)
+ .exceptionally {
+ Log.e(
+ TAG,
+ "Stop the service directly because the VM instance isn't stopped with " +
+ "graceful shutdown",
+ )
+ r.vm.stop()
+ null
+ }
}
runner = null
} else {
@@ -498,6 +515,7 @@
stopDebianServer()
bgThreads.shutdownNow()
mainWorkerThread.shutdown()
+ stopForeground(STOP_FOREGROUND_REMOVE)
super.onDestroy()
}
@@ -517,6 +535,8 @@
private const val KEY_TERMINAL_IPADDRESS = "address"
private const val KEY_TERMINAL_PORT = "port"
+ private const val SHUTDOWN_TIMEOUT_SECONDS = 3L
+
private const val GUEST_SPARSE_DISK_SIZE_PERCENTAGE = 95
private const val EXPECTED_PHYSICAL_SIZE_PERCENTAGE_FOR_NON_SPARSE = 90
diff --git a/android/TerminalApp/res/values/strings.xml b/android/TerminalApp/res/values/strings.xml
index a6d461e..273032e 100644
--- a/android/TerminalApp/res/values/strings.xml
+++ b/android/TerminalApp/res/values/strings.xml
@@ -75,6 +75,8 @@
<string name="settings_disk_resize_resize_gb_assigned_format"><xliff:g id="assigned_size" example="10GB">\u200E%1$s\u200E</xliff:g> assigned</string>
<!-- Settings menu option description format of the maximum resizable disk size. [CHAR LIMIT=none] -->
<string name="settings_disk_resize_resize_gb_max_format"><xliff:g id="max_size" example="256GB">\u200E%1$s\u200E</xliff:g> max</string>
+ <!-- Snackbar message for showing not enough space error. [CHAR LIMIT=none] -->
+ <string name="settings_disk_resize_not_enough_space_message">Not enough space on the device to resize disk</string>
<!-- Settings menu button to cancel disk resize. [CHAR LIMIT=16] -->
<string name="settings_disk_resize_resize_cancel">Cancel</string>
<!-- Settings menu button to apply change Terminal app. This will launch a confirmation dialog [CHAR LIMIT=16] -->
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 8934de0..f0eba7f 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -56,6 +56,7 @@
"libvirtualizationservice_jni",
"libvirtualmachine_jni",
],
+ native_shared_libs: ["libavf"],
// TODO(b/295593640) Unfortunately these are added to the apex even though they are unused.
// Once the build system is fixed, remove this.
unwanted_transitive_deps: [
@@ -108,7 +109,6 @@
"rialto_bin",
"android_bootloader_crosvm_aarch64",
],
- native_shared_libs: ["libavf"],
},
x86_64: {
binaries: [
@@ -129,7 +129,6 @@
prebuilts: [
"android_bootloader_crosvm_x86_64",
],
- native_shared_libs: ["libavf"],
},
},
binaries: [
diff --git a/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index 6f113c8..cd32f8f 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -113,13 +113,15 @@
rust_test {
name: "libpvmfw.dice.test",
- srcs: ["src/dice.rs"],
+ srcs: ["src/dice/mod.rs"],
defaults: ["libpvmfw.test.defaults"],
rustlibs: [
"libcbor_util",
"libciborium",
+ "libcoset_nostd",
"libdiced_open_dice_nostd",
"libhwtrust",
+ "liblog_rust",
"libpvmfw_avb_nostd",
"libdiced_sample_inputs_nostd",
"libzerocopy_nostd",
diff --git a/guest/pvmfw/README.md b/guest/pvmfw/README.md
index c7f3dd6..08b0d5c 100644
--- a/guest/pvmfw/README.md
+++ b/guest/pvmfw/README.md
@@ -1,19 +1,30 @@
# Protected Virtual Machine Firmware
+## Protected VM (_"pVM"_)
+
In the context of the [Android Virtualization Framework][AVF], a hypervisor
(_e.g._ [pKVM]) enforces full memory isolation between its virtual machines
-(VMs) and the host. As a result, the host is only allowed to access memory that
-has been explicitly shared back by a VM. Such _protected VMs_ (“pVMs”) are
-therefore able to manipulate secrets without being at risk of an attacker
-stealing them by compromising the Android host.
+(VMs) and the host. As a result, such VMs are given strong guarantees regarding
+their confidentiality and integrity.
-As pVMs are started dynamically by a _virtual machine manager_ (“VMM”) running
-as a host process and as pVMs must not trust the host (see [_Why
-AVF?_][why-avf]), the virtual machine it configures can't be trusted either.
-Furthermore, even though the isolation mentioned above allows pVMs to protect
-their secrets from the host, it does not help with provisioning them during
-boot. In particular, the threat model would prohibit the host from ever having
-access to those secrets, preventing the VMM from passing them to the pVM.
+A _protected VMs_ (“pVMs”) is a VM running in the non-secure or realm world,
+started dynamically by a _virtual machine manager_ (“VMM”) running as a process
+of the untrusted Android host (see [_Why AVF?_][why-avf]) and which is isolated
+from the host OS so that access to its memory is restricted, even in the event
+of a compromised Android host. pVMs support rich environments, including
+Linux-based distributions.
+
+The pVM concept is not Google-exclusive. Partner-defined VMs (SoC/OEM) meeting
+isolation/memory access restrictions are also pVMs.
+
+## Protected VM Root-of-Trust: pvmfw
+
+As pVMs are managed by a VMM running on the untrusted host, the virtual machine
+it configures can't be trusted either. Furthermore, even though the isolation
+mentioned above allows pVMs to protect their secrets from the host, it does not
+help with provisioning them during boot. In particular, the threat model would
+prohibit the host from ever having access to those secrets, preventing the VMM
+from passing them to the pVM.
To address these concerns the hypervisor securely loads the pVM firmware
(“pvmfw”) in the pVM from a protected memory region (this prevents the host or
diff --git a/guest/pvmfw/avb/tests/api_test.rs b/guest/pvmfw/avb/tests/api_test.rs
index b3899d9..b8ec0bf 100644
--- a/guest/pvmfw/avb/tests/api_test.rs
+++ b/guest/pvmfw/avb/tests/api_test.rs
@@ -71,6 +71,7 @@
expected_rollback_index,
vec![Capability::TrustySecurityVm],
None,
+ Some("trusty_test_vm".to_owned()),
)
}
diff --git a/guest/pvmfw/avb/tests/utils.rs b/guest/pvmfw/avb/tests/utils.rs
index 227daa2..38541c5 100644
--- a/guest/pvmfw/avb/tests/utils.rs
+++ b/guest/pvmfw/avb/tests/utils.rs
@@ -148,6 +148,7 @@
expected_rollback_index: u64,
capabilities: Vec<Capability>,
page_size: Option<usize>,
+ expected_name: Option<String>,
) -> Result<()> {
let public_key = load_trusted_public_key()?;
let verified_boot_data = verify_payload(
@@ -168,7 +169,7 @@
capabilities,
rollback_index: expected_rollback_index,
page_size,
- name: None,
+ name: expected_name,
};
assert_eq!(expected_boot_data, verified_boot_data);
diff --git a/guest/pvmfw/src/bcc.rs b/guest/pvmfw/src/dice/chain.rs
similarity index 98%
rename from guest/pvmfw/src/bcc.rs
rename to guest/pvmfw/src/dice/chain.rs
index 7ce50e9..0f5b058 100644
--- a/guest/pvmfw/src/bcc.rs
+++ b/guest/pvmfw/src/dice/chain.rs
@@ -59,6 +59,7 @@
/// Return a new CBOR encoded BccHandover that is based on the incoming CDIs but does not chain
/// from the received BCC.
+#[cfg_attr(test, allow(dead_code))]
pub fn truncate(bcc_handover: BccHandover) -> Result<Vec<u8>> {
// Note: The strings here are deliberately different from those used in a normal DICE handover
// because we want this to not be equivalent to any valid DICE derivation.
@@ -75,6 +76,7 @@
cbor_util::serialize(&bcc_handover).map_err(|_| BccError::CborEncodeError)
}
+#[cfg_attr(test, allow(dead_code))]
fn taint_cdi(cdi: &Cdi, info: &str) -> Result<Cdi> {
// An arbitrary value generated randomly.
const SALT: [u8; 64] = [
diff --git a/guest/pvmfw/src/dice.rs b/guest/pvmfw/src/dice/mod.rs
similarity index 99%
rename from guest/pvmfw/src/dice.rs
rename to guest/pvmfw/src/dice/mod.rs
index 49a3807..94348a5 100644
--- a/guest/pvmfw/src/dice.rs
+++ b/guest/pvmfw/src/dice/mod.rs
@@ -15,9 +15,12 @@
//! Support for DICE derivation and BCC generation.
extern crate alloc;
+pub(crate) mod chain;
+
use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
+pub use chain::Bcc;
use ciborium::cbor;
use ciborium::Value;
use core::mem::size_of;
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index 30624cd..d3d5527 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -20,7 +20,6 @@
extern crate alloc;
mod arch;
-mod bcc;
mod bootargs;
mod config;
mod device_assignment;
@@ -32,8 +31,7 @@
mod memory;
mod rollback;
-use crate::bcc::Bcc;
-use crate::dice::PartialInputs;
+use crate::dice::{Bcc, PartialInputs};
use crate::entry::RebootReason;
use crate::fdt::{modify_for_next_stage, read_instance_id, sanitize_device_tree};
use crate::rollback::perform_rollback_protection;
@@ -134,7 +132,7 @@
// entire chain we were given and taint the CDIs. Note that the resulting CDIs are
// still deterministically derived from those we received, so will vary iff they do.
// TODO(b/280405545): Remove this post Android 14.
- let truncated_bcc_handover = bcc::truncate(bcc_handover).map_err(|e| {
+ let truncated_bcc_handover = dice::chain::truncate(bcc_handover).map_err(|e| {
error!("{e}");
RebootReason::InternalError
})?;
diff --git a/guest/trusty/security_vm/vm/Android.bp b/guest/trusty/security_vm/vm/Android.bp
index 6fa0c32..9928b56 100644
--- a/guest/trusty/security_vm/vm/Android.bp
+++ b/guest/trusty/security_vm/vm/Android.bp
@@ -123,6 +123,10 @@
name: "com.android.virt.cap",
value: "trusty_security_vm",
},
+ {
+ name: "com.android.virt.name",
+ value: "trusty_security_vm",
+ },
],
src: select(soong_config_variable("trusty_system_vm", "enabled"), {
true: ":trusty_security_vm_unsigned",
diff --git a/guest/trusty/test_vm/vm/Android.bp b/guest/trusty/test_vm/vm/Android.bp
index f978c92..b919599 100644
--- a/guest/trusty/test_vm/vm/Android.bp
+++ b/guest/trusty/test_vm/vm/Android.bp
@@ -101,6 +101,10 @@
name: "com.android.virt.cap",
value: "trusty_security_vm",
},
+ {
+ name: "com.android.virt.name",
+ value: "trusty_test_vm",
+ },
],
src: ":trusty_test_vm_unsigned",
enabled: false,
diff --git a/guest/trusty/test_vm_os/vm/Android.bp b/guest/trusty/test_vm_os/vm/Android.bp
index 2e81828..0e4116c 100644
--- a/guest/trusty/test_vm_os/vm/Android.bp
+++ b/guest/trusty/test_vm_os/vm/Android.bp
@@ -100,6 +100,10 @@
name: "com.android.virt.cap",
value: "trusty_security_vm",
},
+ {
+ name: "com.android.virt.name",
+ value: "trusty_test_vm_os",
+ },
],
src: ":trusty_test_vm_os_unsigned",
enabled: false,
diff --git a/libs/dice/sample_inputs/Android.bp b/libs/dice/sample_inputs/Android.bp
index c1c4566..4010741 100644
--- a/libs/dice/sample_inputs/Android.bp
+++ b/libs/dice/sample_inputs/Android.bp
@@ -80,3 +80,9 @@
],
static_libs: ["libopen_dice_clear_memory"],
}
+
+dirgroup {
+ name: "trusty_dirgroup_packages_modules_virtualization_libs_dice_sample_inputs",
+ visibility: ["//trusty/vendor/google/aosp/scripts"],
+ dirs: ["."],
+}
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
index eba6fcc..9641882 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
@@ -813,6 +813,10 @@
*/
@GuardedBy("mLock")
private void dropVm() {
+ if (mInputEventExecutor != null) {
+ mInputEventExecutor.shutdownNow();
+ mInputEventExecutor = null;
+ }
if (mMemoryManagementCallbacks != null) {
mContext.unregisterComponentCallbacks(mMemoryManagementCallbacks);
}
@@ -1825,9 +1829,6 @@
try {
mVirtualMachine.stop();
dropVm();
- if (mInputEventExecutor != null) {
- mInputEventExecutor.shutdownNow();
- }
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} catch (ServiceSpecificException e) {
diff --git a/libs/libavf/Android.bp b/libs/libavf/Android.bp
index aceb927..4469af5 100644
--- a/libs/libavf/Android.bp
+++ b/libs/libavf/Android.bp
@@ -40,30 +40,8 @@
defaults: ["libavf.default"],
}
-soong_config_module_type {
- name: "virt_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- bool_variables: [
- "avf_enabled",
- ],
- properties: [
- "apex_available",
- ],
-}
-
-virt_cc_defaults {
- name: "libavf_apex_available_defaults",
- soong_config_variables: {
- avf_enabled: {
- apex_available: ["com.android.virt"],
- },
- },
-}
-
cc_library {
name: "libavf",
- defaults: ["libavf_apex_available_defaults"],
llndk: {
symbol_file: "libavf.map.txt",
moved_to_apex: true,
@@ -79,4 +57,5 @@
stubs: {
symbol_file: "libavf.map.txt",
},
+ apex_available: ["com.android.virt"],
}
diff --git a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
index fcef19a..7eb7748 100644
--- a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
+++ b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
@@ -262,6 +262,11 @@
}
public List<String> getSupportedOSList() throws Exception {
+ // The --os flag was introduced in SDK level 36. When running tests on earlier dessert
+ // releases only use "microdroid" OS.
+ if (getAndroidDevice().getApiLevel() < 36) {
+ return Arrays.asList("microdroid");
+ }
return parseStringArrayFieldsFromVmInfo("Available OS list: ");
}
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 2434ed0..379ac98 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -496,15 +496,20 @@
final String configPath = "assets/vm_config_apex.json";
// Act
- mMicrodroidDevice =
+ MicrodroidBuilder microdroidBuilder =
MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
.debugLevel(DEBUG_LEVEL_FULL)
.memoryMib(minMemorySize())
.cpuTopology("match_host")
.protectedVm(true)
- .os(SUPPORTED_OSES.get(os))
- .name("protected_vm_runs_pvmfw")
- .build(getAndroidDevice());
+ .name("protected_vm_runs_pvmfw");
+
+ // --os flag was introduced in SDK 36
+ if (getAndroidDevice().getApiLevel() >= 36) {
+ microdroidBuilder.os(SUPPORTED_OSES.get(os));
+ }
+
+ mMicrodroidDevice = microdroidBuilder.build(getAndroidDevice());
// Assert
mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
@@ -647,14 +652,18 @@
CommandRunner android = new CommandRunner(getDevice());
String testStartTime = android.runWithTimeout(1000, "date", "'+%Y-%m-%d %H:%M:%S.%N'");
- mMicrodroidDevice =
+ MicrodroidBuilder microdroidBuilder =
MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
.debugLevel(DEBUG_LEVEL_FULL)
.memoryMib(minMemorySize())
.cpuTopology("match_host")
- .protectedVm(protectedVm)
- .os(SUPPORTED_OSES.get(os))
- .build(getAndroidDevice());
+ .protectedVm(protectedVm);
+
+ if (getAndroidDevice().getApiLevel() >= 36) {
+ microdroidBuilder.os(SUPPORTED_OSES.get(os));
+ }
+
+ mMicrodroidDevice = microdroidBuilder.build(getAndroidDevice());
mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
mMicrodroidDevice.enableAdbRoot();
@@ -874,15 +883,20 @@
// Create VM with microdroid
TestDevice device = getAndroidDevice();
final String configPath = "assets/vm_config_apex.json"; // path inside the APK
- ITestDevice microdroid =
+ MicrodroidBuilder microdroidBuilder =
MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
.debugLevel(DEBUG_LEVEL_FULL)
.memoryMib(minMemorySize())
.cpuTopology("match_host")
.protectedVm(protectedVm)
- .os(SUPPORTED_OSES.get(os))
- .name("test_telemetry_pushed_atoms")
- .build(device);
+ .name("test_telemetry_pushed_atoms");
+
+ if (device.getApiLevel() >= 36) {
+ microdroidBuilder.os(SUPPORTED_OSES.get(os));
+ }
+
+ ITestDevice microdroid = microdroidBuilder.build(device);
+
microdroid.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
device.shutdownMicrodroid(microdroid);
@@ -1026,14 +1040,18 @@
assumeVmTypeSupported(os, protectedVm);
final String configPath = "assets/vm_config.json"; // path inside the APK
- testMicrodroidBootsWithBuilder(
+ MicrodroidBuilder microdroidBuilder =
MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
.debugLevel(DEBUG_LEVEL_FULL)
.memoryMib(minMemorySize())
.cpuTopology("match_host")
.protectedVm(protectedVm)
- .name("test_microdroid_boots")
- .os(SUPPORTED_OSES.get(os)));
+ .name("test_microdroid_boots");
+ if (getAndroidDevice().getApiLevel() >= 36) {
+ microdroidBuilder.os(SUPPORTED_OSES.get(os));
+ }
+
+ testMicrodroidBootsWithBuilder(microdroidBuilder);
}
@Test
@@ -1064,15 +1082,18 @@
assumeVmTypeSupported(os, protectedVm);
final String configPath = "assets/vm_config.json";
- mMicrodroidDevice =
+ MicrodroidBuilder microdroidBuilder =
MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
.debugLevel(DEBUG_LEVEL_FULL)
.memoryMib(minMemorySize())
.cpuTopology("match_host")
.protectedVm(protectedVm)
- .os(SUPPORTED_OSES.get(os))
- .name("test_microdroid_ram_usage")
- .build(getAndroidDevice());
+ .name("test_microdroid_ram_usage");
+ if (getAndroidDevice().getApiLevel() >= 36) {
+ microdroidBuilder.os(SUPPORTED_OSES.get(os));
+ }
+
+ mMicrodroidDevice = microdroidBuilder.build(getAndroidDevice());
mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
mMicrodroidDevice.enableAdbRoot();
@@ -1362,16 +1383,18 @@
Objects.requireNonNull(device);
final String configPath = "assets/vm_config.json";
- mMicrodroidDevice =
+ MicrodroidBuilder microdroidBuilder =
MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
.debugLevel(DEBUG_LEVEL_FULL)
.memoryMib(minMemorySize())
.cpuTopology("match_host")
.protectedVm(protectedVm)
- .os(SUPPORTED_OSES.get(os))
- .addAssignableDevice(device)
- .build(getAndroidDevice());
+ .addAssignableDevice(device);
+ if (getAndroidDevice().getApiLevel() >= 36) {
+ microdroidBuilder.os(SUPPORTED_OSES.get(os));
+ }
+ mMicrodroidDevice = microdroidBuilder.build(getAndroidDevice());
assertThat(mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT)).isTrue();
assertThat(mMicrodroidDevice.enableAdbRoot()).isTrue();
}
@@ -1408,16 +1431,19 @@
android.run("echo advise > " + SHMEM_ENABLED_PATH);
final String configPath = "assets/vm_config.json";
- mMicrodroidDevice =
+ MicrodroidBuilder microdroidBuilder =
MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
.debugLevel(DEBUG_LEVEL_FULL)
.memoryMib(minMemorySize())
.cpuTopology("match_host")
.protectedVm(protectedVm)
- .os(SUPPORTED_OSES.get(os))
.hugePages(true)
- .name("test_huge_pages")
- .build(getAndroidDevice());
+ .name("test_huge_pages");
+ if (getAndroidDevice().getApiLevel() >= 36) {
+ microdroidBuilder.os(SUPPORTED_OSES.get(os));
+ }
+
+ mMicrodroidDevice = microdroidBuilder.build(getAndroidDevice());
mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
android.run("echo never >" + SHMEM_ENABLED_PATH);