1 // Copyright (C) 2024 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 //! Rust wrapper for `ANativeWindow` and related types.
16 
17 use binder::{
18     binder_impl::{BorrowedParcel, UnstructuredParcelable},
19     impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
20     unstable_api::{status_result, AsNative},
21     StatusCode,
22 };
23 use nativewindow_bindgen::{
24     AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire, ANativeWindow_getFormat,
25     ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_readFromParcel,
26     ANativeWindow_release, ANativeWindow_writeToParcel,
27 };
28 use std::error::Error;
29 use std::fmt::{self, Debug, Display, Formatter};
30 use std::ptr::{null_mut, NonNull};
31 
32 /// Wrapper around an opaque C `ANativeWindow`.
33 #[derive(PartialEq, Eq)]
34 pub struct Surface(NonNull<ANativeWindow>);
35 
36 impl Surface {
37     /// Returns the current width in pixels of the window surface.
width(&self) -> Result<u32, ErrorCode>38     pub fn width(&self) -> Result<u32, ErrorCode> {
39         // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
40         // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
41         // and we have not yet released it.
42         let width = unsafe { ANativeWindow_getWidth(self.0.as_ptr()) };
43         width.try_into().map_err(|_| ErrorCode(width))
44     }
45 
46     /// Returns the current height in pixels of the window surface.
height(&self) -> Result<u32, ErrorCode>47     pub fn height(&self) -> Result<u32, ErrorCode> {
48         // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
49         // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
50         // and we have not yet released it.
51         let height = unsafe { ANativeWindow_getHeight(self.0.as_ptr()) };
52         height.try_into().map_err(|_| ErrorCode(height))
53     }
54 
55     /// Returns the current pixel format of the window surface.
format(&self) -> Result<AHardwareBuffer_Format::Type, ErrorCode>56     pub fn format(&self) -> Result<AHardwareBuffer_Format::Type, ErrorCode> {
57         // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
58         // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
59         // and we have not yet released it.
60         let format = unsafe { ANativeWindow_getFormat(self.0.as_ptr()) };
61         format.try_into().map_err(|_| ErrorCode(format))
62     }
63 }
64 
65 impl Drop for Surface {
drop(&mut self)66     fn drop(&mut self) {
67         // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
68         // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
69         // and we have not yet released it.
70         unsafe { ANativeWindow_release(self.0.as_ptr()) }
71     }
72 }
73 
74 impl Debug for Surface {
fmt(&self, f: &mut Formatter) -> fmt::Result75     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
76         f.debug_struct("Surface")
77             .field("width", &self.width())
78             .field("height", &self.height())
79             .field("format", &self.format())
80             .finish()
81     }
82 }
83 
84 impl Clone for Surface {
clone(&self) -> Self85     fn clone(&self) -> Self {
86         // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
87         // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
88         // and we have not yet released it.
89         unsafe { ANativeWindow_acquire(self.0.as_ptr()) };
90         Self(self.0)
91     }
92 }
93 
94 impl UnstructuredParcelable for Surface {
write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode>95     fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
96         let status =
97         // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
98         // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
99         // and we have not yet released it.
100         unsafe { ANativeWindow_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) };
101         status_result(status)
102     }
103 
from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode>104     fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
105         let mut buffer = null_mut();
106 
107         let status =
108         // SAFETY: Both pointers must be valid because they are obtained from references.
109         // `ANativeWindow_readFromParcel` doesn't store them or do anything else special
110         // with them. If it returns success then it will have allocated a new
111         // `ANativeWindow` and incremented the reference count, so we can use it until we
112         // release it.
113             unsafe { ANativeWindow_readFromParcel(parcel.as_native(), &mut buffer) };
114 
115         status_result(status)?;
116 
117         Ok(Self(
118             NonNull::new(buffer)
119                 .expect("ANativeWindow_readFromParcel returned success but didn't allocate buffer"),
120         ))
121     }
122 }
123 
124 impl_deserialize_for_unstructured_parcelable!(Surface);
125 impl_serialize_for_unstructured_parcelable!(Surface);
126 
127 // SAFETY: The underlying *ANativeWindow can be moved between threads.
128 unsafe impl Send for Surface {}
129 
130 // SAFETY: The underlying *ANativeWindow can be used from multiple threads concurrently.
131 unsafe impl Sync for Surface {}
132 
133 /// An error code returned by methods on [`Surface`].
134 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
135 pub struct ErrorCode(i32);
136 
137 impl Error for ErrorCode {}
138 
139 impl Display for ErrorCode {
fmt(&self, f: &mut Formatter) -> fmt::Result140     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
141         write!(f, "Error {}", self.0)
142     }
143 }
144