diff options
author | 2024-01-17 00:39:28 +0000 | |
---|---|---|
committer | 2024-01-17 00:39:28 +0000 | |
commit | ee12a1eec3f48786d5ffe7d16204cf86e84f180a (patch) | |
tree | d0903ba76b663b60f220a0652abde7d5bfc564fa | |
parent | c65973d538ffad687d48dab87ba91d54e284d7af (diff) | |
parent | ca340b1f0a1232b16219ff4ab008b431bb2850b7 (diff) |
Merge changes from topic "unstructured_parcelable_macros" into main am: ca340b1f0a
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/2906637
Change-Id: I98292b1f6e640601a9cee0342ebad397d501c03c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | libs/binder/rust/src/lib.rs | 4 | ||||
-rw-r--r-- | libs/binder/rust/src/parcel.rs | 2 | ||||
-rw-r--r-- | libs/binder/rust/src/parcel/parcelable.rs | 150 | ||||
-rw-r--r-- | libs/nativewindow/rust/src/lib.rs | 99 |
4 files changed, 180 insertions, 75 deletions
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 7f9348d913..16049f28c5 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -136,8 +136,8 @@ pub mod binder_impl { pub use crate::native::Binder; pub use crate::parcel::{ BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Parcel, - ParcelableMetadata, Serialize, SerializeArray, SerializeOption, NON_NULL_PARCELABLE_FLAG, - NULL_PARCELABLE_FLAG, + ParcelableMetadata, Serialize, SerializeArray, SerializeOption, UnstructuredParcelable, + NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG, }; pub use crate::proxy::{AssociateClass, Proxy}; } diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs index f9f135d572..3bfc425ee3 100644 --- a/libs/binder/rust/src/parcel.rs +++ b/libs/binder/rust/src/parcel.rs @@ -34,7 +34,7 @@ mod parcelable_holder; pub use self::file_descriptor::ParcelFileDescriptor; pub use self::parcelable::{ Deserialize, DeserializeArray, DeserializeOption, Parcelable, Serialize, SerializeArray, - SerializeOption, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG, + SerializeOption, UnstructuredParcelable, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG, }; pub use self::parcelable_holder::{ParcelableHolder, ParcelableMetadata}; diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs index 9008a3cc0e..33dfe19fe9 100644 --- a/libs/binder/rust/src/parcel/parcelable.rs +++ b/libs/binder/rust/src/parcel/parcelable.rs @@ -27,7 +27,7 @@ use std::os::raw::c_char; use std::ptr; use std::slice; -/// Super-trait for Binder parcelables. +/// Super-trait for structured Binder parcelables, i.e. those generated from AIDL. /// /// This trait is equivalent `android::Parcelable` in C++, /// and defines a common interface that all parcelables need @@ -50,6 +50,35 @@ pub trait Parcelable { fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()>; } +/// Super-trait for unstructured Binder parcelables, i.e. those implemented manually. +/// +/// These differ from structured parcelables in that they may not have a reasonable default value +/// and so aren't required to implement `Default`. +pub trait UnstructuredParcelable: Sized { + /// Internal serialization function for parcelables. + /// + /// This method is mainly for internal use. `Serialize::serialize` and its variants are + /// generally preferred over calling this function, since the former also prepend a header. + fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>; + + /// Internal deserialization function for parcelables. + /// + /// This method is mainly for internal use. `Deserialize::deserialize` and its variants are + /// generally preferred over calling this function, since the former also parse the additional + /// header. + fn from_parcel(parcel: &BorrowedParcel<'_>) -> Result<Self>; + + /// Internal deserialization function for parcelables. + /// + /// This method is mainly for internal use. `Deserialize::deserialize_from` and its variants are + /// generally preferred over calling this function, since the former also parse the additional + /// header. + fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> { + *self = Self::from_parcel(parcel)?; + Ok(()) + } +} + /// A struct whose instances can be written to a [`crate::parcel::Parcel`]. // Might be able to hook this up as a serde backend in the future? pub trait Serialize { @@ -1002,6 +1031,125 @@ macro_rules! impl_deserialize_for_parcelable { }; } +/// Implements `Serialize` trait and friends for an unstructured parcelable. +/// +/// The target type must implement the `UnstructuredParcelable` trait. +#[macro_export] +macro_rules! impl_serialize_for_unstructured_parcelable { + ($parcelable:ident) => { + $crate::impl_serialize_for_unstructured_parcelable!($parcelable < >); + }; + ($parcelable:ident < $( $param:ident ),* , >) => { + $crate::impl_serialize_for_unstructured_parcelable!($parcelable < $($param),* >); + }; + ($parcelable:ident < $( $param:ident ),* > ) => { + impl < $($param),* > $crate::binder_impl::Serialize for $parcelable < $($param),* > { + fn serialize( + &self, + parcel: &mut $crate::binder_impl::BorrowedParcel<'_>, + ) -> std::result::Result<(), $crate::StatusCode> { + <Self as $crate::binder_impl::SerializeOption>::serialize_option(Some(self), parcel) + } + } + + impl < $($param),* > $crate::binder_impl::SerializeArray for $parcelable < $($param),* > {} + + impl < $($param),* > $crate::binder_impl::SerializeOption for $parcelable < $($param),* > { + fn serialize_option( + this: Option<&Self>, + parcel: &mut $crate::binder_impl::BorrowedParcel<'_>, + ) -> std::result::Result<(), $crate::StatusCode> { + if let Some(this) = this { + use $crate::binder_impl::UnstructuredParcelable; + parcel.write(&$crate::binder_impl::NON_NULL_PARCELABLE_FLAG)?; + this.write_to_parcel(parcel) + } else { + parcel.write(&$crate::binder_impl::NULL_PARCELABLE_FLAG) + } + } + } + }; +} + +/// Implement `Deserialize` trait and friends for an unstructured parcelable +/// +/// The target type must implement the `UnstructuredParcelable` trait. +#[macro_export] +macro_rules! impl_deserialize_for_unstructured_parcelable { + ($parcelable:ident) => { + $crate::impl_deserialize_for_unstructured_parcelable!($parcelable < >); + }; + ($parcelable:ident < $( $param:ident ),* , >) => { + $crate::impl_deserialize_for_unstructured_parcelable!($parcelable < $($param),* >); + }; + ($parcelable:ident < $( $param:ident ),* > ) => { + impl < $($param: Default),* > $crate::binder_impl::Deserialize for $parcelable < $($param),* > { + type UninitType = Option<Self>; + fn uninit() -> Self::UninitType { None } + fn from_init(value: Self) -> Self::UninitType { Some(value) } + fn deserialize( + parcel: &$crate::binder_impl::BorrowedParcel<'_>, + ) -> std::result::Result<Self, $crate::StatusCode> { + $crate::binder_impl::DeserializeOption::deserialize_option(parcel) + .transpose() + .unwrap_or(Err($crate::StatusCode::UNEXPECTED_NULL)) + } + fn deserialize_from( + &mut self, + parcel: &$crate::binder_impl::BorrowedParcel<'_>, + ) -> std::result::Result<(), $crate::StatusCode> { + let status: i32 = parcel.read()?; + if status == $crate::binder_impl::NULL_PARCELABLE_FLAG { + Err($crate::StatusCode::UNEXPECTED_NULL) + } else { + use $crate::binder_impl::UnstructuredParcelable; + self.read_from_parcel(parcel) + } + } + } + + impl < $($param: Default),* > $crate::binder_impl::DeserializeArray for $parcelable < $($param),* > {} + + impl < $($param: Default),* > $crate::binder_impl::DeserializeOption for $parcelable < $($param),* > { + fn deserialize_option( + parcel: &$crate::binder_impl::BorrowedParcel<'_>, + ) -> std::result::Result<Option<Self>, $crate::StatusCode> { + let present: i32 = parcel.read()?; + match present { + $crate::binder_impl::NULL_PARCELABLE_FLAG => Ok(None), + $crate::binder_impl::NON_NULL_PARCELABLE_FLAG => { + use $crate::binder_impl::UnstructuredParcelable; + Ok(Some(Self::from_parcel(parcel)?)) + } + _ => Err(StatusCode::BAD_VALUE), + } + } + fn deserialize_option_from( + this: &mut Option<Self>, + parcel: &$crate::binder_impl::BorrowedParcel<'_>, + ) -> std::result::Result<(), $crate::StatusCode> { + let present: i32 = parcel.read()?; + match present { + $crate::binder_impl::NULL_PARCELABLE_FLAG => { + *this = None; + Ok(()) + } + $crate::binder_impl::NON_NULL_PARCELABLE_FLAG => { + use $crate::binder_impl::UnstructuredParcelable; + if let Some(this) = this { + this.read_from_parcel(parcel)?; + } else { + *this = Some(Self::from_parcel(parcel)?); + } + Ok(()) + } + _ => Err(StatusCode::BAD_VALUE), + } + } + } + }; +} + impl<T: Serialize> Serialize for Box<T> { fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { Serialize::serialize(&**self, parcel) diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs index 6f86c4a48f..e41651737f 100644 --- a/libs/nativewindow/rust/src/lib.rs +++ b/libs/nativewindow/rust/src/lib.rs @@ -19,10 +19,8 @@ extern crate nativewindow_bindgen as ffi; 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, - }, + binder_impl::{BorrowedParcel, UnstructuredParcelable}, + impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable, unstable_api::{status_result, AsNative}, StatusCode, }; @@ -210,81 +208,40 @@ impl Clone for HardwareBuffer { } } -impl Serialize for HardwareBuffer { - fn serialize(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> { - SerializeOption::serialize_option(Some(self), parcel) +impl UnstructuredParcelable for HardwareBuffer { + fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> { + 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(self.0.as_ptr(), parcel.as_native_mut()) }; + status_result(status) } -} -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) - } - } -} + fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> { + let mut buffer = null_mut(); -impl Deserialize for HardwareBuffer { - type UninitType = Option<Self>; + 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) }; - 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)) - } -} + status_result(status)?; -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), - } + Ok(Self( + NonNull::new(buffer).expect( + "AHardwareBuffer_readFromParcel returned success but didn't allocate buffer", + ), + )) } } -impl SerializeArray for HardwareBuffer {} - -impl DeserializeArray for HardwareBuffer {} +impl_deserialize_for_unstructured_parcelable!(HardwareBuffer); +impl_serialize_for_unstructured_parcelable!(HardwareBuffer); // SAFETY: The underlying *AHardwareBuffers can be moved between threads. unsafe impl Send for HardwareBuffer {} |