Add methods to convert between HardwareBuffer and native handle.

Bug: 359100544
Test: atest libnativewindow_rs-internal_test
Change-Id: I7db2cc091aae36ee4b62f3925504a634feb6daac
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs
index ffde137..54dad04 100644
--- a/libs/nativewindow/rust/src/lib.rs
+++ b/libs/nativewindow/rust/src/lib.rs
@@ -106,6 +106,50 @@
         }
     }
 
+    /// Creates a `HardwareBuffer` from a native handle.
+    ///
+    /// The native handle is cloned, so this doesn't take ownership of the original handle passed
+    /// in.
+    pub fn create_from_handle(
+        handle: &NativeHandle,
+        buffer_desc: &ffi::AHardwareBuffer_Desc,
+    ) -> Result<Self, StatusCode> {
+        let mut buffer = ptr::null_mut();
+        // SAFETY: The caller guarantees that `handle` is valid, and the buffer pointer is valid
+        // because it comes from a reference. The method we pass means that
+        // `AHardwareBuffer_createFromHandle` will clone the handle rather than taking ownership of
+        // it.
+        let status = unsafe {
+            ffi::AHardwareBuffer_createFromHandle(
+                buffer_desc,
+                handle.as_raw().as_ptr(),
+                ffi::CreateFromHandleMethod_AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE
+                    .try_into()
+                    .unwrap(),
+                &mut buffer,
+            )
+        };
+        status_result(status)?;
+        Ok(Self(NonNull::new(buffer).expect("Allocated AHardwareBuffer was null")))
+    }
+
+    /// Returns a clone of the native handle of the buffer.
+    ///
+    /// Returns `None` if the operation fails for any reason.
+    pub fn cloned_native_handle(&self) -> Option<NativeHandle> {
+        // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
+        // because it must have been allocated by `AHardwareBuffer_allocate`,
+        // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
+        // released it.
+        let native_handle = unsafe { ffi::AHardwareBuffer_getNativeHandle(self.0.as_ptr()) };
+        NonNull::new(native_handle.cast_mut()).and_then(|native_handle| {
+            // SAFETY: `AHardwareBuffer_getNativeHandle` should have returned a valid pointer which
+            // is valid at least as long as the buffer is, and `clone_from_raw` clones it rather
+            // than taking ownership of it so the original `native_handle` isn't stored.
+            unsafe { NativeHandle::clone_from_raw(native_handle) }
+        })
+    }
+
     /// Adopts the given raw pointer and wraps it in a Rust HardwareBuffer.
     ///
     /// # Safety
@@ -393,4 +437,34 @@
 
         assert_eq!(remade_buffer, buffer2);
     }
+
+    #[test]
+    fn native_handle_and_back() {
+        let buffer = HardwareBuffer::new(
+            1024,
+            512,
+            1,
+            AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+            AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+        )
+        .expect("Buffer with some basic parameters was not created successfully");
+
+        let native_handle =
+            buffer.cloned_native_handle().expect("Failed to get native handle for buffer");
+        let buffer_desc = ffi::AHardwareBuffer_Desc {
+            width: 1024,
+            height: 512,
+            layers: 1,
+            format: AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+            usage: AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN.0,
+            stride: 1024,
+            rfu0: 0,
+            rfu1: 0,
+        };
+        let buffer2 = HardwareBuffer::create_from_handle(&native_handle, &buffer_desc)
+            .expect("Failed to create buffer from native handle");
+
+        assert_eq!(buffer.description(), buffer_desc);
+        assert_eq!(buffer2.description(), buffer_desc);
+    }
 }