Snap for 10453563 from 227eeb228a8062775d3a3e9ce89f7e8bd68fbc67 to mainline-scheduling-release

Change-Id: I8c54fc66afb680dc777b4aaa5ced565c2de5b2ac
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index eb2050d..0562cca 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "cb5819f26b7e1b2eab75994bdd73309ef2859df7"
-  }
-}
+    "sha1": "425bb5dc189f3a5130bdc80ca47d6da5001157b4"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index f2faab7..dc3d4e7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,15 +23,18 @@
     host_supported: true,
     crate_name: "command_fds",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.2.1",
+    cargo_pkg_version: "0.2.2",
     srcs: ["src/lib.rs"],
     edition: "2018",
+    features: ["default"],
     rustlibs: [
         "libnix",
         "libthiserror",
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.virt",
+        "//apex_available:anyapex",
     ],
+    product_available: true,
+    vendor_available: true,
 }
diff --git a/Cargo.toml b/Cargo.toml
index 1d72a8c..bb015ea 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
 name = "command-fds"
-version = "0.2.1"
+version = "0.2.2"
 authors = ["Andrew Walbran <qwandor@google.com>"]
 description = "A library for passing arbitrary file descriptors when spawning child processes."
 keywords = ["command", "process", "child", "subprocess", "fd"]
@@ -25,3 +24,14 @@
 
 [dependencies.thiserror]
 version = "1.0.24"
+
+[dependencies.tokio-crate]
+version = "^1.0"
+features = ["process"]
+optional = true
+default-features = false
+package = "tokio"
+
+[features]
+default = []
+tokio = ["tokio-crate"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 15a6874..ef218ac 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "command-fds"
-version = "0.2.1"
+version = "0.2.2"
 edition = "2018"
 authors = ["Andrew Walbran <qwandor@google.com>"]
 license = "Apache-2.0"
@@ -12,3 +12,14 @@
 [dependencies]
 nix = "0.22.0"
 thiserror = "1.0.24"
+
+[dependencies.tokio-crate]
+package = "tokio"
+version = "^1.0"
+optional = true
+default-features = false
+features = ["process"]
+
+[features]
+default = []
+tokio = ["tokio-crate"]
diff --git a/METADATA b/METADATA
index 9ed08b1..7b98618 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/command-fds/command-fds-0.2.1.crate"
+    value: "https://static.crates.io/crates/command-fds/command-fds-0.2.2.crate"
   }
-  version: "0.2.1"
+  version: "0.2.2"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 8
-    day: 16
+    year: 2022
+    month: 6
+    day: 28
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 061ff86..5366bfb 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,13 +1,11 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
-  "presubmit": [
+  "imports": [
     {
-      "name": "virtualizationservice_device_test"
-    }
-  ],
-  "presubmit-rust": [
+      "path": "packages/modules/Virtualization/virtualizationmanager"
+    },
     {
-      "name": "virtualizationservice_device_test"
+      "path": "packages/modules/Virtualization/vm"
     }
   ]
 }
diff --git a/cargo2android.json b/cargo2android.json
index 42b7833..1b6cca2 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,8 +1,4 @@
 {
-  "apex-available": [
-    "//apex_available:platform",
-    "com.android.virt"
-  ],
   "dependencies": true,
   "device": true,
   "run": true
diff --git a/src/lib.rs b/src/lib.rs
index 2dfb63f..fde680a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -48,6 +48,9 @@
 //! child.wait().unwrap();
 //! ```
 
+#[cfg(feature = "tokio")]
+pub mod tokio;
+
 use nix::fcntl::{fcntl, FcntlArg, FdFlag};
 use nix::unistd::dup2;
 use std::cmp::max;
@@ -90,13 +93,7 @@
         &mut self,
         mut mappings: Vec<FdMapping>,
     ) -> Result<&mut Self, FdMappingCollision> {
-        // Validate that there are no conflicting mappings to the same child FD.
-        let mut child_fds: Vec<RawFd> = mappings.iter().map(|mapping| mapping.child_fd).collect();
-        child_fds.sort_unstable();
-        child_fds.dedup();
-        if child_fds.len() != mappings.len() {
-            return Err(FdMappingCollision);
-        }
+        let child_fds = validate_child_fds(&mappings)?;
 
         // Register the callback to apply the mappings after forking but before execing.
         // Safety: `map_fds` will not allocate, so it is safe to call from this hook.
@@ -120,6 +117,17 @@
     }
 }
 
+/// Validates that there are no conflicting mappings to the same child FD.
+fn validate_child_fds(mappings: &[FdMapping]) -> Result<Vec<RawFd>, FdMappingCollision> {
+    let mut child_fds: Vec<RawFd> = mappings.iter().map(|mapping| mapping.child_fd).collect();
+    child_fds.sort_unstable();
+    child_fds.dedup();
+    if child_fds.len() != mappings.len() {
+        return Err(FdMappingCollision);
+    }
+    Ok(child_fds)
+}
+
 // This function must not do any allocation, as it is called from the pre_exec hook.
 fn map_fds(mappings: &mut [FdMapping], child_fds: &[RawFd]) -> io::Result<()> {
     if mappings.is_empty() {
diff --git a/src/tokio.rs b/src/tokio.rs
new file mode 100644
index 0000000..78979bf
--- /dev/null
+++ b/src/tokio.rs
@@ -0,0 +1,42 @@
+use std::os::unix::prelude::RawFd;
+
+use tokio::process::Command;
+use tokio_crate as tokio;
+
+use crate::{map_fds, preserve_fds, validate_child_fds, FdMapping, FdMappingCollision};
+
+/// Extension to add file descriptor mappings to a [`Command`].
+pub trait CommandFdAsyncExt {
+    /// Adds the given set of file descriptors to the command.
+    ///
+    /// Warning: Calling this more than once on the same command, or attempting to run the same
+    /// command more than once after calling this, may result in unexpected behaviour.
+    fn fd_mappings(&mut self, mappings: Vec<FdMapping>) -> Result<&mut Self, FdMappingCollision>;
+
+    /// Adds the given set of file descriptors to be passed on to the child process when the command
+    /// is run.
+    fn preserved_fds(&mut self, fds: Vec<RawFd>) -> &mut Self;
+}
+
+impl CommandFdAsyncExt for Command {
+    fn fd_mappings(
+        &mut self,
+        mut mappings: Vec<FdMapping>,
+    ) -> Result<&mut Self, FdMappingCollision> {
+        let child_fds = validate_child_fds(&mappings)?;
+
+        unsafe {
+            self.pre_exec(move || map_fds(&mut mappings, &child_fds));
+        }
+
+        Ok(self)
+    }
+
+    fn preserved_fds(&mut self, fds: Vec<RawFd>) -> &mut Self {
+        unsafe {
+            self.pre_exec(move || preserve_fds(&fds));
+        }
+
+        self
+    }
+}