Sign artifacts after compilation

If compilation succeeds, pass over all the artifacts we generated and
produce an OdsignInfo file with all the names and digests and a
signature of it using the CompOS key.

Various refactorings along the way to make it eaiser:
- Extract the odrefresh ExitCode enum for reuse
- Extracted a Signer, distinct from an ArtifactSigner
- Defined OdrefreshContext to stop the linter complaining about a
  function with >7 arguments.

Also added more debugging to help fix my various silly mistakes.

Bug: 161471326
Test: composd_cmd forced-odrefresh -> signature file produced
Change-Id: Ia6a6abd9e28158f4767e7752727635087f9bb566
diff --git a/compos/composd/Android.bp b/compos/composd/Android.bp
index 735b9a5..3190395 100644
--- a/compos/composd/Android.bp
+++ b/compos/composd/Android.bp
@@ -20,13 +20,11 @@
         "libcomposd_native_rust",
         "libminijail_rust",
         "libnix",
-        "libnum_traits",
         "liblibc",
         "liblog_rust",
         "librustutils",
         "libshared_child",
     ],
-    proc_macros: ["libnum_derive"],
     apex_available: [
         "com.android.compos",
     ],
diff --git a/compos/composd/src/compilation_task.rs b/compos/composd/src/compilation_task.rs
index 18f5aac..f82a3e9 100644
--- a/compos/composd/src/compilation_task.rs
+++ b/compos/composd/src/compilation_task.rs
@@ -15,12 +15,13 @@
  */
 
 use crate::instance_starter::CompOsInstance;
-use crate::odrefresh::{self, Odrefresh};
+use crate::odrefresh::Odrefresh;
 use android_system_composd::aidl::android::system::composd::{
     ICompilationTask::ICompilationTask, ICompilationTaskCallback::ICompilationTaskCallback,
 };
 use android_system_composd::binder::{Interface, Result as BinderResult, Strong};
 use anyhow::Result;
+use compos_common::odrefresh::ExitCode;
 use log::{error, warn};
 use std::sync::{Arc, Mutex};
 use std::thread;
@@ -91,7 +92,7 @@
             // We don't do the callback if cancel has already happened.
             if let Some(task) = task {
                 let result = match exit_code {
-                    Ok(odrefresh::ExitCode::CompilationSuccess) => task.callback.onSuccess(),
+                    Ok(ExitCode::CompilationSuccess) => task.callback.onSuccess(),
                     Ok(exit_code) => {
                         error!("Unexpected odrefresh result: {:?}", exit_code);
                         task.callback.onFailure()
diff --git a/compos/composd/src/odrefresh.rs b/compos/composd/src/odrefresh.rs
index d6a3435..2cefab0 100644
--- a/compos/composd/src/odrefresh.rs
+++ b/compos/composd/src/odrefresh.rs
@@ -20,10 +20,9 @@
 use anyhow::{bail, Context, Result};
 use compos_aidl_interface::aidl::com::android::compos::ICompOsService::ICompOsService;
 use compos_aidl_interface::binder::Strong;
+use compos_common::odrefresh::{ExitCode, ODREFRESH_PATH};
 use compos_common::timeouts::{need_extra_time, EXTENDED_TIMEOUTS};
 use compos_common::VMADDR_CID_ANY;
-use num_derive::FromPrimitive;
-use num_traits::FromPrimitive;
 use rustutils::system_properties;
 use shared_child::SharedChild;
 use std::fs::{File, OpenOptions};
@@ -32,23 +31,8 @@
 use std::path::Path;
 use std::process::Command;
 
-// TODO: What if this changes?
-const EX_MAX: i8 = 78;
-
-const ODREFRESH_BIN: &str = "/apex/com.android.art/bin/odrefresh";
 const ART_APEX_DATA: &str = "/data/misc/apexdata/com.android.art";
 
-#[derive(Debug, PartialEq, Eq, FromPrimitive)]
-#[repr(i8)]
-pub enum ExitCode {
-    // Copied from art/odrefresh/include/odrefresh/odrefresh.h
-    Okay = 0i8,
-    CompilationRequired = EX_MAX + 1,
-    CompilationSuccess = EX_MAX + 2,
-    CompilationFailed = EX_MAX + 3,
-    CleanupFailed = EX_MAX + 4,
-}
-
 pub struct Odrefresh {
     child: SharedChild,
 }
@@ -64,7 +48,7 @@
 
     fn spawn_odrefresh(target_dir: &str, compile_arg: &str) -> Result<Self> {
         // We don`t need to capture stdout/stderr - odrefresh writes to the log
-        let mut cmdline = Command::new(ODREFRESH_BIN);
+        let mut cmdline = Command::new(ODREFRESH_PATH);
         if need_extra_time()? {
             cmdline
                 .arg(format!(
@@ -87,7 +71,7 @@
     pub fn wait_for_exit(&self) -> Result<ExitCode> {
         // No timeout here - but clients can kill the process, which will end the wait.
         let status = self.child.wait()?;
-        if let Some(exit_code) = status.code().and_then(FromPrimitive::from_i32) {
+        if let Some(exit_code) = status.code().and_then(ExitCode::from_i32) {
             Ok(exit_code)
         } else {
             bail!("odrefresh exited with {}", status)
@@ -122,7 +106,7 @@
     )?;
 
     drop(fd_server_raii);
-    if let Some(exit_code) = FromPrimitive::from_i8(exit_code) {
+    if let Some(exit_code) = ExitCode::from_i32(exit_code.into()) {
         Ok(exit_code)
     } else {
         bail!("odrefresh exited with {}", exit_code)
diff --git a/compos/composd/src/odrefresh_task.rs b/compos/composd/src/odrefresh_task.rs
index 64565dd..262021c 100644
--- a/compos/composd/src/odrefresh_task.rs
+++ b/compos/composd/src/odrefresh_task.rs
@@ -22,6 +22,7 @@
 use android_system_composd::binder::{Interface, Result as BinderResult, Strong};
 use anyhow::Result;
 use compos_aidl_interface::aidl::com::android::compos::ICompOsService::ICompOsService;
+use compos_common::odrefresh::ExitCode;
 use log::{error, warn};
 use std::sync::{Arc, Mutex};
 use std::thread;
@@ -72,7 +73,7 @@
             // We don't do the callback if cancel has already happened.
             if let Some(task) = task {
                 let result = match exit_code {
-                    Ok(odrefresh::ExitCode::CompilationSuccess) => task.callback.onSuccess(),
+                    Ok(ExitCode::CompilationSuccess) => task.callback.onSuccess(),
                     Ok(exit_code) => {
                         error!("Unexpected odrefresh result: {:?}", exit_code);
                         task.callback.onFailure()