diff --git a/ndk/CHANGELOG.md b/ndk/CHANGELOG.md index 40defe35..ed19a4c9 100644 --- a/ndk/CHANGELOG.md +++ b/ndk/CHANGELOG.md @@ -15,6 +15,7 @@ - Improve library and structure documentation, linking back to the NDK docs more rigorously. (#290) - **Breaking:** input_queue: `get_event()` now returns a `Result` with `std::io::Error`; `InputQueueError` has been removed. (#292) - **Breaking:** input_queue: `has_events()` now returns a `bool` directly without being wrapped in `Result`. (#294) +- **Breaking:** hardware_buffer: `HardwareBufferError` has been removed and replaced with `std::io::Error` in return types. (#295) - **Breaking:** Update `jni` crate (used in public API) from `0.18` to `0.19`. (#300) # 0.6.0 (2022-01-05) diff --git a/ndk/src/hardware_buffer.rs b/ndk/src/hardware_buffer.rs index ea682a0b..63571b2c 100644 --- a/ndk/src/hardware_buffer.rs +++ b/ndk/src/hardware_buffer.rs @@ -4,11 +4,13 @@ #![cfg(feature = "hardware_buffer")] +use crate::utils::status_to_io_result; + pub use super::hardware_buffer_format::HardwareBufferFormat; use jni_sys::{jobject, JNIEnv}; use std::{ - convert::TryInto, mem::MaybeUninit, ops::Deref, os::raw::c_void, os::unix::io::RawFd, - ptr::NonNull, + convert::TryInto, io::Result, mem::MaybeUninit, ops::Deref, os::raw::c_void, + os::unix::io::RawFd, ptr::NonNull, }; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -84,21 +86,12 @@ impl HardwareBufferUsage { Self(ffi::AHardwareBuffer_UsageFlags_AHARDWAREBUFFER_USAGE_VENDOR_19); } -#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] -pub struct HardwareBufferError(pub i32); - -pub type Result = std::result::Result; - pub type Rect = ffi::ARect; -fn construct(with_ptr: impl FnOnce(*mut T) -> i32) -> Result { +fn construct(with_ptr: impl FnOnce(*mut T) -> i32) -> Result { let mut result = MaybeUninit::uninit(); let status = with_ptr(result.as_mut_ptr()); - if status == 0 { - Ok(unsafe { result.assume_init() }) - } else { - Err(HardwareBufferError(status)) - } + status_to_io_result(status, unsafe { result.assume_init() }) } /// A native [`AHardwareBuffer *`] @@ -141,7 +134,7 @@ impl HardwareBuffer { /// Create a [`HardwareBuffer`] from JNI pointers /// /// # Safety - /// By calling this function, you assert that it these are valid pointers to JNI objects. + /// By calling this function, you assert that these are valid pointers to JNI objects. pub unsafe fn from_jni(env: *mut JNIEnv, hardware_buffer: jobject) -> Self { let ptr = ffi::AHardwareBuffer_fromHardwareBuffer(env, hardware_buffer); @@ -219,17 +212,13 @@ impl HardwareBuffer { bytes_per_stride.as_mut_ptr(), ) }; - if status == 0 { - Ok(unsafe { - LockedPlaneInfo { - virtual_address: virtual_address.assume_init(), - bytes_per_pixel: bytes_per_pixel.assume_init() as u32, - bytes_per_stride: bytes_per_stride.assume_init() as u32, - } - }) - } else { - Err(HardwareBufferError(status)) - } + status_to_io_result(status, ()).map(|()| unsafe { + LockedPlaneInfo { + virtual_address: virtual_address.assume_init(), + bytes_per_pixel: bytes_per_pixel.assume_init() as u32, + bytes_per_stride: bytes_per_stride.assume_init() as u32, + } + }) } #[cfg(feature = "api-level-29")] @@ -256,11 +245,7 @@ impl HardwareBuffer { pub fn unlock(&self) -> Result<()> { let status = unsafe { ffi::AHardwareBuffer_unlock(self.as_ptr(), std::ptr::null_mut()) }; - if status == 0 { - Ok(()) - } else { - Err(HardwareBufferError(status)) - } + status_to_io_result(status, ()) } /// Returns a fence file descriptor that will become signalled when unlocking is completed, @@ -283,14 +268,9 @@ impl HardwareBuffer { } pub fn send_handle_to_unix_socket(&self, socket_fd: RawFd) -> Result<()> { - unsafe { - let status = ffi::AHardwareBuffer_sendHandleToUnixSocket(self.as_ptr(), socket_fd); - if status == 0 { - Ok(()) - } else { - Err(HardwareBufferError(status)) - } - } + let status = + unsafe { ffi::AHardwareBuffer_sendHandleToUnixSocket(self.as_ptr(), socket_fd) }; + status_to_io_result(status, ()) } pub fn acquire(&self) -> HardwareBufferRef { diff --git a/ndk/src/input_queue.rs b/ndk/src/input_queue.rs index 209d2fc2..ecd8c006 100644 --- a/ndk/src/input_queue.rs +++ b/ndk/src/input_queue.rs @@ -2,7 +2,7 @@ //! //! [`AInputQueue`]: https://developer.android.com/ndk/reference/group/input#ainputqueue -use std::io::{Error, Result}; +use std::io::Result; use std::os::raw::c_int; use std::ptr::{self, NonNull}; @@ -10,6 +10,7 @@ use crate::event::InputEvent; #[cfg(doc)] use crate::event::KeyEvent; use crate::looper::ForeignLooper; +use crate::utils::status_to_io_result; /// A native [`AInputQueue *`] /// @@ -43,18 +44,16 @@ impl InputQueue { /// Returns [`None`] if no event is available. pub fn get_event(&self) -> Result> { let mut out_event = ptr::null_mut(); - match unsafe { ffi::AInputQueue_getEvent(self.ptr.as_ptr(), &mut out_event) } { - 0 => { + let status = unsafe { ffi::AInputQueue_getEvent(self.ptr.as_ptr(), &mut out_event) }; + match status_to_io_result(status, ()) { + Ok(()) => { debug_assert!(!out_event.is_null()); Ok(Some(unsafe { InputEvent::from_ptr(NonNull::new_unchecked(out_event)) })) } - r if r < 0 => match Error::from_raw_os_error(-r) { - e if e.kind() == std::io::ErrorKind::WouldBlock => Ok(None), - e => Err(e), - }, - r => unreachable!("AInputQueue_getEvent returned positive integer {}", r), + Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => Ok(None), + Err(e) => Err(e), } } diff --git a/ndk/src/lib.rs b/ndk/src/lib.rs index ae56bf2a..7fb6979c 100644 --- a/ndk/src/lib.rs +++ b/ndk/src/lib.rs @@ -19,3 +19,4 @@ pub mod native_activity; pub mod native_window; pub mod surface_texture; pub mod trace; +mod utils; diff --git a/ndk/src/native_window.rs b/ndk/src/native_window.rs index 08ccec07..37047158 100644 --- a/ndk/src/native_window.rs +++ b/ndk/src/native_window.rs @@ -2,10 +2,12 @@ //! //! [`ANativeWindow`]: https://developer.android.com/ndk/reference/group/a-native-window#anativewindow +use crate::utils::status_to_io_result; + pub use super::hardware_buffer_format::HardwareBufferFormat; use jni_sys::{jobject, JNIEnv}; use raw_window_handle::{AndroidNdkHandle, HasRawWindowHandle, RawWindowHandle}; -use std::{convert::TryFrom, ffi::c_void, ptr::NonNull}; +use std::{convert::TryFrom, ffi::c_void, io::Result, ptr::NonNull}; // [`NativeWindow`] represents the producer end of an image queue /// @@ -94,16 +96,12 @@ impl NativeWindow { width: i32, height: i32, format: Option, - ) -> Result<(), i32> { + ) -> Result<()> { let format: u32 = format.map_or(0, |f| f.into()); - let r = unsafe { + let status = unsafe { ffi::ANativeWindow_setBuffersGeometry(self.ptr.as_ptr(), width, height, format as i32) }; - if r == 0 { - Ok(()) - } else { - Err(r) - } + status_to_io_result(status, ()) } /// Return the [`NativeWindow`] associated with a JNI [`android.view.Surface`] pointer. diff --git a/ndk/src/surface_texture.rs b/ndk/src/surface_texture.rs index 60c68502..c35130f4 100644 --- a/ndk/src/surface_texture.rs +++ b/ndk/src/surface_texture.rs @@ -6,14 +6,9 @@ //! [`ASurfaceTexture`]: https://developer.android.com/ndk/reference/group/surface-texture #![cfg(feature = "api-level-28")] -use crate::native_window::NativeWindow; +use crate::{native_window::NativeWindow, utils::status_to_io_result}; use jni_sys::{jobject, JNIEnv}; -use std::{ - convert::TryInto, - io::{Error, Result}, - ptr::NonNull, - time::Duration, -}; +use std::{convert::TryInto, io::Result, ptr::NonNull, time::Duration}; /// An opaque type to manage [`android.graphics.SurfaceTexture`] from native code /// @@ -88,14 +83,8 @@ impl SurfaceTexture { /// contexts. Note, however, that the image contents are only accessible from one OpenGL ES /// context at a time. pub fn attach_to_gl_context(&self, tex_name: u32) -> Result<()> { - match unsafe { ffi::ASurfaceTexture_attachToGLContext(self.ptr.as_ptr(), tex_name) } { - 0 => Ok(()), - r if r < 0 => Err(Error::from_raw_os_error(-r)), - r => unreachable!( - "ASurfaceTexture_attachToGLContext returned positive integer {}", - r - ), - } + let status = unsafe { ffi::ASurfaceTexture_attachToGLContext(self.ptr.as_ptr(), tex_name) }; + status_to_io_result(status, ()) } /// Detach the [`SurfaceTexture`] from the OpenGL ES context that owns the OpenGL ES texture @@ -110,14 +99,8 @@ impl SurfaceTexture { /// contexts. Note, however, that the image contents are only accessible from one OpenGL ES /// context at a time. pub fn detach_from_gl_context(&self) -> Result<()> { - match unsafe { ffi::ASurfaceTexture_detachFromGLContext(self.ptr.as_ptr()) } { - 0 => Ok(()), - r if r < 0 => Err(Error::from_raw_os_error(-r)), - r => unreachable!( - "ASurfaceTexture_detachFromGLContext returned positive integer {}", - r - ), - } + let status = unsafe { ffi::ASurfaceTexture_detachFromGLContext(self.ptr.as_ptr()) }; + status_to_io_result(status, ()) } /// Retrieve the 4x4 texture coordinate transform matrix associated with the texture image set @@ -170,13 +153,7 @@ impl SurfaceTexture { /// calling thread. It will implicitly bind its texture to the `GL_TEXTURE_EXTERNAL_OES` /// texture target. pub fn update_tex_image(&self) -> Result<()> { - match unsafe { ffi::ASurfaceTexture_updateTexImage(self.ptr.as_ptr()) } { - 0 => Ok(()), - r if r < 0 => Err(Error::from_raw_os_error(-r)), - r => unreachable!( - "ASurfaceTexture_updateTexImage returned positive integer {}", - r - ), - } + let status = unsafe { ffi::ASurfaceTexture_updateTexImage(self.ptr.as_ptr()) }; + status_to_io_result(status, ()) } } diff --git a/ndk/src/utils.rs b/ndk/src/utils.rs new file mode 100644 index 00000000..2c70e364 --- /dev/null +++ b/ndk/src/utils.rs @@ -0,0 +1,14 @@ +//! Internal utilities +use std::io::{Error, Result}; + +/// Turns standard `` status codes - typically rewrapped by Android's [`Errors.h`] - into +/// Rust's [`std::io::Error`]. +/// +/// [`Errors.h`]: https://cs.android.com/android/platform/superproject/+/master:system/core/libutils/include/utils/Errors.h +pub(crate) fn status_to_io_result(status: i32, value: T) -> Result { + match status { + 0 => Ok(value), + r if r < 0 => Err(Error::from_raw_os_error(-r)), + r => unreachable!("Status is positive integer {}", r), + } +}