Merge "EGL Multifile Blobcache: Make use of crc32_z algorithm instead of crc32c" into main
diff --git a/libs/nativewindow/rust/Android.bp b/libs/nativewindow/rust/Android.bp
index c572ee7..faab48b 100644
--- a/libs/nativewindow/rust/Android.bp
+++ b/libs/nativewindow/rust/Android.bp
@@ -110,6 +110,7 @@
     name: "libnativewindow_defaults",
     srcs: ["src/lib.rs"],
     rustlibs: [
+        "android.hardware.common-V2-rust",
         "libbinder_rs",
         "libbitflags",
         "libnativewindow_bindgen",
diff --git a/libs/nativewindow/rust/src/handle.rs b/libs/nativewindow/rust/src/handle.rs
index c41ab8d..2b08c1b 100644
--- a/libs/nativewindow/rust/src/handle.rs
+++ b/libs/nativewindow/rust/src/handle.rs
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use android_hardware_common::{
+    aidl::android::hardware::common::NativeHandle::NativeHandle as AidlNativeHandle,
+    binder::ParcelFileDescriptor,
+};
 use std::{
     ffi::c_int,
     mem::forget,
@@ -81,6 +85,12 @@
 
     /// Destroys the `NativeHandle`, taking ownership of the file descriptors it contained.
     pub fn into_fds(self) -> Vec<OwnedFd> {
+        // Unset FDSan tag since this `native_handle_t` is no longer the owner of the file
+        // descriptors after this function.
+        // SAFETY: Our wrapped `native_handle_t` pointer is always valid.
+        unsafe {
+            ffi::native_handle_unset_fdsan_tag(self.as_ref());
+        }
         let fds = self.data()[..self.fd_count()]
             .iter()
             .map(|fd| {
@@ -190,6 +200,21 @@
     }
 }
 
+impl From<AidlNativeHandle> for NativeHandle {
+    fn from(aidl_native_handle: AidlNativeHandle) -> Self {
+        let fds = aidl_native_handle.fds.into_iter().map(OwnedFd::from).collect();
+        Self::new(fds, &aidl_native_handle.ints).unwrap()
+    }
+}
+
+impl From<NativeHandle> for AidlNativeHandle {
+    fn from(native_handle: NativeHandle) -> Self {
+        let ints = native_handle.ints().to_owned();
+        let fds = native_handle.into_fds().into_iter().map(ParcelFileDescriptor::new).collect();
+        Self { ints, fds }
+    }
+}
+
 // SAFETY: `NativeHandle` owns the `native_handle_t`, which just contains some integers and file
 // descriptors, which aren't tied to any particular thread.
 unsafe impl Send for NativeHandle {}
@@ -240,4 +265,43 @@
 
         drop(cloned);
     }
+
+    #[test]
+    fn to_fds() {
+        let file = File::open("/dev/null").unwrap();
+        let original = NativeHandle::new(vec![file.into()], &[42]).unwrap();
+        assert_eq!(original.ints(), &[42]);
+        assert_eq!(original.fds().len(), 1);
+
+        let fds = original.into_fds();
+        assert_eq!(fds.len(), 1);
+    }
+
+    #[test]
+    fn to_aidl() {
+        let file = File::open("/dev/null").unwrap();
+        let original = NativeHandle::new(vec![file.into()], &[42]).unwrap();
+        assert_eq!(original.ints(), &[42]);
+        assert_eq!(original.fds().len(), 1);
+
+        let aidl = AidlNativeHandle::from(original);
+        assert_eq!(&aidl.ints, &[42]);
+        assert_eq!(aidl.fds.len(), 1);
+    }
+
+    #[test]
+    fn to_from_aidl() {
+        let file = File::open("/dev/null").unwrap();
+        let original = NativeHandle::new(vec![file.into()], &[42]).unwrap();
+        assert_eq!(original.ints(), &[42]);
+        assert_eq!(original.fds().len(), 1);
+
+        let aidl = AidlNativeHandle::from(original);
+        assert_eq!(&aidl.ints, &[42]);
+        assert_eq!(aidl.fds.len(), 1);
+
+        let converted_back = NativeHandle::from(aidl);
+        assert_eq!(converted_back.ints(), &[42]);
+        assert_eq!(converted_back.fds().len(), 1);
+    }
 }