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

Commit 828b2acb authored by Matthew Maurer's avatar Matthew Maurer Committed by Gerrit Code Review
Browse files

Merge "binder_rs: add OwnedParcel"

parents b05265ac 268458c0
Loading
Loading
Loading
Loading
+8 −8
Original line number Original line Diff line number Diff line
@@ -17,7 +17,7 @@
//! Trait definitions for binder objects
//! Trait definitions for binder objects


use crate::error::{status_t, Result, StatusCode};
use crate::error::{status_t, Result, StatusCode};
use crate::parcel::Parcel;
use crate::parcel::{OwnedParcel, Parcel};
use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
use crate::sys;
use crate::sys;


@@ -177,25 +177,25 @@ pub trait IBinderInternal: IBinder {
    fn get_extension(&mut self) -> Result<Option<SpIBinder>>;
    fn get_extension(&mut self) -> Result<Option<SpIBinder>>;


    /// Create a Parcel that can be used with `submit_transact`.
    /// Create a Parcel that can be used with `submit_transact`.
    fn prepare_transact(&self) -> Result<Parcel>;
    fn prepare_transact(&self) -> Result<OwnedParcel>;


    /// Perform a generic operation with the object.
    /// Perform a generic operation with the object.
    ///
    ///
    /// The provided [`Parcel`] must have been created by a call to
    /// The provided [`OwnedParcel`] must have been created by a call to
    /// `prepare_transact` on the same binder.
    /// `prepare_transact` on the same binder.
    ///
    ///
    /// # Arguments
    /// # Arguments
    ///
    ///
    /// * `code` - Transaction code for the operation.
    /// * `code` - Transaction code for the operation.
    /// * `data` - [`Parcel`] with input data.
    /// * `data` - [`OwnedParcel`] with input data.
    /// * `flags` - Transaction flags, e.g. marking the transaction as
    /// * `flags` - Transaction flags, e.g. marking the transaction as
    ///   asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY)).
    ///   asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY)).
    fn submit_transact(
    fn submit_transact(
        &self,
        &self,
        code: TransactionCode,
        code: TransactionCode,
        data: Parcel,
        data: OwnedParcel,
        flags: TransactionFlags,
        flags: TransactionFlags,
    ) -> Result<Parcel>;
    ) -> Result<OwnedParcel>;


    /// Perform a generic operation with the object. This is a convenience
    /// Perform a generic operation with the object. This is a convenience
    /// method that internally calls `prepare_transact` followed by
    /// method that internally calls `prepare_transact` followed by
@@ -213,8 +213,8 @@ pub trait IBinderInternal: IBinder {
        input_callback: F,
        input_callback: F,
    ) -> Result<Parcel> {
    ) -> Result<Parcel> {
        let mut parcel = self.prepare_transact()?;
        let mut parcel = self.prepare_transact()?;
        input_callback(&mut parcel)?;
        input_callback(&mut parcel.borrowed())?;
        self.submit_transact(code, parcel, flags)
        self.submit_transact(code, parcel, flags).map(OwnedParcel::into_parcel)
    }
    }
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -113,7 +113,7 @@ pub use crate::binder::{
};
};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder};
pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder};
pub use parcel::Parcel;
pub use parcel::{OwnedParcel, Parcel};
pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service};
pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service};
pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder};
pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder};
pub use state::{ProcessState, ThreadState};
pub use state::{ProcessState, ThreadState};
+120 −27
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ use crate::sys;


use std::cell::RefCell;
use std::cell::RefCell;
use std::convert::TryInto;
use std::convert::TryInto;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::mem::ManuallyDrop;
use std::ptr;
use std::ptr;
use std::fmt;
use std::fmt;
@@ -52,6 +53,106 @@ pub enum Parcel {
    Borrowed(*mut sys::AParcel),
    Borrowed(*mut sys::AParcel),
}
}


/// A variant of Parcel that is known to be owned.
pub struct OwnedParcel {
    ptr: *mut sys::AParcel,
}

/// # Safety
///
/// This type guarantees that it owns the AParcel and that all access to
/// the AParcel happens through the OwnedParcel, so it is ok to send across
/// threads.
unsafe impl Send for OwnedParcel {}

/// A variant of Parcel that is known to be borrowed.
pub struct BorrowedParcel<'a> {
    inner: Parcel,
    _lifetime: PhantomData<&'a mut Parcel>,
}

impl OwnedParcel {
    /// Create a new empty `OwnedParcel`.
    pub fn new() -> OwnedParcel {
        let ptr = unsafe {
            // Safety: If `AParcel_create` succeeds, it always returns
            // a valid pointer. If it fails, the process will crash.
            sys::AParcel_create()
        };
        assert!(!ptr.is_null());
        Self { ptr }
    }

    /// Create an owned reference to a parcel object from a raw pointer.
    ///
    /// # Safety
    ///
    /// This constructor is safe if the raw pointer parameter is either null
    /// (resulting in `None`), or a valid pointer to an `AParcel` object. The
    /// parcel object must be owned by the caller prior to this call, as this
    /// constructor takes ownership of the parcel and will destroy it on drop.
    ///
    /// Additionally, the caller must guarantee that it is valid to take
    /// ownership of the AParcel object. All future access to the AParcel
    /// must happen through this `OwnedParcel`.
    ///
    /// Because `OwnedParcel` implements `Send`, the pointer must never point
    /// to any thread-local data, e.g., a variable on the stack, either directly
    /// or indirectly.
    pub unsafe fn from_raw(ptr: *mut sys::AParcel) -> Option<OwnedParcel> {
        ptr.as_mut().map(|ptr| Self { ptr })
    }

    /// Consume the parcel, transferring ownership to the caller.
    pub(crate) fn into_raw(self) -> *mut sys::AParcel {
        let ptr = self.ptr;
        let _ = ManuallyDrop::new(self);
        ptr
    }

    /// Convert this `OwnedParcel` into an owned `Parcel`.
    pub fn into_parcel(self) -> Parcel {
        Parcel::Owned(self.into_raw())
    }

    /// Get a borrowed view into the contents of this `Parcel`.
    pub fn borrowed(&mut self) -> BorrowedParcel<'_> {
        BorrowedParcel {
            inner: Parcel::Borrowed(self.ptr),
            _lifetime: PhantomData,
        }
    }
}

impl Default for OwnedParcel {
    fn default() -> Self {
        Self::new()
    }
}

impl Clone for OwnedParcel {
    fn clone(&self) -> Self {
        let mut new_parcel = Self::new();
        new_parcel
            .borrowed()
            .append_all_from(&Parcel::Borrowed(self.ptr))
            .expect("Failed to append from Parcel");
        new_parcel
    }
}

impl<'a> std::ops::Deref for BorrowedParcel<'a> {
    type Target = Parcel;
    fn deref(&self) -> &Parcel {
        &self.inner
    }
}
impl<'a> std::ops::DerefMut for BorrowedParcel<'a> {
    fn deref_mut(&mut self) -> &mut Parcel {
        &mut self.inner
    }
}

/// # Safety
/// # Safety
///
///
/// The `Parcel` constructors guarantee that a `Parcel` object will always
/// The `Parcel` constructors guarantee that a `Parcel` object will always
@@ -95,33 +196,6 @@ impl Parcel {
    pub(crate) unsafe fn borrowed(ptr: *mut sys::AParcel) -> Option<Parcel> {
    pub(crate) unsafe fn borrowed(ptr: *mut sys::AParcel) -> Option<Parcel> {
        ptr.as_mut().map(|ptr| Self::Borrowed(ptr))
        ptr.as_mut().map(|ptr| Self::Borrowed(ptr))
    }
    }

    /// Create an owned reference to a parcel object from a raw pointer.
    ///
    /// # Safety
    ///
    /// This constructor is safe if the raw pointer parameter is either null
    /// (resulting in `None`), or a valid pointer to an `AParcel` object. The
    /// parcel object must be owned by the caller prior to this call, as this
    /// constructor takes ownership of the parcel and will destroy it on drop.
    pub(crate) unsafe fn owned(ptr: *mut sys::AParcel) -> Option<Parcel> {
        ptr.as_mut().map(|ptr| Self::Owned(ptr))
    }

    /// Consume the parcel, transferring ownership to the caller if the parcel
    /// was owned.
    pub(crate) fn into_raw(mut self) -> *mut sys::AParcel {
        let ptr = self.as_native_mut();
        let _ = ManuallyDrop::new(self);
        ptr
    }

    pub(crate) fn is_owned(&self) -> bool {
        match *self {
            Self::Owned(_) => true,
            Self::Borrowed(_) => false,
        }
    }
}
}


impl Default for Parcel {
impl Default for Parcel {
@@ -478,6 +552,18 @@ impl Drop for Parcel {
    }
    }
}
}


impl Drop for OwnedParcel {
    fn drop(&mut self) {
        // Run the C++ Parcel complete object destructor
        unsafe {
            // Safety: `OwnedParcel` always contains a valid pointer to an
            // `AParcel`. Since we own the parcel, we can safely delete it
            // here.
            sys::AParcel_delete(self.ptr)
        }
    }
}

impl fmt::Debug for Parcel {
impl fmt::Debug for Parcel {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Parcel")
        f.debug_struct("Parcel")
@@ -485,6 +571,13 @@ impl fmt::Debug for Parcel {
    }
    }
}
}


impl fmt::Debug for OwnedParcel {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OwnedParcel")
            .finish()
    }
}

#[test]
#[test]
fn test_read_write() {
fn test_read_write() {
    let mut parcel = Parcel::new();
    let mut parcel = Parcel::new();
+8 −10
Original line number Original line Diff line number Diff line
@@ -22,7 +22,7 @@ use crate::binder::{
};
};
use crate::error::{status_result, Result, StatusCode};
use crate::error::{status_result, Result, StatusCode};
use crate::parcel::{
use crate::parcel::{
    Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray,
    Deserialize, DeserializeArray, DeserializeOption, OwnedParcel, Parcel, Serialize, SerializeArray,
    SerializeOption,
    SerializeOption,
};
};
use crate::sys;
use crate::sys;
@@ -235,7 +235,7 @@ impl Drop for SpIBinder {
}
}


impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
    fn prepare_transact(&self) -> Result<Parcel> {
    fn prepare_transact(&self) -> Result<OwnedParcel> {
        let mut input = ptr::null_mut();
        let mut input = ptr::null_mut();
        let status = unsafe {
        let status = unsafe {
            // Safety: `SpIBinder` guarantees that `self` always contains a
            // Safety: `SpIBinder` guarantees that `self` always contains a
@@ -253,20 +253,19 @@ impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {


        unsafe {
        unsafe {
            // Safety: At this point, `input` is either a valid, owned `AParcel`
            // Safety: At this point, `input` is either a valid, owned `AParcel`
            // pointer, or null. `Parcel::owned` safely handles both cases,
            // pointer, or null. `OwnedParcel::from_raw` safely handles both cases,
            // taking ownership of the parcel.
            // taking ownership of the parcel.
            Parcel::owned(input).ok_or(StatusCode::UNEXPECTED_NULL)
            OwnedParcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL)
        }
        }
    }
    }


    fn submit_transact(
    fn submit_transact(
        &self,
        &self,
        code: TransactionCode,
        code: TransactionCode,
        data: Parcel,
        data: OwnedParcel,
        flags: TransactionFlags,
        flags: TransactionFlags,
    ) -> Result<Parcel> {
    ) -> Result<OwnedParcel> {
        let mut reply = ptr::null_mut();
        let mut reply = ptr::null_mut();
        assert!(data.is_owned());
        let status = unsafe {
        let status = unsafe {
            // Safety: `SpIBinder` guarantees that `self` always contains a
            // Safety: `SpIBinder` guarantees that `self` always contains a
            // valid pointer to an `AIBinder`. Although `IBinder::transact` is
            // valid pointer to an `AIBinder`. Although `IBinder::transact` is
@@ -299,9 +298,8 @@ impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
            // after the call to `AIBinder_transact` above, so we can
            // after the call to `AIBinder_transact` above, so we can
            // construct a `Parcel` out of it. `AIBinder_transact` passes
            // construct a `Parcel` out of it. `AIBinder_transact` passes
            // ownership of the `reply` parcel to Rust, so we need to
            // ownership of the `reply` parcel to Rust, so we need to
            // construct an owned variant. `Parcel::owned` takes ownership
            // construct an owned variant.
            // of the parcel pointer.
            OwnedParcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL)
            Parcel::owned(reply).ok_or(StatusCode::UNEXPECTED_NULL)
        }
        }
    }
    }