Merge "Revert "Remove references to android15-6.1 microdroid kernel"" into main
diff --git a/apex/Android.bp b/apex/Android.bp
index da17040..5e74aca 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -35,7 +35,6 @@
soong_config_string_variable {
name: "avf_microdroid_guest_gki_version",
values: [
- "android14_61_pkvm_experimental",
"android15_66",
],
}
@@ -168,14 +167,6 @@
],
soong_config_variables: {
avf_microdroid_guest_gki_version: {
- android14_61_pkvm_experimental: {
- prebuilts: [
- "microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable",
- "microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal",
- "microdroid_gki-android14-6.1-pkvm_experimental_kernel",
- "microdroid_gki-android14-6.1-pkvm_experimental.json",
- ],
- },
android15_66: {
prebuilts: [
"microdroid_gki-android15-6.6_initrd_debuggable",
diff --git a/apex/sign_virt_apex.py b/apex/sign_virt_apex.py
index 1a59894..4a19c3d 100644
--- a/apex/sign_virt_apex.py
+++ b/apex/sign_virt_apex.py
@@ -498,7 +498,7 @@
RunCommand(args, cmd)
-gki_versions = ['android14-6.1-pkvm_experimental', 'android15-6.6']
+gki_versions = ['android15-6.6']
# dict of (key, file) for re-sign/verification. keys are un-versioned for readability.
virt_apex_non_gki_files = {
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
index b3c0746..a2d8ee6 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -687,12 +687,28 @@
for (int i = 0; i < config.disks.length; i++) {
config.disks[i] = new DiskImage();
config.disks[i].writable = customImageConfig.getDisks()[i].isWritable();
+ String diskImagePath = customImageConfig.getDisks()[i].getImagePath();
+ if (diskImagePath != null) {
+ config.disks[i].image =
+ ParcelFileDescriptor.open(
+ new File(diskImagePath),
+ config.disks[i].writable ? MODE_READ_WRITE : MODE_READ_ONLY);
+ }
- config.disks[i].image =
- ParcelFileDescriptor.open(
- new File(customImageConfig.getDisks()[i].getImagePath()),
- config.disks[i].writable ? MODE_READ_WRITE : MODE_READ_ONLY);
- config.disks[i].partitions = new Partition[0];
+ List<Partition> partitions = new ArrayList<>();
+ for (VirtualMachineCustomImageConfig.Partition p :
+ customImageConfig.getDisks()[i].getPartitions()) {
+ Partition part = new Partition();
+ part.label = p.name;
+ part.image =
+ ParcelFileDescriptor.open(
+ new File(p.imagePath),
+ p.writable ? MODE_READ_WRITE : MODE_READ_ONLY);
+ part.writable = p.writable;
+ part.guid = TextUtils.isEmpty(p.guid) ? null : p.guid;
+ partitions.add(part);
+ }
+ config.disks[i].partitions = partitions.toArray(new Partition[0]);
}
config.displayConfig =
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java b/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
index 125e01c..2a571ff 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
@@ -32,6 +32,10 @@
private static final String KEY_PARAMS = "params";
private static final String KEY_DISK_WRITABLES = "disk_writables";
private static final String KEY_DISK_IMAGES = "disk_images";
+ private static final String KEY_PARTITION_LABELS = "partition_labels_";
+ private static final String KEY_PARTITION_IMAGES = "partition_images_";
+ private static final String KEY_PARTITION_WRITABLES = "partition_writables_";
+ private static final String KEY_PARTITION_GUIDS = "partition_guids_";
private static final String KEY_DISPLAY_CONFIG = "display_config";
private static final String KEY_TOUCH = "touch";
private static final String KEY_KEYBOARD = "keyboard";
@@ -155,8 +159,23 @@
if (writables != null && diskImages != null) {
if (writables.length == diskImages.length) {
for (int i = 0; i < writables.length; i++) {
- builder.addDisk(
- writables[i] ? Disk.RWDisk(diskImages[i]) : Disk.RODisk(diskImages[i]));
+ String diskImage = diskImages[i];
+ diskImage = diskImage.equals("") ? null : diskImage;
+ Disk disk = writables[i] ? Disk.RWDisk(diskImage) : Disk.RODisk(diskImage);
+ String[] labels =
+ customImageConfigBundle.getStringArray(KEY_PARTITION_LABELS + i);
+ String[] images =
+ customImageConfigBundle.getStringArray(KEY_PARTITION_IMAGES + i);
+ boolean[] partitionWritables =
+ customImageConfigBundle.getBooleanArray(KEY_PARTITION_WRITABLES + i);
+ String[] guids =
+ customImageConfigBundle.getStringArray(KEY_PARTITION_GUIDS + i);
+ for (int j = 0; j < labels.length; j++) {
+ disk.addPartition(
+ new Partition(
+ labels[j], images[j], partitionWritables[j], guids[j]));
+ }
+ builder.addDisk(disk);
}
}
}
@@ -189,7 +208,26 @@
String[] images = new String[disks.length];
for (int i = 0; i < disks.length; i++) {
writables[i] = disks[i].writable;
- images[i] = disks[i].imagePath;
+ String imagePath = disks[i].imagePath;
+ images[i] = imagePath == null ? "" : imagePath;
+
+ int numPartitions = disks[i].getPartitions().size();
+ String[] partitionLabels = new String[numPartitions];
+ String[] partitionImages = new String[numPartitions];
+ boolean[] partitionWritables = new boolean[numPartitions];
+ String[] partitionGuids = new String[numPartitions];
+
+ for (int j = 0; j < numPartitions; j++) {
+ Partition p = disks[i].getPartitions().get(j);
+ partitionLabels[j] = p.name;
+ partitionImages[j] = p.imagePath;
+ partitionWritables[j] = p.writable;
+ partitionGuids[j] = p.guid == null ? "" : p.guid;
+ }
+ pb.putStringArray(KEY_PARTITION_LABELS + i, partitionLabels);
+ pb.putStringArray(KEY_PARTITION_IMAGES + i, partitionImages);
+ pb.putBooleanArray(KEY_PARTITION_WRITABLES + i, partitionWritables);
+ pb.putStringArray(KEY_PARTITION_GUIDS + i, partitionGuids);
}
pb.putBooleanArray(KEY_DISK_WRITABLES, writables);
pb.putStringArray(KEY_DISK_IMAGES, images);
@@ -232,10 +270,12 @@
public static final class Disk {
private final boolean writable;
private final String imagePath;
+ private final List<Partition> partitions;
private Disk(boolean writable, String imagePath) {
this.writable = writable;
this.imagePath = imagePath;
+ this.partitions = new ArrayList<>();
}
/** @hide */
@@ -257,6 +297,32 @@
public String getImagePath() {
return imagePath;
}
+
+ /** @hide */
+ public Disk addPartition(Partition p) {
+ this.partitions.add(p);
+ return this;
+ }
+
+ /** @hide */
+ public List<Partition> getPartitions() {
+ return partitions;
+ }
+ }
+
+ /** @hide */
+ public static final class Partition {
+ public final String name;
+ public final String imagePath;
+ public final boolean writable;
+ public final String guid;
+
+ public Partition(String name, String imagePath, boolean writable, String guid) {
+ this.name = name;
+ this.imagePath = imagePath;
+ this.writable = writable;
+ this.guid = guid;
+ }
}
/** @hide */
diff --git a/libs/vmconfig/Android.bp b/libs/vmconfig/Android.bp
index 728033c..657e604 100644
--- a/libs/vmconfig/Android.bp
+++ b/libs/vmconfig/Android.bp
@@ -14,6 +14,7 @@
"libsemver",
"libserde",
"libserde_json",
+ "libuuid",
],
apex_available: [
"com.android.virt",
diff --git a/libs/vmconfig/src/lib.rs b/libs/vmconfig/src/lib.rs
index 1413b51..ff115f3 100644
--- a/libs/vmconfig/src/lib.rs
+++ b/libs/vmconfig/src/lib.rs
@@ -32,6 +32,7 @@
use std::io::BufReader;
use std::num::NonZeroU32;
use std::path::{Path, PathBuf};
+use uuid::Uuid;
/// Configuration for a particular VM to be started.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
@@ -176,6 +177,9 @@
/// Whether the partition should be writable.
#[serde(default)]
pub writable: bool,
+ /// GUID of this partition.
+ #[serde(default)]
+ pub guid: Option<Uuid>,
}
impl Partition {
@@ -184,6 +188,7 @@
image: Some(open_parcel_file(&self.path, self.writable)?),
writable: self.writable,
label: self.label.to_owned(),
+ guid: None,
})
}
}
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index d4158d4..289bc82 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -579,74 +579,6 @@
}
///////////////////////////////////////
-// GKI-android14-6.1-pkvm_experimental modules
-///////////////////////////////////////
-prebuilt_etc {
- name: "microdroid_gki-android14-6.1-pkvm_experimental.json",
- src: "microdroid_gki-android14-6.1-pkvm_experimental.json",
-}
-
-avb_add_hash_footer {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed",
- defaults: ["microdroid_kernel_signed_defaults"],
- filename: "microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed",
- arch: {
- arm64: {
- src: ":microdroid_gki_kernel_prebuilts-6.1-pkvm_experimental-arm64",
- },
- x86_64: {
- src: ":microdroid_gki_kernel_prebuilts-6.1-pkvm_experimental-x86_64",
- },
- },
- include_descriptors_from_images: [
- ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_hashdesc",
- ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_debug_hashdesc",
- ],
-}
-
-// HACK: use cc_genrule for arch-specific properties
-cc_genrule {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed-lz4",
- out: ["microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed-lz4"],
- srcs: [":empty_file"],
- arch: {
- arm64: {
- srcs: [":microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed"],
- exclude_srcs: [":empty_file"],
- },
- },
- tools: ["lz4"],
- cmd: "$(location lz4) -9 $(in) $(out)",
-}
-
-prebuilt_etc {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_kernel",
- filename: "microdroid_gki-android14-6.1-pkvm_experimental_kernel",
- src: ":empty_file",
- relative_install_path: "fs",
- arch: {
- arm64: {
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed-lz4",
- },
- x86_64: {
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed",
- },
- },
-}
-
-avb_gen_vbmeta_image {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_hashdesc",
- defaults: ["microdroid_initrd_normal_defaults"],
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal",
-}
-
-avb_gen_vbmeta_image {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_debug_hashdesc",
- defaults: ["microdroid_initrd_debug_defaults"],
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable",
-}
-
-///////////////////////////////////////
// GKI-android15-6.6
///////////////////////////////////////
prebuilt_etc {
@@ -726,13 +658,11 @@
arch: {
arm64: {
srcs: [
- ":microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed",
":microdroid_gki-android15-6.6_kernel_signed",
],
},
x86_64: {
srcs: [
- ":microdroid_gki-android14-6.1-pkvm_experimental_kernel_signed",
":microdroid_gki-android15-6.6_kernel_signed",
],
},
diff --git a/microdroid/initrd/Android.bp b/microdroid/initrd/Android.bp
index 9bb4657..9904511 100644
--- a/microdroid/initrd/Android.bp
+++ b/microdroid/initrd/Android.bp
@@ -41,17 +41,6 @@
}
genrule {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_gen_arm64",
- srcs: [
- ":microdroid_ramdisk",
- ":microdroid_first_stage_ramdisk",
- ":microdroid_gki_modules-6.1-pkvm_experimental-arm64",
- ],
- out: ["microdroid_initrd.img"],
- cmd: "cat $(in) > $(out)",
-}
-
-genrule {
name: "microdroid_gki-android15-6.6_initrd_gen_arm64",
srcs: [
":microdroid_ramdisk",
@@ -63,17 +52,6 @@
}
genrule {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_gen_x86_64",
- srcs: [
- ":microdroid_ramdisk",
- ":microdroid_first_stage_ramdisk",
- ":microdroid_gki_modules-6.1-pkvm_experimental-x86_64",
- ],
- out: ["microdroid_initrd.img"],
- cmd: "cat $(in) > $(out)",
-}
-
-genrule {
name: "microdroid_gki-android15-6.6_initrd_gen_x86_64",
srcs: [
":microdroid_ramdisk",
@@ -118,17 +96,6 @@
}
genrule {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable_arm64",
- tools: ["initrd_bootconfig"],
- srcs: [
- ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_gen_arm64",
- ":microdroid_bootconfig_debuggable_src",
- ] + bootconfigs_arm64,
- out: ["microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable_arm64"],
- cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
-}
-
-genrule {
name: "microdroid_gki-android15-6.6_initrd_debuggable_arm64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -151,17 +118,6 @@
}
genrule {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable_x86_64",
- tools: ["initrd_bootconfig"],
- srcs: [
- ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_gen_x86_64",
- ":microdroid_bootconfig_debuggable_src",
- ] + bootconfigs_x86_64,
- out: ["microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable_x86_64"],
- cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
-}
-
-genrule {
name: "microdroid_gki-android15-6.6_initrd_debuggable_x86_64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -184,17 +140,6 @@
}
genrule {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_arm64",
- tools: ["initrd_bootconfig"],
- srcs: [
- ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_gen_arm64",
- ":microdroid_bootconfig_normal_src",
- ] + bootconfigs_arm64,
- out: ["microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_arm64"],
- cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
-}
-
-genrule {
name: "microdroid_gki-android15-6.6_initrd_normal_arm64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -217,17 +162,6 @@
}
genrule {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_x86_64",
- tools: ["initrd_bootconfig"],
- srcs: [
- ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_gen_x86_64",
- ":microdroid_bootconfig_normal_src",
- ] + bootconfigs_x86_64,
- out: ["microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_x86_64"],
- cmd: "$(location initrd_bootconfig) attach --output $(out) $(in)",
-}
-
-genrule {
name: "microdroid_gki-android15-6.6_initrd_normal_x86_64",
tools: ["initrd_bootconfig"],
srcs: [
@@ -254,21 +188,6 @@
}
prebuilt_etc {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable",
- // We don't have ramdisk for architectures other than x86_64 & arm64
- src: ":empty_file",
- arch: {
- x86_64: {
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable_x86_64",
- },
- arm64: {
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable_arm64",
- },
- },
- filename: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_debuggable.img",
-}
-
-prebuilt_etc {
name: "microdroid_gki-android15-6.6_initrd_debuggable",
// We don't have ramdisk for architectures other than x86_64 & arm64
src: ":empty_file",
@@ -299,21 +218,6 @@
}
prebuilt_etc {
- name: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal",
- // We don't have ramdisk for architectures other than x86_64 & arm64
- src: ":empty_file",
- arch: {
- x86_64: {
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_x86_64",
- },
- arm64: {
- src: ":microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal_arm64",
- },
- },
- filename: "microdroid_gki-android14-6.1-pkvm_experimental_initrd_normal.img",
-}
-
-prebuilt_etc {
name: "microdroid_gki-android15-6.6_initrd_normal",
// We don't have ramdisk for architectures other than x86_64 & arm64
src: ":empty_file",
diff --git a/microdroid/microdroid_gki-android14-6.1-pkvm_experimental.json b/microdroid/microdroid_gki-android14-6.1-pkvm_experimental.json
deleted file mode 100644
index 4e58573..0000000
--- a/microdroid/microdroid_gki-android14-6.1-pkvm_experimental.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "kernel": "/apex/com.android.virt/etc/fs/microdroid_gki-android14-6.1-pkvm_experimental_kernel",
- "disks": [
- {
- "partitions": [
- {
- "label": "vbmeta_a",
- "path": "/apex/com.android.virt/etc/fs/microdroid_vbmeta.img"
- },
- {
- "label": "super",
- "path": "/apex/com.android.virt/etc/fs/microdroid_super.img"
- }
- ],
- "writable": false
- }
- ],
- "memory_mib": 256,
- "platform_version": "~1.0"
-}
diff --git a/service_vm/manager/src/lib.rs b/service_vm/manager/src/lib.rs
index 987325d..78ed85b 100644
--- a/service_vm/manager/src/lib.rs
+++ b/service_vm/manager/src/lib.rs
@@ -220,6 +220,7 @@
label: "vm-instance".to_owned(),
image: Some(instance_img),
writable: true,
+ guid: None,
}];
let rialto = File::open(RIALTO_PATH).context("Failed to open Rialto kernel binary")?;
let instance_id_file = Path::new(VIRT_DATA_DIR).join(INSTANCE_ID_FILENAME);
diff --git a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
index b646ea1..ec1a553 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -27,12 +27,14 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
+import android.app.Application;
import android.app.Instrumentation;
+import android.content.ComponentCallbacks2;
+import android.content.Context;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.AutoCloseInputStream;
import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
-import android.os.Process;
import android.os.RemoteException;
import android.system.Os;
import android.system.virtualmachine.VirtualMachine;
@@ -619,7 +621,8 @@
.setMemoryBytes(256 * ONE_MEBI)
.build();
VirtualMachine vm = forceCreateNewVirtualMachine(vmName, config);
- MemoryReclaimListener listener = new MemoryReclaimListener(this::executeCommand);
+ MemoryReclaimListener listener =
+ new MemoryReclaimListener(this::executeCommand, getContext());
BenchmarkVmListener.create(listener).runToFinish(TAG, vm);
assertWithMessage("VM failed to start").that(listener.mPreCrosvm).isNotNull();
assertWithMessage("Post trim stats not available").that(listener.mPostCrosvm).isNotNull();
@@ -654,11 +657,13 @@
}
private static class MemoryReclaimListener implements BenchmarkVmListener.InnerListener {
- MemoryReclaimListener(Function<String, String> shellExecutor) {
+ MemoryReclaimListener(Function<String, String> shellExecutor, Context applicationCtx) {
mShellExecutor = shellExecutor;
+ mApplication = (Application) applicationCtx;
}
public final Function<String, String> mShellExecutor;
+ private final Application mApplication;
public CrosvmStats mPreCrosvm;
public CrosvmStats mPostCrosvm;
@@ -674,7 +679,7 @@
service.allocAnonMemory(256);
mPreCrosvm = new CrosvmStats(vmPid, mShellExecutor);
// Send a memory trim hint to cause memory reclaim.
- mShellExecutor.apply("am send-trim-memory " + Process.myPid() + " RUNNING_CRITICAL");
+ mApplication.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL);
// Give time for the memory reclaim to do its work.
try {
Thread.sleep(isCuttlefish() ? 10000 : 5000);
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index aee118c..91ff4d8 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -15,9 +15,10 @@
*/
package com.android.microdroid.test.device;
+import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_VIRTUALIZATION_FRAMEWORK;
import static android.content.pm.PackageManager.FEATURE_WATCH;
-import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
@@ -70,8 +71,7 @@
protected static final String KERNEL_VERSION = SystemProperties.get("ro.kernel.version");
protected static final Set<String> SUPPORTED_GKI_VERSIONS =
- Collections.unmodifiableSet(
- new HashSet(Arrays.asList("android14-6.1-pkvm_experimental", "android15-6.6")));
+ Collections.unmodifiableSet(new HashSet(Arrays.asList("android15-6.6")));
public static boolean isCuttlefish() {
return getDeviceProperties().isCuttlefish();
@@ -226,7 +226,8 @@
protected void assumeVsrCompliant() {
boolean featureCheck = mCtx.getPackageManager().hasSystemFeature(FEATURE_WATCH) ||
- mCtx.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE);
+ mCtx.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE) ||
+ mCtx.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
assume().withMessage("This device is not VSR compliant")
.that(featureCheck)
.isFalse();
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 432f5e6..cd90fbe 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
@@ -71,8 +71,7 @@
/ MICRODROID_COMMAND_RETRY_INTERVAL_MILLIS);
protected static final Set<String> SUPPORTED_GKI_VERSIONS =
- Collections.unmodifiableSet(
- new HashSet(Arrays.asList("android14-6.1-pkvm_experimental", "android15-6.6")));
+ Collections.unmodifiableSet(new HashSet(Arrays.asList("android15-6.6")));
/* Keep this sync with AssignableDevice.aidl */
public static final class AssignableDevice {
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index e32ff88..8314f43 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -57,6 +57,9 @@
"MicrodroidCrashNativeLib",
"libmicrodroid_testlib_rust",
"libvm_attestation_test_payload",
+
+ // Non-VM payload libraries
+ "libhwtrust_jni",
],
min_sdk_version: "33",
}
@@ -186,3 +189,20 @@
"libvm_payload_rs",
],
}
+
+rust_ffi_shared {
+ name: "libhwtrust_jni",
+ crate_name: "hwtrust_jni",
+ srcs: ["src/native/hwtrust_jni.rs"],
+ prefer_rlib: true,
+ rustlibs: [
+ "libandroid_logger",
+ "libanyhow",
+ "liblog_rust",
+ "libhwtrust",
+ "libjni",
+ ],
+ shared_libs: [
+ "libcrypto",
+ ],
+}
diff --git a/tests/testapk/src/java/com/android/microdroid/test/HwTrustJni.java b/tests/testapk/src/java/com/android/microdroid/test/HwTrustJni.java
new file mode 100644
index 0000000..3b237aa
--- /dev/null
+++ b/tests/testapk/src/java/com/android/microdroid/test/HwTrustJni.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.microdroid.test;
+
+class HwTrustJni {
+ static {
+ System.loadLibrary("hwtrust_jni");
+ }
+
+ /**
+ * Validates a DICE chain.
+ *
+ * @param diceChain The dice chain to validate.
+ * @return true if the dice chain is valid, false otherwise.
+ */
+ public static native boolean validateDiceChain(byte[] diceChain);
+}
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index fd67659..658b1bb 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -1308,6 +1308,36 @@
}
@Test
+ @VsrTest(requirements = {"VSR-7.1-001.005"})
+ public void protectedVmHasValidDiceChain() throws Exception {
+ // This test validates two things regarding the pVM DICE chain:
+ // 1. The DICE chain is well-formed that all the entries conform to the DICE spec.
+ // 2. Each entry in the DICE chain is signed by the previous entry's subject public key.
+ assumeSupportedDevice();
+ assumeProtectedVM();
+ assumeVsrCompliant();
+ assumeTrue("Vendor API must be at least 202404", getVendorApiLevel() >= 202404);
+
+ grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
+ VirtualMachineConfig config =
+ newVmConfigBuilderWithPayloadConfig("assets/vm_config.json")
+ .setDebugLevel(DEBUG_LEVEL_FULL)
+ .build();
+ VirtualMachine vm = forceCreateNewVirtualMachine("bcc_vm_for_vsr", config);
+ TestResults testResults =
+ runVmTestService(
+ TAG,
+ vm,
+ (service, results) -> {
+ results.mBcc = service.getBcc();
+ });
+ testResults.assertNoException();
+ byte[] bccBytes = testResults.mBcc;
+ assertThat(bccBytes).isNotNull();
+ assertThat(HwTrustJni.validateDiceChain(bccBytes)).isTrue();
+ }
+
+ @Test
@CddTest(requirements = {
"9.17/C-1-1",
"9.17/C-1-2"
diff --git a/tests/testapk/src/native/hwtrust_jni.rs b/tests/testapk/src/native/hwtrust_jni.rs
new file mode 100644
index 0000000..3b00364
--- /dev/null
+++ b/tests/testapk/src/native/hwtrust_jni.rs
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 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.
+ */
+
+//! JNI bindings to call into `hwtrust` from Java.
+
+use anyhow::Result;
+use hwtrust::{dice, session::Session};
+use jni::objects::{JByteArray, JClass};
+use jni::sys::jboolean;
+use jni::JNIEnv;
+use log::{debug, error, info};
+
+/// Validates the given DICE chain.
+#[no_mangle]
+pub extern "system" fn Java_com_android_microdroid_test_HwTrustJni_validateDiceChain(
+ env: JNIEnv,
+ _class: JClass,
+ dice_chain: JByteArray,
+) -> jboolean {
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("hwtrust_jni")
+ .with_max_level(log::LevelFilter::Debug),
+ );
+ debug!("Starting the DICE chain validation ...");
+ match validate_dice_chain(env, dice_chain) {
+ Ok(_) => {
+ info!("DICE chain validated successfully");
+ true
+ }
+ Err(e) => {
+ error!("Failed to validate DICE chain: {:?}", e);
+ false
+ }
+ }
+ .into()
+}
+
+fn validate_dice_chain(env: JNIEnv, jdice_chain: JByteArray) -> Result<()> {
+ let dice_chain = env.convert_byte_array(jdice_chain)?;
+ let session = Session::default();
+ let _chain = dice::Chain::from_cbor(&session, &dice_chain)?;
+ Ok(())
+}
diff --git a/virtualizationmanager/Android.bp b/virtualizationmanager/Android.bp
index ada66dd..ae85934 100644
--- a/virtualizationmanager/Android.bp
+++ b/virtualizationmanager/Android.bp
@@ -71,6 +71,7 @@
"liblibfdt",
"libfsfdt",
"libhypervisor_props",
+ "libuuid",
// TODO(b/202115393) stabilize the interface
"packagemanager_aidl-rust",
],
diff --git a/virtualizationmanager/src/composite.rs b/virtualizationmanager/src/composite.rs
index a4b7eae..681ec59 100644
--- a/virtualizationmanager/src/composite.rs
+++ b/virtualizationmanager/src/composite.rs
@@ -23,6 +23,8 @@
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
+use uuid::Uuid;
+
/// Constructs a composite disk image for the given list of partitions, and opens it ready to use.
///
/// Returns the composite disk image file, and a list of files whose file descriptors must be passed
@@ -105,6 +107,7 @@
partition_type: ImagePartitionType::LinuxFilesystem,
writable: partition.writable,
size,
+ part_guid: partition.guid.as_deref().map(Uuid::parse_str).transpose()?,
})
})
.collect::<Result<_, Error>>()?;
diff --git a/virtualizationmanager/src/payload.rs b/virtualizationmanager/src/payload.rs
index 9d0c7d6..82d9ba0 100644
--- a/virtualizationmanager/src/payload.rs
+++ b/virtualizationmanager/src/payload.rs
@@ -289,6 +289,7 @@
label: "payload-metadata".to_owned(),
image: Some(metadata_file),
writable: false,
+ guid: None,
}];
for (i, apex_info) in apex_infos.iter().enumerate() {
@@ -297,17 +298,20 @@
label: format!("microdroid-apex-{}", i),
image: Some(apex_file),
writable: false,
+ guid: None,
});
}
partitions.push(Partition {
label: "microdroid-apk".to_owned(),
image: Some(ParcelFileDescriptor::new(apk_file)),
writable: false,
+ guid: None,
});
partitions.push(Partition {
label: "microdroid-apk-idsig".to_owned(),
image: Some(ParcelFileDescriptor::new(idsig_file)),
writable: false,
+ guid: None,
});
// we've already checked that extra_apks and extraIdsigs are in the same size.
@@ -319,6 +323,7 @@
label: format!("extra-apk-{i}"),
image: Some(ParcelFileDescriptor::new(extra_apk_file)),
writable: false,
+ guid: None,
});
partitions.push(Partition {
@@ -330,6 +335,7 @@
.with_context(|| format!("Failed to clone the extra idsig #{i}"))?,
)),
writable: false,
+ guid: None,
});
}
@@ -416,6 +422,7 @@
label: "microdroid-vendor".to_owned(),
image: Some(ParcelFileDescriptor::new(vendor_image)),
writable: false,
+ guid: None,
}],
})
}
@@ -439,6 +446,7 @@
label: "vm-instance".to_owned(),
image: Some(ParcelFileDescriptor::new(instance_file)),
writable: true,
+ guid: None,
}];
if let Some(file) = storage_image {
@@ -446,6 +454,7 @@
label: "encryptedstore".to_owned(),
image: Some(ParcelFileDescriptor::new(file)),
writable: true,
+ guid: None,
});
}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
index 825c3da..11a2115 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
@@ -25,4 +25,7 @@
/** Whether the partition should be writable by the VM. */
boolean writable;
+
+ /** GUID of the partition. If not set, automatically created */
+ @nullable String guid;
}
diff --git a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
index 258aeea..ef94be5 100644
--- a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
+++ b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
@@ -131,6 +131,26 @@
VirtualMachineCustomImageConfig.Disk.RODisk(
item.getString("image")));
}
+ } else if (item.has("partitions")) {
+ boolean diskWritable = item.optBoolean("writable", false);
+ VirtualMachineCustomImageConfig.Disk disk =
+ diskWritable
+ ? VirtualMachineCustomImageConfig.Disk.RWDisk(null)
+ : VirtualMachineCustomImageConfig.Disk.RODisk(null);
+ JSONArray partitions = item.getJSONArray("partitions");
+ for (int j = 0; j < partitions.length(); j++) {
+ JSONObject partition = partitions.getJSONObject(j);
+ String label = partition.getString("label");
+ String path = partition.getString("path");
+ boolean partitionWritable =
+ diskWritable && partition.optBoolean("writable", false);
+ String guid = partition.optString("guid");
+ VirtualMachineCustomImageConfig.Partition p =
+ new VirtualMachineCustomImageConfig.Partition(
+ label, path, partitionWritable, guid);
+ disk.addPartition(p);
+ }
+ customImageConfigBuilder.addDisk(disk);
}
}
}
@@ -303,7 +323,7 @@
} catch (VirtualMachineException e) {
vmm.delete(VM_NAME);
mVirtualMachine = vmm.create(VM_NAME, config);
- Log.e(TAG, "error" + e);
+ Log.e(TAG, "error for setting VM config", e);
}
Log.d(TAG, "vm start");
@@ -367,7 +387,9 @@
@Override
public void surfaceChanged(
SurfaceHolder holder, int format, int width, int height) {
- Log.d(TAG, "width: " + width + ", height: " + height);
+ Log.d(
+ TAG,
+ "surface changed, width: " + width + ", height: " + height);
}
@Override
@@ -393,8 +415,13 @@
runWithDisplayService(
(service) -> service.setCursorStream(pfds[1]));
} catch (Exception e) {
- Log.d("TAG", "failed to run cursor stream handler", e);
+ Log.d(TAG, "failed to run cursor stream handler", e);
}
+ Log.d(
+ TAG,
+ "ICrosvmAndroidDisplayService.setSurface("
+ + holder.getSurface()
+ + ")");
runWithDisplayService(
(service) ->
service.setSurface(
@@ -404,7 +431,12 @@
@Override
public void surfaceChanged(
SurfaceHolder holder, int format, int width, int height) {
- Log.d(TAG, "width: " + width + ", height: " + height);
+ Log.d(
+ TAG,
+ "cursor surface changed, width: "
+ + width
+ + ", height: "
+ + height);
}
@Override
@@ -412,13 +444,6 @@
Log.d(TAG, "ICrosvmAndroidDisplayService.removeSurface()");
runWithDisplayService(
(service) -> service.removeSurface(true /* forCursor */));
- if (mCursorStream != null) {
- try {
- mCursorStream.close();
- } catch (IOException e) {
- Log.d(TAG, "failed to close fd", e);
- }
- }
}
});
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@@ -481,13 +506,13 @@
// Byte 0: Data type
// Byte 1-3: Padding alignment & Reserved for other use cases in the future
// Byte 4-7: Data size of the payload
- private ByteBuffer constructClipboardHeader(byte type, int dataSize) {
+ private byte[] constructClipboardHeader(byte type, int dataSize) {
ByteBuffer header = ByteBuffer.allocate(8);
header.clear();
header.order(ByteOrder.LITTLE_ENDIAN);
header.put(0, type);
header.putInt(4, dataSize);
- return header;
+ return header.array();
}
private ParcelFileDescriptor connectClipboardSharingServer() {
@@ -504,25 +529,22 @@
private boolean writeClipboardToVm() {
ClipboardManager clipboardManager = getClipboardManager();
-
if (!clipboardManager.hasPrimaryClip()) {
Log.d(TAG, "host device has no clipboard data");
return true;
}
ClipData clip = clipboardManager.getPrimaryClip();
String text = clip.getItemAt(0).getText().toString();
- ByteBuffer header =
+ byte[] header =
constructClipboardHeader(
WRITE_CLIPBOARD_TYPE_TEXT_PLAIN, text.getBytes().length + 1);
-
ParcelFileDescriptor pfd = connectClipboardSharingServer();
if (pfd == null) {
Log.d(TAG, "file descriptor of ClipboardSharingServer is null");
return false;
}
- OutputStream stream = new AutoCloseOutputStream(pfd);
- try {
- stream.write(header.array());
+ try (OutputStream stream = new AutoCloseOutputStream(pfd)) {
+ stream.write(header);
stream.write(text.getBytes());
stream.flush();
Log.d(TAG, "successfully wrote clipboard data to the VM");
@@ -534,16 +556,14 @@
}
private boolean readClipboardFromVm() {
- ByteBuffer request = constructClipboardHeader(READ_CLIPBOARD_FROM_VM, 0);
-
+ byte[] request = constructClipboardHeader(READ_CLIPBOARD_FROM_VM, 0);
ParcelFileDescriptor pfd = connectClipboardSharingServer();
if (pfd == null) {
Log.d(TAG, "file descriptor of ClipboardSharingServer is null");
return false;
}
- OutputStream output = new AutoCloseOutputStream(pfd);
- try {
- output.write(request.array());
+ try (OutputStream output = new AutoCloseOutputStream(pfd)) {
+ output.write(request);
output.flush();
Log.d(TAG, "successfully send request to the VM for reading clipboard");
} catch (IOException e) {
@@ -551,8 +571,7 @@
return false;
}
- InputStream input = new AutoCloseInputStream(pfd);
- try {
+ try (InputStream input = new AutoCloseInputStream(pfd)) {
ByteBuffer header = ByteBuffer.wrap(input.readNBytes(8));
header.order(ByteOrder.LITTLE_ENDIAN);
switch (header.get(0)) {
@@ -611,9 +630,9 @@
ICrosvmAndroidDisplayService.Stub.asInterface(vs.waitDisplayService());
assert service != null;
func.apply(service);
- Log.d(TAG, "job done");
+ Log.d(TAG, "display service runs successfully");
} catch (Exception e) {
- Log.d(TAG, "error", e);
+ Log.d(TAG, "error on running display service", e);
}
}
@@ -628,7 +647,7 @@
@Override
public void run() {
- Log.d(TAG, "CursorHandler");
+ Log.d(TAG, "running CursorHandler");
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(8 /* (x: u32, y: u32) */);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
@@ -649,7 +668,7 @@
});
}
} catch (IOException e) {
- Log.e(TAG, e.getMessage());
+ Log.e(TAG, "failed to run CursorHandler", e);
}
}
}