Use --force-compile for tests

The test uses --force-compile outside the VM, so we also need to
inside the VM. But we want --compile for the normal case of
compilation, so we only produce exactly the required artifacts.

That means we have to pass whether we are testing or not from the host
to guest, so lots of plumbing is needed.

(Also figured out how to solve a problem with type deduction that the
me of a few months ago was baffled by.)

Bug: 211458160
Test: atest ComposTestCase
Change-Id: Ie7e36bc3fab40744e9f9ea5e5928126899d9060d
diff --git a/compos/src/compilation.rs b/compos/src/compilation.rs
index e8f55f8..7e3834a 100644
--- a/compos/src/compilation.rs
+++ b/compos/src/compilation.rs
@@ -18,6 +18,7 @@
 use log::{debug, info, warn};
 use minijail::{self, Minijail};
 use regex::Regex;
+use rustutils::system_properties;
 use std::collections::HashMap;
 use std::env;
 use std::ffi::OsString;
@@ -35,11 +36,13 @@
     IAuthFsService::IAuthFsService,
 };
 use authfs_aidl_interface::binder::Strong;
+use compos_aidl_interface::aidl::com::android::compos::ICompOsService::CompilationMode::CompilationMode;
 use compos_common::odrefresh::ExitCode;
 
 const FD_SERVER_PORT: i32 = 3264; // TODO: support dynamic port
 
 pub struct OdrefreshContext<'a> {
+    compilation_mode: CompilationMode,
     system_dir_fd: i32,
     output_dir_fd: i32,
     staging_dir_fd: i32,
@@ -50,6 +53,7 @@
 
 impl<'a> OdrefreshContext<'a> {
     pub fn new(
+        compilation_mode: CompilationMode,
         system_dir_fd: i32,
         output_dir_fd: i32,
         staging_dir_fd: i32,
@@ -57,6 +61,13 @@
         zygote_arch: &'a str,
         system_server_compiler_filter: &'a str,
     ) -> Result<Self> {
+        if compilation_mode != CompilationMode::NORMAL_COMPILE {
+            let debuggable = system_properties::read_bool("ro.boot.microdroid.debuggable", false)?;
+            if !debuggable {
+                bail!("Requested compilation mode only available in debuggable VMs");
+            }
+        }
+
         if system_dir_fd < 0 || output_dir_fd < 0 || staging_dir_fd < 0 {
             bail!("The remote FDs are expected to be non-negative");
         }
@@ -75,6 +86,7 @@
         // CompOS.
 
         Ok(Self {
+            compilation_mode,
             system_dir_fd,
             output_dir_fd,
             staging_dir_fd,
@@ -143,18 +155,21 @@
         ));
     }
 
-    args.push("--compile".to_string());
+    let compile_flag = match context.compilation_mode {
+        CompilationMode::NORMAL_COMPILE => "--compile",
+        CompilationMode::TEST_COMPILE => "--force-compile",
+        other => bail!("Unknown compilation mode {:?}", other),
+    };
+    args.push(compile_flag.to_string());
 
     debug!("Running odrefresh with args: {:?}", &args);
     let jail = spawn_jailed_task(odrefresh_path, &args, &odrefresh_vars.into_env())
         .context("Spawn odrefresh")?;
     let exit_code = match jail.wait() {
-        Ok(_) => Result::<u8>::Ok(0),
-        Err(minijail::Error::ReturnCode(exit_code)) => Ok(exit_code),
-        Err(e) => {
-            bail!("Unexpected minijail error: {}", e)
-        }
-    }?;
+        Ok(_) => 0,
+        Err(minijail::Error::ReturnCode(exit_code)) => exit_code,
+        Err(e) => bail!("Unexpected minijail error: {}", e),
+    };
 
     let exit_code = ExitCode::from_i32(exit_code.into())?;
     info!("odrefresh exited with {:?}", exit_code);
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index 422f271..9d754a7 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -31,7 +31,7 @@
 use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
 use compos_aidl_interface::aidl::com::android::compos::{
     CompOsKeyData::CompOsKeyData,
-    ICompOsService::{BnCompOsService, ICompOsService},
+    ICompOsService::{BnCompOsService, CompilationMode::CompilationMode, ICompOsService},
 };
 use compos_aidl_interface::binder::{
     BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong,
@@ -82,6 +82,7 @@
 
     fn odrefresh(
         &self,
+        compilation_mode: CompilationMode,
         system_dir_fd: i32,
         output_dir_fd: i32,
         staging_dir_fd: i32,
@@ -90,6 +91,7 @@
         system_server_compiler_filter: &str,
     ) -> BinderResult<i8> {
         let context = to_binder_result(OdrefreshContext::new(
+            compilation_mode,
             system_dir_fd,
             output_dir_fd,
             staging_dir_fd,