@@ -106,6 +106,50 @@ impl HardwareBuffer {
106106 }
107107 }
108108
109+ /// Creates a `HardwareBuffer` from a native handle.
110+ ///
111+ /// The native handle is cloned, so this doesn't take ownership of the original handle passed
112+ /// in.
113+ pub fn create_from_handle (
114+ handle : & NativeHandle ,
115+ buffer_desc : & ffi:: AHardwareBuffer_Desc ,
116+ ) -> Result < Self , StatusCode > {
117+ let mut buffer = ptr:: null_mut ( ) ;
118+ // SAFETY: The caller guarantees that `handle` is valid, and the buffer pointer is valid
119+ // because it comes from a reference. The method we pass means that
120+ // `AHardwareBuffer_createFromHandle` will clone the handle rather than taking ownership of
121+ // it.
122+ let status = unsafe {
123+ ffi:: AHardwareBuffer_createFromHandle (
124+ buffer_desc,
125+ handle. as_raw ( ) . as_ptr ( ) ,
126+ ffi:: CreateFromHandleMethod_AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE
127+ . try_into ( )
128+ . unwrap ( ) ,
129+ & mut buffer,
130+ )
131+ } ;
132+ status_result ( status) ?;
133+ Ok ( Self ( NonNull :: new ( buffer) . expect ( "Allocated AHardwareBuffer was null" ) ) )
134+ }
135+
136+ /// Returns a clone of the native handle of the buffer.
137+ ///
138+ /// Returns `None` if the operation fails for any reason.
139+ pub fn cloned_native_handle ( & self ) -> Option < NativeHandle > {
140+ // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
141+ // because it must have been allocated by `AHardwareBuffer_allocate`,
142+ // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
143+ // released it.
144+ let native_handle = unsafe { ffi:: AHardwareBuffer_getNativeHandle ( self . 0 . as_ptr ( ) ) } ;
145+ NonNull :: new ( native_handle. cast_mut ( ) ) . and_then ( |native_handle| {
146+ // SAFETY: `AHardwareBuffer_getNativeHandle` should have returned a valid pointer which
147+ // is valid at least as long as the buffer is, and `clone_from_raw` clones it rather
148+ // than taking ownership of it so the original `native_handle` isn't stored.
149+ unsafe { NativeHandle :: clone_from_raw ( native_handle) }
150+ } )
151+ }
152+
109153 /// Adopts the given raw pointer and wraps it in a Rust HardwareBuffer.
110154 ///
111155 /// # Safety
@@ -393,4 +437,34 @@ mod test {
393437
394438 assert_eq ! ( remade_buffer, buffer2) ;
395439 }
440+
441+ #[ test]
442+ fn native_handle_and_back ( ) {
443+ let buffer = HardwareBuffer :: new (
444+ 1024 ,
445+ 512 ,
446+ 1 ,
447+ AHardwareBuffer_Format :: AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM ,
448+ AHardwareBuffer_UsageFlags :: AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN ,
449+ )
450+ . expect ( "Buffer with some basic parameters was not created successfully" ) ;
451+
452+ let native_handle =
453+ buffer. cloned_native_handle ( ) . expect ( "Failed to get native handle for buffer" ) ;
454+ let buffer_desc = ffi:: AHardwareBuffer_Desc {
455+ width : 1024 ,
456+ height : 512 ,
457+ layers : 1 ,
458+ format : AHardwareBuffer_Format :: AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM ,
459+ usage : AHardwareBuffer_UsageFlags :: AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN . 0 ,
460+ stride : 1024 ,
461+ rfu0 : 0 ,
462+ rfu1 : 0 ,
463+ } ;
464+ let buffer2 = HardwareBuffer :: create_from_handle ( & native_handle, & buffer_desc)
465+ . expect ( "Failed to create buffer from native handle" ) ;
466+
467+ assert_eq ! ( buffer. description( ) , buffer_desc) ;
468+ assert_eq ! ( buffer2. description( ) , buffer_desc) ;
469+ }
396470}
0 commit comments