microdroid_manager: start zipfuse early

Microdroid_manager orchestrates sub tasks with more explicit
events.
- starts zipfuse after APK verification is done & before reading config
  from payload.
- executes payload after apex_config is done.

Bug: n/a
Test: MicrodroidHostTestCases
Change-Id: I3bd7adf97b3aaa6709aea516d41d6c9002025207
diff --git a/microdroid_manager/src/ioutil.rs b/microdroid_manager/src/ioutil.rs
index e8732ad..ab82e05 100644
--- a/microdroid_manager/src/ioutil.rs
+++ b/microdroid_manager/src/ioutil.rs
@@ -14,6 +14,7 @@
 
 //! IO utilities
 
+use anyhow::{anyhow, Result};
 use std::fs::File;
 use std::io;
 use std::path::Path;
@@ -23,17 +24,17 @@
 const SLEEP_DURATION: Duration = Duration::from_millis(5);
 
 /// waits for a file with a timeout and returns it
-pub fn wait_for_file<P: AsRef<Path>>(path: P, timeout: Duration) -> io::Result<File> {
+pub fn wait_for_file<P: AsRef<Path>>(path: P, timeout: Duration) -> Result<File> {
     let begin = Instant::now();
     loop {
         match File::open(&path) {
             Ok(file) => return Ok(file),
             Err(error) => {
                 if error.kind() != io::ErrorKind::NotFound {
-                    return Err(error);
+                    return Err(anyhow!(error));
                 }
                 if begin.elapsed() > timeout {
-                    return Err(io::Error::from(io::ErrorKind::NotFound));
+                    return Err(anyhow!(io::Error::from(io::ErrorKind::NotFound)));
                 }
                 thread::sleep(SLEEP_DURATION);
             }
@@ -47,7 +48,7 @@
     use std::io::{Read, Write};
 
     #[test]
-    fn test_wait_for_file() -> io::Result<()> {
+    fn test_wait_for_file() -> Result<()> {
         let test_dir = tempfile::TempDir::new().unwrap();
         let test_file = test_dir.path().join("test.txt");
         thread::spawn(move || -> io::Result<()> {
@@ -69,6 +70,9 @@
         let test_file = test_dir.path().join("test.txt");
         let file = wait_for_file(&test_file, Duration::from_secs(1));
         assert!(file.is_err());
-        assert_eq!(io::ErrorKind::NotFound, file.unwrap_err().kind());
+        assert_eq!(
+            io::ErrorKind::NotFound,
+            file.unwrap_err().root_cause().downcast_ref::<io::Error>().unwrap().kind()
+        );
     }
 }
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 2e80b90..6db3cab 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -111,13 +111,11 @@
         instance.write_microdroid_data(&verified_data).context("Failed to write identity data")?;
     }
 
-    wait_for_apex_config_done()?;
+    // Before reading a file from the APK, start zipfuse
+    system_properties::write("ctl.start", "zipfuse")?;
 
     let service = get_vms_rpc_binder().expect("cannot connect to VirtualMachineService");
     if !metadata.payload_config_path.is_empty() {
-        // Before reading a file from the APK, start zipfuse
-        system_properties::write("ctl.start", "zipfuse")?;
-
         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.";
@@ -125,7 +123,10 @@
             warn!("failed to set ro.vmsecret.keymint: {}", err);
         }
 
+        // Wait until apex config is done. (e.g. linker configuration for apexes)
         // TODO(jooyung): wait until sys.boot_completed?
+        wait_for_apex_config_done()?;
+
         if let Some(main_task) = &config.task {
             exec_task(main_task, &service).map_err(|e| {
                 error!("failed to execute task: {}", e);
diff --git a/zipfuse/Android.bp b/zipfuse/Android.bp
index 46f4b5a..79e6bad 100644
--- a/zipfuse/Android.bp
+++ b/zipfuse/Android.bp
@@ -29,6 +29,7 @@
     name: "zipfuse",
     defaults: ["zipfuse.defaults"],
     init_rc: ["zipfuse.rc"],
+    bootstrap: true,
 }
 
 rust_test {