vm_accessor_test: Redirect VM log to logcat

Even though this CL redirects VM log to logcat,
we can't see it directly with atest.

It's because teardown reboots the device,
so we need a way to see logcat after the test is over.

Here's two options (except for modifying AndroidTest.xml)
  - Disable test teardown:
    `atest -d vm_accessor_test; atest -t vm_accessor_test`
    I don't know why, but both IAccessor implementation nor
    VM don't print any log for the first `atest -d`.
    But it would be a separated issue.
  - Check logcat at `/tmp/atest_result_${USER}/LATEST/`

Test: Manually
Change-Id: Ic4ce8265413fca57c4c326a622ded1ceafd498a2
diff --git a/tests/vm_accessor/accessor/Android.bp b/tests/vm_accessor/accessor/Android.bp
index d9d1026..7c0ee6d 100644
--- a/tests/vm_accessor/accessor/Android.bp
+++ b/tests/vm_accessor/accessor/Android.bp
@@ -21,11 +21,11 @@
         "libenv_logger",
         "libglob",
         "libhypervisor_props",
-        "liblibc",
         "liblog_rust",
         "libmicrodroid_payload_config",
         "librand",
         "libvmconfig",
         "libvmclient",
+        "libnix",
     ],
 }
diff --git a/tests/vm_accessor/accessor/src/run.rs b/tests/vm_accessor/accessor/src/run.rs
index 03aa80d..932baab 100644
--- a/tests/vm_accessor/accessor/src/run.rs
+++ b/tests/vm_accessor/accessor/src/run.rs
@@ -26,11 +26,10 @@
 use glob::glob;
 use log::{error, info};
 use rand::{distributions::Alphanumeric, Rng};
-use std::fs;
-use std::fs::File;
-use std::io;
-use std::os::unix::io::{AsRawFd, FromRawFd};
+use std::fs::{self, File};
+use std::io::{self, BufRead, BufReader};
 use std::path::PathBuf;
+use std::thread;
 use vmclient::{ErrorCode, VmInstance};
 use vmconfig::open_parcel_file;
 
@@ -126,9 +125,9 @@
     let vm = VmInstance::create(
         service.as_ref(),
         &vm_config,
-        Some(duplicate_fd(io::stdout())?), /* console_out */
-        None,                              /* console_in */
-        Some(duplicate_fd(io::stdout())?), /* log */
+        Some(android_log_fd()?), /* console_out */
+        None,                    /* console_in */
+        Some(android_log_fd()?), /* log */
         Some(Box::new(Callback {})),
     )
     .context("Failed to create VM")?;
@@ -159,17 +158,24 @@
     }
 }
 
-/// Safely duplicate the file descriptor.
-fn duplicate_fd<T: AsRawFd>(file: T) -> io::Result<File> {
-    let fd = file.as_raw_fd();
-    // SAFETY: This just duplicates a file descriptor which we know to be valid, and we check for an
-    // an error.
-    let dup_fd = unsafe { libc::dup(fd) };
-    if dup_fd < 0 {
-        Err(io::Error::last_os_error())
-    } else {
-        // SAFETY: We have just duplicated the file descriptor so we own it, and `from_raw_fd` takes
-        // ownership of it.
-        Ok(unsafe { File::from_raw_fd(dup_fd) })
-    }
+/// This function is only exposed for testing.
+/// Production code prefer not expose logs from VM.
+fn android_log_fd() -> io::Result<File> {
+    let (reader_fd, writer_fd) = nix::unistd::pipe()?;
+
+    let reader = File::from(reader_fd);
+    let writer = File::from(writer_fd);
+
+    thread::spawn(|| {
+        for line in BufReader::new(reader).lines() {
+            match line {
+                Ok(l) => info!("{}", l),
+                Err(e) => {
+                    error!("Failed to read line from VM: {e:?}");
+                    break;
+                }
+            }
+        }
+    });
+    Ok(writer)
 }