Merge "Don't wait for onDied"
diff --git a/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl b/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
index a565a6f..d8f481a 100644
--- a/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
+++ b/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
@@ -16,21 +16,16 @@
 
 package com.android.virt.fs;
 
-/** {@hide} */
+/**
+ * A service that works like a file server, where the files and directories are identified by "FD"
+ * as the unique identifier.
+ *
+ * When a binder error is returned and it is a service specific error, the error code is an errno
+ * value which is an int.
+ *
+ * {@hide}
+ */
 interface IVirtFdService {
-    /** Error when the requesting FD is unknown. */
-    const int ERROR_UNKNOWN_FD = 1;
-
-    /**
-     * Error when I/O fails. This can happen when actual I/O error happens to the backing file,
-     * when the given offset or size are invalid, or any problems that can fail a read/write
-     * request.
-     */
-    const int ERROR_IO = 2;
-
-    /** Error when the file is too large to handle correctly. */
-    const int ERROR_FILE_TOO_LARGE = 3;
-
     /** Maximum content size that the service allows the client to request. */
     const int MAX_REQUESTING_DATA = 16384;
 
diff --git a/authfs/fd_server/src/aidl.rs b/authfs/fd_server/src/aidl.rs
index b235025..48547e7 100644
--- a/authfs/fd_server/src/aidl.rs
+++ b/authfs/fd_server/src/aidl.rs
@@ -16,6 +16,7 @@
 
 use anyhow::Result;
 use log::error;
+use nix::errno::Errno;
 use std::cmp::min;
 use std::collections::BTreeMap;
 use std::convert::TryInto;
@@ -26,30 +27,22 @@
 
 use crate::fsverity;
 use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
-    BnVirtFdService, IVirtFdService, ERROR_FILE_TOO_LARGE, ERROR_IO, ERROR_UNKNOWN_FD,
-    MAX_REQUESTING_DATA,
+    BnVirtFdService, IVirtFdService, MAX_REQUESTING_DATA,
 };
 use authfs_aidl_interface::binder::{
-    BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
+    BinderFeatures, Interface, Result as BinderResult, Status, StatusCode, Strong,
 };
-use binder_common::new_binder_exception;
+use binder_common::new_binder_service_specific_error;
 
 fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
-    offset.try_into().map_err(|_| {
-        new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, format!("Invalid offset: {}", offset))
-    })
+    offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
 }
 
 fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
     if size > MAX_REQUESTING_DATA {
-        Err(new_binder_exception(
-            ExceptionCode::ILLEGAL_ARGUMENT,
-            format!("Unexpectedly large size: {}", size),
-        ))
+        Err(new_errno_error(Errno::EFBIG))
     } else {
-        size.try_into().map_err(|_| {
-            new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, format!("Invalid size: {}", size))
-        })
+        size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
     }
 }
 
@@ -89,7 +82,7 @@
     where
         F: FnOnce(&FdConfig) -> BinderResult<R>,
     {
-        let fd_config = self.fd_pool.get(&id).ok_or_else(|| Status::from(ERROR_UNKNOWN_FD))?;
+        let fd_config = self.fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
         handler(fd_config)
     }
 }
@@ -105,7 +98,7 @@
             FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
                 read_into_buf(file, size, offset).map_err(|e| {
                     error!("readFile: read error: {}", e);
-                    Status::from(ERROR_IO)
+                    new_errno_error(Errno::EIO)
                 })
             }
         })
@@ -120,14 +113,14 @@
                 if let Some(tree_file) = &alt_merkle_tree {
                     read_into_buf(tree_file, size, offset).map_err(|e| {
                         error!("readFsverityMerkleTree: read error: {}", e);
-                        Status::from(ERROR_IO)
+                        new_errno_error(Errno::EIO)
                     })
                 } else {
                     let mut buf = vec![0; size];
                     let s = fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf)
                         .map_err(|e| {
                             error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
-                            Status::from(e.raw_os_error().unwrap_or(ERROR_IO))
+                            new_errno_error(Errno::EIO)
                         })?;
                     debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
                     buf.truncate(s);
@@ -138,7 +131,7 @@
                 // For a writable file, Merkle tree is not expected to be served since Auth FS
                 // doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
                 // use.
-                Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+                Err(new_errno_error(Errno::ENOSYS))
             }
         })
     }
@@ -152,13 +145,13 @@
                     let offset = 0;
                     read_into_buf(sig_file, size, offset).map_err(|e| {
                         error!("readFsveritySignature: read error: {}", e);
-                        Status::from(ERROR_IO)
+                        new_errno_error(Errno::EIO)
                     })
                 } else {
                     let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
                     let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
                         error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
-                        Status::from(e.raw_os_error().unwrap_or(ERROR_IO))
+                        new_errno_error(Errno::EIO)
                     })?;
                     debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
                     buf.truncate(s);
@@ -167,7 +160,7 @@
             }
             FdConfig::ReadWrite(_file) => {
                 // There is no signature for a writable file.
-                Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+                Err(new_errno_error(Errno::ENOSYS))
             }
         })
     }
@@ -176,19 +169,14 @@
         self.handle_fd(id, |config| match config {
             FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
             FdConfig::ReadWrite(file) => {
-                let offset: u64 = offset.try_into().map_err(|_| {
-                    new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, "Invalid offset")
-                })?;
+                let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
                 // Check buffer size just to make `as i32` safe below.
                 if buf.len() > i32::MAX as usize {
-                    return Err(new_binder_exception(
-                        ExceptionCode::ILLEGAL_ARGUMENT,
-                        "Buffer size is too big",
-                    ));
+                    return Err(new_errno_error(Errno::EOVERFLOW));
                 }
                 Ok(file.write_at(buf, offset).map_err(|e| {
                     error!("writeFile: write error: {}", e);
-                    Status::from(ERROR_IO)
+                    new_errno_error(Errno::EIO)
                 })? as i32)
             }
         })
@@ -199,14 +187,11 @@
             FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
             FdConfig::ReadWrite(file) => {
                 if size < 0 {
-                    return Err(new_binder_exception(
-                        ExceptionCode::ILLEGAL_ARGUMENT,
-                        "Invalid size to resize to",
-                    ));
+                    return Err(new_errno_error(Errno::EINVAL));
                 }
                 file.set_len(size as u64).map_err(|e| {
                     error!("resize: set_len error: {}", e);
-                    Status::from(ERROR_IO)
+                    new_errno_error(Errno::EIO)
                 })
             }
         })
@@ -219,19 +204,19 @@
                     .metadata()
                     .map_err(|e| {
                         error!("getFileSize error: {}", e);
-                        Status::from(ERROR_IO)
+                        new_errno_error(Errno::EIO)
                     })?
                     .len();
                 Ok(size.try_into().map_err(|e| {
                     error!("getFileSize: File too large: {}", e);
-                    Status::from(ERROR_FILE_TOO_LARGE)
+                    new_errno_error(Errno::EFBIG)
                 })?)
             }
             FdConfig::ReadWrite(_file) => {
                 // Content and metadata of a writable file needs to be tracked by authfs, since
                 // fd_server isn't considered trusted. So there is no point to support getFileSize
                 // for a writable file.
-                Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+                Err(new_errno_error(Errno::ENOSYS))
             }
         })
     }
@@ -244,3 +229,7 @@
     file.read_exact_at(&mut buf, offset)?;
     Ok(buf)
 }
+
+fn new_errno_error(errno: Errno) -> Status {
+    new_binder_service_specific_error(errno as i32, errno.desc())
+}
diff --git a/authfs/tests/Android.bp b/authfs/tests/Android.bp
index 88c1ba6..92fa428 100644
--- a/authfs/tests/Android.bp
+++ b/authfs/tests/Android.bp
@@ -14,7 +14,7 @@
         "VirtualizationTestHelper",
     ],
     test_suites: ["general-tests"],
-    target_required: ["open_then_run"],
+    target_required: ["open_then_run_module"],
     data: [
         ":authfs_test_files",
         ":MicrodroidTestApp.signed",
@@ -22,7 +22,16 @@
 }
 
 rust_test {
-    name: "open_then_run",
+    // PushFilePreparer can sometimes push the directory (if named "open_then_run", which contains
+    // the actual executable in a per-architecture sub-directory) instead of the executable. This
+    // makes it harder to use because the host Java test have to detect the executable path
+    // dynamically, e.g. if it's a directory, append the device's architecture to build the actual
+    // executable path. By simply renaming the module (thus the host directory), this forces
+    // PushFilePreparer to always push the executable to the destination, so that the Java test can
+    // easily locate the executable with a constant path.
+    name: "open_then_run_module",
+    stem: "open_then_run",
+
     crate_name: "open_then_run",
     srcs: ["open_then_run.rs"],
     edition: "2018",
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
index 7229dde..3ed8748 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
@@ -57,6 +57,9 @@
     /** Mount point of authfs on Microdroid during the test */
     private static final String MOUNT_DIR = "/data/local/tmp";
 
+    /** Path to open_then_run on Android */
+    private static final String OPEN_THEN_RUN_BIN = TEST_DIR + "/open_then_run";
+
     /** Path to fd_server on Android */
     private static final String FD_SERVER_BIN = "/apex/com.android.virt/bin/fd_server";
 
@@ -374,18 +377,13 @@
         }
     }
 
-    private String getOpenThenRunPath() {
-        // Construct path to match PushFilePreparer's upload path.
-        return TEST_DIR + "/open_then_run/" + mArch + "/open_then_run";
-    }
-
     private void runFdServerOnAndroid(String helperFlags, String fdServerFlags)
             throws DeviceNotAvailableException {
         String cmd =
                 "cd "
                         + TEST_DIR
                         + " && "
-                        + getOpenThenRunPath()
+                        + OPEN_THEN_RUN_BIN
                         + " "
                         + helperFlags
                         + " -- "
diff --git a/microdroid/bootconfig.x86_64 b/microdroid/bootconfig.x86_64
index 2977ee3..6076889 100644
--- a/microdroid/bootconfig.x86_64
+++ b/microdroid/bootconfig.x86_64
@@ -1 +1 @@
-androidboot.boot_devices = pci0000:00/0000:00:03.0,pci0000:00/0000:00:04.0,pci0000:00/0000:00:05.0
+androidboot.boot_devices = pci0000:00/0000:00:04.0,pci0000:00/0000:00:05.0,pci0000:00/0000:00:06.0
diff --git a/microdroid/init.rc b/microdroid/init.rc
index ad551cc..664402f 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -195,7 +195,7 @@
     seclabel u:r:shell:s0
     setenv HOSTNAME console
 
-service seriallogging /system/bin/logcat -b all -v threadtime -f /dev/hvc1 *:V
+service seriallogging /system/bin/logcat -b all -v threadtime -f /dev/hvc2 *:V
     disabled
     user logd
     group root logd
diff --git a/microdroid/ueventd.rc b/microdroid/ueventd.rc
index 85f2f9d..037b8fc 100644
--- a/microdroid/ueventd.rc
+++ b/microdroid/ueventd.rc
@@ -26,4 +26,4 @@
 /dev/tty0                 0660   root       system
 
 # Virtual console for logcat
-/dev/hvc1                 0660   logd       logd
+/dev/hvc2                 0660   logd       logd
diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs
index 08be052..bf1ff0c 100644
--- a/virtualizationservice/src/crosvm.rs
+++ b/virtualizationservice/src/crosvm.rs
@@ -251,8 +251,9 @@
 
     // Setup the serial devices.
     // 1. uart device: used as the output device by bootloaders and as early console by linux
-    // 2. virtio-console device: used as the console device
-    // 3. virtio-console device: used as the logcat output
+    // 2. virtio-console device: used as the console device where kmsg is redirected to
+    // 3. virtio-console device: used as the androidboot.console device (not used currently)
+    // 4. virtio-console device: used as the logcat output
     //
     // When [console|log]_fd is not specified, the devices are attached to sink, which means what's
     // written there is discarded.
@@ -273,8 +274,10 @@
     command.arg(format!("--serial={},hardware=serial", &console_arg));
     // /dev/hvc0
     command.arg(format!("--serial={},hardware=virtio-console,num=1", &console_arg));
-    // /dev/hvc1
-    command.arg(format!("--serial={},hardware=virtio-console,num=2", &log_arg));
+    // /dev/hvc1 (not used currently)
+    command.arg("--serial=type=sink,hardware=virtio-console,num=2");
+    // /dev/hvc2
+    command.arg(format!("--serial={},hardware=virtio-console,num=3", &log_arg));
 
     if let Some(bootloader) = &config.bootloader {
         command.arg("--bios").arg(add_preserved_fd(&mut preserved_fds, bootloader));