diff options
| -rw-r--r-- | libs/nativewindow/rust/src/lib.rs | 74 | ||||
| -rw-r--r-- | libs/nativewindow/rust/sys/nativewindow_bindings.h | 1 |
2 files changed, 75 insertions, 0 deletions
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs index ffde137ccb..54dad04071 100644 --- a/libs/nativewindow/rust/src/lib.rs +++ b/libs/nativewindow/rust/src/lib.rs @@ -106,6 +106,50 @@ impl HardwareBuffer { } } + /// 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 @@ mod test { 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); + } } diff --git a/libs/nativewindow/rust/sys/nativewindow_bindings.h b/libs/nativewindow/rust/sys/nativewindow_bindings.h index 7c93c5aa1b..5046a80095 100644 --- a/libs/nativewindow/rust/sys/nativewindow_bindings.h +++ b/libs/nativewindow/rust/sys/nativewindow_bindings.h @@ -21,3 +21,4 @@ #include <android/native_window.h> #include <android/native_window_aidl.h> #include <cutils/native_handle.h> +#include <vndk/hardware_buffer.h> |