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