blob: c812612d406c582fcf28b63641cb0994c640fe6b [file] [log] [blame]
Andrew Walbran8ee0ef12024-01-12 15:56:14 +00001// 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
17use 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};
23use nativewindow_bindgen::{
24 AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire, ANativeWindow_getFormat,
25 ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_readFromParcel,
26 ANativeWindow_release, ANativeWindow_writeToParcel,
27};
28use std::error::Error;
29use std::fmt::{self, Debug, Display, Formatter};
30use std::ptr::{null_mut, NonNull};
31
32/// Wrapper around an opaque C `ANativeWindow`.
33#[derive(PartialEq, Eq)]
34pub struct Surface(NonNull<ANativeWindow>);
35
36impl Surface {
37 /// Returns the current width in pixels of the window surface.
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.
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.
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
65impl Drop for Surface {
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
74impl Debug for Surface {
75 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
84impl Clone for Surface {
85 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
94impl UnstructuredParcelable for Surface {
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
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
124impl_deserialize_for_unstructured_parcelable!(Surface);
125impl_serialize_for_unstructured_parcelable!(Surface);
126
127// SAFETY: The underlying *ANativeWindow can be moved between threads.
128unsafe impl Send for Surface {}
129
130/// An error code returned by methods on [`Surface`].
131#[derive(Copy, Clone, Debug, Eq, PartialEq)]
132pub struct ErrorCode(i32);
133
134impl Error for ErrorCode {}
135
136impl Display for ErrorCode {
137 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
138 write!(f, "Error {}", self.0)
139 }
140}