Fix race condition between authfs_service and /data mounted

Currently there is a race condition between authfs_service starting and
/data/misc/authfs directory being created. If authfs_service is started
before the /data/misc/authfs has been created then authfs_service will
exit abnormally. One way this race condition is surface is
android.compos.test.ComposTestCase#testOdrefreshSpeedProfile being
flaky.

This change attempts to fix the race condition by starting the
authfs_service on post-fs-data trigger, which guarantees that
/data/misc/authfs has been prepared.

In more detail this change includes:

* Introducing new setup_config_syspros function inside the
  microdroid_manager. This function is responsible for setting sysprops
  derived from the payload config, e.g. if config has enable_authfs,
  then microdroid.config.enable_authfs sysprop will be set. Once all the
  necessary sysprops were set, microdroid_manager will set the
  microdroid.config_done property.
* Adding wait_for_prop microdroid.config_done before triggering
  post-fs-data action in the init.rc
* Adding on post-fs-data && prop:microdroid.config.enable_authfs=1
  trigger to start authfs_service
* Moving setprop dev.bootcomplete to on boot action, and switching
  microdroid_manager to wait for the dev.bootcomplete property before
  running the payload.

The first three points should get rid of the race condition with
authfs_service startup, while the last one should guarantee that by the
time payload runs the authfs_service is already running.

Bug: 260361248
Bug: 260005615
Test: presubmit
Test: atest --iterations 20 android.compos.test.ComposTestCase#testOdrefreshSpeedProfile
Change-Id: Ib8d2dde5f340ffead9e681c18fa8dd18ba2dd859
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 94ef940..7d04557 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -74,6 +74,12 @@
     # some services can be started.
     trigger late-fs
 
+    # Wait for microdroid_manager to finish setting up sysprops from the payload config.
+    # Some further actions in the boot sequence might depend on the sysprops from the payloag,
+    # e.g. microdroid.config.enable_authfs configures whether to run authfs_service after
+    # /data is mounted.
+    wait_for_prop microdroid_manager.config_done 1
+
     trigger post-fs-data
 
     # Load persist properties and override properties (if enabled) from /data.
@@ -132,6 +138,13 @@
     mkdir /data/local 0751 root root
     mkdir /data/local/tmp 0771 shell shell
 
+on post-fs-data && property:microdroid_manager.authfs.enabled=1
+    start authfs_service
+
+on boot
+    # Mark boot completed. This will notify microdroid_manager to run payload.
+    setprop dev.bootcomplete 1
+
 service tombstone_transmit /system/bin/tombstone_transmit.microdroid -cid 2 -port 2000 -remove_tombstones_after_transmitting
     user system
     group system
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index a706dbe..17532d7 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -417,9 +417,10 @@
     mount_extra_apks(&config)?;
 
     // Wait until apex config is done. (e.g. linker configuration for apexes)
-    // TODO(jooyung): wait until sys.boot_completed?
     wait_for_apex_config_done()?;
 
+    setup_config_sysprops(&config)?;
+
     // Start tombstone_transmit if enabled
     if config.export_tombstones {
         control_service("start", "tombstone_transmit")?;
@@ -427,11 +428,6 @@
         control_service("stop", "tombstoned")?;
     }
 
-    // Start authfs if enabled
-    if config.enable_authfs {
-        control_service("start", "authfs_service")?;
-    }
-
     // Wait until zipfuse has mounted the APK so we can access the payload
     wait_for_property_true(APK_MOUNT_DONE_PROP).context("Failed waiting for APK mount done")?;
 
@@ -442,7 +438,8 @@
         ensure!(exitcode.success(), "Unable to prepare encrypted storage. Exitcode={}", exitcode);
     }
 
-    system_properties::write("dev.bootcomplete", "1").context("set dev.bootcomplete")?;
+    wait_for_property_true("dev.bootcomplete").context("failed waiting for dev.bootcomplete")?;
+    info!("boot completed, time to run payload");
     exec_task(task, service).context("Failed to run payload")
 }
 
@@ -682,6 +679,16 @@
     Ok(())
 }
 
+fn setup_config_sysprops(config: &VmPayloadConfig) -> Result<()> {
+    if config.enable_authfs {
+        system_properties::write("microdroid_manager.authfs.enabled", "1")
+            .context("failed to write microdroid_manager.authfs.enabled")?;
+    }
+    system_properties::write("microdroid_manager.config_done", "1")
+        .context("failed to write microdroid_manager.config_done")?;
+    Ok(())
+}
+
 // Waits until linker config is generated
 fn wait_for_apex_config_done() -> Result<()> {
     wait_for_property_true(APEX_CONFIG_DONE_PROP).context("Failed waiting for apex config done")