Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2735b49 authored by Stephen Crane's avatar Stephen Crane
Browse files

Revert^2 "[binder] Expose public Rust API at crate top level"

Previously the public API for the binder Rust crate was nested in a
`public_api` module and re-exported by AIDL interface crates. This
caused confusion, when using multiple AIDL interfaces in the same file,
as there were multiple options to import the binder API.

Moves the public API to the top level of the binder crate and nests the
AIDL implementation API into a submodule.

Original change: I811426fa715a324ebb09f5ce04ee539a1c3b9dfd

Test: atest -p --include-subdirs frameworks/native/binder
Bug: 196056781

Change-Id: I7aa0aa41e4162bb25720974065ae3ac8069e6598
parent f9ce300c
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -28,8 +28,8 @@
//!
//! [`Tokio`]: crate::Tokio

use binder::public_api::{BinderAsyncPool, BoxFuture, Strong};
use binder::{FromIBinder, StatusCode, BinderAsyncRuntime};
use binder::{BinderAsyncPool, BoxFuture, FromIBinder, StatusCode, Strong};
use binder::binder_impl::BinderAsyncRuntime;
use std::future::Future;

/// Retrieve an existing service for a particular interface, sleeping for a few
@@ -37,12 +37,12 @@ use std::future::Future;
pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
    if binder::is_handling_transaction() {
        // See comment in the BinderAsyncPool impl.
        return binder::public_api::get_interface::<T>(name);
        return binder::get_interface::<T>(name);
    }

    let name = name.to_string();
    let res = tokio::task::spawn_blocking(move || {
        binder::public_api::get_interface::<T>(&name)
        binder::get_interface::<T>(&name)
    }).await;

    // The `is_panic` branch is not actually reachable in Android as we compile
@@ -61,12 +61,12 @@ pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Res
pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
    if binder::is_handling_transaction() {
        // See comment in the BinderAsyncPool impl.
        return binder::public_api::wait_for_interface::<T>(name);
        return binder::wait_for_interface::<T>(name);
    }

    let name = name.to_string();
    let res = tokio::task::spawn_blocking(move || {
        binder::public_api::wait_for_interface::<T>(&name)
        binder::wait_for_interface::<T>(&name)
    }).await;

    // The `is_panic` branch is not actually reachable in Android as we compile
+53 −53
Original line number Diff line number Diff line
@@ -536,13 +536,13 @@ impl<I: FromIBinder + ?Sized> Eq for Weak<I> {}
/// ```
macro_rules! binder_fn_get_class {
    ($class:ty) => {
        binder_fn_get_class!($crate::InterfaceClass::new::<$class>());
        binder_fn_get_class!($crate::binder_impl::InterfaceClass::new::<$class>());
    };

    ($constructor:expr) => {
        fn get_class() -> $crate::InterfaceClass {
        fn get_class() -> $crate::binder_impl::InterfaceClass {
            static CLASS_INIT: std::sync::Once = std::sync::Once::new();
            static mut CLASS: Option<$crate::InterfaceClass> = None;
            static mut CLASS: Option<$crate::binder_impl::InterfaceClass> = None;

            CLASS_INIT.call_once(|| unsafe {
                // Safety: This assignment is guarded by the `CLASS_INIT` `Once`
@@ -772,7 +772,7 @@ macro_rules! declare_binder_interface {
                native: $native($on_transact),
                proxy: $proxy {},
                $(async: $async_interface,)?
                stability: $crate::Stability::default(),
                stability: $crate::binder_impl::Stability::default(),
            }
        }
    };
@@ -811,7 +811,7 @@ macro_rules! declare_binder_interface {
                    $($fname: $fty = $finit),*
                },
                $(async: $async_interface,)?
                stability: $crate::Stability::default(),
                stability: $crate::binder_impl::Stability::default(),
            }
        }
    };
@@ -828,9 +828,9 @@ macro_rules! declare_binder_interface {
    } => {
        $crate::declare_binder_interface! {
            $interface[$descriptor] {
                @doc[concat!("A binder [`Remotable`]($crate::Remotable) that holds an [`", stringify!($interface), "`] object.")]
                @doc[concat!("A binder [`Remotable`]($crate::binder_impl::Remotable) that holds an [`", stringify!($interface), "`] object.")]
                native: $native($on_transact),
                @doc[concat!("A binder [`Proxy`]($crate::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")]
                @doc[concat!("A binder [`Proxy`]($crate::binder_impl::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")]
                proxy: $proxy {
                    $($fname: $fty = $finit),*
                },
@@ -867,7 +867,7 @@ macro_rules! declare_binder_interface {
            }
        }

        impl $crate::Proxy for $proxy
        impl $crate::binder_impl::Proxy for $proxy
        where
            $proxy: $interface,
        {
@@ -875,7 +875,7 @@ macro_rules! declare_binder_interface {
                $descriptor
            }

            fn from_binder(mut binder: $crate::SpIBinder) -> $crate::Result<Self> {
            fn from_binder(mut binder: $crate::SpIBinder) -> std::result::Result<Self, $crate::StatusCode> {
                Ok(Self { binder, $($fname: $finit),* })
            }
        }
@@ -887,19 +887,19 @@ macro_rules! declare_binder_interface {
        impl $native {
            /// Create a new binder service.
            pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> {
                let mut binder = $crate::Binder::new_with_stability($native(Box::new(inner)), $stability);
                let mut binder = $crate::binder_impl::Binder::new_with_stability($native(Box::new(inner)), $stability);
                #[cfg(not(android_vndk))]
                $crate::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
                $crate::binder_impl::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
                $crate::Strong::new(Box::new(binder))
            }
        }

        impl $crate::Remotable for $native {
        impl $crate::binder_impl::Remotable for $native {
            fn get_descriptor() -> &'static str {
                $descriptor
            }

            fn on_transact(&self, code: $crate::TransactionCode, data: &$crate::BorrowedParcel<'_>, reply: &mut $crate::BorrowedParcel<'_>) -> $crate::Result<()> {
            fn on_transact(&self, code: $crate::binder_impl::TransactionCode, data: &$crate::binder_impl::BorrowedParcel<'_>, reply: &mut $crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), $crate::StatusCode> {
                match $on_transact(&*self.0, code, data, reply) {
                    // The C++ backend converts UNEXPECTED_NULL into an exception
                    Err($crate::StatusCode::UNEXPECTED_NULL) => {
@@ -913,19 +913,19 @@ macro_rules! declare_binder_interface {
                }
            }

            fn on_dump(&self, file: &std::fs::File, args: &[&std::ffi::CStr]) -> $crate::Result<()> {
            fn on_dump(&self, file: &std::fs::File, args: &[&std::ffi::CStr]) -> std::result::Result<(), $crate::StatusCode> {
                self.0.dump(file, args)
            }

            fn get_class() -> $crate::InterfaceClass {
            fn get_class() -> $crate::binder_impl::InterfaceClass {
                static CLASS_INIT: std::sync::Once = std::sync::Once::new();
                static mut CLASS: Option<$crate::InterfaceClass> = None;
                static mut CLASS: Option<$crate::binder_impl::InterfaceClass> = None;

                CLASS_INIT.call_once(|| unsafe {
                    // Safety: This assignment is guarded by the `CLASS_INIT` `Once`
                    // variable, and therefore is thread-safe, as it can only occur
                    // once.
                    CLASS = Some($crate::InterfaceClass::new::<$crate::Binder<$native>>());
                    CLASS = Some($crate::binder_impl::InterfaceClass::new::<$crate::binder_impl::Binder<$native>>());
                });
                unsafe {
                    // Safety: The `CLASS` variable can only be mutated once, above,
@@ -936,25 +936,25 @@ macro_rules! declare_binder_interface {
        }

        impl $crate::FromIBinder for dyn $interface {
            fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> {
                use $crate::AssociateClass;
            fn try_from(mut ibinder: $crate::SpIBinder) -> std::result::Result<$crate::Strong<dyn $interface>, $crate::StatusCode> {
                use $crate::binder_impl::AssociateClass;

                let existing_class = ibinder.get_class();
                if let Some(class) = existing_class {
                    if class != <$native as $crate::Remotable>::get_class() &&
                        class.get_descriptor() == <$native as $crate::Remotable>::get_descriptor()
                    if class != <$native as $crate::binder_impl::Remotable>::get_class() &&
                        class.get_descriptor() == <$native as $crate::binder_impl::Remotable>::get_descriptor()
                    {
                        // The binder object's descriptor string matches what we
                        // expect. We still need to treat this local or already
                        // associated object as remote, because we can't cast it
                        // into a Rust service object without a matching class
                        // pointer.
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
                    }
                }

                if ibinder.associate_class(<$native as $crate::Remotable>::get_class()) {
                    let service: $crate::Result<$crate::Binder<$native>> =
                if ibinder.associate_class(<$native as $crate::binder_impl::Remotable>::get_class()) {
                    let service: std::result::Result<$crate::binder_impl::Binder<$native>, $crate::StatusCode> =
                        std::convert::TryFrom::try_from(ibinder.clone());
                    if let Ok(service) = service {
                        // We were able to associate with our expected class and
@@ -962,7 +962,7 @@ macro_rules! declare_binder_interface {
                        return Ok($crate::Strong::new(Box::new(service)));
                    } else {
                        // Service is remote
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
                    }
                }

@@ -970,18 +970,18 @@ macro_rules! declare_binder_interface {
            }
        }

        impl $crate::parcel::Serialize for dyn $interface + '_
        impl $crate::binder_impl::Serialize for dyn $interface + '_
        where
            dyn $interface: $crate::Interface
        {
            fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
            fn serialize(&self, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), $crate::StatusCode> {
                let binder = $crate::Interface::as_binder(self);
                parcel.write(&binder)
            }
        }

        impl $crate::parcel::SerializeOption for dyn $interface + '_ {
            fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
        impl $crate::binder_impl::SerializeOption for dyn $interface + '_ {
            fn serialize_option(this: Option<&Self>, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), $crate::StatusCode> {
                parcel.write(&this.map($crate::Interface::as_binder))
            }
        }
@@ -1004,25 +1004,25 @@ macro_rules! declare_binder_interface {
        $(
        // Async interface trait implementations.
        impl<P: $crate::BinderAsyncPool> $crate::FromIBinder for dyn $async_interface<P> {
            fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $async_interface<P>>> {
                use $crate::AssociateClass;
            fn try_from(mut ibinder: $crate::SpIBinder) -> std::result::Result<$crate::Strong<dyn $async_interface<P>>, $crate::StatusCode> {
                use $crate::binder_impl::AssociateClass;

                let existing_class = ibinder.get_class();
                if let Some(class) = existing_class {
                    if class != <$native as $crate::Remotable>::get_class() &&
                        class.get_descriptor() == <$native as $crate::Remotable>::get_descriptor()
                    if class != <$native as $crate::binder_impl::Remotable>::get_class() &&
                        class.get_descriptor() == <$native as $crate::binder_impl::Remotable>::get_descriptor()
                    {
                        // The binder object's descriptor string matches what we
                        // expect. We still need to treat this local or already
                        // associated object as remote, because we can't cast it
                        // into a Rust service object without a matching class
                        // pointer.
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
                    }
                }

                if ibinder.associate_class(<$native as $crate::Remotable>::get_class()) {
                    let service: $crate::Result<$crate::Binder<$native>> =
                if ibinder.associate_class(<$native as $crate::binder_impl::Remotable>::get_class()) {
                    let service: std::result::Result<$crate::binder_impl::Binder<$native>, $crate::StatusCode> =
                        std::convert::TryFrom::try_from(ibinder.clone());
                    if let Ok(service) = service {
                        // We were able to associate with our expected class and
@@ -1031,7 +1031,7 @@ macro_rules! declare_binder_interface {
                        //return Ok($crate::Strong::new(Box::new(service)));
                    } else {
                        // Service is remote
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
                    }
                }

@@ -1039,15 +1039,15 @@ macro_rules! declare_binder_interface {
            }
        }

        impl<P: $crate::BinderAsyncPool> $crate::parcel::Serialize for dyn $async_interface<P> + '_ {
            fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
        impl<P: $crate::BinderAsyncPool> $crate::binder_impl::Serialize for dyn $async_interface<P> + '_ {
            fn serialize(&self, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), $crate::StatusCode> {
                let binder = $crate::Interface::as_binder(self);
                parcel.write(&binder)
            }
        }

        impl<P: $crate::BinderAsyncPool> $crate::parcel::SerializeOption for dyn $async_interface<P> + '_ {
            fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
        impl<P: $crate::BinderAsyncPool> $crate::binder_impl::SerializeOption for dyn $async_interface<P> + '_ {
            fn serialize_option(this: Option<&Self>, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), $crate::StatusCode> {
                parcel.write(&this.map($crate::Interface::as_binder))
            }
        }
@@ -1067,11 +1067,11 @@ macro_rules! declare_binder_interface {
            }
        }

        impl<P: $crate::BinderAsyncPool> $crate::ToAsyncInterface<P> for dyn $interface {
        impl<P: $crate::BinderAsyncPool> $crate::binder_impl::ToAsyncInterface<P> for dyn $interface {
            type Target = dyn $async_interface<P>;
        }

        impl<P: $crate::BinderAsyncPool> $crate::ToSyncInterface for dyn $async_interface<P> {
        impl<P: $crate::BinderAsyncPool> $crate::binder_impl::ToSyncInterface for dyn $async_interface<P> {
            type Target = dyn $interface;
        }
        )?
@@ -1103,29 +1103,29 @@ macro_rules! declare_binder_enum {
            }
        }

        impl $crate::parcel::Serialize for $enum {
            fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
        impl $crate::binder_impl::Serialize for $enum {
            fn serialize(&self, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), $crate::StatusCode> {
                parcel.write(&self.0)
            }
        }

        impl $crate::parcel::SerializeArray for $enum {
            fn serialize_array(slice: &[Self], parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
        impl $crate::binder_impl::SerializeArray for $enum {
            fn serialize_array(slice: &[Self], parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), $crate::StatusCode> {
                let v: Vec<$backing> = slice.iter().map(|x| x.0).collect();
                <$backing as binder::parcel::SerializeArray>::serialize_array(&v[..], parcel)
                <$backing as $crate::binder_impl::SerializeArray>::serialize_array(&v[..], parcel)
            }
        }

        impl $crate::parcel::Deserialize for $enum {
            fn deserialize(parcel: &$crate::parcel::BorrowedParcel<'_>) -> $crate::Result<Self> {
        impl $crate::binder_impl::Deserialize for $enum {
            fn deserialize(parcel: &$crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<Self, $crate::StatusCode> {
                parcel.read().map(Self)
            }
        }

        impl $crate::parcel::DeserializeArray for $enum {
            fn deserialize_array(parcel: &$crate::parcel::BorrowedParcel<'_>) -> $crate::Result<Option<Vec<Self>>> {
        impl $crate::binder_impl::DeserializeArray for $enum {
            fn deserialize_array(parcel: &$crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<Option<Vec<Self>>, $crate::StatusCode> {
                let v: Option<Vec<$backing>> =
                    <$backing as binder::parcel::DeserializeArray>::deserialize_array(parcel)?;
                    <$backing as $crate::binder_impl::DeserializeArray>::deserialize_array(parcel)?;
                Ok(v.map(|v| v.into_iter().map(Self).collect()))
            }
        }
+34 −29
Original line number Diff line number Diff line
@@ -101,45 +101,50 @@ mod binder;
mod binder_async;
mod error;
mod native;
mod parcel;
mod state;

use binder_ndk_sys as sys;

pub mod parcel;
pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak};
pub use crate::binder_async::{BinderAsyncPool, BoxFuture};
pub use error::{ExceptionCode, Status, StatusCode};
pub use native::{
    add_service, force_lazy_services_persist, is_handling_transaction, register_lazy_service,
};
pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder};
pub use proxy::{
    get_interface, get_service, wait_for_interface, wait_for_service, DeathRecipient, SpIBinder,
    WpIBinder,
};
pub use state::{ProcessState, ThreadState};

/// Binder result containing a [`Status`] on error.
pub type Result<T> = std::result::Result<T, Status>;

/// Advanced Binder APIs needed internally by AIDL or when manually using Binder
/// without AIDL.
pub mod binder_impl {
    pub use crate::binder::{
    BinderFeatures, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable,
    Stability, Strong, ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, Weak,
    FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
        IBinderInternal, InterfaceClass, Remotable, Stability, ToAsyncInterface, ToSyncInterface,
        TransactionCode, TransactionFlags, FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY,
        FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
    };
pub use crate::binder_async::{BoxFuture, BinderAsyncPool, BinderAsyncRuntime};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
pub use native::{add_service, force_lazy_services_persist, is_handling_transaction, register_lazy_service, Binder};
pub use parcel::{BorrowedParcel, Parcel};
pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service};
pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder};
pub use state::{ProcessState, ThreadState};
    pub use crate::binder_async::BinderAsyncRuntime;
    pub use crate::error::status_t;
    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,
    };
    pub use crate::proxy::{AssociateClass, Proxy};
}

/// Unstable, in-development API that only allowlisted clients are allowed to use.
#[doc(hidden)]
pub mod unstable_api {
    pub use crate::binder::AsNative;
    pub use crate::proxy::unstable_api::new_spibinder;
    pub use crate::sys::AIBinder;
}

/// The public API usable outside AIDL-generated interface crates.
pub mod public_api {
    pub use super::parcel::{ParcelFileDescriptor, ParcelableHolder};
    pub use super::{
        add_service, force_lazy_services_persist, get_interface, register_lazy_service,
        wait_for_interface,
    };
    pub use super::{
        BinderAsyncPool, BinderFeatures, BoxFuture, DeathRecipient, ExceptionCode, IBinder,
        Interface, ProcessState, SpIBinder, Status, StatusCode, Strong, ThreadState, Weak,
        WpIBinder,
    };

    /// Binder result containing a [`Status`] on error.
    pub type Result<T> = std::result::Result<T, Status>;
}
+30 −33

File changed.

Preview size limit exceeded, changes collapsed.

+6 −6
Original line number Diff line number Diff line
@@ -15,8 +15,8 @@
 */

use crate::binder::Stability;
use crate::error::{Result, StatusCode};
use crate::parcel::{Parcel, BorrowedParcel, Parcelable};
use crate::error::StatusCode;
use crate::parcel::{BorrowedParcel, Parcel, Parcelable};
use crate::{impl_deserialize_for_parcelable, impl_serialize_for_parcelable};

use downcast_rs::{impl_downcast, DowncastSync};
@@ -97,7 +97,7 @@ impl ParcelableHolder {
    }

    /// Set the parcelable contained in this `ParcelableHolder`.
    pub fn set_parcelable<T>(&mut self, p: Arc<T>) -> Result<()>
    pub fn set_parcelable<T>(&mut self, p: Arc<T>) -> Result<(), StatusCode>
    where
        T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug + Send + Sync,
    {
@@ -126,7 +126,7 @@ impl ParcelableHolder {
    /// * `Ok(None)` if the holder is empty or the descriptor does not match
    /// * `Ok(Some(_))` if the object holds a parcelable of type `T`
    ///   with the correct descriptor
    pub fn get_parcelable<T>(&self) -> Result<Option<Arc<T>>>
    pub fn get_parcelable<T>(&self) -> Result<Option<Arc<T>>, StatusCode>
    where
        T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug + Send + Sync,
    {
@@ -180,7 +180,7 @@ impl_serialize_for_parcelable!(ParcelableHolder);
impl_deserialize_for_parcelable!(ParcelableHolder);

impl Parcelable for ParcelableHolder {
    fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
    fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode> {
        parcel.write(&self.stability)?;

        let mut data = self.data.lock().unwrap();
@@ -219,7 +219,7 @@ impl Parcelable for ParcelableHolder {
        }
    }

    fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
    fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode> {
        self.stability = parcel.read()?;

        let data_size: i32 = parcel.read()?;
Loading