Skip to content

Commit 8ee0ef1

Browse files
committed
Add Rust support for Surface unstructured parcelable.
Bug: 307535208 Test: m rust Change-Id: I4bb57b773ab7c1884d0341a3bc7dd100c3636bde
1 parent 0e622d7 commit 8ee0ef1

4 files changed

Lines changed: 145 additions & 2 deletions

File tree

aidl/gui/android/view/Surface.aidl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717

1818
package android.view;
1919

20-
@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable Surface cpp_header "gui/view/Surface.h" ndk_header "android/native_window_aidl.h";
20+
@JavaOnlyStableParcelable @NdkOnlyStableParcelable @RustOnlyStableParcelable parcelable Surface cpp_header "gui/view/Surface.h" ndk_header "android/native_window_aidl.h" rust_type "nativewindow::Surface";

libs/nativewindow/rust/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
1717
extern crate nativewindow_bindgen as ffi;
1818

19+
pub mod surface;
20+
1921
pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
2022

2123
use binder::{
@@ -210,7 +212,7 @@ impl Drop for HardwareBuffer {
210212
}
211213

212214
impl Debug for HardwareBuffer {
213-
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
215+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
214216
f.debug_struct("HardwareBuffer").field("id", &self.id()).finish()
215217
}
216218
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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.
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+
65+
impl 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+
74+
impl 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+
84+
impl 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+
94+
impl 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+
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+
/// An error code returned by methods on [`Surface`].
131+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
132+
pub struct ErrorCode(i32);
133+
134+
impl Error for ErrorCode {}
135+
136+
impl Display for ErrorCode {
137+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
138+
write!(f, "Error {}", self.0)
139+
}
140+
}

libs/nativewindow/rust/sys/nativewindow_bindings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@
1919
#include <android/hardware_buffer_aidl.h>
2020
#include <android/hdr_metadata.h>
2121
#include <android/native_window.h>
22+
#include <android/native_window_aidl.h>

0 commit comments

Comments
 (0)