Skip to content

Commit 647864a

Browse files
Treehugger RobotGerrit Code Review
authored andcommitted
Merge "Add methods to convert between HardwareBuffer and native handle." into main
2 parents b169c75 + a73d62c commit 647864a

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

libs/nativewindow/rust/src/lib.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

libs/nativewindow/rust/sys/nativewindow_bindings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@
2121
#include <android/native_window.h>
2222
#include <android/native_window_aidl.h>
2323
#include <cutils/native_handle.h>
24+
#include <vndk/hardware_buffer.h>

0 commit comments

Comments
 (0)