1use std::{ffi::CStr, mem::MaybeUninit, os::{fd::{AsRawFd, BorrowedFd}, unix::net::UnixStream}, ptr::{null, null_mut, NonNull}};
10
11use cstr::cstr;
12use lazy_static::lazy_static;
13use libc::{c_char, c_int, c_void, dlopen, dlsym, RTLD_LAZY, RTLD_LOCAL};
14
15
16mod hb_raw {
17 #![allow(non_upper_case_globals)]
18 #![allow(non_camel_case_types)]
19 #![allow(non_snake_case)]
20 #![allow(unused)]
21
22 include!(concat!(env!("OUT_DIR"), "/hardware_buffer.rs"));
23}
24
25pub use hb_raw::*;
26
27
28#[allow(non_snake_case, dead_code)]
30pub struct HBHolder {
31 pub api_level: c_int,
34 AHardwareBuffer_acquire: *const fn(buffer: NonNull<AHardwareBuffer>) -> c_void,
35 AHardwareBuffer_allocate: *const fn(desc: NonNull<AHardwareBufferDesc>, outBuffer: NonNull<*mut AHardwareBuffer>) -> c_int,
36 AHardwareBuffer_describe: *const fn(buffer: NonNull<AHardwareBuffer>, outDesc: NonNull<AHardwareBufferDesc>) -> c_void,
37 AHardwareBuffer_getId: *const fn(buffer: NonNull<AHardwareBuffer>, outId: NonNull<u64>) -> c_int,
38 AHardwareBuffer_isSupported: *const fn(desc: NonNull<AHardwareBufferDesc>) -> c_int,
39 AHardwareBuffer_recvHandleFromUnixSocket: *const fn(fd: c_int, outBuffer: NonNull<*mut AHardwareBuffer>) -> c_int,
40 AHardwareBuffer_lock: *const fn(buffer: NonNull<AHardwareBuffer>, usage: u64, fence: i32, rect: *const ARect, outAddr: NonNull<*mut c_void>) -> c_int,
41 AHardwareBuffer_lockAndGetInfo: *const fn(buffer: NonNull<AHardwareBuffer>, usage: u64, fence: i32, rect: *const ARect, outAddr: NonNull<*mut c_void>, bpp: NonNull<i32>, bps: NonNull<i32>) -> c_int,
42 AHardwareBuffer_lockPlanes: *const fn(buffer: NonNull<AHardwareBuffer>, usage: u64, fence: i32, rect: *const ARect, planes: NonNull<AHardwareBufferPlanes>) -> c_int,
43 AHardwareBuffer_release: *const fn(buffer: NonNull<AHardwareBuffer>) -> c_void,
44 AHardwareBuffer_sendHandleToUnixSocket: *const fn(buffer: NonNull<AHardwareBuffer>, fd: c_int) -> c_int,
45 AHardwareBuffer_unlock: *const fn(buffer: NonNull<AHardwareBuffer>, fence: *mut i32) -> c_int,
46}
47
48
49unsafe impl Sync for HBHolder {}
52
53lazy_static! {
54 pub static ref HB: HBHolder = HBHolder::new();
56}
57
58
59impl HBHolder {
60 fn new() -> Self {
61 let lib = unsafe { dlopen(cstr!("libandroid.so").as_ptr(), RTLD_LAZY | RTLD_LOCAL) };
62 if lib == null_mut() {
63 return Self {
64 api_level: -1,
65 AHardwareBuffer_release: null(),
66 AHardwareBuffer_recvHandleFromUnixSocket: null(),
67 AHardwareBuffer_acquire: null(),
68 AHardwareBuffer_allocate: null(),
69 AHardwareBuffer_describe: null(),
70 AHardwareBuffer_getId: null(),
71 AHardwareBuffer_isSupported: null(),
72 AHardwareBuffer_lock: null(),
73 AHardwareBuffer_lockAndGetInfo: null(),
74 AHardwareBuffer_lockPlanes: null(),
75 AHardwareBuffer_sendHandleToUnixSocket: null(),
76 AHardwareBuffer_unlock: null(),
77 };
78 }
79
80 let mut api_level = -1;
81 {
82 let __system_property_get = unsafe { dlsym(lib, cstr!("__system_property_get").as_ptr()) } as *const fn(name: *const c_char, value: *mut c_char) -> c_int;
85 if __system_property_get != null() {
86 let mut buffer: [c_char; 92] = [0; 92];
88 if (unsafe { *__system_property_get })(cstr!("ro.build.version.sdk").as_ptr(), buffer.as_mut_ptr()) >= 1 {
89 if let Ok(s) = CStr::from_bytes_until_nul(bytemuck::cast_slice(&buffer[..])) {
90 if let Ok(l) = s.to_str() {
91 if let Ok(l) = l.parse() {
92 api_level = l;
93 }
94 }
95 }
96 }
97 }
98 }
99
100 #[allow(non_snake_case)]
101 {
102 let AHardwareBuffer_acquire = unsafe { dlsym(lib, cstr!("AHardwareBuffer_acquire").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>) -> c_void;
103 let AHardwareBuffer_allocate = unsafe { dlsym(lib, cstr!("AHardwareBuffer_allocate").as_ptr()) } as *const fn(desc: NonNull<AHardwareBufferDesc>, outBuffer: NonNull<*mut AHardwareBuffer>) -> c_int;
104 let AHardwareBuffer_describe = unsafe { dlsym(lib, cstr!("AHardwareBuffer_describe").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>, outDesc: NonNull<AHardwareBufferDesc>) -> c_void;
105 let AHardwareBuffer_getId = unsafe { dlsym(lib, cstr!("AHardwareBuffer_getId").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>, outId: NonNull<u64>) -> c_int;
106 let AHardwareBuffer_isSupported = unsafe { dlsym(lib, cstr!("AHardwareBuffer_isSupported").as_ptr()) } as *const fn(desc: NonNull<AHardwareBufferDesc>) -> c_int;
107 let AHardwareBuffer_recvHandleFromUnixSocket = unsafe { dlsym(lib, cstr!("AHardwareBuffer_recvHandleFromUnixSocket").as_ptr()) } as *const fn(fd: c_int, outBuffer: NonNull<*mut AHardwareBuffer>) -> c_int;
108 let AHardwareBuffer_lock = unsafe { dlsym(lib, cstr!("AHardwareBuffer_lock").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>, usage: u64, fence: i32, rect: *const ARect, outAddr: NonNull<*mut c_void>) -> c_int;
109 let AHardwareBuffer_lockAndGetInfo = unsafe { dlsym(lib, cstr!("AHardwareBuffer_lockAndGetInfo").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>, usage: u64, fence: i32, rect: *const ARect, outAddr: NonNull<*mut c_void>, bpp: NonNull<i32>, bps: NonNull<i32>) -> c_int;
110 let AHardwareBuffer_lockPlanes = unsafe { dlsym(lib, cstr!("AHardwareBuffer_lockPlanes").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>, usage: u64, fence: i32, rect: *const ARect, planes: NonNull<AHardwareBufferPlanes>) -> c_int;
111 let AHardwareBuffer_release = unsafe { dlsym(lib, cstr!("AHardwareBuffer_release").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>) -> c_void;
112 let AHardwareBuffer_sendHandleToUnixSocket = unsafe { dlsym(lib, cstr!("AHardwareBuffer_sendHandleToUnixSocket").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>, fd: c_int) -> c_int;
113 let AHardwareBuffer_unlock = unsafe { dlsym(lib, cstr!("AHardwareBuffer_unlock").as_ptr()) } as *const fn(buffer: NonNull<AHardwareBuffer>, fence: *mut i32) -> c_int;
114 Self {
115 api_level,
116 AHardwareBuffer_acquire,
117 AHardwareBuffer_release,
118 AHardwareBuffer_allocate,
119 AHardwareBuffer_describe,
120 AHardwareBuffer_getId,
121 AHardwareBuffer_isSupported,
122 AHardwareBuffer_recvHandleFromUnixSocket,
123 AHardwareBuffer_sendHandleToUnixSocket,
124 AHardwareBuffer_lock,
125 AHardwareBuffer_lockAndGetInfo,
126 AHardwareBuffer_lockPlanes,
127 AHardwareBuffer_unlock,
128 }
129 }
130 }
131
132
133
134 pub unsafe fn acquire(&self, buffer: NonNull<AHardwareBuffer>) {
138 if self.api_level < 26 {
139 return;
140 }
141 (*self.AHardwareBuffer_acquire)(buffer);
142 }
143
144
145
146 pub unsafe fn release(&self, buffer: NonNull<AHardwareBuffer>) {
149 if self.api_level < 26 {
150 return;
151 }
152 (*self.AHardwareBuffer_release)(buffer);
153 }
154
155 pub fn allocate(&self, desc: AHardwareBufferDesc) -> Option<HBRef> {
160 if self.api_level < 26 {
161 return None;
162 }
163 let mut desc = desc;
164 let mut buffer: *mut AHardwareBuffer = null_mut();
165 unsafe {
166 if (*self.AHardwareBuffer_allocate)(NonNull::new_unchecked(&mut desc), NonNull::new_unchecked(&mut buffer as *mut *mut AHardwareBuffer)) != 0 {
167 buffer = null_mut();
168 }
169 }
170 if buffer == null_mut() {
171 return None;
172 }
173 return Some(HBRef { data: unsafe { NonNull::new_unchecked(buffer) } });
174 }
175
176 pub fn describe(&self, buffer: &HBRef) -> Option<AHardwareBufferDesc> {
179 if self.api_level < 26 {
180 return None;
181 }
182 let mut desc: MaybeUninit<AHardwareBufferDesc> = MaybeUninit::uninit();
183 unsafe {
184 (*self.AHardwareBuffer_describe)(buffer.get(), NonNull::new_unchecked(desc.as_mut_ptr()));
185 return Some(desc.assume_init());
186 }
187 }
188
189 pub fn get_id(&self, buffer: &HBRef) -> Option<u64> {
192 if self.api_level < 31 {
193 return None;
194 }
195 let mut id: u64 = 0;
196 unsafe {
197 if (*self.AHardwareBuffer_getId)(buffer.get(), NonNull::new_unchecked(&mut id)) != 0 {
198 None
199 } else {
200 Some(id)
201 }
202 }
203 }
204
205 pub fn is_supported(&self, desc: &AHardwareBufferDesc) -> bool {
212 if self.api_level < 29 {
213 return false;
214 }
215 if (unsafe { *self.AHardwareBuffer_isSupported })(desc.into()) == 1 {
216 true
217 } else {
218 false
219 }
220 }
221
222 pub fn recv(&self, socket: &UnixStream) -> Option<HBRef> {
225 if self.api_level < 26 {
226 return None;
227 }
228 let mut buffer: *mut AHardwareBuffer = null_mut();
229 unsafe {
230 if (*self.AHardwareBuffer_recvHandleFromUnixSocket)(socket.as_raw_fd(), NonNull::new_unchecked(&mut buffer as *mut *mut AHardwareBuffer)) != 0 {
231 buffer = null_mut();
232 }
233 }
234 if buffer == null_mut() {
235 return None;
236 }
237 return Some(HBRef { data: unsafe { NonNull::new_unchecked(buffer) } });
238 }
239
240 pub fn send(&self, socket: &UnixStream, buffer: &HBRef) -> bool {
243 if self.api_level < 26 {
244 return false;
245 }
246 if (unsafe { *self.AHardwareBuffer_sendHandleToUnixSocket })(buffer.get(), socket.as_raw_fd()) == 0 {
247 true
248 } else {
249 false
250 }
251 }
252
253 pub fn lock(&self, buffer: &HBRef, usage: u64, fence: Option<BorrowedFd>, rect: Option<&ARect>) -> *mut c_void {
256 if self.api_level < 26 {
257 return null_mut();
258 }
259 let mut out: *mut c_void = null_mut();
260 if (unsafe { *self.AHardwareBuffer_lock })(buffer.get(), usage, fence.and_then(|f| Some(f.as_raw_fd())).unwrap_or(-1), rect.and_then(|r| Some(r as *const ARect)).unwrap_or(null()), unsafe { NonNull::new_unchecked(&mut out) }) != 0 {
261 out = null_mut();
262 }
263 return out;
264 }
265
266 pub fn lock_info(&self, buffer: &HBRef, usage: u64, fence: Option<BorrowedFd>, rect: Option<&ARect>) -> Option<LockInfo> {
269 if self.api_level < 29 {
270 return None;
271 }
272 let mut bpp: i32 = 0;
273 let mut bps: i32 = 0;
274 let mut out: *mut c_void = null_mut();
275 if (unsafe { *self.AHardwareBuffer_lockAndGetInfo })(buffer.get(), usage, fence.and_then(|f| Some(f.as_raw_fd())).unwrap_or(-1), rect.and_then(|r| Some(r as *const ARect)).unwrap_or(null()), unsafe { NonNull::new_unchecked(&mut out) }, (&mut bpp).into(), (&mut bps).into()) != 0 {
276 return None;
277 }
278 return Some(LockInfo { address: out, bytes_per_pixel: bpp, bytes_per_stride: bps });
279 }
280
281 pub fn lock_planes(&self, buffer: &HBRef, usage: u64, fence: Option<BorrowedFd>, rect: Option<&ARect>) -> Option<AHardwareBufferPlanes> {
284 if self.api_level < 29 {
285 return None;
286 }
287 let mut out: MaybeUninit<AHardwareBufferPlanes> = MaybeUninit::uninit();
288 if (unsafe { *self.AHardwareBuffer_lockPlanes })(buffer.get(), usage, fence.and_then(|f| Some(f.as_raw_fd())).unwrap_or(-1), rect.and_then(|r| Some(r as *const ARect)).unwrap_or(null()), unsafe { NonNull::new_unchecked(out.as_mut_ptr()) }) != 0 {
289 return None;
290 }
291 return Some(unsafe { out.assume_init() });
292 }
293
294 pub fn unlock(&self, buffer: &HBRef) -> bool {
297 if self.api_level < 26 {
298 return false;
299 }
300 if (unsafe { *self.AHardwareBuffer_unlock })(buffer.get(), null_mut()) == 0 {
301 true
302 } else {
303 false
304 }
305 }
306}
307
308pub struct LockInfo {
310 pub address: *mut c_void,
312 pub bytes_per_pixel: i32,
314 pub bytes_per_stride: i32,
316}
317
318#[repr(transparent)]
320pub struct HBRef {
321 data: NonNull<AHardwareBuffer>
322}
323
324impl HBRef {
325 pub fn get(&self) -> NonNull<AHardwareBuffer> {
327 self.data
328 }
329}
330
331impl Clone for HBRef {
332 fn clone(&self) -> Self {
333 unsafe { (*HB.AHardwareBuffer_acquire)(self.data) };
334 Self { data: self.data.clone() }
335 }
336}
337
338
339impl Drop for HBRef {
340 fn drop(&mut self) {
341 unsafe { (*HB.AHardwareBuffer_release)(self.data) };
342 }
343}