Merge "Fix microdroid boot with newer crosvm"
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 39a612f..a0215c3 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -35,6 +35,10 @@
         target: "/system/etc",
         name: "etc",
     },
+    {
+        target: "/system/bin",
+        name: "bin",
+    },
 ]
 
 android_system_image {
@@ -88,6 +92,12 @@
         "microdroid_keystore2_key_contexts",
         "microdroid_compatibility_matrix",
         "microdroid_manifest",
+
+        // TODO(b/195425111) these four should be added automatically
+        "android.hardware.security.secureclock-V1-ndk",
+        "android.hardware.security.sharedsecret-V1-ndk",
+        "libcrypto",
+        "liblzma",
     ] + microdroid_shell_and_utilities,
     multilib: {
         common: {
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 043577d..d43ab22 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -117,17 +117,9 @@
     # The bind+remount combination allows this to work in containers.
     mount rootfs rootfs / remount bind ro nodev
 
-    start keystore2
-
-on late-fs
-    start vendor.keymint-microdroid
-
     # TODO(b/185767624): change the hard-coded size?
     mount tmpfs tmpfs /data noatime nosuid nodev rw size=128M
 
-on post-fs-data
-    mark_post_data
-
     # We chown/chmod /data again so because mount is run as root + defaults
     chown system system /data
     chmod 0771 /data
@@ -135,6 +127,21 @@
     # We restorecon /data in case the userdata partition has been reset.
     restorecon /data
 
+    # set up keystore directory structure first so that we can end early boot
+    # and start apexd
+    mkdir /data/misc 01771 system misc
+    mkdir /data/misc/keystore 0700 keystore keystore
+    # work around b/183668221
+    restorecon /data/misc /data/misc/keystore
+
+    start keystore2
+
+on late-fs
+    start vendor.keymint-microdroid
+
+on post-fs-data
+    mark_post_data
+
     mkdir /data/vendor 0771 root root
     mkdir /data/vendor_ce 0771 root root
     mkdir /data/vendor_de 0771 root root
@@ -148,13 +155,6 @@
 
     start tombstoned
 
-    # set up keystore directory structure first so that we can end early boot
-    # and start apexd
-    mkdir /data/misc 01771 system misc
-    mkdir /data/misc/keystore 0700 keystore keystore
-    # work around b/183668221
-    restorecon /data/misc /data/misc/keystore
-
     # Boot level 30
     # odsign signing keys have MAX_BOOT_LEVEL=30
     # This is currently the earliest boot level, but we start at 30
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index 4ea156a..0ea5d87 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -16,9 +16,9 @@
         "libmicrodroid_metadata",
         "libmicrodroid_payload_config",
         "libprotobuf",
+        "librustutils",
         "libserde",
         "libserde_json",
-        "libsystem_properties-rust",
         "libvsock",
     ],
     init_rc: ["microdroid_manager.rc"],
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 9efa68a..2586737 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -20,13 +20,13 @@
 use anyhow::{anyhow, bail, Result};
 use log::{error, info, warn};
 use microdroid_payload_config::{Task, TaskType, VmPayloadConfig};
+use rustutils::system_properties::PropertyWatcher;
 use std::fs::{self, File};
 use std::os::unix::io::{FromRawFd, IntoRawFd};
 use std::path::Path;
 use std::process::{Command, Stdio};
 use std::str;
 use std::time::Duration;
-use system_properties::PropertyWatcher;
 use vsock::VsockStream;
 
 const WAIT_TIMEOUT: Duration = Duration::from_secs(10);
@@ -40,7 +40,7 @@
         let config = load_config(Path::new(&metadata.payload_config_path))?;
 
         let fake_secret = "This is a placeholder for a value that is derived from the images that are loaded in the VM.";
-        if let Err(err) = system_properties::write("ro.vmsecret.keymint", fake_secret) {
+        if let Err(err) = rustutils::system_properties::write("ro.vmsecret.keymint", fake_secret) {
             warn!("failed to set ro.vmsecret.keymint: {}", err);
         }
 
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index c05a841..8881c51 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -69,13 +69,8 @@
         assertThat(runOnMicrodroid("getprop", "debug.microdroid.app.run"), is("true"));
         assertThat(runOnMicrodroid("getprop", "debug.microdroid.app.sublib.run"), is("true"));
 
-        // Manually execute the library and check the output
-        final String microdroidLauncher = "system/bin/microdroid_launcher";
-        assertThat(
-                runOnMicrodroid(microdroidLauncher, testLib, "arg1", "arg2"),
-                is("Hello Microdroid " + testLib + " arg1 arg2"));
-
-        // Check that keystore was found by the payload
+        // Check that keystore was found by the payload. Wait until the property is set.
+        tryRunOnMicrodroid("watch -e \"getprop debug.microdroid.test.keystore | grep '^$'\"");
         assertThat(runOnMicrodroid("getprop", "debug.microdroid.test.keystore"), is("PASS"));
 
         shutdownMicrodroid(getDevice(), cid);
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 64d3913..dc38075 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -128,14 +128,13 @@
         let config = config.as_ref();
 
         let zero_filler_path = temporary_directory.join("zero.img");
-        let zero_filler_file = write_zero_filler(&zero_filler_path).map_err(|e| {
+        write_zero_filler(&zero_filler_path).map_err(|e| {
             error!("Failed to make composite image: {}", e);
             new_binder_exception(
                 ExceptionCode::SERVICE_SPECIFIC,
                 format!("Failed to make composite image: {}", e),
             )
         })?;
-        indirect_files.push(zero_filler_file);
 
         // Assemble disk images if needed.
         let disks = config
@@ -291,7 +290,7 @@
     Ok(())
 }
 
-fn write_zero_filler(zero_filler_path: &Path) -> Result<File> {
+fn write_zero_filler(zero_filler_path: &Path) -> Result<()> {
     let file = OpenOptions::new()
         .create_new(true)
         .read(true)
@@ -299,7 +298,7 @@
         .open(zero_filler_path)
         .with_context(|| "Failed to create zero.img")?;
     file.set_len(ZERO_FILLER_SIZE)?;
-    Ok(file)
+    Ok(())
 }
 
 /// Given the configuration for a disk image, assembles the `DiskFile` to pass to crosvm.
diff --git a/virtualizationservice/src/composite.rs b/virtualizationservice/src/composite.rs
index 685d0e6..ded0053 100644
--- a/virtualizationservice/src/composite.rs
+++ b/virtualizationservice/src/composite.rs
@@ -290,9 +290,9 @@
 
 /// 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 FD mappings which must be applied to any
-/// process which wants to use it. This is necessary because the composite image contains paths of
-/// the form `/proc/self/fd/N` for the partition images.
+/// Returns the composite disk image file, and a list of files whose file descriptors must be passed
+/// to any process which wants to use it. This is necessary because the composite image contains
+/// paths of the form `/proc/self/fd/N` for the partition images.
 pub fn make_composite_image(
     partitions: &[Partition],
     zero_filler_path: &Path,
@@ -300,7 +300,7 @@
     header_path: &Path,
     footer_path: &Path,
 ) -> Result<(File, Vec<File>), Error> {
-    let (partitions, files) = convert_partitions(partitions)?;
+    let (partitions, mut files) = convert_partitions(partitions)?;
 
     let mut composite_image = OpenOptions::new()
         .create_new(true)
@@ -316,13 +316,16 @@
         OpenOptions::new().create_new(true).read(true).write(true).open(footer_path).with_context(
             || format!("Failed to create composite image header {:?}", footer_path),
         )?;
+    let zero_filler_file = File::open(&zero_filler_path).with_context(|| {
+        format!("Failed to open composite image zero filler {:?}", zero_filler_path)
+    })?;
 
     create_composite_disk(
         &partitions,
-        zero_filler_path,
-        header_path,
+        &fd_path_for_file(&zero_filler_file),
+        &fd_path_for_file(&header_file),
         &mut header_file,
-        footer_path,
+        &fd_path_for_file(&footer_file),
         &mut footer_file,
         &mut composite_image,
     )?;
@@ -331,12 +334,16 @@
     let composite_image = File::open(&output_path)
         .with_context(|| format!("Failed to open composite image {:?}", output_path))?;
 
+    files.push(header_file);
+    files.push(footer_file);
+    files.push(zero_filler_file);
+
     Ok((composite_image, files))
 }
 
 /// Given the AIDL config containing a list of partitions, with a [`ParcelFileDescriptor`] for each
-/// partition, return the list of file descriptors which must be passed to the composite disk image
-/// partition configuration for it.
+/// partition, returns the corresponding list of PartitionInfo and the list of files whose file
+/// descriptors must be passed to any process using the composite image.
 fn convert_partitions(partitions: &[Partition]) -> Result<(Vec<PartitionInfo>, Vec<File>), Error> {
     // File descriptors to pass to child process.
     let mut files = vec![];
@@ -353,12 +360,12 @@
                 .try_clone()
                 .context("Failed to clone partition image file descriptor")?;
             let size = get_partition_size(&file)?;
-            let fd = file.as_raw_fd();
+            let path = fd_path_for_file(&file);
             files.push(file);
 
             Ok(PartitionInfo {
                 label: partition.label.to_owned(),
-                path: format!("/proc/self/fd/{}", fd).into(),
+                path,
                 partition_type: ImagePartitionType::LinuxFilesystem,
                 writable: partition.writable,
                 size,
@@ -369,6 +376,11 @@
     Ok((partitions, files))
 }
 
+fn fd_path_for_file(file: &File) -> PathBuf {
+    let fd = file.as_raw_fd();
+    format!("/proc/self/fd/{}", fd).into()
+}
+
 /// Find the size of the partition image in the given file by parsing the header.
 ///
 /// This will work for raw, QCOW2, composite and Android sparse images.