Async interface for running odrefresh

This creates a variant of startTestOdrefresh that uses the
ICompilationTask async mechanism of startTestCompile.

OdrefreshTask implements ICompilationTask; instead of owning a spawned
odrefresh process it owns the VM and runs the blocking call to compsvc
inside a thread.

Add a new command to composd_cmd to exercise this.

Test: composd_cmd async-odrefresh
Bug: 209572296
Change-Id: I3780d40876dbca17d4e2a3d8f7c2b809f5561aee
diff --git a/compos/composd/src/service.rs b/compos/composd/src/service.rs
index a2898a2..ab28e0a 100644
--- a/compos/composd/src/service.rs
+++ b/compos/composd/src/service.rs
@@ -20,6 +20,7 @@
 use crate::compilation_task::CompilationTask;
 use crate::fd_server_helper::FdServerConfig;
 use crate::instance_manager::InstanceManager;
+use crate::odrefresh_task::OdrefreshTask;
 use crate::util::to_binder_result;
 use android_system_composd::aidl::android::system::composd::{
     ICompilationTask::{BnCompilationTask, ICompilationTask},
@@ -67,6 +68,14 @@
         to_binder_result(self.do_start_test_compile(callback))
     }
 
+    fn startAsyncOdrefresh(
+        &self,
+        callback: &Strong<dyn ICompilationTaskCallback>,
+    ) -> binder::Result<Strong<dyn ICompilationTask>> {
+        check_permissions()?;
+        to_binder_result(self.do_start_async_odrefresh(callback))
+    }
+
     fn startTestOdrefresh(&self) -> binder::Result<i8> {
         check_permissions()?;
         to_binder_result(self.do_odrefresh_for_test())
@@ -97,6 +106,20 @@
         Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
     }
 
+    fn do_start_async_odrefresh(
+        &self,
+        callback: &Strong<dyn ICompilationTaskCallback>,
+    ) -> Result<Strong<dyn ICompilationTask>> {
+        let output_dir_path =
+            composd_native::palette_create_odrefresh_staging_directory()?.to_path_buf();
+
+        let comp_os = self.instance_manager.start_test_instance().context("Starting CompOS")?;
+
+        let task = OdrefreshTask::start(comp_os, output_dir_path, callback)?;
+
+        Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
+    }
+
     fn do_odrefresh_for_test(&self) -> Result<i8> {
         let compos = self
             .instance_manager
@@ -137,7 +160,7 @@
 
 /// Returns an owned FD of the directory. It currently returns a `File` as a FD owner, but
 /// it's better to use `std::os::unix::io::OwnedFd` once/if it becomes standard.
-fn open_dir(path: &Path) -> Result<File> {
+pub fn open_dir(path: &Path) -> Result<File> {
     OpenOptions::new()
         .custom_flags(libc::O_DIRECTORY)
         .read(true) // O_DIRECTORY can only be opened with read