Merge "cleanup:Rename IBenchmarkService#readFile to measureReadRate"
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index 946bc5b..d74a6f9 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -33,7 +33,7 @@
 use std::num::NonZeroU32;
 use std::path::{Path, PathBuf};
 use std::thread;
-use vmclient::{DeathReason, VmInstance, VmWaitError};
+use vmclient::{DeathReason, ErrorCode, VmInstance, VmWaitError};
 
 /// This owns an instance of the CompOS VM.
 pub struct ComposClient(VmInstance);
@@ -241,8 +241,8 @@
         log::warn!("VM payload finished, cid = {}, exit code = {}", cid, exit_code);
     }
 
-    fn on_error(&self, cid: i32, error_code: i32, message: &str) {
-        log::warn!("VM error, cid = {}, error code = {}, message = {}", cid, error_code, message);
+    fn on_error(&self, cid: i32, error_code: ErrorCode, message: &str) {
+        log::warn!("VM error, cid = {}, error code = {:?}, message = {}", cid, error_code, message);
     }
 
     fn on_died(&self, cid: i32, death_reason: DeathReason) {
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index cfb851b..f3fa2f5 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -11,6 +11,7 @@
     rustlibs: [
         "android.hardware.security.dice-V1-rust",
         "android.security.dice-rust",
+        "android.system.virtualizationcommon-rust",
         "android.system.virtualizationservice-rust",
         "android.system.virtualmachineservice-rust",
         "libanyhow",
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 9e1890f..e3ad495 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -23,6 +23,10 @@
     Config::Config, InputValues::InputValues, Mode::Mode,
 };
 use android_security_dice::aidl::android::security::dice::IDiceMaintenance::IDiceMaintenance;
+use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode;
+use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::{
+    VM_BINDER_SERVICE_PORT, VM_STREAM_SERVICE_PORT, IVirtualMachineService,
+};
 use anyhow::{anyhow, bail, ensure, Context, Error, Result};
 use apkverify::{get_public_key_der, verify};
 use binder::{wait_for_interface, Strong};
@@ -49,10 +53,6 @@
 use std::time::{Duration, SystemTime};
 use vsock::VsockStream;
 
-use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::{
-    ERROR_PAYLOAD_CHANGED, ERROR_PAYLOAD_VERIFICATION_FAILED, ERROR_PAYLOAD_INVALID_CONFIG, ERROR_UNKNOWN, VM_BINDER_SERVICE_PORT, VM_STREAM_SERVICE_PORT, IVirtualMachineService,
-};
-
 const WAIT_TIMEOUT: Duration = Duration::from_secs(10);
 const MAIN_APK_PATH: &str = "/dev/block/by-name/microdroid-apk";
 const MAIN_APK_IDSIG_PATH: &str = "/dev/block/by-name/microdroid-apk-idsig";
@@ -88,22 +88,24 @@
     InvalidConfig(String),
 }
 
-fn translate_error(err: &Error) -> (i32, String) {
+fn translate_error(err: &Error) -> (ErrorCode, String) {
     if let Some(e) = err.downcast_ref::<MicrodroidError>() {
         match e {
-            MicrodroidError::PayloadChanged(msg) => (ERROR_PAYLOAD_CHANGED, msg.to_string()),
+            MicrodroidError::PayloadChanged(msg) => (ErrorCode::PAYLOAD_CHANGED, msg.to_string()),
             MicrodroidError::PayloadVerificationFailed(msg) => {
-                (ERROR_PAYLOAD_VERIFICATION_FAILED, msg.to_string())
+                (ErrorCode::PAYLOAD_VERIFICATION_FAILED, msg.to_string())
             }
-            MicrodroidError::InvalidConfig(msg) => (ERROR_PAYLOAD_INVALID_CONFIG, msg.to_string()),
+            MicrodroidError::InvalidConfig(msg) => {
+                (ErrorCode::PAYLOAD_CONFIG_INVALID, msg.to_string())
+            }
 
             // Connection failure won't be reported to VS; return the default value
             MicrodroidError::FailedToConnectToVirtualizationService(msg) => {
-                (ERROR_UNKNOWN, msg.to_string())
+                (ErrorCode::UNKNOWN, msg.to_string())
             }
         }
     } else {
-        (ERROR_UNKNOWN, err.to_string())
+        (ErrorCode::UNKNOWN, err.to_string())
     }
 }
 
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index b6b7b09..1493cb8 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -20,6 +20,7 @@
     },
     prefer_rlib: true,
     rustlibs: [
+        "android.system.virtualizationcommon-rust",
         "android.system.virtualizationservice-rust",
         "android.system.virtualmachineservice-rust",
         "android.os.permissions_aidl-rust",
diff --git a/virtualizationservice/aidl/Android.bp b/virtualizationservice/aidl/Android.bp
index 30a4b03..4d5326a 100644
--- a/virtualizationservice/aidl/Android.bp
+++ b/virtualizationservice/aidl/Android.bp
@@ -5,6 +5,7 @@
 aidl_interface {
     name: "android.system.virtualizationservice",
     srcs: ["android/system/virtualizationservice/**/*.aidl"],
+    imports: ["android.system.virtualizationcommon"],
     // This is never accessed directly. Apps are expected to use this indirectly via the Java
     // wrapper android.system.virtualmachine.
     unstable: true,
@@ -35,6 +36,7 @@
 aidl_interface {
     name: "android.system.virtualmachineservice",
     srcs: ["android/system/virtualmachineservice/**/*.aidl"],
+    imports: ["android.system.virtualizationcommon"],
     unstable: true,
     backend: {
         rust: {
@@ -46,3 +48,27 @@
         },
     },
 }
+
+aidl_interface {
+    name: "android.system.virtualizationcommon",
+    srcs: ["android/system/virtualizationcommon/**/*.aidl"],
+    unstable: true,
+    backend: {
+        java: {
+            apex_available: ["com.android.virt"],
+        },
+        ndk: {
+            apex_available: [
+                "com.android.virt",
+                "com.android.compos",
+            ],
+        },
+        rust: {
+            enabled: true,
+            apex_available: [
+                "com.android.virt",
+                "com.android.compos",
+            ],
+        },
+    },
+}
diff --git a/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl b/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
new file mode 100644
index 0000000..04b9749
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 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.
+ */
+package android.system.virtualizationcommon;
+
+/**
+ * Errors reported from within a VM.
+ */
+@Backing(type="int")
+enum ErrorCode {
+    /**
+     * Error code for all other errors not listed below.
+     */
+    UNKNOWN = 0,
+
+    /**
+     * Error code indicating that the payload can't be verified due to various reasons (e.g invalid
+     * merkle tree, invalid formats, etc).
+     */
+    PAYLOAD_VERIFICATION_FAILED = 1,
+
+    /**
+     * Error code indicating that the payload is verified, but has changed since the last boot.
+     */
+    PAYLOAD_CHANGED = 2,
+
+    /**
+     * Error code indicating that the payload config is invalid.
+     */
+    PAYLOAD_CONFIG_INVALID = 3,
+}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachineCallback.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachineCallback.aidl
index 6c8eb4a..8d6ed08 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachineCallback.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachineCallback.aidl
@@ -15,6 +15,7 @@
  */
 package android.system.virtualizationservice;
 
+import android.system.virtualizationcommon.ErrorCode;
 import android.system.virtualizationservice.DeathReason;
 
 /**
@@ -44,7 +45,7 @@
     /**
      * Called when an error occurs in the VM.
      */
-    void onError(int cid, int errorCode, in String message);
+    void onError(int cid, ErrorCode errorCode, in String message);
 
     /**
      * Called when the VM dies.
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index 8eb5497..d86f2bf 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -48,7 +48,7 @@
     }
 
     /** Debug level of the VM */
-    DebugLevel debugLevel;
+    DebugLevel debugLevel = DebugLevel.NONE;
 
     /** Whether the VM should be a protected VM. */
     boolean protectedVm;
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
index 672c41a..bed4097 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
@@ -38,5 +38,5 @@
     int requesterPid;
 
     /** The current lifecycle state of the VM. */
-    VirtualMachineState state;
+    VirtualMachineState state = VirtualMachineState.NOT_STARTED;
 }
diff --git a/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl b/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
index dff5d46..e8c1724 100644
--- a/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
+++ b/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
@@ -15,6 +15,8 @@
  */
 package android.system.virtualmachineservice;
 
+import android.system.virtualizationcommon.ErrorCode;
+
 /** {@hide} */
 interface IVirtualMachineService {
     /**
@@ -51,28 +53,7 @@
     void notifyPayloadFinished(int exitCode);
 
     /**
-     * Notifies that an error has occurred. See the ERROR_* constants.
+     * Notifies that an error has occurred inside the VM..
      */
-    void notifyError(int errorCode, in String message);
-
-    /**
-     * Error code for all other errors not listed below.
-     */
-    const int ERROR_UNKNOWN = 0;
-
-    /**
-     * Error code indicating that the payload can't be verified due to various reasons (e.g invalid
-     * merkle tree, invalid formats, etc).
-     */
-    const int ERROR_PAYLOAD_VERIFICATION_FAILED = 1;
-
-    /**
-     * Error code indicating that the payload is verified, but has changed since the last boot.
-     */
-    const int ERROR_PAYLOAD_CHANGED = 2;
-
-    /**
-     * Error code indicating that the payload config is invalid.
-     */
-    const int ERROR_PAYLOAD_INVALID_CONFIG = 3;
+    void notifyError(ErrorCode errorCode, in String message);
 }
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 6a4cc93..352b4f1 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -39,12 +39,11 @@
     self, BinderFeatures, ExceptionCode, Interface, LazyServiceGuard, ParcelFileDescriptor,
     SpIBinder, Status, StatusCode, Strong, ThreadState,
 };
-use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::{
-    IVirtualMachineService::{
+use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::{
         BnVirtualMachineService, IVirtualMachineService, VM_BINDER_SERVICE_PORT,
         VM_STREAM_SERVICE_PORT, VM_TOMBSTONES_SERVICE_PORT,
-    },
 };
+use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode;
 use anyhow::{anyhow, bail, Context, Result};
 use rpcbinder::run_rpc_server_with_factory;
 use disk::QcowFile;
@@ -878,7 +877,7 @@
     }
 
     /// Call all registered callbacks to say that the VM encountered an error.
-    pub fn notify_error(&self, cid: Cid, error_code: i32, message: &str) {
+    pub fn notify_error(&self, cid: Cid, error_code: ErrorCode, message: &str) {
         let callbacks = &*self.0.lock().unwrap();
         for callback in callbacks {
             if let Err(e) = callback.onError(cid as i32, error_code, message) {
@@ -1116,7 +1115,7 @@
         }
     }
 
-    fn notifyError(&self, error_code: i32, message: &str) -> binder::Result<()> {
+    fn notifyError(&self, error_code: ErrorCode, message: &str) -> binder::Result<()> {
         let cid = self.cid;
         if let Some(vm) = self.state.lock().unwrap().get_vm(cid) {
             info!("VM having CID {} encountered an error", cid);
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 058405e..aaa3988 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -28,7 +28,7 @@
 use std::io::{self, BufRead, BufReader};
 use std::os::unix::io::{AsRawFd, FromRawFd};
 use std::path::{Path, PathBuf};
-use vmclient::VmInstance;
+use vmclient::{ErrorCode, VmInstance};
 use vmconfig::{open_parcel_file, VmConfig};
 use zip::ZipArchive;
 
@@ -223,7 +223,7 @@
         if let Some(path) = ramdump_path {
             save_ramdump_if_available(path, &vm)?;
         }
-        println!("{}", death_reason);
+        println!("VM ended: {:?}", death_reason);
     }
 
     Ok(())
@@ -273,8 +273,8 @@
         eprintln!("payload finished with exit code {}", exit_code);
     }
 
-    fn on_error(&self, _cid: i32, error_code: i32, message: &str) {
-        eprintln!("VM encountered an error: code={}, message={}", error_code, message);
+    fn on_error(&self, _cid: i32, error_code: ErrorCode, message: &str) {
+        eprintln!("VM encountered an error: code={:?}, message={}", error_code, message);
     }
 }
 
diff --git a/vmclient/Android.bp b/vmclient/Android.bp
index 213125e..88b0c9a 100644
--- a/vmclient/Android.bp
+++ b/vmclient/Android.bp
@@ -8,6 +8,7 @@
     srcs: ["src/lib.rs"],
     edition: "2021",
     rustlibs: [
+        "android.system.virtualizationcommon-rust",
         "android.system.virtualizationservice-rust",
         "libbinder_rs",
         "liblog_rust",
diff --git a/vmclient/src/death_reason.rs b/vmclient/src/death_reason.rs
index b976f6f..fbf2523 100644
--- a/vmclient/src/death_reason.rs
+++ b/vmclient/src/death_reason.rs
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use std::fmt::{self, Debug, Display, Formatter};
 use android_system_virtualizationservice::{
         aidl::android::system::virtualizationservice::{
             DeathReason::DeathReason as AidlDeathReason}};
@@ -96,48 +95,3 @@
         }
     }
 }
-
-impl Display for DeathReason {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        let s = match self {
-            Self::VirtualizationServiceDied => "VirtualizationService died.",
-            Self::InfrastructureError => "Error waiting for VM to finish.",
-            Self::Killed => "VM was killed.",
-            Self::Unknown => "VM died for an unknown reason.",
-            Self::Shutdown => "VM shutdown cleanly.",
-            Self::Error => "Error starting VM.",
-            Self::Reboot => "VM tried to reboot, possibly due to a kernel panic.",
-            Self::Crash => "VM crashed.",
-            Self::PvmFirmwarePublicKeyMismatch => {
-                "pVM firmware failed to verify the VM because the public key doesn't match."
-            }
-            Self::PvmFirmwareInstanceImageChanged => {
-                "pVM firmware failed to verify the VM because the instance image changed."
-            }
-            Self::BootloaderPublicKeyMismatch => {
-                "Bootloader failed to verify the VM because the public key doesn't match."
-            }
-            Self::BootloaderInstanceImageChanged => {
-                "Bootloader failed to verify the VM because the instance image changed."
-            }
-            Self::MicrodroidFailedToConnectToVirtualizationService => {
-                "The microdroid failed to connect to VirtualizationService's RPC server."
-            }
-            Self::MicrodroidPayloadHasChanged => "The payload for microdroid is changed.",
-            Self::MicrodroidPayloadVerificationFailed => {
-                "The microdroid failed to verify given payload APK."
-            }
-            Self::MicrodroidInvalidPayloadConfig => {
-                "The VM config for microdroid is invalid (e.g. missing tasks)."
-            }
-            Self::MicrodroidUnknownRuntimeError => {
-                "There was a runtime error while running microdroid manager."
-            }
-            Self::Hangup => "VM hangup.",
-            Self::Unrecognised(reason) => {
-                return write!(f, "Unrecognised death reason {:?}.", reason);
-            }
-        };
-        f.write_str(s)
-    }
-}
diff --git a/vmclient/src/error_code.rs b/vmclient/src/error_code.rs
new file mode 100644
index 0000000..a7c442f
--- /dev/null
+++ b/vmclient/src/error_code.rs
@@ -0,0 +1,47 @@
+// Copyright 2022, 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.
+
+use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode as AidlErrorCode;
+
+/// Errors reported from within a VM.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ErrorCode {
+    /// Error code for all other errors not listed below.
+    Unknown,
+
+    /// Error code indicating that the payload can't be verified due to various reasons (e.g invalid
+    /// merkle tree, invalid formats, etc).
+    PayloadVerificationFailed,
+
+    /// Error code indicating that the payload is verified, but has changed since the last boot.
+    PayloadChanged,
+
+    /// Error code indicating that the payload config is invalid.
+    PayloadConfigInvalid,
+
+    /// Payload sent a death reason which was not recognised by the client library.
+    Unrecognised(AidlErrorCode),
+}
+
+impl From<AidlErrorCode> for ErrorCode {
+    fn from(error_code: AidlErrorCode) -> Self {
+        match error_code {
+            AidlErrorCode::UNKNOWN => Self::Unknown,
+            AidlErrorCode::PAYLOAD_VERIFICATION_FAILED => Self::PayloadVerificationFailed,
+            AidlErrorCode::PAYLOAD_CHANGED => Self::PayloadChanged,
+            AidlErrorCode::PAYLOAD_CONFIG_INVALID => Self::PayloadConfigInvalid,
+            _ => Self::Unrecognised(error_code),
+        }
+    }
+}
diff --git a/vmclient/src/errors.rs b/vmclient/src/errors.rs
index 231f81f..a6dca91 100644
--- a/vmclient/src/errors.rs
+++ b/vmclient/src/errors.rs
@@ -22,7 +22,7 @@
     #[error("Timed out waiting for VM.")]
     TimedOut,
     /// The VM died before it was ready.
-    #[error("VM died. ({reason})")]
+    #[error("VM died. ({reason:?})")]
     Died {
         /// The reason why the VM died.
         reason: DeathReason,
diff --git a/vmclient/src/lib.rs b/vmclient/src/lib.rs
index 16b5d5a..e6f32b4 100644
--- a/vmclient/src/lib.rs
+++ b/vmclient/src/lib.rs
@@ -15,12 +15,15 @@
 //! Client library for VirtualizationService.
 
 mod death_reason;
+mod error_code;
 mod errors;
 mod sync;
 
 pub use crate::death_reason::DeathReason;
+pub use crate::error_code::ErrorCode;
 pub use crate::errors::VmWaitError;
 use crate::sync::Monitor;
+use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::ErrorCode::ErrorCode as AidlErrorCode;
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
         DeathReason::DeathReason as AidlDeathReason,
@@ -83,7 +86,7 @@
 
     /// Called when an error has occurred in the VM. The `error_code` and `message` may give
     /// further details.
-    fn on_error(&self, cid: i32, error_code: i32, message: &str) {}
+    fn on_error(&self, cid: i32, error_code: ErrorCode, message: &str) {}
 
     /// Called when the VM has exited, all resources have been freed, and any logs have been
     /// written. `death_reason` gives an indication why the VM exited.
@@ -294,9 +297,10 @@
         Ok(())
     }
 
-    fn onError(&self, cid: i32, error_code: i32, message: &str) -> BinderResult<()> {
+    fn onError(&self, cid: i32, error_code: AidlErrorCode, message: &str) -> BinderResult<()> {
         self.state.notify_state(VirtualMachineState::FINISHED);
         if let Some(ref callback) = self.client_callback {
+            let error_code = error_code.into();
             callback.on_error(cid, error_code, message);
         }
         Ok(())