Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a73d62cd authored by Andrew Walbran's avatar Andrew Walbran
Browse files

Add methods to convert between HardwareBuffer and native handle.

Bug: 359100544
Test: atest libnativewindow_rs-internal_test
Change-Id: I7db2cc091aae36ee4b62f3925504a634feb6daac
parent 9487efdc
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -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>