Start to add a function to compile staged APEXes

Add a new method to IIsolatedCompilationService which will eventually
run compilation over staged APEXes. Currently it doesn't, but it is
slightly more realistic than the test compile (which I'm leaving in
place since it's useful for testing) - we use the pending instance of
compos (so odsign will attempt to verify the keys) and we run
odrefresh --compile instead of --force-compile. For now the artifacts
are still written to the test-artifacts directory so odsign doesn't
see them.

Bug: 205296305
Test: composd_cmd staged-apex-compile
Change-Id: If4d449878e38a97aa0f1f1dbb71c9df9b86ca4d5
diff --git a/compos/composd_cmd/composd_cmd.rs b/compos/composd_cmd/composd_cmd.rs
index e591794..f22dc13 100644
--- a/compos/composd_cmd/composd_cmd.rs
+++ b/compos/composd_cmd/composd_cmd.rs
@@ -18,12 +18,13 @@
 
 use android_system_composd::{
     aidl::android::system::composd::{
+        ICompilationTask::ICompilationTask,
         ICompilationTaskCallback::{BnCompilationTaskCallback, ICompilationTaskCallback},
         IIsolatedCompilationService::IIsolatedCompilationService,
     },
     binder::{
         wait_for_interface, BinderFeatures, DeathRecipient, IBinder, Interface, ProcessState,
-        Result as BinderResult,
+        Result as BinderResult, Strong,
     },
 };
 use anyhow::{bail, Context, Result};
@@ -37,7 +38,7 @@
             .index(1)
             .takes_value(true)
             .required(true)
-            .possible_values(&["forced-compile-test", "forced-odrefresh"]),
+            .possible_values(&["staged-apex-compile", "forced-compile-test", "forced-odrefresh"]),
     );
     let args = app.get_matches();
     let command = args.value_of("command").unwrap();
@@ -45,6 +46,7 @@
     ProcessState::start_thread_pool();
 
     match command {
+        "staged-apex-compile" => run_staged_apex_compile()?,
         "forced-compile-test" => run_forced_compile_for_test()?,
         "forced-odrefresh" => run_forced_odrefresh_for_test()?,
         _ => panic!("Unexpected command {}", command),
@@ -103,14 +105,28 @@
     }
 }
 
+fn run_staged_apex_compile() -> Result<()> {
+    run_async_compilation(|service, callback| service.startStagedApexCompile(callback))
+}
+
 fn run_forced_compile_for_test() -> Result<()> {
+    run_async_compilation(|service, callback| service.startTestCompile(callback))
+}
+
+fn run_async_compilation<F>(start_compile_fn: F) -> Result<()>
+where
+    F: FnOnce(
+        &dyn IIsolatedCompilationService,
+        &Strong<dyn ICompilationTaskCallback>,
+    ) -> BinderResult<Strong<dyn ICompilationTask>>,
+{
     let service = wait_for_interface::<dyn IIsolatedCompilationService>("android.system.composd")
         .context("Failed to connect to composd service")?;
 
     let state = Arc::new(State::default());
     let callback = Callback(state.clone());
     let callback = BnCompilationTaskCallback::new_binder(callback, BinderFeatures::default());
-    let task = service.startTestCompile(&callback).context("Compilation failed")?;
+    let task = start_compile_fn(&*service, &callback).context("Compilation failed")?;
 
     // Make sure composd keeps going even if we don't hold a reference to its service.
     drop(service);