diff options
| author | 2025-01-17 18:46:50 -0800 | |
|---|---|---|
| committer | 2025-01-17 18:46:50 -0800 | |
| commit | 57731c36e1db23c3cd1baecb4eb931aee42c54fd (patch) | |
| tree | 3aa36f4555503a6e85a64b2be8b958959901c37f /libs | |
| parent | 20e2a26f26efa5f9c0511f1ccdcb7a1e666667fd (diff) | |
| parent | f733f5232de54695e308b0caac6867ec10683b63 (diff) | |
Merge changes I2ba487b6,I398a9bf9 into main am: 5714afd531 am: f733f5232d
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/3452199
Change-Id: Ia29c10d8cab8ba2fca246234a3d6baac09ff8426
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/binder/rust/src/lib.rs | 4 | ||||
| -rw-r--r-- | libs/binder/rust/src/persistable_bundle.rs | 134 | ||||
| -rw-r--r-- | libs/binder/rust/sys/BinderBindings.hpp | 1 |
3 files changed, 139 insertions, 0 deletions
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index e08a76312d..77b80fe1ec 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -99,6 +99,8 @@ mod binder_async; mod error; mod native; mod parcel; +#[cfg(not(trusty))] +mod persistable_bundle; mod proxy; #[cfg(not(any(trusty, android_ndk)))] mod service; @@ -113,6 +115,8 @@ pub use crate::binder_async::{BinderAsyncPool, BoxFuture}; pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak}; pub use error::{ExceptionCode, IntoBinderResult, Status, StatusCode}; pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder}; +#[cfg(not(trusty))] +pub use persistable_bundle::PersistableBundle; pub use proxy::{DeathRecipient, SpIBinder, WpIBinder}; #[cfg(not(any(trusty, android_ndk)))] pub use service::{ diff --git a/libs/binder/rust/src/persistable_bundle.rs b/libs/binder/rust/src/persistable_bundle.rs new file mode 100644 index 0000000000..1323d99e9a --- /dev/null +++ b/libs/binder/rust/src/persistable_bundle.rs @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::{ + binder::AsNative, + error::{status_result, StatusCode}, + impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable, + parcel::{BorrowedParcel, UnstructuredParcelable}, +}; +use binder_ndk_sys::{ + APersistableBundle, APersistableBundle_delete, APersistableBundle_dup, + APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_readFromParcel, + APersistableBundle_size, APersistableBundle_writeToParcel, +}; +use std::ptr::{null_mut, NonNull}; + +/// A mapping from string keys to values of various types. +#[derive(Debug)] +pub struct PersistableBundle(NonNull<APersistableBundle>); + +impl PersistableBundle { + /// Creates a new `PersistableBundle`. + pub fn new() -> Self { + // SAFETY: APersistableBundle_new doesn't actually have any safety requirements. + let bundle = unsafe { APersistableBundle_new() }; + Self(NonNull::new(bundle).expect("Allocated APersistableBundle was null")) + } + + /// Returns the number of mappings in the bundle. + pub fn size(&self) -> usize { + // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the + // lifetime of the `PersistableBundle`. + unsafe { APersistableBundle_size(self.0.as_ptr()) } + .try_into() + .expect("APersistableBundle_size returned a negative size") + } +} + +// SAFETY: The underlying *APersistableBundle can be moved between threads. +unsafe impl Send for PersistableBundle {} + +// SAFETY: The underlying *APersistableBundle can be read from multiple threads, and we require +// `&mut PersistableBundle` for any operations which mutate it. +unsafe impl Sync for PersistableBundle {} + +impl Default for PersistableBundle { + fn default() -> Self { + Self::new() + } +} + +impl Drop for PersistableBundle { + fn drop(&mut self) { + // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the + // lifetime of this `PersistableBundle`. + unsafe { APersistableBundle_delete(self.0.as_ptr()) }; + } +} + +impl Clone for PersistableBundle { + fn clone(&self) -> Self { + // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the + // lifetime of the `PersistableBundle`. + let duplicate = unsafe { APersistableBundle_dup(self.0.as_ptr()) }; + Self(NonNull::new(duplicate).expect("Duplicated APersistableBundle was null")) + } +} + +impl PartialEq for PersistableBundle { + fn eq(&self, other: &Self) -> bool { + // SAFETY: The wrapped `APersistableBundle` pointers are guaranteed to be valid for the + // lifetime of the `PersistableBundle`s. + unsafe { APersistableBundle_isEqual(self.0.as_ptr(), other.0.as_ptr()) } + } +} + +impl UnstructuredParcelable for PersistableBundle { + fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> { + let status = + // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the + // lifetime of the `PersistableBundle`. `parcel.as_native_mut()` always returns a valid + // parcel pointer. + unsafe { APersistableBundle_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) }; + status_result(status) + } + + fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> { + let mut bundle = null_mut(); + + // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the + // lifetime of the `PersistableBundle`. `parcel.as_native()` always returns a valid parcel + // pointer. + let status = unsafe { APersistableBundle_readFromParcel(parcel.as_native(), &mut bundle) }; + status_result(status)?; + + Ok(Self(NonNull::new(bundle).expect( + "APersistableBundle_readFromParcel returned success but didn't allocate bundle", + ))) + } +} + +impl_deserialize_for_unstructured_parcelable!(PersistableBundle); +impl_serialize_for_unstructured_parcelable!(PersistableBundle); + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn create_delete() { + let bundle = PersistableBundle::new(); + drop(bundle); + } + + #[test] + fn duplicate_equal() { + let bundle = PersistableBundle::new(); + let duplicate = bundle.clone(); + assert_eq!(bundle, duplicate); + } +} diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp index 557f0e895d..deeaa37b94 100644 --- a/libs/binder/rust/sys/BinderBindings.hpp +++ b/libs/binder/rust/sys/BinderBindings.hpp @@ -17,6 +17,7 @@ #include <android/binder_ibinder.h> #include <android/binder_parcel.h> #include <android/binder_status.h> +#include <android/persistable_bundle.h> /* Platform only */ #if defined(ANDROID_PLATFORM) || defined(__ANDROID_VENDOR__) |