Skip to content

Commit 8a60523

Browse files
authored
ndk: Add bindings for sync.h (#423)
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.
1 parent 0792dba commit 8a60523

File tree

7 files changed

+152
-0
lines changed

7 files changed

+152
-0
lines changed

ndk-sys/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

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

89
# 0.4.1 (2022-11-23)
910

ndk-sys/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ test = []
2020
audio = []
2121
bitmap = []
2222
media = []
23+
sync = []
2324

2425
[package.metadata.docs.rs]
2526
rustdoc-args = ["--cfg", "docsrs"]

ndk-sys/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@ extern "C" {}
5151
#[cfg(all(feature = "audio", target_os = "android"))]
5252
#[link(name = "aaudio")]
5353
extern "C" {}
54+
55+
#[cfg(all(feature = "sync", target_os = "android"))]
56+
#[link(name = "sync")]
57+
extern "C" {}

ndk/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- looper: Add `remove_fd()` to unregister events/callbacks for a file descriptor. (#416)
2525
- **Breaking:** Use `BorrowedFd` and `OwnedFd` to clarify possible ownership transitions. (#417)
2626
- **Breaking:** Upgrade to [`ndk-sys 0.5.0`](../ndk-sys/CHANGELOG.md#050-beta0-2023-08-15). (#420)
27+
- Add bindings for `sync.h`. (#423)
2728
- **Breaking:** bitmap: Provide detailed implementation for `AndroidBitmapInfoFlags`. (#424)
2829
- native_window: Add `set_buffers_transform()`, `try_allocate_buffers()` and `set_frame_rate*()`. (#425)
2930
- Add bindings for `ASharedMemory`. (#427)

ndk/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ all = ["audio", "bitmap","media", "api-level-31", "rwh_04", "rwh_05", "rwh_06"]
1919
audio = ["ffi/audio", "api-level-26"]
2020
bitmap = ["ffi/bitmap"]
2121
media = ["ffi/media"]
22+
sync = ["ffi/sync", "api-level-26"]
2223

2324
api-level-23 = []
2425
api-level-24 = ["api-level-23"]

ndk/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ pub mod native_activity;
2828
pub mod native_window;
2929
pub mod shared_memory;
3030
pub mod surface_texture;
31+
pub mod sync;
3132
pub mod trace;
3233
mod utils;

ndk/src/sync.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
//! Bindings for [sync functions]
2+
//!
3+
//! [sync functions]: https://developer.android.com/ndk/reference/group/sync
4+
#![cfg(feature = "sync")]
5+
6+
use std::{
7+
ffi::CStr,
8+
fmt::Debug,
9+
// TODO: Import from std::os::fd::{} since Rust 1.66
10+
os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd},
11+
ptr::NonNull,
12+
};
13+
14+
#[doc(alias = "sync_file_info")]
15+
#[repr(transparent)]
16+
pub struct SyncFileInfo {
17+
inner: NonNull<ffi::sync_file_info>,
18+
}
19+
20+
impl Debug for SyncFileInfo {
21+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22+
f.debug_struct("SyncFileInfo")
23+
.field("name", &self.name())
24+
.field("status", &self.status())
25+
.field("flags", &self.flags())
26+
.field("num_fences", &self.num_fences())
27+
.field("fence_info", &self.fence_info())
28+
.finish()
29+
}
30+
}
31+
32+
impl SyncFileInfo {
33+
/// Retrieve detailed information about a sync file and its fences.
34+
#[doc(alias = "sync_file_info")]
35+
pub fn new(fd: BorrowedFd<'_>) -> Option<Self> {
36+
let inner = NonNull::new(unsafe { ffi::sync_file_info(fd.as_raw_fd()) })?;
37+
Some(Self { inner })
38+
}
39+
40+
pub fn name(&self) -> &CStr {
41+
let inner = unsafe { self.inner.as_ref() };
42+
// TODO: Switch to CStr::from_bytes_until_nul (with c_char -> u8 transmute) since MSRV 1.69
43+
// https://github.com/ash-rs/ash/pull/746
44+
unsafe { CStr::from_ptr(inner.name.as_ptr()) }
45+
}
46+
47+
pub fn status(&self) -> i32 {
48+
let inner = unsafe { self.inner.as_ref() };
49+
inner.status
50+
}
51+
52+
pub fn flags(&self) -> u32 {
53+
let inner = unsafe { self.inner.as_ref() };
54+
inner.flags
55+
}
56+
57+
pub fn num_fences(&self) -> usize {
58+
let inner = unsafe { self.inner.as_ref() };
59+
inner.num_fences as usize
60+
}
61+
62+
/// Get the array of fence infos from the sync file's info.
63+
#[doc(alias = "sync_get_fence_info")]
64+
pub fn fence_info(&self) -> &[SyncFenceInfo] {
65+
let inner = unsafe { self.inner.as_ref() };
66+
67+
if inner.num_fences == 0 {
68+
&[]
69+
} else {
70+
let sync_fence_info = NonNull::new(inner.sync_fence_info as *mut _)
71+
.expect("sync_fence_info cannot be null if num_fences > 0");
72+
unsafe {
73+
std::slice::from_raw_parts(sync_fence_info.as_ptr(), inner.num_fences as usize)
74+
}
75+
}
76+
}
77+
}
78+
79+
impl Drop for SyncFileInfo {
80+
/// Free a [`struct@ffi::sync_file_info`] structure.
81+
#[doc(alias = "sync_file_info_free")]
82+
fn drop(&mut self) {
83+
unsafe { ffi::sync_file_info_free(self.inner.as_ptr()) }
84+
}
85+
}
86+
87+
#[doc(alias = "sync_fence_info")]
88+
#[repr(transparent)]
89+
pub struct SyncFenceInfo(ffi::sync_fence_info);
90+
91+
impl Debug for SyncFenceInfo {
92+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93+
f.debug_struct("SyncFenceInfo")
94+
.field("obj_name", &self.obj_name())
95+
.field("driver_name", &self.driver_name())
96+
.field("status", &self.status())
97+
.field("flags", &self.flags())
98+
.field("timestamp_ns", &self.timestamp_ns())
99+
.finish()
100+
}
101+
}
102+
103+
impl SyncFenceInfo {
104+
pub fn obj_name(&self) -> &CStr {
105+
// TODO: Switch to CStr::from_bytes_until_nul (with c_char -> u8 transmute) since MSRV 1.69
106+
unsafe { CStr::from_ptr(self.0.obj_name.as_ptr()) }
107+
}
108+
109+
pub fn driver_name(&self) -> &CStr {
110+
// TODO: Switch to CStr::from_bytes_until_nul (with c_char -> u8 transmute) since MSRV 1.69
111+
unsafe { CStr::from_ptr(self.0.driver_name.as_ptr()) }
112+
}
113+
114+
pub fn status(&self) -> i32 {
115+
self.0.status
116+
}
117+
118+
pub fn flags(&self) -> u32 {
119+
self.0.flags
120+
}
121+
122+
pub fn timestamp_ns(&self) -> u64 {
123+
self.0.timestamp_ns
124+
}
125+
}
126+
127+
/// Merge two sync files.
128+
///
129+
/// This produces a new sync file with the given name which has the union of the two original sync
130+
/// file's fences; redundant fences may be removed.
131+
///
132+
/// If one of the input sync files is signaled or invalid, then this function may behave like
133+
/// `dup()`: the new file descriptor refers to the valid/unsignaled sync file with its original
134+
/// name, rather than a new sync file.
135+
pub fn sync_merge(name: &CStr, fd1: BorrowedFd<'_>, fd2: BorrowedFd<'_>) -> OwnedFd {
136+
unsafe {
137+
OwnedFd::from_raw_fd(ffi::sync_merge(
138+
name.as_ptr(),
139+
fd1.as_raw_fd(),
140+
fd2.as_raw_fd(),
141+
))
142+
}
143+
}

0 commit comments

Comments
 (0)