1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Pleasant Rust bindings for libnativewindow, including AHardwareBuffer
16 
17 extern crate nativewindow_bindgen as ffi;
18 
19 mod surface;
20 pub use surface::Surface;
21 
22 pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
23 
24 use binder::{
25     binder_impl::{BorrowedParcel, UnstructuredParcelable},
26     impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
27     unstable_api::{status_result, AsNative},
28     StatusCode,
29 };
30 use ffi::{AHardwareBuffer, AHardwareBuffer_readFromParcel, AHardwareBuffer_writeToParcel};
31 use std::fmt::{self, Debug, Formatter};
32 use std::mem::ManuallyDrop;
33 use std::ptr::{self, null_mut, NonNull};
34 
35 /// Wrapper around an opaque C `AHardwareBuffer`.
36 #[derive(PartialEq, Eq)]
37 pub struct HardwareBuffer(NonNull<AHardwareBuffer>);
38 
39 impl HardwareBuffer {
40     /// Test whether the given format and usage flag combination is allocatable.  If this function
41     /// returns true, it means that a buffer with the given description can be allocated on this
42     /// implementation, unless resource exhaustion occurs. If this function returns false, it means
43     /// that the allocation of the given description will never succeed.
44     ///
45     /// Available since API 29
is_supported( width: u32, height: u32, layers: u32, format: AHardwareBuffer_Format::Type, usage: AHardwareBuffer_UsageFlags, stride: u32, ) -> bool46     pub fn is_supported(
47         width: u32,
48         height: u32,
49         layers: u32,
50         format: AHardwareBuffer_Format::Type,
51         usage: AHardwareBuffer_UsageFlags,
52         stride: u32,
53     ) -> bool {
54         let buffer_desc = ffi::AHardwareBuffer_Desc {
55             width,
56             height,
57             layers,
58             format,
59             usage: usage.0,
60             stride,
61             rfu0: 0,
62             rfu1: 0,
63         };
64         // SAFETY: *buffer_desc will never be null.
65         let status = unsafe { ffi::AHardwareBuffer_isSupported(&buffer_desc) };
66 
67         status == 1
68     }
69 
70     /// Allocates a buffer that matches the passed AHardwareBuffer_Desc. If allocation succeeds, the
71     /// buffer can be used according to the usage flags specified in its description. If a buffer is
72     /// used in ways not compatible with its usage flags, the results are undefined and may include
73     /// program termination.
74     ///
75     /// Available since API level 26.
76     #[inline]
new( width: u32, height: u32, layers: u32, format: AHardwareBuffer_Format::Type, usage: AHardwareBuffer_UsageFlags, ) -> Option<Self>77     pub fn new(
78         width: u32,
79         height: u32,
80         layers: u32,
81         format: AHardwareBuffer_Format::Type,
82         usage: AHardwareBuffer_UsageFlags,
83     ) -> Option<Self> {
84         let buffer_desc = ffi::AHardwareBuffer_Desc {
85             width,
86             height,
87             layers,
88             format,
89             usage: usage.0,
90             stride: 0,
91             rfu0: 0,
92             rfu1: 0,
93         };
94         let mut ptr = ptr::null_mut();
95         // SAFETY: The returned pointer is valid until we drop/deallocate it. The function may fail
96         // and return a status, but we check it later.
97         let status = unsafe { ffi::AHardwareBuffer_allocate(&buffer_desc, &mut ptr) };
98 
99         if status == 0 {
100             Some(Self(NonNull::new(ptr).expect("Allocated AHardwareBuffer was null")))
101         } else {
102             None
103         }
104     }
105 
106     /// Adopts the given raw pointer and wraps it in a Rust HardwareBuffer.
107     ///
108     /// # Safety
109     ///
110     /// This function takes ownership of the pointer and does NOT increment the refcount on the
111     /// buffer. If the caller uses the pointer after the created object is dropped it will cause
112     /// undefined behaviour. If the caller wants to continue using the pointer after calling this
113     /// then use [`clone_from_raw`](Self::clone_from_raw) instead.
from_raw(buffer_ptr: NonNull<AHardwareBuffer>) -> Self114     pub unsafe fn from_raw(buffer_ptr: NonNull<AHardwareBuffer>) -> Self {
115         Self(buffer_ptr)
116     }
117 
118     /// Creates a new Rust HardwareBuffer to wrap the given AHardwareBuffer without taking ownership
119     /// of it.
120     ///
121     /// Unlike [`from_raw`](Self::from_raw) this method will increment the refcount on the buffer.
122     /// This means that the caller can continue to use the raw buffer it passed in, and must call
123     /// [`AHardwareBuffer_release`](ffi::AHardwareBuffer_release) when it is finished with it to
124     /// avoid a memory leak.
125     ///
126     /// # Safety
127     ///
128     /// The buffer pointer must point to a valid `AHardwareBuffer`.
clone_from_raw(buffer: NonNull<AHardwareBuffer>) -> Self129     pub unsafe fn clone_from_raw(buffer: NonNull<AHardwareBuffer>) -> Self {
130         // SAFETY: The caller guarantees that the AHardwareBuffer pointer is valid.
131         unsafe { ffi::AHardwareBuffer_acquire(buffer.as_ptr()) };
132         Self(buffer)
133     }
134 
135     /// Get the internal |AHardwareBuffer| pointer without decrementing the refcount. This can
136     /// be used to provide a pointer to the AHB for a C/C++ API over the FFI.
into_raw(self) -> NonNull<AHardwareBuffer>137     pub fn into_raw(self) -> NonNull<AHardwareBuffer> {
138         let buffer = ManuallyDrop::new(self);
139         buffer.0
140     }
141 
142     /// Get the system wide unique id for an AHardwareBuffer. This function may panic in extreme
143     /// and undocumented circumstances.
144     ///
145     /// Available since API level 31.
id(&self) -> u64146     pub fn id(&self) -> u64 {
147         let mut out_id = 0;
148         // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
149         // because it must have been allocated by `AHardwareBuffer_allocate`,
150         // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
151         // released it. The id pointer must be valid because it comes from a reference.
152         let status = unsafe { ffi::AHardwareBuffer_getId(self.0.as_ptr(), &mut out_id) };
153         assert_eq!(status, 0, "id() failed for AHardwareBuffer with error code: {status}");
154 
155         out_id
156     }
157 
158     /// Get the width of this buffer
width(&self) -> u32159     pub fn width(&self) -> u32 {
160         self.description().width
161     }
162 
163     /// Get the height of this buffer
height(&self) -> u32164     pub fn height(&self) -> u32 {
165         self.description().height
166     }
167 
168     /// Get the number of layers of this buffer
layers(&self) -> u32169     pub fn layers(&self) -> u32 {
170         self.description().layers
171     }
172 
173     /// Get the format of this buffer
format(&self) -> AHardwareBuffer_Format::Type174     pub fn format(&self) -> AHardwareBuffer_Format::Type {
175         self.description().format
176     }
177 
178     /// Get the usage bitvector of this buffer
usage(&self) -> AHardwareBuffer_UsageFlags179     pub fn usage(&self) -> AHardwareBuffer_UsageFlags {
180         AHardwareBuffer_UsageFlags(self.description().usage)
181     }
182 
183     /// Get the stride of this buffer
stride(&self) -> u32184     pub fn stride(&self) -> u32 {
185         self.description().stride
186     }
187 
description(&self) -> ffi::AHardwareBuffer_Desc188     fn description(&self) -> ffi::AHardwareBuffer_Desc {
189         let mut buffer_desc = ffi::AHardwareBuffer_Desc {
190             width: 0,
191             height: 0,
192             layers: 0,
193             format: 0,
194             usage: 0,
195             stride: 0,
196             rfu0: 0,
197             rfu1: 0,
198         };
199         // SAFETY: neither the buffer nor AHardwareBuffer_Desc pointers will be null.
200         unsafe { ffi::AHardwareBuffer_describe(self.0.as_ref(), &mut buffer_desc) };
201         buffer_desc
202     }
203 }
204 
205 impl Drop for HardwareBuffer {
drop(&mut self)206     fn drop(&mut self) {
207         // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
208         // because it must have been allocated by `AHardwareBuffer_allocate`,
209         // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
210         // released it.
211         unsafe { ffi::AHardwareBuffer_release(self.0.as_ptr()) }
212     }
213 }
214 
215 impl Debug for HardwareBuffer {
fmt(&self, f: &mut Formatter) -> fmt::Result216     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
217         f.debug_struct("HardwareBuffer").field("id", &self.id()).finish()
218     }
219 }
220 
221 impl Clone for HardwareBuffer {
clone(&self) -> Self222     fn clone(&self) -> Self {
223         // SAFETY: ptr is guaranteed to be non-null and the acquire can not fail.
224         unsafe { ffi::AHardwareBuffer_acquire(self.0.as_ptr()) };
225         Self(self.0)
226     }
227 }
228 
229 impl UnstructuredParcelable for HardwareBuffer {
write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode>230     fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
231         let status =
232         // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
233         // because it must have been allocated by `AHardwareBuffer_allocate`,
234         // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
235         // released it.
236             unsafe { AHardwareBuffer_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) };
237         status_result(status)
238     }
239 
from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode>240     fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
241         let mut buffer = null_mut();
242 
243         let status =
244         // SAFETY: Both pointers must be valid because they are obtained from references.
245         // `AHardwareBuffer_readFromParcel` doesn't store them or do anything else special
246         // with them. If it returns success then it will have allocated a new
247         // `AHardwareBuffer` and incremented the reference count, so we can use it until we
248         // release it.
249             unsafe { AHardwareBuffer_readFromParcel(parcel.as_native(), &mut buffer) };
250 
251         status_result(status)?;
252 
253         Ok(Self(
254             NonNull::new(buffer).expect(
255                 "AHardwareBuffer_readFromParcel returned success but didn't allocate buffer",
256             ),
257         ))
258     }
259 }
260 
261 impl_deserialize_for_unstructured_parcelable!(HardwareBuffer);
262 impl_serialize_for_unstructured_parcelable!(HardwareBuffer);
263 
264 // SAFETY: The underlying *AHardwareBuffers can be moved between threads.
265 unsafe impl Send for HardwareBuffer {}
266 
267 // SAFETY: The underlying *AHardwareBuffers can be used from multiple threads.
268 //
269 // AHardwareBuffers are backed by C++ GraphicBuffers, which are mostly immutable. The only cases
270 // where they are not immutable are:
271 //
272 //   - reallocation (which is never actually done across the codebase and requires special
273 //     privileges/platform code access to do)
274 //   - "locking" for reading/writing (which is explicitly allowed to be done across multiple threads
275 //     according to the docs on the underlying gralloc calls)
276 unsafe impl Sync for HardwareBuffer {}
277 
278 #[cfg(test)]
279 mod test {
280     use super::*;
281 
282     #[test]
create_valid_buffer_returns_ok()283     fn create_valid_buffer_returns_ok() {
284         let buffer = HardwareBuffer::new(
285             512,
286             512,
287             1,
288             AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
289             AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
290         );
291         assert!(buffer.is_some());
292     }
293 
294     #[test]
create_invalid_buffer_returns_err()295     fn create_invalid_buffer_returns_err() {
296         let buffer = HardwareBuffer::new(512, 512, 1, 0, AHardwareBuffer_UsageFlags(0));
297         assert!(buffer.is_none());
298     }
299 
300     #[test]
from_raw_allows_getters()301     fn from_raw_allows_getters() {
302         let buffer_desc = ffi::AHardwareBuffer_Desc {
303             width: 1024,
304             height: 512,
305             layers: 1,
306             format: AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
307             usage: AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN.0,
308             stride: 0,
309             rfu0: 0,
310             rfu1: 0,
311         };
312         let mut raw_buffer_ptr = ptr::null_mut();
313 
314         // SAFETY: The pointers are valid because they come from references, and
315         // `AHardwareBuffer_allocate` doesn't retain them after it returns.
316         let status = unsafe { ffi::AHardwareBuffer_allocate(&buffer_desc, &mut raw_buffer_ptr) };
317         assert_eq!(status, 0);
318 
319         // SAFETY: The pointer must be valid because it was just allocated successfully, and we
320         // don't use it after calling this.
321         let buffer = unsafe { HardwareBuffer::from_raw(NonNull::new(raw_buffer_ptr).unwrap()) };
322         assert_eq!(buffer.width(), 1024);
323     }
324 
325     #[test]
basic_getters()326     fn basic_getters() {
327         let buffer = HardwareBuffer::new(
328             1024,
329             512,
330             1,
331             AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
332             AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
333         )
334         .expect("Buffer with some basic parameters was not created successfully");
335 
336         assert_eq!(buffer.width(), 1024);
337         assert_eq!(buffer.height(), 512);
338         assert_eq!(buffer.layers(), 1);
339         assert_eq!(buffer.format(), AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM);
340         assert_eq!(
341             buffer.usage(),
342             AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
343         );
344     }
345 
346     #[test]
id_getter()347     fn id_getter() {
348         let buffer = HardwareBuffer::new(
349             1024,
350             512,
351             1,
352             AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
353             AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
354         )
355         .expect("Buffer with some basic parameters was not created successfully");
356 
357         assert_ne!(0, buffer.id());
358     }
359 
360     #[test]
clone()361     fn clone() {
362         let buffer = HardwareBuffer::new(
363             1024,
364             512,
365             1,
366             AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
367             AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
368         )
369         .expect("Buffer with some basic parameters was not created successfully");
370         let buffer2 = buffer.clone();
371 
372         assert_eq!(buffer, buffer2);
373     }
374 
375     #[test]
into_raw()376     fn into_raw() {
377         let buffer = HardwareBuffer::new(
378             1024,
379             512,
380             1,
381             AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
382             AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
383         )
384         .expect("Buffer with some basic parameters was not created successfully");
385         let buffer2 = buffer.clone();
386 
387         let raw_buffer = buffer.into_raw();
388         // SAFETY: This is the same pointer we had before.
389         let remade_buffer = unsafe { HardwareBuffer::from_raw(raw_buffer) };
390 
391         assert_eq!(remade_buffer, buffer2);
392     }
393 }
394