diff options
author | 2023-09-01 16:43:09 +0100 | |
---|---|---|
committer | 2023-10-11 16:45:57 +0100 | |
commit | 43bddb630f6c8aa743ba366d730058a10c18bb6d (patch) | |
tree | 6c311fbe8aec43286f1790a206992725060e7541 | |
parent | 0b3e8b2ae37f2e51f3ade5dd5c8731390f7eaa63 (diff) |
Support AIDL serializing and deserializing Rust HardwareBuffer.
Bug: 295245772
Test: Built a simple binary depending on it.
Change-Id: I64856b6063fd0e0ffe9f3bd1f066a73fbeffdb32
-rw-r--r-- | libs/binder/rust/src/lib.rs | 1 | ||||
-rw-r--r-- | libs/nativewindow/rust/Android.bp | 42 | ||||
-rw-r--r-- | libs/nativewindow/rust/src/lib.rs | 107 | ||||
-rw-r--r-- | libs/nativewindow/rust/sys/nativewindow_bindings.h | 1 |
4 files changed, 140 insertions, 11 deletions
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 8841fe640b..ed870b6d8c 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -144,6 +144,7 @@ pub mod binder_impl { #[doc(hidden)] pub mod unstable_api { pub use crate::binder::AsNative; + pub use crate::error::status_result; pub use crate::proxy::unstable_api::new_spibinder; pub use crate::sys::AIBinder; pub use crate::sys::AParcel; diff --git a/libs/nativewindow/rust/Android.bp b/libs/nativewindow/rust/Android.bp index dc1575ca33..90d0a8e400 100644 --- a/libs/nativewindow/rust/Android.bp +++ b/libs/nativewindow/rust/Android.bp @@ -19,7 +19,7 @@ package { } rust_bindgen { - name: "libnativewindow_bindgen", + name: "libnativewindow_bindgen_internal", crate_name: "nativewindow_bindgen", wrapper_src: "sys/nativewindow_bindings.h", source_stem: "bindings", @@ -28,13 +28,21 @@ rust_bindgen { "--bitfield-enum=AHardwareBuffer_UsageFlags", "--allowlist-file=.*/nativewindow/include/.*\\.h", + "--blocklist-type", + "AParcel", + "--raw-line", + "use binder::unstable_api::AParcel;", "--with-derive-eq", "--with-derive-partialeq", ], shared_libs: [ + "libbinder_ndk", "libnativewindow", ], + rustlibs: [ + "libbinder_rs", + ], // Currently necessary for host builds // TODO(b/31559095): bionic on host should define this @@ -44,12 +52,40 @@ rust_bindgen { }, }, min_sdk_version: "VanillaIceCream", + vendor_available: true, +} + +rust_library { + name: "libnativewindow_bindgen", + crate_name: "nativewindow_bindgen", + srcs: [":libnativewindow_bindgen_internal"], + shared_libs: [ + "libbinder_ndk", + "libnativewindow", + ], + rustlibs: [ + "libbinder_rs", + ], + lints: "none", + clippy_lints: "none", + // Currently necessary for host builds + // TODO(b/31559095): bionic on host should define this + target: { + darwin: { + enabled: false, + }, + }, + min_sdk_version: "VanillaIceCream", + vendor_available: true, } rust_test { name: "libnativewindow_bindgen_test", - srcs: [":libnativewindow_bindgen"], + srcs: [":libnativewindow_bindgen_internal"], crate_name: "nativewindow_bindgen_test", + rustlibs: [ + "libbinder_rs", + ], test_suites: ["general-tests"], auto_gen_config: true, clippy_lints: "none", @@ -60,6 +96,7 @@ rust_defaults { name: "libnativewindow_defaults", srcs: ["src/lib.rs"], rustlibs: [ + "libbinder_rs", "libnativewindow_bindgen", ], } @@ -77,6 +114,7 @@ rust_library { }, }, min_sdk_version: "VanillaIceCream", + vendor_available: true, } rust_test { diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs index 6eb3bbcdb3..6f86c4a48f 100644 --- a/libs/nativewindow/rust/src/lib.rs +++ b/libs/nativewindow/rust/src/lib.rs @@ -16,13 +16,22 @@ extern crate nativewindow_bindgen as ffi; -pub use ffi::{AHardwareBuffer, AHardwareBuffer_Format, AHardwareBuffer_UsageFlags}; - +pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags}; + +use binder::{ + binder_impl::{ + BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize, + SerializeArray, SerializeOption, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG, + }, + unstable_api::{status_result, AsNative}, + StatusCode, +}; +use ffi::{AHardwareBuffer, AHardwareBuffer_readFromParcel, AHardwareBuffer_writeToParcel}; use std::fmt::{self, Debug, Formatter}; use std::mem::ManuallyDrop; -use std::ptr::{self, NonNull}; +use std::ptr::{self, null_mut, NonNull}; -/// Wrapper around an opaque C AHardwareBuffer. +/// Wrapper around an opaque C `AHardwareBuffer`. #[derive(PartialEq, Eq)] pub struct HardwareBuffer(NonNull<AHardwareBuffer>); @@ -120,8 +129,11 @@ impl HardwareBuffer { /// Available since API level 31. pub fn id(&self) -> u64 { let mut out_id = 0; - // SAFETY: Neither pointers can be null. - let status = unsafe { ffi::AHardwareBuffer_getId(self.0.as_ref(), &mut out_id) }; + // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid + // because it must have been allocated by `AHardwareBuffer_allocate`, + // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet + // released it. The id pointer must be valid because it comes from a reference. + let status = unsafe { ffi::AHardwareBuffer_getId(self.0.as_ptr(), &mut out_id) }; assert_eq!(status, 0, "id() failed for AHardwareBuffer with error code: {status}"); out_id @@ -176,9 +188,10 @@ impl HardwareBuffer { impl Drop for HardwareBuffer { fn drop(&mut self) { - // SAFETY: self.0 will never be null. AHardwareBuffers allocated from within Rust will have - // a refcount of one, and there is a safety warning on taking an AHardwareBuffer from a raw - // pointer requiring callers to ensure the refcount is managed appropriately. + // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid + // because it must have been allocated by `AHardwareBuffer_allocate`, + // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet + // released it. unsafe { ffi::AHardwareBuffer_release(self.0.as_ptr()) } } } @@ -197,6 +210,82 @@ impl Clone for HardwareBuffer { } } +impl Serialize for HardwareBuffer { + fn serialize(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> { + SerializeOption::serialize_option(Some(self), parcel) + } +} + +impl SerializeOption for HardwareBuffer { + fn serialize_option( + this: Option<&Self>, + parcel: &mut BorrowedParcel, + ) -> Result<(), StatusCode> { + if let Some(this) = this { + parcel.write(&NON_NULL_PARCELABLE_FLAG)?; + + let status = + // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid + // because it must have been allocated by `AHardwareBuffer_allocate`, + // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet + // released it. + unsafe { AHardwareBuffer_writeToParcel(this.0.as_ptr(), parcel.as_native_mut()) }; + status_result(status) + } else { + parcel.write(&NULL_PARCELABLE_FLAG) + } + } +} + +impl Deserialize for HardwareBuffer { + type UninitType = Option<Self>; + + fn uninit() -> Option<Self> { + None + } + + fn from_init(value: Self) -> Option<Self> { + Some(value) + } + + fn deserialize(parcel: &BorrowedParcel) -> Result<Self, StatusCode> { + DeserializeOption::deserialize_option(parcel) + .transpose() + .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) + } +} + +impl DeserializeOption for HardwareBuffer { + fn deserialize_option(parcel: &BorrowedParcel) -> Result<Option<Self>, StatusCode> { + let present: i32 = parcel.read()?; + match present { + NULL_PARCELABLE_FLAG => Ok(None), + NON_NULL_PARCELABLE_FLAG => { + let mut buffer = null_mut(); + + let status = + // SAFETY: Both pointers must be valid because they are obtained from references. + // `AHardwareBuffer_readFromParcel` doesn't store them or do anything else special + // with them. If it returns success then it will have allocated a new + // `AHardwareBuffer` and incremented the reference count, so we can use it until we + // release it. + unsafe { AHardwareBuffer_readFromParcel(parcel.as_native(), &mut buffer) }; + + status_result(status)?; + + Ok(Some(Self(NonNull::new(buffer).expect( + "AHardwareBuffer_readFromParcel returned success but didn't allocate buffer", + )))) + } + _ => Err(StatusCode::BAD_VALUE), + } + } +} + +impl SerializeArray for HardwareBuffer {} + +impl DeserializeArray for HardwareBuffer {} + // SAFETY: The underlying *AHardwareBuffers can be moved between threads. unsafe impl Send for HardwareBuffer {} diff --git a/libs/nativewindow/rust/sys/nativewindow_bindings.h b/libs/nativewindow/rust/sys/nativewindow_bindings.h index e652aee711..4525a42502 100644 --- a/libs/nativewindow/rust/sys/nativewindow_bindings.h +++ b/libs/nativewindow/rust/sys/nativewindow_bindings.h @@ -16,5 +16,6 @@ #include <android/data_space.h> #include <android/hardware_buffer.h> +#include <android/hardware_buffer_aidl.h> #include <android/hdr_metadata.h> #include <android/native_window.h> |