Skip to content

Commit

Permalink
ndk: Add bindings for sync.h (#423)
Browse files Browse the repository at this point in the history
Bind a few free functions and conveniently re-wrap the resulting struct
types to access sync information from file descriptors, and merge sync
file descriptors into one.
  • Loading branch information
MarijnS95 authored Oct 14, 2023
1 parent 0792dba commit 8a60523
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 0 deletions.
1 change: 1 addition & 0 deletions ndk-sys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- **Breaking:** Regenerate against NDK `25.2.9519653` with `rust-bindgen 0.66.0`. (#324, #370)
- Add `font`, `font_matcher`, `system_fonts` bindings. (#397)
- Add `sync` feature for linking against `libsync.so`. (#423)

# 0.4.1 (2022-11-23)

Expand Down
1 change: 1 addition & 0 deletions ndk-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ test = []
audio = []
bitmap = []
media = []
sync = []

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
Expand Down
4 changes: 4 additions & 0 deletions ndk-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ extern "C" {}
#[cfg(all(feature = "audio", target_os = "android"))]
#[link(name = "aaudio")]
extern "C" {}

#[cfg(all(feature = "sync", target_os = "android"))]
#[link(name = "sync")]
extern "C" {}
1 change: 1 addition & 0 deletions ndk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- looper: Add `remove_fd()` to unregister events/callbacks for a file descriptor. (#416)
- **Breaking:** Use `BorrowedFd` and `OwnedFd` to clarify possible ownership transitions. (#417)
- **Breaking:** Upgrade to [`ndk-sys 0.5.0`](../ndk-sys/CHANGELOG.md#050-beta0-2023-08-15). (#420)
- Add bindings for `sync.h`. (#423)
- **Breaking:** bitmap: Provide detailed implementation for `AndroidBitmapInfoFlags`. (#424)
- native_window: Add `set_buffers_transform()`, `try_allocate_buffers()` and `set_frame_rate*()`. (#425)
- Add bindings for `ASharedMemory`. (#427)
Expand Down
1 change: 1 addition & 0 deletions ndk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ all = ["audio", "bitmap","media", "api-level-31", "rwh_04", "rwh_05", "rwh_06"]
audio = ["ffi/audio", "api-level-26"]
bitmap = ["ffi/bitmap"]
media = ["ffi/media"]
sync = ["ffi/sync", "api-level-26"]

api-level-23 = []
api-level-24 = ["api-level-23"]
Expand Down
1 change: 1 addition & 0 deletions ndk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ pub mod native_activity;
pub mod native_window;
pub mod shared_memory;
pub mod surface_texture;
pub mod sync;
pub mod trace;
mod utils;
143 changes: 143 additions & 0 deletions ndk/src/sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//! Bindings for [sync functions]
//!
//! [sync functions]: https://developer.android.com/ndk/reference/group/sync
#![cfg(feature = "sync")]

use std::{
ffi::CStr,
fmt::Debug,
// TODO: Import from std::os::fd::{} since Rust 1.66
os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd},
ptr::NonNull,
};

#[doc(alias = "sync_file_info")]
#[repr(transparent)]
pub struct SyncFileInfo {
inner: NonNull<ffi::sync_file_info>,
}

impl Debug for SyncFileInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SyncFileInfo")
.field("name", &self.name())
.field("status", &self.status())
.field("flags", &self.flags())
.field("num_fences", &self.num_fences())
.field("fence_info", &self.fence_info())
.finish()
}
}

impl SyncFileInfo {
/// Retrieve detailed information about a sync file and its fences.
#[doc(alias = "sync_file_info")]
pub fn new(fd: BorrowedFd<'_>) -> Option<Self> {
let inner = NonNull::new(unsafe { ffi::sync_file_info(fd.as_raw_fd()) })?;
Some(Self { inner })
}

pub fn name(&self) -> &CStr {
let inner = unsafe { self.inner.as_ref() };
// TODO: Switch to CStr::from_bytes_until_nul (with c_char -> u8 transmute) since MSRV 1.69
// https://github.com/ash-rs/ash/pull/746
unsafe { CStr::from_ptr(inner.name.as_ptr()) }
}

pub fn status(&self) -> i32 {
let inner = unsafe { self.inner.as_ref() };
inner.status
}

pub fn flags(&self) -> u32 {
let inner = unsafe { self.inner.as_ref() };
inner.flags
}

pub fn num_fences(&self) -> usize {
let inner = unsafe { self.inner.as_ref() };
inner.num_fences as usize
}

/// Get the array of fence infos from the sync file's info.
#[doc(alias = "sync_get_fence_info")]
pub fn fence_info(&self) -> &[SyncFenceInfo] {
let inner = unsafe { self.inner.as_ref() };

if inner.num_fences == 0 {
&[]
} else {
let sync_fence_info = NonNull::new(inner.sync_fence_info as *mut _)
.expect("sync_fence_info cannot be null if num_fences > 0");
unsafe {
std::slice::from_raw_parts(sync_fence_info.as_ptr(), inner.num_fences as usize)
}
}
}
}

impl Drop for SyncFileInfo {
/// Free a [`struct@ffi::sync_file_info`] structure.
#[doc(alias = "sync_file_info_free")]
fn drop(&mut self) {
unsafe { ffi::sync_file_info_free(self.inner.as_ptr()) }
}
}

#[doc(alias = "sync_fence_info")]
#[repr(transparent)]
pub struct SyncFenceInfo(ffi::sync_fence_info);

impl Debug for SyncFenceInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SyncFenceInfo")
.field("obj_name", &self.obj_name())
.field("driver_name", &self.driver_name())
.field("status", &self.status())
.field("flags", &self.flags())
.field("timestamp_ns", &self.timestamp_ns())
.finish()
}
}

impl SyncFenceInfo {
pub fn obj_name(&self) -> &CStr {
// TODO: Switch to CStr::from_bytes_until_nul (with c_char -> u8 transmute) since MSRV 1.69
unsafe { CStr::from_ptr(self.0.obj_name.as_ptr()) }
}

pub fn driver_name(&self) -> &CStr {
// TODO: Switch to CStr::from_bytes_until_nul (with c_char -> u8 transmute) since MSRV 1.69
unsafe { CStr::from_ptr(self.0.driver_name.as_ptr()) }
}

pub fn status(&self) -> i32 {
self.0.status
}

pub fn flags(&self) -> u32 {
self.0.flags
}

pub fn timestamp_ns(&self) -> u64 {
self.0.timestamp_ns
}
}

/// Merge two sync files.
///
/// This produces a new sync file with the given name which has the union of the two original sync
/// file's fences; redundant fences may be removed.
///
/// If one of the input sync files is signaled or invalid, then this function may behave like
/// `dup()`: the new file descriptor refers to the valid/unsignaled sync file with its original
/// name, rather than a new sync file.
pub fn sync_merge(name: &CStr, fd1: BorrowedFd<'_>, fd2: BorrowedFd<'_>) -> OwnedFd {
unsafe {
OwnedFd::from_raw_fd(ffi::sync_merge(
name.as_ptr(),
fd1.as_raw_fd(),
fd2.as_raw_fd(),
))
}
}

0 comments on commit 8a60523

Please sign in to comment.