Merge "Revert "Revert "Upgrade to android13-5.15 kernel"""
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 929a96b..998b94b 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -41,6 +41,7 @@
 use rustutils::system_properties::PropertyWatcher;
 use std::convert::TryInto;
 use std::fs::{self, create_dir, File, OpenOptions};
+use std::io::Write;
 use std::os::unix::io::{FromRawFd, IntoRawFd};
 use std::path::Path;
 use std::process::{Child, Command, Stdio};
@@ -71,8 +72,13 @@
 const LOGD_ENABLED_PROP: &str = "ro.boot.logd.enabled";
 const APP_DEBUGGABLE_PROP: &str = "ro.boot.microdroid.app_debuggable";
 
+// SYNC WITH virtualizationservice/src/crosvm.rs
+const FAILURE_SERIAL_DEVICE: &str = "/dev/ttyS1";
+
 #[derive(thiserror::Error, Debug)]
 enum MicrodroidError {
+    #[error("Cannot connect to virtualization service: {0}")]
+    FailedToConnectToVirtualizationService(String),
     #[error("Payload has changed: {0}")]
     PayloadChanged(String),
     #[error("Payload verification has failed: {0}")]
@@ -89,12 +95,50 @@
                 (ERROR_PAYLOAD_VERIFICATION_FAILED, msg.to_string())
             }
             MicrodroidError::InvalidConfig(msg) => (ERROR_PAYLOAD_INVALID_CONFIG, msg.to_string()),
+
+            // Connection failure won't be reported to VS; return the default value
+            MicrodroidError::FailedToConnectToVirtualizationService(msg) => {
+                (ERROR_UNKNOWN, msg.to_string())
+            }
         }
     } else {
         (ERROR_UNKNOWN, err.to_string())
     }
 }
 
+fn write_death_reason_to_serial(err: &Error) -> Result<()> {
+    let death_reason = if let Some(e) = err.downcast_ref::<MicrodroidError>() {
+        match e {
+            MicrodroidError::FailedToConnectToVirtualizationService(_) => {
+                "MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE"
+            }
+            MicrodroidError::PayloadChanged(_) => "MICRODROID_PAYLOAD_HAS_CHANGED",
+            MicrodroidError::PayloadVerificationFailed(_) => {
+                "MICRODROID_PAYLOAD_VERIFICATION_FAILED"
+            }
+            MicrodroidError::InvalidConfig(_) => "MICRODROID_INVALID_PAYLOAD_CONFIG",
+        }
+    } else {
+        "MICRODROID_UNKNOWN_RUNTIME_ERROR"
+    };
+
+    let death_reason_bytes = death_reason.as_bytes();
+    let mut sent_total = 0;
+    while sent_total < death_reason_bytes.len() {
+        // TODO(b/220071963): Sometimes, sending more than 16 bytes at once makes MM hang.
+        let begin = sent_total;
+        let end = std::cmp::min(begin.saturating_add(16), death_reason_bytes.len());
+        OpenOptions::new()
+            .read(false)
+            .write(true)
+            .open(FAILURE_SERIAL_DEVICE)?
+            .write_all(&death_reason_bytes[begin..end])?;
+        sent_total = end;
+    }
+
+    Ok(())
+}
+
 fn get_vms_rpc_binder() -> Result<Strong<dyn IVirtualMachineService>> {
     // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can be
     // safely taken by new_spibinder.
@@ -114,6 +158,9 @@
 fn main() {
     if let Err(e) = try_main() {
         error!("Failed with {:?}. Shutting down...", e);
+        if let Err(e) = write_death_reason_to_serial(&e) {
+            error!("Failed to write death reason {:?}", e);
+        }
         if let Err(e) = system_properties::write("sys.powerctl", "shutdown") {
             error!("failed to shutdown {:?}", e);
         }
@@ -125,7 +172,9 @@
     let _ = kernlog::init();
     info!("started.");
 
-    let service = get_vms_rpc_binder().context("cannot connect to VirtualMachineService")?;
+    let service = get_vms_rpc_binder()
+        .context("cannot connect to VirtualMachineService")
+        .map_err(|e| MicrodroidError::FailedToConnectToVirtualizationService(e.to_string()))?;
     match try_run_payload(&service) {
         Ok(code) => {
             info!("notifying payload finished");
@@ -225,8 +274,9 @@
     }
 
     // Verify the payload before using it.
-    let verified_data =
-        verify_payload(&metadata, saved_data.as_ref()).context("Payload verification failed")?;
+    let verified_data = verify_payload(&metadata, saved_data.as_ref())
+        .context("Payload verification failed")
+        .map_err(|e| MicrodroidError::PayloadVerificationFailed(e.to_string()))?;
     if let Some(saved_data) = saved_data {
         ensure!(
             saved_data == verified_data,
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/DeathReason.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/DeathReason.aidl
index 7b80fc9..577e868 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/DeathReason.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/DeathReason.aidl
@@ -42,4 +42,14 @@
     BOOTLOADER_PUBLIC_KEY_MISMATCH = 9,
     /** The bootloader failed to verify the VM because the instance image changed. */
     BOOTLOADER_INSTANCE_IMAGE_CHANGED = 10,
+    /** The microdroid failed to connect to VirtualizationService's RPC server. */
+    MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE = 11,
+    /** The payload for microdroid is changed. */
+    MICRODROID_PAYLOAD_HAS_CHANGED = 12,
+    /** The microdroid failed to verify given payload APK. */
+    MICRODROID_PAYLOAD_VERIFICATION_FAILED = 13,
+    /** The VM config for microdroid is invalid (e.g. missing tasks). */
+    MICRODROID_INVALID_PAYLOAD_CONFIG = 14,
+    /** There was a runtime error while running microdroid manager. */
+    MICRODROID_UNKNOWN_RUNTIME_ERROR = 15,
 }
diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs
index b184dca..fcc09c6 100644
--- a/virtualizationservice/src/crosvm.rs
+++ b/virtualizationservice/src/crosvm.rs
@@ -276,6 +276,19 @@
             "BOOTLOADER_INSTANCE_IMAGE_CHANGED" => {
                 return DeathReason::BOOTLOADER_INSTANCE_IMAGE_CHANGED
             }
+            "MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE" => {
+                return DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE
+            }
+            "MICRODROID_PAYLOAD_HAS_CHANGED" => return DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED,
+            "MICRODROID_PAYLOAD_VERIFICATION_FAILED" => {
+                return DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED
+            }
+            "MICRODROID_INVALID_PAYLOAD_CONFIG" => {
+                return DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG
+            }
+            "MICRODROID_UNKNOWN_RUNTIME_ERROR" => {
+                return DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR
+            }
             _ => {}
         }
         match status.code() {