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/common/Android.bp b/compos/common/Android.bp
index 5893fd6..7c61d94 100644
--- a/compos/common/Android.bp
+++ b/compos/common/Android.bp
@@ -14,8 +14,10 @@
         "libbinder_rpc_unstable_bindgen",
         "libbinder_rs",
         "liblog_rust",
+        "libnum_traits",
         "librustutils",
     ],
+    proc_macros: ["libnum_derive"],
     shared_libs: [
         "libbinder_rpc_unstable",
     ],
diff --git a/compos/common/lib.rs b/compos/common/lib.rs
index 9b07030..5c28379 100644
--- a/compos/common/lib.rs
+++ b/compos/common/lib.rs
@@ -17,6 +17,7 @@
 //! Common items used by CompOS server and/or clients
 
 pub mod compos_client;
+pub mod odrefresh;
 pub mod timeouts;
 
 /// Special CID indicating "any".
diff --git a/compos/common/odrefresh.rs b/compos/common/odrefresh.rs
new file mode 100644
index 0000000..7838b69
--- /dev/null
+++ b/compos/common/odrefresh.rs
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! Helpers for running odrefresh
+
+use num_derive::FromPrimitive;
+use num_traits::FromPrimitive;
+
+/// The path to the odrefresh binary
+pub const ODREFRESH_PATH: &str = "/apex/com.android.art/bin/odrefresh";
+
+// TODO: What if this changes?
+const EX_MAX: i8 = 78;
+
+/// The defined odrefresh exit codes - see art/odrefresh/include/odrefresh/odrefresh.h
+#[derive(Debug, PartialEq, Eq, FromPrimitive)]
+#[repr(i8)]
+pub enum ExitCode {
+    /// No compilation required, all artifacts look good
+    Okay = 0i8,
+    /// Compilation required
+    CompilationRequired = EX_MAX + 1,
+    /// New artifacts successfully generated
+    CompilationSuccess = EX_MAX + 2,
+    /// Compilation failed
+    CompilationFailed = EX_MAX + 3,
+    /// Removal of existing invalid artifacts failed
+    CleanupFailed = EX_MAX + 4,
+}
+
+impl ExitCode {
+    /// Map an integer to the corresponding ExitCode enum, if there is one
+    pub fn from_i32(exit_code: i32) -> Option<Self> {
+        FromPrimitive::from_i32(exit_code)
+    }
+}