Merge "Invoke commit callback after latch buffers"
diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
index 34f1cbf..5baa4d7 100644
--- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
+++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
@@ -32,9 +32,11 @@
 bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param),
                           void* param);
 
-// Starts an RPC server on a given port and a given root IBinder object.
-// This function sets up the server, calls readyCallback with a given param, and
-// then joins before returning.
+// Starts an RPC server on a given port and a given root IBinder factory.
+// RunRpcServerWithFactory acts like RunRpcServerCallback, but instead of
+// assigning single root IBinder object to all connections, factory is called
+// whenever a client connects, making it possible to assign unique IBinder
+// object to each client.
 bool RunRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
                           void* factoryContext, unsigned int port);
 
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 4e048d7..bd2e695 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -17,7 +17,7 @@
 //! Trait definitions for binder objects
 
 use crate::error::{status_t, Result, StatusCode};
-use crate::parcel::{OwnedParcel, Parcel};
+use crate::parcel::{Parcel, BorrowedParcel};
 use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
 use crate::sys;
 
@@ -129,7 +129,7 @@
     /// Handle and reply to a request to invoke a transaction on this object.
     ///
     /// `reply` may be [`None`] if the sender does not expect a reply.
-    fn on_transact(&self, code: TransactionCode, data: &Parcel, reply: &mut Parcel) -> Result<()>;
+    fn on_transact(&self, code: TransactionCode, data: &BorrowedParcel<'_>, reply: &mut BorrowedParcel<'_>) -> Result<()>;
 
     /// Handle a request to invoke the dump transaction on this
     /// object.
@@ -177,25 +177,25 @@
     fn get_extension(&mut self) -> Result<Option<SpIBinder>>;
 
     /// Create a Parcel that can be used with `submit_transact`.
-    fn prepare_transact(&self) -> Result<OwnedParcel>;
+    fn prepare_transact(&self) -> Result<Parcel>;
 
     /// Perform a generic operation with the object.
     ///
-    /// The provided [`OwnedParcel`] must have been created by a call to
+    /// The provided [`Parcel`] must have been created by a call to
     /// `prepare_transact` on the same binder.
     ///
     /// # Arguments
     ///
     /// * `code` - Transaction code for the operation.
-    /// * `data` - [`OwnedParcel`] with input data.
+    /// * `data` - [`Parcel`] with input data.
     /// * `flags` - Transaction flags, e.g. marking the transaction as
     ///   asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY)).
     fn submit_transact(
         &self,
         code: TransactionCode,
-        data: OwnedParcel,
+        data: Parcel,
         flags: TransactionFlags,
-    ) -> Result<OwnedParcel>;
+    ) -> Result<Parcel>;
 
     /// Perform a generic operation with the object. This is a convenience
     /// method that internally calls `prepare_transact` followed by
@@ -206,15 +206,15 @@
     /// * `flags` - Transaction flags, e.g. marking the transaction as
     ///   asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY))
     /// * `input_callback` A callback for building the `Parcel`.
-    fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
+    fn transact<F: FnOnce(BorrowedParcel<'_>) -> Result<()>>(
         &self,
         code: TransactionCode,
         flags: TransactionFlags,
         input_callback: F,
     ) -> Result<Parcel> {
         let mut parcel = self.prepare_transact()?;
-        input_callback(&mut parcel.borrowed())?;
-        self.submit_transact(code, parcel, flags).map(OwnedParcel::into_parcel)
+        input_callback(parcel.borrowed())?;
+        self.submit_transact(code, parcel, flags)
     }
 }
 
@@ -475,8 +475,8 @@
 ///     fn on_transact(
 ///         &self,
 ///         code: TransactionCode,
-///         data: &Parcel,
-///         reply: &mut Parcel,
+///         data: &BorrowedParcel,
+///         reply: &mut BorrowedParcel,
 ///     ) -> Result<()> {
 ///         // ...
 ///     }
@@ -655,13 +655,13 @@
 /// have the following type:
 ///
 /// ```
-/// # use binder::{Interface, TransactionCode, Parcel};
+/// # use binder::{Interface, TransactionCode, BorrowedParcel};
 /// # trait Placeholder {
 /// fn on_transact(
 ///     service: &dyn Interface,
 ///     code: TransactionCode,
-///     data: &Parcel,
-///     reply: &mut Parcel,
+///     data: &BorrowedParcel,
+///     reply: &mut BorrowedParcel,
 /// ) -> binder::Result<()>;
 /// # }
 /// ```
@@ -676,7 +676,7 @@
 /// using the provided function, `on_transact`.
 ///
 /// ```
-/// use binder::{declare_binder_interface, Binder, Interface, TransactionCode, Parcel};
+/// use binder::{declare_binder_interface, Binder, Interface, TransactionCode, BorrowedParcel};
 ///
 /// pub trait IServiceManager: Interface {
 ///     // remote methods...
@@ -692,8 +692,8 @@
 /// fn on_transact(
 ///     service: &dyn IServiceManager,
 ///     code: TransactionCode,
-///     data: &Parcel,
-///     reply: &mut Parcel,
+///     data: &BorrowedParcel,
+///     reply: &mut BorrowedParcel,
 /// ) -> binder::Result<()> {
 ///     // ...
 ///     Ok(())
@@ -847,7 +847,7 @@
                 $descriptor
             }
 
-            fn on_transact(&self, code: $crate::TransactionCode, data: &$crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> {
+            fn on_transact(&self, code: $crate::TransactionCode, data: &$crate::BorrowedParcel<'_>, reply: &mut $crate::BorrowedParcel<'_>) -> $crate::Result<()> {
                 match $on_transact(&*self.0, code, data, reply) {
                     // The C++ backend converts UNEXPECTED_NULL into an exception
                     Err($crate::StatusCode::UNEXPECTED_NULL) => {
@@ -922,14 +922,14 @@
         where
             dyn $interface: $crate::Interface
         {
-            fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+            fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
                 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::Parcel) -> $crate::Result<()> {
+            fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
                 parcel.write(&this.map($crate::Interface::as_binder))
             }
         }
@@ -988,14 +988,14 @@
         }
 
         impl<P: $crate::BinderAsyncPool> $crate::parcel::Serialize for dyn $async_interface<P> + '_ {
-            fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+            fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
                 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::Parcel) -> $crate::Result<()> {
+            fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
                 parcel.write(&this.map($crate::Interface::as_binder))
             }
         }
@@ -1040,26 +1040,26 @@
         }
 
         impl $crate::parcel::Serialize for $enum {
-            fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+            fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
                 parcel.write(&self.0)
             }
         }
 
         impl $crate::parcel::SerializeArray for $enum {
-            fn serialize_array(slice: &[Self], parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+            fn serialize_array(slice: &[Self], parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> {
                 let v: Vec<$backing> = slice.iter().map(|x| x.0).collect();
                 <$backing as binder::parcel::SerializeArray>::serialize_array(&v[..], parcel)
             }
         }
 
         impl $crate::parcel::Deserialize for $enum {
-            fn deserialize(parcel: &$crate::parcel::Parcel) -> $crate::Result<Self> {
+            fn deserialize(parcel: &$crate::parcel::BorrowedParcel<'_>) -> $crate::Result<Self> {
                 parcel.read().map(Self)
             }
         }
 
         impl $crate::parcel::DeserializeArray for $enum {
-            fn deserialize_array(parcel: &$crate::parcel::Parcel) -> $crate::Result<Option<Vec<Self>>> {
+            fn deserialize_array(parcel: &$crate::parcel::BorrowedParcel<'_>) -> $crate::Result<Option<Vec<Self>>> {
                 let v: Option<Vec<$backing>> =
                     <$backing as binder::parcel::DeserializeArray>::deserialize_array(parcel)?;
                 Ok(v.map(|v| v.into_iter().map(Self).collect()))
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 2ac2d2f..cce55c0 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -50,8 +50,8 @@
 //! fn on_transact(
 //!     service: &dyn ITest,
 //!     code: TransactionCode,
-//!     _data: &Parcel,
-//!     reply: &mut Parcel,
+//!     _data: &BorrowedParcel,
+//!     reply: &mut BorrowedParcel,
 //! ) -> binder::Result<()> {
 //!     match code {
 //!         SpIBinder::FIRST_CALL_TRANSACTION => {
@@ -115,7 +115,7 @@
 pub use crate::binder_async::{BoxFuture, BinderAsyncPool};
 pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
 pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder};
-pub use parcel::{OwnedParcel, Parcel};
+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};
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index a91092e..f5d7187 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -18,7 +18,7 @@
     AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode,
 };
 use crate::error::{status_result, status_t, Result, StatusCode};
-use crate::parcel::{Parcel, Serialize};
+use crate::parcel::{BorrowedParcel, Serialize};
 use crate::proxy::SpIBinder;
 use crate::sys;
 
@@ -161,8 +161,8 @@
     ///        # fn on_transact(
     ///        #     service: &dyn IBar,
     ///        #     code: TransactionCode,
-    ///        #     data: &Parcel,
-    ///        #     reply: &mut Parcel,
+    ///        #     data: &BorrowedParcel,
+    ///        #     reply: &mut BorrowedParcel,
     ///        # ) -> binder::Result<()> {
     ///        #     Ok(())
     ///        # }
@@ -277,8 +277,8 @@
         reply: *mut sys::AParcel,
     ) -> status_t {
         let res = {
-            let mut reply = Parcel::borrowed(reply).unwrap();
-            let data = Parcel::borrowed(data as *mut sys::AParcel).unwrap();
+            let mut reply = BorrowedParcel::from_raw(reply).unwrap();
+            let data = BorrowedParcel::from_raw(data as *mut sys::AParcel).unwrap();
             let object = sys::AIBinder_getUserData(binder);
             let binder: &T = &*(object as *const T);
             binder.on_transact(code, &data, &mut reply)
@@ -384,7 +384,7 @@
 }
 
 impl<B: Remotable> Serialize for Binder<B> {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         parcel.write_binder(Some(&self.as_binder()))
     }
 }
@@ -503,8 +503,8 @@
     fn on_transact(
         &self,
         _code: TransactionCode,
-        _data: &Parcel,
-        _reply: &mut Parcel,
+        _data: &BorrowedParcel<'_>,
+        _reply: &mut BorrowedParcel<'_>,
     ) -> Result<()> {
         Ok(())
     }
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index a0e1478..206b90c 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -21,11 +21,10 @@
 use crate::proxy::SpIBinder;
 use crate::sys;
 
-use std::cell::RefCell;
 use std::convert::TryInto;
 use std::marker::PhantomData;
 use std::mem::ManuallyDrop;
-use std::ptr;
+use std::ptr::{self, NonNull};
 use std::fmt;
 
 mod file_descriptor;
@@ -46,53 +45,41 @@
 /// other side of the IPC, and references to live Binder objects that will
 /// result in the other side receiving a proxy Binder connected with the
 /// original Binder in the Parcel.
-pub enum Parcel {
-    /// Owned parcel pointer
-    Owned(*mut sys::AParcel),
-    /// Borrowed parcel pointer (will not be destroyed on drop)
-    Borrowed(*mut sys::AParcel),
-}
-
-/// A variant of Parcel that is known to be owned.
-pub struct OwnedParcel {
-    ptr: *mut sys::AParcel,
+///
+/// This type represents a parcel that is owned by Rust code.
+#[repr(transparent)]
+pub struct Parcel {
+    ptr: NonNull<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
+/// the AParcel happens through the Parcel, so it is ok to send across
 /// threads.
-unsafe impl Send for OwnedParcel {}
+unsafe impl Send for Parcel {}
 
-/// A variant of Parcel that is known to be borrowed.
+/// Container for a message (data and object references) that can be sent
+/// through Binder.
+///
+/// This object is a borrowed variant of [`Parcel`]. It is a separate type from
+/// `&mut Parcel` because it is not valid to `mem::swap` two parcels.
+#[repr(transparent)]
 pub struct BorrowedParcel<'a> {
-    inner: Parcel,
+    ptr: NonNull<sys::AParcel>,
     _lifetime: PhantomData<&'a mut Parcel>,
 }
 
-impl OwnedParcel {
-    /// Create a new empty `OwnedParcel`.
-    pub fn new() -> OwnedParcel {
+impl Parcel {
+    /// Create a new empty `Parcel`.
+    pub fn new() -> Parcel {
         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 }
-    }
-
-    /// Convert the provided parcel to an owned parcel, or return `None` if it
-    /// is borrowed.
-    pub fn try_from(parcel: Parcel) -> Option<OwnedParcel> {
-        match &parcel {
-            Parcel::Owned(ptr) => {
-                let ptr = *ptr;
-                std::mem::forget(parcel);
-                Some(OwnedParcel { ptr })
-            }
-            Parcel::Borrowed(_) => None,
+        Self {
+            ptr: NonNull::new(ptr).expect("AParcel_create returned null pointer")
         }
     }
 
@@ -107,108 +94,43 @@
     ///
     /// 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`.
+    /// must happen through this `Parcel`.
     ///
-    /// 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 })
+    /// Because `Parcel` 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<Parcel> {
+        NonNull::new(ptr).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 ptr = self.ptr.as_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<'_> {
+        // Safety: The raw pointer is a valid pointer to an AParcel, and the
+        // lifetime of the returned `BorrowedParcel` is tied to `self`, so the
+        // borrow checker will ensure that the `AParcel` can only be accessed
+        // via the `BorrowParcel` until it goes out of scope.
         BorrowedParcel {
-            inner: Parcel::Borrowed(self.ptr),
+            ptr: 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
-///
-/// The `Parcel` constructors guarantee that a `Parcel` object will always
-/// contain a valid pointer to an `AParcel`.
-unsafe impl AsNative<sys::AParcel> for Parcel {
-    fn as_native(&self) -> *const sys::AParcel {
-        match *self {
-            Self::Owned(x) | Self::Borrowed(x) => x,
+    /// Get an immutable borrowed view into the contents of this `Parcel`.
+    pub fn borrowed_ref(&self) -> &BorrowedParcel<'_> {
+        // Safety: Parcel and BorrowedParcel are both represented in the same
+        // way as a NonNull<sys::AParcel> due to their use of repr(transparent),
+        // so casting references as done here is valid.
+        unsafe {
+            &*(self as *const Parcel as *const BorrowedParcel<'_>)
         }
     }
-
-    fn as_native_mut(&mut self) -> *mut sys::AParcel {
-        match *self {
-            Self::Owned(x) | Self::Borrowed(x) => x,
-        }
-    }
-}
-
-impl Parcel {
-    /// Create a new empty `Parcel`.
-    ///
-    /// Creates a new owned empty parcel that can be written to
-    /// using the serialization methods and appended to and
-    /// from using `append_from` and `append_from_all`.
-    pub fn new() -> Parcel {
-        let parcel = unsafe {
-            // Safety: If `AParcel_create` succeeds, it always returns
-            // a valid pointer. If it fails, the process will crash.
-            sys::AParcel_create()
-        };
-        assert!(!parcel.is_null());
-        Self::Owned(parcel)
-    }
-
-    /// Create a borrowed 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.
-    pub(crate) unsafe fn borrowed(ptr: *mut sys::AParcel) -> Option<Parcel> {
-        ptr.as_mut().map(|ptr| Self::Borrowed(ptr))
-    }
 }
 
 impl Default for Parcel {
@@ -221,14 +143,77 @@
     fn clone(&self) -> Self {
         let mut new_parcel = Self::new();
         new_parcel
-            .append_all_from(self)
+            .borrowed()
+            .append_all_from(self.borrowed_ref())
             .expect("Failed to append from Parcel");
         new_parcel
     }
 }
 
+impl<'a> BorrowedParcel<'a> {
+    /// Create a borrowed 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.
+    ///
+    /// Since the raw pointer is not restricted by any lifetime, the lifetime on
+    /// the returned `BorrowedParcel` object can be chosen arbitrarily by the
+    /// caller. The caller must ensure it is valid to mutably borrow the AParcel
+    /// for the duration of the lifetime that the caller chooses. Note that
+    /// since this is a mutable borrow, it must have exclusive access to the
+    /// AParcel for the duration of the borrow.
+    pub unsafe fn from_raw(ptr: *mut sys::AParcel) -> Option<BorrowedParcel<'a>> {
+        Some(Self {
+            ptr: NonNull::new(ptr)?,
+            _lifetime: PhantomData,
+        })
+    }
+
+    /// Get a sub-reference to this reference to the parcel.
+    pub fn reborrow(&mut self) -> BorrowedParcel<'_> {
+        // Safety: The raw pointer is a valid pointer to an AParcel, and the
+        // lifetime of the returned `BorrowedParcel` is tied to `self`, so the
+        // borrow checker will ensure that the `AParcel` can only be accessed
+        // via the `BorrowParcel` until it goes out of scope.
+        BorrowedParcel {
+            ptr: self.ptr,
+            _lifetime: PhantomData,
+        }
+    }
+}
+
+/// # Safety
+///
+/// The `Parcel` constructors guarantee that a `Parcel` object will always
+/// contain a valid pointer to an `AParcel`.
+unsafe impl AsNative<sys::AParcel> for Parcel {
+    fn as_native(&self) -> *const sys::AParcel {
+        self.ptr.as_ptr()
+    }
+
+    fn as_native_mut(&mut self) -> *mut sys::AParcel {
+        self.ptr.as_ptr()
+    }
+}
+
+/// # Safety
+///
+/// The `BorrowedParcel` constructors guarantee that a `BorrowedParcel` object
+/// will always contain a valid pointer to an `AParcel`.
+unsafe impl<'a> AsNative<sys::AParcel> for BorrowedParcel<'a> {
+    fn as_native(&self) -> *const sys::AParcel {
+        self.ptr.as_ptr()
+    }
+
+    fn as_native_mut(&mut self) -> *mut sys::AParcel {
+        self.ptr.as_ptr()
+    }
+}
+
 // Data serialization methods
-impl Parcel {
+impl<'a> BorrowedParcel<'a> {
     /// Data written to parcelable is zero'd before being deleted or reallocated.
     pub fn mark_sensitive(&mut self) {
         unsafe {
@@ -237,12 +222,12 @@
         }
     }
 
-    /// Write a type that implements [`Serialize`] to the `Parcel`.
+    /// Write a type that implements [`Serialize`] to the parcel.
     pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> {
         parcelable.serialize(self)
     }
 
-    /// Writes the length of a slice to the `Parcel`.
+    /// Writes the length of a slice to the parcel.
     ///
     /// This is used in AIDL-generated client side code to indicate the
     /// allocated space for an output array parameter.
@@ -255,7 +240,7 @@
         }
     }
 
-    /// Perform a series of writes to the `Parcel`, prepended with the length
+    /// Perform a series of writes to the parcel, prepended with the length
     /// (in bytes) of the written data.
     ///
     /// The length `0i32` will be written to the parcel first, followed by the
@@ -269,7 +254,7 @@
     ///
     /// ```
     /// # use binder::{Binder, Interface, Parcel};
-    /// # let mut parcel = Parcel::Owned(std::ptr::null_mut());
+    /// # let mut parcel = Parcel::new();
     /// parcel.sized_write(|subparcel| {
     ///     subparcel.write(&1u32)?;
     ///     subparcel.write(&2u32)?;
@@ -283,14 +268,14 @@
     /// [16i32, 1u32, 2u32, 3u32]
     /// ```
     pub fn sized_write<F>(&mut self, f: F) -> Result<()>
-    where for<'a>
-        F: Fn(&'a WritableSubParcel<'a>) -> Result<()>
+    where
+        for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()>
     {
         let start = self.get_data_position();
         self.write(&0i32)?;
         {
-            let subparcel = WritableSubParcel(RefCell::new(self));
-            f(&subparcel)?;
+            let mut subparcel = WritableSubParcel(self.reborrow());
+            f(&mut subparcel)?;
         }
         let end = self.get_data_position();
         unsafe {
@@ -307,8 +292,8 @@
     /// Returns the current position in the parcel data.
     pub fn get_data_position(&self) -> i32 {
         unsafe {
-            // Safety: `Parcel` always contains a valid pointer to an `AParcel`,
-            // and this call is otherwise safe.
+            // Safety: `BorrowedParcel` always contains a valid pointer to an
+            // `AParcel`, and this call is otherwise safe.
             sys::AParcel_getDataPosition(self.as_native())
         }
     }
@@ -316,8 +301,8 @@
     /// Returns the total size of the parcel.
     pub fn get_data_size(&self) -> i32 {
         unsafe {
-            // Safety: `Parcel` always contains a valid pointer to an `AParcel`,
-            // and this call is otherwise safe.
+            // Safety: `BorrowedParcel` always contains a valid pointer to an
+            // `AParcel`, and this call is otherwise safe.
             sys::AParcel_getDataSize(self.as_native())
         }
     }
@@ -335,11 +320,11 @@
         status_result(sys::AParcel_setDataPosition(self.as_native(), pos))
     }
 
-    /// Append a subset of another `Parcel`.
+    /// Append a subset of another parcel.
     ///
     /// This appends `size` bytes of data from `other` starting at offset
-    /// `start` to the current `Parcel`, or returns an error if not possible.
-    pub fn append_from(&mut self, other: &Self, start: i32, size: i32) -> Result<()> {
+    /// `start` to the current parcel, or returns an error if not possible.
+    pub fn append_from(&mut self, other: &impl AsNative<sys::AParcel>, start: i32, size: i32) -> Result<()> {
         let status = unsafe {
             // Safety: `Parcel::appendFrom` from C++ checks that `start`
             // and `size` are in bounds, and returns an error otherwise.
@@ -354,33 +339,125 @@
         status_result(status)
     }
 
-    /// Append the contents of another `Parcel`.
-    pub fn append_all_from(&mut self, other: &Self) -> Result<()> {
-        self.append_from(other, 0, other.get_data_size())
+    /// Append the contents of another parcel.
+    pub fn append_all_from(&mut self, other: &impl AsNative<sys::AParcel>) -> Result<()> {
+        // Safety: `BorrowedParcel` always contains a valid pointer to an
+        // `AParcel`, and this call is otherwise safe.
+        let size = unsafe { sys::AParcel_getDataSize(other.as_native()) };
+        self.append_from(other, 0, size)
     }
 }
 
-/// A segment of a writable parcel, used for [`Parcel::sized_write`].
-pub struct WritableSubParcel<'a>(RefCell<&'a mut Parcel>);
+/// A segment of a writable parcel, used for [`BorrowedParcel::sized_write`].
+pub struct WritableSubParcel<'a>(BorrowedParcel<'a>);
 
 impl<'a> WritableSubParcel<'a> {
     /// Write a type that implements [`Serialize`] to the sub-parcel.
-    pub fn write<S: Serialize + ?Sized>(&self, parcelable: &S) -> Result<()> {
-        parcelable.serialize(&mut *self.0.borrow_mut())
+    pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> {
+        parcelable.serialize(&mut self.0)
+    }
+}
+
+impl Parcel {
+    /// Data written to parcelable is zero'd before being deleted or reallocated.
+    pub fn mark_sensitive(&mut self) {
+        self.borrowed().mark_sensitive()
+    }
+
+    /// Write a type that implements [`Serialize`] to the parcel.
+    pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> {
+        self.borrowed().write(parcelable)
+    }
+
+    /// Writes the length of a slice to the parcel.
+    ///
+    /// This is used in AIDL-generated client side code to indicate the
+    /// allocated space for an output array parameter.
+    pub fn write_slice_size<T>(&mut self, slice: Option<&[T]>) -> Result<()> {
+        self.borrowed().write_slice_size(slice)
+    }
+
+    /// Perform a series of writes to the parcel, prepended with the length
+    /// (in bytes) of the written data.
+    ///
+    /// The length `0i32` will be written to the parcel first, followed by the
+    /// writes performed by the callback. The initial length will then be
+    /// updated to the length of all data written by the callback, plus the
+    /// size of the length elemement itself (4 bytes).
+    ///
+    /// # Examples
+    ///
+    /// After the following call:
+    ///
+    /// ```
+    /// # use binder::{Binder, Interface, Parcel};
+    /// # let mut parcel = Parcel::new();
+    /// parcel.sized_write(|subparcel| {
+    ///     subparcel.write(&1u32)?;
+    ///     subparcel.write(&2u32)?;
+    ///     subparcel.write(&3u32)
+    /// });
+    /// ```
+    ///
+    /// `parcel` will contain the following:
+    ///
+    /// ```ignore
+    /// [16i32, 1u32, 2u32, 3u32]
+    /// ```
+    pub fn sized_write<F>(&mut self, f: F) -> Result<()>
+    where
+        for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()>
+    {
+        self.borrowed().sized_write(f)
+    }
+
+    /// Returns the current position in the parcel data.
+    pub fn get_data_position(&self) -> i32 {
+        self.borrowed_ref().get_data_position()
+    }
+
+    /// Returns the total size of the parcel.
+    pub fn get_data_size(&self) -> i32 {
+        self.borrowed_ref().get_data_size()
+    }
+
+    /// Move the current read/write position in the parcel.
+    ///
+    /// # Safety
+    ///
+    /// This method is safe if `pos` is less than the current size of the parcel
+    /// data buffer. Otherwise, we are relying on correct bounds checking in the
+    /// Parcel C++ code on every subsequent read or write to this parcel. If all
+    /// accesses are bounds checked, this call is still safe, but we can't rely
+    /// on that.
+    pub unsafe fn set_data_position(&self, pos: i32) -> Result<()> {
+        self.borrowed_ref().set_data_position(pos)
+    }
+
+    /// Append a subset of another parcel.
+    ///
+    /// This appends `size` bytes of data from `other` starting at offset
+    /// `start` to the current parcel, or returns an error if not possible.
+    pub fn append_from(&mut self, other: &impl AsNative<sys::AParcel>, start: i32, size: i32) -> Result<()> {
+        self.borrowed().append_from(other, start, size)
+    }
+
+    /// Append the contents of another parcel.
+    pub fn append_all_from(&mut self, other: &impl AsNative<sys::AParcel>) -> Result<()> {
+        self.borrowed().append_all_from(other)
     }
 }
 
 // Data deserialization methods
-impl Parcel {
-    /// Attempt to read a type that implements [`Deserialize`] from this
-    /// `Parcel`.
+impl<'a> BorrowedParcel<'a> {
+    /// Attempt to read a type that implements [`Deserialize`] from this parcel.
     pub fn read<D: Deserialize>(&self) -> Result<D> {
         D::deserialize(self)
     }
 
-    /// Attempt to read a type that implements [`Deserialize`] from this
-    /// `Parcel` onto an existing value. This operation will overwrite the old
-    /// value partially or completely, depending on how much data is available.
+    /// Attempt to read a type that implements [`Deserialize`] from this parcel
+    /// onto an existing value. This operation will overwrite the old value
+    /// partially or completely, depending on how much data is available.
     pub fn read_onto<D: Deserialize>(&self, x: &mut D) -> Result<()> {
         x.deserialize_from(self)
     }
@@ -413,9 +490,9 @@
     /// });
     /// ```
     ///
-    pub fn sized_read<F>(&self, mut f: F) -> Result<()>
+    pub fn sized_read<F>(&self, f: F) -> Result<()>
     where
-        for<'a> F: FnMut(ReadableSubParcel<'a>) -> Result<()>
+        for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()>
     {
         let start = self.get_data_position();
         let parcelable_size: i32 = self.read()?;
@@ -430,7 +507,10 @@
         }
 
         let subparcel = ReadableSubParcel {
-            parcel: self,
+            parcel: BorrowedParcel {
+                ptr: self.ptr,
+                _lifetime: PhantomData,
+            },
             end_position: end,
         };
         f(subparcel)?;
@@ -444,8 +524,8 @@
         Ok(())
     }
 
-    /// Read a vector size from the `Parcel` and resize the given output vector
-    /// to be correctly sized for that amount of data.
+    /// Read a vector size from the parcel and resize the given output vector to
+    /// be correctly sized for that amount of data.
     ///
     /// This method is used in AIDL-generated server side code for methods that
     /// take a mutable slice reference parameter.
@@ -463,7 +543,7 @@
         Ok(())
     }
 
-    /// Read a vector size from the `Parcel` and either create a correctly sized
+    /// Read a vector size from the parcel and either create a correctly sized
     /// vector for that amount of data or set the output parameter to None if
     /// the vector should be null.
     ///
@@ -491,7 +571,7 @@
 
 /// A segment of a readable parcel, used for [`Parcel::sized_read`].
 pub struct ReadableSubParcel<'a> {
-    parcel: &'a Parcel,
+    parcel: BorrowedParcel<'a>,
     end_position: i32,
 }
 
@@ -501,7 +581,7 @@
         // The caller should have checked this,
         // but it can't hurt to double-check
         assert!(self.has_more_data());
-        D::deserialize(self.parcel)
+        D::deserialize(&self.parcel)
     }
 
     /// Check if the sub-parcel has more data to read
@@ -510,11 +590,82 @@
     }
 }
 
-// Internal APIs
 impl Parcel {
+    /// Attempt to read a type that implements [`Deserialize`] from this parcel.
+    pub fn read<D: Deserialize>(&self) -> Result<D> {
+        self.borrowed_ref().read()
+    }
+
+    /// Attempt to read a type that implements [`Deserialize`] from this parcel
+    /// onto an existing value. This operation will overwrite the old value
+    /// partially or completely, depending on how much data is available.
+    pub fn read_onto<D: Deserialize>(&self, x: &mut D) -> Result<()> {
+        self.borrowed_ref().read_onto(x)
+    }
+
+    /// Safely read a sized parcelable.
+    ///
+    /// Read the size of a parcelable, compute the end position
+    /// of that parcelable, then build a sized readable sub-parcel
+    /// and call a closure with the sub-parcel as its parameter.
+    /// The closure can keep reading data from the sub-parcel
+    /// until it runs out of input data. The closure is responsible
+    /// for calling [`ReadableSubParcel::has_more_data`] to check for
+    /// more data before every read, at least until Rust generators
+    /// are stabilized.
+    /// After the closure returns, skip to the end of the current
+    /// parcelable regardless of how much the closure has read.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// let mut parcelable = Default::default();
+    /// parcel.sized_read(|subparcel| {
+    ///     if subparcel.has_more_data() {
+    ///         parcelable.a = subparcel.read()?;
+    ///     }
+    ///     if subparcel.has_more_data() {
+    ///         parcelable.b = subparcel.read()?;
+    ///     }
+    ///     Ok(())
+    /// });
+    /// ```
+    ///
+    pub fn sized_read<F>(&self, f: F) -> Result<()>
+    where
+        for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()>
+    {
+        self.borrowed_ref().sized_read(f)
+    }
+
+    /// Read a vector size from the parcel and resize the given output vector to
+    /// be correctly sized for that amount of data.
+    ///
+    /// This method is used in AIDL-generated server side code for methods that
+    /// take a mutable slice reference parameter.
+    pub fn resize_out_vec<D: Default + Deserialize>(&self, out_vec: &mut Vec<D>) -> Result<()> {
+        self.borrowed_ref().resize_out_vec(out_vec)
+    }
+
+    /// Read a vector size from the parcel and either create a correctly sized
+    /// vector for that amount of data or set the output parameter to None if
+    /// the vector should be null.
+    ///
+    /// This method is used in AIDL-generated server side code for methods that
+    /// take a mutable slice reference parameter.
+    pub fn resize_nullable_out_vec<D: Default + Deserialize>(
+        &self,
+        out_vec: &mut Option<Vec<D>>,
+    ) -> Result<()> {
+        self.borrowed_ref().resize_nullable_out_vec(out_vec)
+    }
+}
+
+// Internal APIs
+impl<'a> BorrowedParcel<'a> {
     pub(crate) fn write_binder(&mut self, binder: Option<&SpIBinder>) -> Result<()> {
         unsafe {
-            // Safety: `Parcel` always contains a valid pointer to an
+            // Safety: `BorrowedParcel` always contains a valid pointer to an
             // `AParcel`. `AsNative` for `Option<SpIBinder`> will either return
             // null or a valid pointer to an `AIBinder`, both of which are
             // valid, safe inputs to `AParcel_writeStrongBinder`.
@@ -534,7 +685,7 @@
     pub(crate) fn read_binder(&self) -> Result<Option<SpIBinder>> {
         let mut binder = ptr::null_mut();
         let status = unsafe {
-            // Safety: `Parcel` always contains a valid pointer to an
+            // Safety: `BorrowedParcel` always contains a valid pointer to an
             // `AParcel`. We pass a valid, mutable out pointer to the `binder`
             // parameter. After this call, `binder` will be either null or a
             // valid pointer to an `AIBinder` owned by the caller.
@@ -554,25 +705,11 @@
 impl Drop for Parcel {
     fn drop(&mut self) {
         // Run the C++ Parcel complete object destructor
-        if let Self::Owned(ptr) = *self {
-            unsafe {
-                // Safety: `Parcel` always contains a valid pointer to an
-                // `AParcel`. If we own the parcel, we can safely delete it
-                // here.
-                sys::AParcel_delete(ptr)
-            }
-        }
-    }
-}
-
-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
+            // Safety: `Parcel` always contains a valid pointer to an
             // `AParcel`. Since we own the parcel, we can safely delete it
             // here.
-            sys::AParcel_delete(self.ptr)
+            sys::AParcel_delete(self.ptr.as_ptr())
         }
     }
 }
@@ -584,9 +721,9 @@
     }
 }
 
-impl fmt::Debug for OwnedParcel {
+impl<'a> fmt::Debug for BorrowedParcel<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("OwnedParcel")
+        f.debug_struct("BorrowedParcel")
             .finish()
     }
 }
@@ -608,7 +745,7 @@
     assert_eq!(parcel.read::<Option<String>>(), Ok(None));
     assert_eq!(parcel.read::<String>(), Err(StatusCode::UNEXPECTED_NULL));
 
-    assert_eq!(parcel.read_binder().err(), Some(StatusCode::BAD_TYPE));
+    assert_eq!(parcel.borrowed_ref().read_binder().err(), Some(StatusCode::BAD_TYPE));
 
     parcel.write(&1i32).unwrap();
 
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index 8bcc5d0..b0dea94 100644
--- a/libs/binder/rust/src/parcel/file_descriptor.rs
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -15,7 +15,7 @@
  */
 
 use super::{
-    Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray,
+    Deserialize, DeserializeArray, DeserializeOption, BorrowedParcel, Serialize, SerializeArray,
     SerializeOption,
 };
 use crate::binder::AsNative;
@@ -61,7 +61,7 @@
 }
 
 impl Serialize for ParcelFileDescriptor {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         let fd = self.0.as_raw_fd();
         let status = unsafe {
             // Safety: `Parcel` always contains a valid pointer to an
@@ -78,7 +78,7 @@
 impl SerializeArray for ParcelFileDescriptor {}
 
 impl SerializeOption for ParcelFileDescriptor {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         if let Some(f) = this {
             f.serialize(parcel)
         } else {
@@ -95,7 +95,7 @@
 }
 
 impl DeserializeOption for ParcelFileDescriptor {
-    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+    fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
         let mut fd = -1i32;
         unsafe {
             // Safety: `Parcel` always contains a valid pointer to an
@@ -125,7 +125,7 @@
 }
 
 impl Deserialize for ParcelFileDescriptor {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         Deserialize::deserialize(parcel)
             .transpose()
             .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index db9d8b0..9007cba 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -16,14 +16,14 @@
 
 use crate::binder::{AsNative, FromIBinder, Stability, Strong};
 use crate::error::{status_result, status_t, Result, Status, StatusCode};
-use crate::parcel::Parcel;
+use crate::parcel::BorrowedParcel;
 use crate::proxy::SpIBinder;
 use crate::sys;
 
 use std::convert::{TryFrom, TryInto};
 use std::ffi::c_void;
 use std::os::raw::{c_char, c_ulong};
-use std::mem::{self, MaybeUninit};
+use std::mem::{self, MaybeUninit, ManuallyDrop};
 use std::ptr;
 use std::slice;
 
@@ -39,7 +39,7 @@
     /// `Serialize::serialize` and its variants are generally
     /// preferred over this function, since the former also
     /// prepend a header.
-    fn write_to_parcel(&self, parcel: &mut Parcel) -> Result<()>;
+    fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>;
 
     /// Internal deserialization function for parcelables.
     ///
@@ -47,26 +47,26 @@
     /// `Deserialize::deserialize` and its variants are generally
     /// preferred over this function, since the former also
     /// parse the additional header.
-    fn read_from_parcel(&mut self, parcel: &Parcel) -> Result<()>;
+    fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()>;
 }
 
 /// A struct whose instances can be written to a [`Parcel`].
 // Might be able to hook this up as a serde backend in the future?
 pub trait Serialize {
     /// Serialize this instance into the given [`Parcel`].
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()>;
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>;
 }
 
 /// A struct whose instances can be restored from a [`Parcel`].
 // Might be able to hook this up as a serde backend in the future?
 pub trait Deserialize: Sized {
     /// Deserialize an instance from the given [`Parcel`].
-    fn deserialize(parcel: &Parcel) -> Result<Self>;
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self>;
 
     /// Deserialize an instance from the given [`Parcel`] onto the
     /// current object. This operation will overwrite the old value
     /// partially or completely, depending on how much data is available.
-    fn deserialize_from(&mut self, parcel: &Parcel) -> Result<()> {
+    fn deserialize_from(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
         *self = Self::deserialize(parcel)?;
         Ok(())
     }
@@ -80,8 +80,8 @@
 // We want the default implementation for most types, but an override for
 // a few special ones like `readByteArray` for `u8`.
 pub trait SerializeArray: Serialize + Sized {
-    /// Serialize an array of this type into the given [`Parcel`].
-    fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+    /// Serialize an array of this type into the given parcel.
+    fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         let res = unsafe {
             // Safety: Safe FFI, slice will always be a safe pointer to pass.
             sys::AParcel_writeParcelableArray(
@@ -111,7 +111,7 @@
 
     let slice: &[T] = slice::from_raw_parts(array.cast(), index+1);
 
-    let mut parcel = match Parcel::borrowed(parcel) {
+    let mut parcel = match BorrowedParcel::from_raw(parcel) {
         None => return StatusCode::UNEXPECTED_NULL as status_t,
         Some(p) => p,
     };
@@ -126,8 +126,8 @@
 /// Defaults to calling Deserialize::deserialize() manually for every element,
 /// but can be overridden for custom implementations like `readByteArray`.
 pub trait DeserializeArray: Deserialize {
-    /// Deserialize an array of type from the given [`Parcel`].
-    fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> {
+    /// Deserialize an array of type from the given parcel.
+    fn deserialize_array(parcel: &BorrowedParcel<'_>) -> Result<Option<Vec<Self>>> {
         let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
         let res = unsafe {
             // Safety: Safe FFI, vec is the correct opaque type expected by
@@ -173,7 +173,7 @@
         None => return StatusCode::BAD_INDEX as status_t,
     };
 
-    let parcel = match Parcel::borrowed(parcel as *mut _) {
+    let parcel = match BorrowedParcel::from_raw(parcel as *mut _) {
         None => return StatusCode::UNEXPECTED_NULL as status_t,
         Some(p) => p,
     };
@@ -205,8 +205,8 @@
 // We also use it to provide a default implementation for AIDL-generated
 // parcelables.
 pub trait SerializeOption: Serialize {
-    /// Serialize an Option of this type into the given [`Parcel`].
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    /// Serialize an Option of this type into the given parcel.
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         if let Some(inner) = this {
             parcel.write(&NON_NULL_PARCELABLE_FLAG)?;
             parcel.write(inner)
@@ -218,8 +218,8 @@
 
 /// Helper trait for types that can be nullable when deserialized.
 pub trait DeserializeOption: Deserialize {
-    /// Deserialize an Option of this type from the given [`Parcel`].
-    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+    /// Deserialize an Option of this type from the given parcel.
+    fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
         let null: i32 = parcel.read()?;
         if null == NULL_PARCELABLE_FLAG {
             Ok(None)
@@ -228,10 +228,10 @@
         }
     }
 
-    /// Deserialize an Option of this type from the given [`Parcel`] onto the
+    /// Deserialize an Option of this type from the given parcel onto the
     /// current object. This operation will overwrite the current value
     /// partially or completely, depending on how much data is available.
-    fn deserialize_option_from(this: &mut Option<Self>, parcel: &Parcel) -> Result<()> {
+    fn deserialize_option_from(this: &mut Option<Self>, parcel: &BorrowedParcel<'_>) -> Result<()> {
         *this = Self::deserialize_option(parcel)?;
         Ok(())
     }
@@ -297,10 +297,23 @@
     };
 }
 
+/// Safety: All elements in the vector must be properly initialized.
+unsafe fn vec_assume_init<T>(vec: Vec<MaybeUninit<T>>) -> Vec<T> {
+    // We can convert from Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T>
+    // has the same alignment and size as T, so the pointer to the vector
+    // allocation will be compatible.
+    let mut vec = ManuallyDrop::new(vec);
+    Vec::from_raw_parts(
+        vec.as_mut_ptr().cast(),
+        vec.len(),
+        vec.capacity(),
+    )
+}
+
 macro_rules! impl_parcelable {
     {Serialize, $ty:ty, $write_fn:path} => {
         impl Serialize for $ty {
-            fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+            fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
                 unsafe {
                     // Safety: `Parcel` always contains a valid pointer to an
                     // `AParcel`, and any `$ty` literal value is safe to pass to
@@ -313,7 +326,7 @@
 
     {Deserialize, $ty:ty, $read_fn:path} => {
         impl Deserialize for $ty {
-            fn deserialize(parcel: &Parcel) -> Result<Self> {
+            fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
                 let mut val = Self::default();
                 unsafe {
                     // Safety: `Parcel` always contains a valid pointer to an
@@ -329,7 +342,7 @@
 
     {SerializeArray, $ty:ty, $write_array_fn:path} => {
         impl SerializeArray for $ty {
-            fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+            fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> {
                 let status = unsafe {
                     // Safety: `Parcel` always contains a valid pointer to an
                     // `AParcel`. If the slice is > 0 length, `slice.as_ptr()`
@@ -353,7 +366,7 @@
 
     {DeserializeArray, $ty:ty, $read_array_fn:path} => {
         impl DeserializeArray for $ty {
-            fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> {
+            fn deserialize_array(parcel: &BorrowedParcel<'_>) -> Result<Option<Vec<Self>>> {
                 let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
                 let status = unsafe {
                     // Safety: `Parcel` always contains a valid pointer to an
@@ -371,11 +384,8 @@
                     // Safety: We are assuming that the NDK correctly
                     // initialized every element of the vector by now, so we
                     // know that all the MaybeUninits are now properly
-                    // initialized. We can transmute from Vec<MaybeUninit<T>> to
-                    // Vec<T> because MaybeUninit<T> has the same alignment and
-                    // size as T, so the pointer to the vector allocation will
-                    // be compatible.
-                    mem::transmute(vec)
+                    // initialized.
+                    vec.map(|vec| vec_assume_init(vec))
                 };
                 Ok(vec)
             }
@@ -443,19 +453,19 @@
 impl DeserializeArray for bool {}
 
 impl Serialize for u8 {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         (*self as i8).serialize(parcel)
     }
 }
 
 impl Deserialize for u8 {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         i8::deserialize(parcel).map(|v| v as u8)
     }
 }
 
 impl SerializeArray for u8 {
-    fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+    fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         let status = unsafe {
             // Safety: `Parcel` always contains a valid pointer to an
             // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` will be a
@@ -474,19 +484,19 @@
 }
 
 impl Serialize for i16 {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         (*self as u16).serialize(parcel)
     }
 }
 
 impl Deserialize for i16 {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         u16::deserialize(parcel).map(|v| v as i16)
     }
 }
 
 impl SerializeArray for i16 {
-    fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+    fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         let status = unsafe {
             // Safety: `Parcel` always contains a valid pointer to an
             // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` will be a
@@ -505,7 +515,7 @@
 }
 
 impl SerializeOption for str {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         match this {
             None => unsafe {
                 // Safety: `Parcel` always contains a valid pointer to an
@@ -541,7 +551,7 @@
 }
 
 impl Serialize for str {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         Some(self).serialize(parcel)
     }
 }
@@ -549,7 +559,7 @@
 impl SerializeArray for &str {}
 
 impl Serialize for String {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         Some(self.as_str()).serialize(parcel)
     }
 }
@@ -557,13 +567,13 @@
 impl SerializeArray for String {}
 
 impl SerializeOption for String {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeOption::serialize_option(this.map(String::as_str), parcel)
     }
 }
 
 impl Deserialize for Option<String> {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         let mut vec: Option<Vec<u8>> = None;
         let status = unsafe {
             // Safety: `Parcel` always contains a valid pointer to an `AParcel`.
@@ -591,7 +601,7 @@
 impl DeserializeArray for Option<String> {}
 
 impl Deserialize for String {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         Deserialize::deserialize(parcel)
             .transpose()
             .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
@@ -601,19 +611,19 @@
 impl DeserializeArray for String {}
 
 impl<T: SerializeArray> Serialize for [T] {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeArray::serialize_array(self, parcel)
     }
 }
 
 impl<T: SerializeArray> Serialize for Vec<T> {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeArray::serialize_array(&self[..], parcel)
     }
 }
 
 impl<T: SerializeArray> SerializeOption for [T] {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         if let Some(v) = this {
             SerializeArray::serialize_array(v, parcel)
         } else {
@@ -623,13 +633,13 @@
 }
 
 impl<T: SerializeArray> SerializeOption for Vec<T> {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeOption::serialize_option(this.map(Vec::as_slice), parcel)
     }
 }
 
 impl<T: DeserializeArray> Deserialize for Vec<T> {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         DeserializeArray::deserialize_array(parcel)
             .transpose()
             .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
@@ -637,25 +647,25 @@
 }
 
 impl<T: DeserializeArray> DeserializeOption for Vec<T> {
-    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+    fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
         DeserializeArray::deserialize_array(parcel)
     }
 }
 
 impl Serialize for Stability {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         i32::from(*self).serialize(parcel)
     }
 }
 
 impl Deserialize for Stability {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         i32::deserialize(parcel).and_then(Stability::try_from)
     }
 }
 
 impl Serialize for Status {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         unsafe {
             // Safety: `Parcel` always contains a valid pointer to an `AParcel`
             // and `Status` always contains a valid pointer to an `AStatus`, so
@@ -670,7 +680,7 @@
 }
 
 impl Deserialize for Status {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         let mut status_ptr = ptr::null_mut();
         let ret_status = unsafe {
             // Safety: `Parcel` always contains a valid pointer to an
@@ -691,13 +701,13 @@
 }
 
 impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         Serialize::serialize(&**self, parcel)
     }
 }
 
 impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeOption::serialize_option(this.map(|b| &**b), parcel)
     }
 }
@@ -705,14 +715,14 @@
 impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {}
 
 impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         let ibinder: SpIBinder = parcel.read()?;
         FromIBinder::try_from(ibinder)
     }
 }
 
 impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> {
-    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+    fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
         let ibinder: Option<SpIBinder> = parcel.read()?;
         ibinder.map(FromIBinder::try_from).transpose()
     }
@@ -722,29 +732,29 @@
 
 // We need these to support Option<&T> for all T
 impl<T: Serialize + ?Sized> Serialize for &T {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         Serialize::serialize(*self, parcel)
     }
 }
 
 impl<T: SerializeOption + ?Sized> SerializeOption for &T {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeOption::serialize_option(this.copied(), parcel)
     }
 }
 
 impl<T: SerializeOption> Serialize for Option<T> {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeOption::serialize_option(self.as_ref(), parcel)
     }
 }
 
 impl<T: DeserializeOption> Deserialize for Option<T> {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         DeserializeOption::deserialize_option(parcel)
     }
 
-    fn deserialize_from(&mut self, parcel: &Parcel) -> Result<()> {
+    fn deserialize_from(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
         DeserializeOption::deserialize_option_from(self, parcel)
     }
 }
@@ -762,7 +772,7 @@
         impl $crate::parcel::Serialize for $parcelable {
             fn serialize(
                 &self,
-                parcel: &mut $crate::parcel::Parcel,
+                parcel: &mut $crate::parcel::BorrowedParcel<'_>,
             ) -> $crate::Result<()> {
                 <Self as $crate::parcel::SerializeOption>::serialize_option(
                     Some(self),
@@ -776,7 +786,7 @@
         impl $crate::parcel::SerializeOption for $parcelable {
             fn serialize_option(
                 this: Option<&Self>,
-                parcel: &mut $crate::parcel::Parcel,
+                parcel: &mut $crate::parcel::BorrowedParcel<'_>,
             ) -> $crate::Result<()> {
                 if let Some(this) = this {
                     use $crate::parcel::Parcelable;
@@ -796,13 +806,12 @@
 /// `Deserialize`, `DeserializeArray` and `DeserializeOption` for
 /// structured parcelables. The target type must implement the
 /// `Parcelable` trait.
-/// ```
 #[macro_export]
 macro_rules! impl_deserialize_for_parcelable {
     ($parcelable:ident) => {
         impl $crate::parcel::Deserialize for $parcelable {
             fn deserialize(
-                parcel: &$crate::parcel::Parcel,
+                parcel: &$crate::parcel::BorrowedParcel<'_>,
             ) -> $crate::Result<Self> {
                 $crate::parcel::DeserializeOption::deserialize_option(parcel)
                     .transpose()
@@ -810,7 +819,7 @@
             }
             fn deserialize_from(
                 &mut self,
-                parcel: &$crate::parcel::Parcel,
+                parcel: &$crate::parcel::BorrowedParcel<'_>,
             ) -> $crate::Result<()> {
                 let status: i32 = parcel.read()?;
                 if status == $crate::parcel::NULL_PARCELABLE_FLAG {
@@ -826,7 +835,7 @@
 
         impl $crate::parcel::DeserializeOption for $parcelable {
             fn deserialize_option(
-                parcel: &$crate::parcel::Parcel,
+                parcel: &$crate::parcel::BorrowedParcel<'_>,
             ) -> $crate::Result<Option<Self>> {
                 let mut result = None;
                 Self::deserialize_option_from(&mut result, parcel)?;
@@ -834,7 +843,7 @@
             }
             fn deserialize_option_from(
                 this: &mut Option<Self>,
-                parcel: &$crate::parcel::Parcel,
+                parcel: &$crate::parcel::BorrowedParcel<'_>,
             ) -> $crate::Result<()> {
                 let status: i32 = parcel.read()?;
                 if status == $crate::parcel::NULL_PARCELABLE_FLAG {
@@ -851,326 +860,332 @@
 }
 
 impl<T: Serialize> Serialize for Box<T> {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         Serialize::serialize(&**self, parcel)
     }
 }
 
 impl<T: Deserialize> Deserialize for Box<T> {
-    fn deserialize(parcel: &Parcel) -> Result<Self> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
         Deserialize::deserialize(parcel).map(Box::new)
     }
 }
 
 impl<T: SerializeOption> SerializeOption for Box<T> {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         SerializeOption::serialize_option(this.map(|inner| &**inner), parcel)
     }
 }
 
 impl<T: DeserializeOption> DeserializeOption for Box<T> {
-    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+    fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
         DeserializeOption::deserialize_option(parcel).map(|t| t.map(Box::new))
     }
 }
 
-#[test]
-fn test_custom_parcelable() {
-    struct Custom(u32, bool, String, Vec<String>);
+#[cfg(test)]
+mod tests {
+    use crate::Parcel;
+    use super::*;
 
-    impl Serialize for Custom {
-        fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
-            self.0.serialize(parcel)?;
-            self.1.serialize(parcel)?;
-            self.2.serialize(parcel)?;
-            self.3.serialize(parcel)
+    #[test]
+    fn test_custom_parcelable() {
+        struct Custom(u32, bool, String, Vec<String>);
+
+        impl Serialize for Custom {
+            fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
+                self.0.serialize(parcel)?;
+                self.1.serialize(parcel)?;
+                self.2.serialize(parcel)?;
+                self.3.serialize(parcel)
+            }
         }
-    }
 
-    impl Deserialize for Custom {
-        fn deserialize(parcel: &Parcel) -> Result<Self> {
-            Ok(Custom(
-                parcel.read()?,
-                parcel.read()?,
-                parcel.read()?,
-                parcel.read::<Option<Vec<String>>>()?.unwrap(),
-            ))
+        impl Deserialize for Custom {
+            fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
+                Ok(Custom(
+                        parcel.read()?,
+                        parcel.read()?,
+                        parcel.read()?,
+                        parcel.read::<Option<Vec<String>>>()?.unwrap(),
+                        ))
+            }
         }
+
+        let string8 = "Custom Parcelable".to_string();
+
+        let s1 = "str1".to_string();
+        let s2 = "str2".to_string();
+        let s3 = "str3".to_string();
+
+        let strs = vec![s1, s2, s3];
+
+        let custom = Custom(123_456_789, true, string8, strs);
+
+        let mut parcel = Parcel::new();
+        let start = parcel.get_data_position();
+
+        assert!(custom.serialize(&mut parcel.borrowed()).is_ok());
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let custom2 = Custom::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(custom2.0, 123_456_789);
+        assert!(custom2.1);
+        assert_eq!(custom2.2, custom.2);
+        assert_eq!(custom2.3, custom.3);
     }
 
-    let string8 = "Custom Parcelable".to_string();
+    #[test]
+    #[allow(clippy::excessive_precision)]
+    fn test_slice_parcelables() {
+        let bools = [true, false, false, true];
 
-    let s1 = "str1".to_string();
-    let s2 = "str2".to_string();
-    let s3 = "str3".to_string();
+        let mut parcel = Parcel::new();
+        let start = parcel.get_data_position();
 
-    let strs = vec![s1, s2, s3];
+        assert!(bools.serialize(&mut parcel.borrowed()).is_ok());
 
-    let custom = Custom(123_456_789, true, string8, strs);
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
 
-    let mut parcel = Parcel::new();
-    let start = parcel.get_data_position();
+        assert_eq!(parcel.read::<u32>().unwrap(), 4);
+        assert_eq!(parcel.read::<u32>().unwrap(), 1);
+        assert_eq!(parcel.read::<u32>().unwrap(), 0);
+        assert_eq!(parcel.read::<u32>().unwrap(), 0);
+        assert_eq!(parcel.read::<u32>().unwrap(), 1);
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
 
-    assert!(custom.serialize(&mut parcel).is_ok());
+        let vec = Vec::<bool>::deserialize(parcel.borrowed_ref()).unwrap();
 
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
+        assert_eq!(vec, [true, false, false, true]);
+
+        let u8s = [101u8, 255, 42, 117];
+
+        let mut parcel = Parcel::new();
+        let start = parcel.get_data_position();
+
+        assert!(parcel.write(&u8s[..]).is_ok());
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+        assert_eq!(parcel.read::<u32>().unwrap(), 0x752aff65); // bytes
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<u8>::deserialize(parcel.borrowed_ref()).unwrap();
+        assert_eq!(vec, [101, 255, 42, 117]);
+
+        let i8s = [-128i8, 127, 42, -117];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        assert!(parcel.write(&i8s[..]).is_ok());
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+        assert_eq!(parcel.read::<u32>().unwrap(), 0x8b2a7f80); // bytes
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<u8>::deserialize(parcel.borrowed_ref()).unwrap();
+        assert_eq!(vec, [-128i8 as u8, 127, 42, -117i8 as u8]);
+
+        let u16s = [u16::max_value(), 12_345, 42, 117];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(u16s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+        assert_eq!(parcel.read::<u32>().unwrap(), 0xffff); // u16::max_value()
+        assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345
+        assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+        assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<u16>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(vec, [u16::max_value(), 12_345, 42, 117]);
+
+        let i16s = [i16::max_value(), i16::min_value(), 42, -117];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(i16s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+        assert_eq!(parcel.read::<u32>().unwrap(), 0x7fff); // i16::max_value()
+        assert_eq!(parcel.read::<u32>().unwrap(), 0x8000); // i16::min_value()
+        assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+        assert_eq!(parcel.read::<u32>().unwrap(), 0xff8b); // -117
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<i16>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(vec, [i16::max_value(), i16::min_value(), 42, -117]);
+
+        let u32s = [u32::max_value(), 12_345, 42, 117];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(u32s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+        assert_eq!(parcel.read::<u32>().unwrap(), 0xffffffff); // u32::max_value()
+        assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345
+        assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+        assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<u32>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(vec, [u32::max_value(), 12_345, 42, 117]);
+
+        let i32s = [i32::max_value(), i32::min_value(), 42, -117];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(i32s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+        assert_eq!(parcel.read::<u32>().unwrap(), 0x7fffffff); // i32::max_value()
+        assert_eq!(parcel.read::<u32>().unwrap(), 0x80000000); // i32::min_value()
+        assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+        assert_eq!(parcel.read::<u32>().unwrap(), 0xffffff8b); // -117
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<i32>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(vec, [i32::max_value(), i32::min_value(), 42, -117]);
+
+        let u64s = [u64::max_value(), 12_345, 42, 117];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(u64s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<u64>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(vec, [u64::max_value(), 12_345, 42, 117]);
+
+        let i64s = [i64::max_value(), i64::min_value(), 42, -117];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(i64s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<i64>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(vec, [i64::max_value(), i64::min_value(), 42, -117]);
+
+        let f32s = [
+            std::f32::NAN,
+            std::f32::INFINITY,
+            1.23456789,
+            std::f32::EPSILON,
+        ];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(f32s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<f32>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        // NAN != NAN so we can't use it in the assert_eq:
+        assert!(vec[0].is_nan());
+        assert_eq!(vec[1..], f32s[1..]);
+
+        let f64s = [
+            std::f64::NAN,
+            std::f64::INFINITY,
+            1.234567890123456789,
+            std::f64::EPSILON,
+        ];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(f64s.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<f64>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        // NAN != NAN so we can't use it in the assert_eq:
+        assert!(vec[0].is_nan());
+        assert_eq!(vec[1..], f64s[1..]);
+
+        let s1 = "Hello, Binder!";
+        let s2 = "This is a utf8 string.";
+        let s3 = "Some more text here.";
+        let s4 = "Embedded nulls \0 \0";
+
+        let strs = [s1, s2, s3, s4];
+
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+        assert!(strs.serialize(&mut parcel.borrowed()).is_ok());
+        unsafe {
+            assert!(parcel.set_data_position(start).is_ok());
+        }
+
+        let vec = Vec::<String>::deserialize(parcel.borrowed_ref()).unwrap();
+
+        assert_eq!(vec, strs);
     }
-
-    let custom2 = Custom::deserialize(&parcel).unwrap();
-
-    assert_eq!(custom2.0, 123_456_789);
-    assert!(custom2.1);
-    assert_eq!(custom2.2, custom.2);
-    assert_eq!(custom2.3, custom.3);
-}
-
-#[test]
-#[allow(clippy::excessive_precision)]
-fn test_slice_parcelables() {
-    let bools = [true, false, false, true];
-
-    let mut parcel = Parcel::new();
-    let start = parcel.get_data_position();
-
-    assert!(bools.serialize(&mut parcel).is_ok());
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert_eq!(parcel.read::<u32>().unwrap(), 4);
-    assert_eq!(parcel.read::<u32>().unwrap(), 1);
-    assert_eq!(parcel.read::<u32>().unwrap(), 0);
-    assert_eq!(parcel.read::<u32>().unwrap(), 0);
-    assert_eq!(parcel.read::<u32>().unwrap(), 1);
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<bool>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, [true, false, false, true]);
-
-    let u8s = [101u8, 255, 42, 117];
-
-    let mut parcel = Parcel::new();
-    let start = parcel.get_data_position();
-
-    assert!(parcel.write(&u8s[..]).is_ok());
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
-    assert_eq!(parcel.read::<u32>().unwrap(), 0x752aff65); // bytes
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<u8>::deserialize(&parcel).unwrap();
-    assert_eq!(vec, [101, 255, 42, 117]);
-
-    let i8s = [-128i8, 127, 42, -117];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert!(parcel.write(&i8s[..]).is_ok());
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
-    assert_eq!(parcel.read::<u32>().unwrap(), 0x8b2a7f80); // bytes
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<u8>::deserialize(&parcel).unwrap();
-    assert_eq!(vec, [-128i8 as u8, 127, 42, -117i8 as u8]);
-
-    let u16s = [u16::max_value(), 12_345, 42, 117];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(u16s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
-    assert_eq!(parcel.read::<u32>().unwrap(), 0xffff); // u16::max_value()
-    assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345
-    assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
-    assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<u16>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, [u16::max_value(), 12_345, 42, 117]);
-
-    let i16s = [i16::max_value(), i16::min_value(), 42, -117];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(i16s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
-    assert_eq!(parcel.read::<u32>().unwrap(), 0x7fff); // i16::max_value()
-    assert_eq!(parcel.read::<u32>().unwrap(), 0x8000); // i16::min_value()
-    assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
-    assert_eq!(parcel.read::<u32>().unwrap(), 0xff8b); // -117
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<i16>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, [i16::max_value(), i16::min_value(), 42, -117]);
-
-    let u32s = [u32::max_value(), 12_345, 42, 117];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(u32s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
-    assert_eq!(parcel.read::<u32>().unwrap(), 0xffffffff); // u32::max_value()
-    assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345
-    assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
-    assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<u32>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, [u32::max_value(), 12_345, 42, 117]);
-
-    let i32s = [i32::max_value(), i32::min_value(), 42, -117];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(i32s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
-    assert_eq!(parcel.read::<u32>().unwrap(), 0x7fffffff); // i32::max_value()
-    assert_eq!(parcel.read::<u32>().unwrap(), 0x80000000); // i32::min_value()
-    assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
-    assert_eq!(parcel.read::<u32>().unwrap(), 0xffffff8b); // -117
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<i32>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, [i32::max_value(), i32::min_value(), 42, -117]);
-
-    let u64s = [u64::max_value(), 12_345, 42, 117];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(u64s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<u64>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, [u64::max_value(), 12_345, 42, 117]);
-
-    let i64s = [i64::max_value(), i64::min_value(), 42, -117];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(i64s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<i64>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, [i64::max_value(), i64::min_value(), 42, -117]);
-
-    let f32s = [
-        std::f32::NAN,
-        std::f32::INFINITY,
-        1.23456789,
-        std::f32::EPSILON,
-    ];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(f32s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<f32>::deserialize(&parcel).unwrap();
-
-    // NAN != NAN so we can't use it in the assert_eq:
-    assert!(vec[0].is_nan());
-    assert_eq!(vec[1..], f32s[1..]);
-
-    let f64s = [
-        std::f64::NAN,
-        std::f64::INFINITY,
-        1.234567890123456789,
-        std::f64::EPSILON,
-    ];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(f64s.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<f64>::deserialize(&parcel).unwrap();
-
-    // NAN != NAN so we can't use it in the assert_eq:
-    assert!(vec[0].is_nan());
-    assert_eq!(vec[1..], f64s[1..]);
-
-    let s1 = "Hello, Binder!";
-    let s2 = "This is a utf8 string.";
-    let s3 = "Some more text here.";
-    let s4 = "Embedded nulls \0 \0";
-
-    let strs = [s1, s2, s3, s4];
-
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-    assert!(strs.serialize(&mut parcel).is_ok());
-    unsafe {
-        assert!(parcel.set_data_position(start).is_ok());
-    }
-
-    let vec = Vec::<String>::deserialize(&parcel).unwrap();
-
-    assert_eq!(vec, strs);
 }
diff --git a/libs/binder/rust/src/parcel/parcelable_holder.rs b/libs/binder/rust/src/parcel/parcelable_holder.rs
index bccfd2d..b4282b2 100644
--- a/libs/binder/rust/src/parcel/parcelable_holder.rs
+++ b/libs/binder/rust/src/parcel/parcelable_holder.rs
@@ -16,7 +16,7 @@
 
 use crate::binder::Stability;
 use crate::error::{Result, StatusCode};
-use crate::parcel::{OwnedParcel, Parcel, Parcelable};
+use crate::parcel::{Parcel, BorrowedParcel, Parcelable};
 use crate::{impl_deserialize_for_parcelable, impl_serialize_for_parcelable};
 
 use downcast_rs::{impl_downcast, DowncastSync};
@@ -50,7 +50,7 @@
         parcelable: Arc<dyn AnyParcelable>,
         name: String,
     },
-    Parcel(OwnedParcel),
+    Parcel(Parcel),
 }
 
 impl Default for ParcelableHolderData {
@@ -148,7 +148,6 @@
                 }
             }
             ParcelableHolderData::Parcel(ref mut parcel) => {
-                let parcel = parcel.borrowed();
                 unsafe {
                     // Safety: 0 should always be a valid position.
                     parcel.set_data_position(0)?;
@@ -160,7 +159,7 @@
                 }
 
                 let mut parcelable = T::default();
-                parcelable.read_from_parcel(&parcel)?;
+                parcelable.read_from_parcel(parcel.borrowed_ref())?;
 
                 let parcelable = Arc::new(parcelable);
                 let result = Arc::clone(&parcelable);
@@ -181,7 +180,7 @@
 impl_deserialize_for_parcelable!(ParcelableHolder);
 
 impl Parcelable for ParcelableHolder {
-    fn write_to_parcel(&self, parcel: &mut Parcel) -> Result<()> {
+    fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         parcel.write(&self.stability)?;
 
         let mut data = self.data.lock().unwrap();
@@ -214,14 +213,13 @@
                 Ok(())
             }
             ParcelableHolderData::Parcel(ref mut p) => {
-                let p = p.borrowed();
                 parcel.write(&p.get_data_size())?;
-                parcel.append_all_from(&p)
+                parcel.append_all_from(&*p)
             }
         }
     }
 
-    fn read_from_parcel(&mut self, parcel: &Parcel) -> Result<()> {
+    fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
         self.stability = parcel.read()?;
 
         let data_size: i32 = parcel.read()?;
@@ -242,10 +240,8 @@
             .checked_add(data_size)
             .ok_or(StatusCode::BAD_VALUE)?;
 
-        let mut new_parcel = OwnedParcel::new();
-        new_parcel
-            .borrowed()
-            .append_from(parcel, data_start, data_size)?;
+        let mut new_parcel = Parcel::new();
+        new_parcel.append_from(parcel, data_start, data_size)?;
         *self.data.get_mut().unwrap() = ParcelableHolderData::Parcel(new_parcel);
 
         unsafe {
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index a8d0c33..83553d7 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -22,8 +22,7 @@
 };
 use crate::error::{status_result, Result, StatusCode};
 use crate::parcel::{
-    Deserialize, DeserializeArray, DeserializeOption, OwnedParcel, Parcel, Serialize, SerializeArray,
-    SerializeOption,
+    Parcel, BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray, SerializeOption,
 };
 use crate::sys;
 
@@ -235,7 +234,7 @@
 }
 
 impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
-    fn prepare_transact(&self) -> Result<OwnedParcel> {
+    fn prepare_transact(&self) -> Result<Parcel> {
         let mut input = ptr::null_mut();
         let status = unsafe {
             // Safety: `SpIBinder` guarantees that `self` always contains a
@@ -255,16 +254,16 @@
             // Safety: At this point, `input` is either a valid, owned `AParcel`
             // pointer, or null. `OwnedParcel::from_raw` safely handles both cases,
             // taking ownership of the parcel.
-            OwnedParcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL)
+            Parcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL)
         }
     }
 
     fn submit_transact(
         &self,
         code: TransactionCode,
-        data: OwnedParcel,
+        data: Parcel,
         flags: TransactionFlags,
-    ) -> Result<OwnedParcel> {
+    ) -> Result<Parcel> {
         let mut reply = ptr::null_mut();
         let status = unsafe {
             // Safety: `SpIBinder` guarantees that `self` always contains a
@@ -299,7 +298,7 @@
             // construct a `Parcel` out of it. `AIBinder_transact` passes
             // ownership of the `reply` parcel to Rust, so we need to
             // construct an owned variant.
-            OwnedParcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL)
+            Parcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL)
         }
     }
 
@@ -415,13 +414,13 @@
 }
 
 impl Serialize for SpIBinder {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         parcel.write_binder(Some(self))
     }
 }
 
 impl SerializeOption for SpIBinder {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         parcel.write_binder(this)
     }
 }
@@ -429,7 +428,7 @@
 impl SerializeArray for SpIBinder {}
 
 impl Deserialize for SpIBinder {
-    fn deserialize(parcel: &Parcel) -> Result<SpIBinder> {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<SpIBinder> {
         parcel
             .read_binder()
             .transpose()
@@ -438,7 +437,7 @@
 }
 
 impl DeserializeOption for SpIBinder {
-    fn deserialize_option(parcel: &Parcel) -> Result<Option<SpIBinder>> {
+    fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<SpIBinder>> {
         parcel.read_binder()
     }
 }
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index ebfe879..1fd2ead 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -17,7 +17,7 @@
 //! Rust Binder crate integration tests
 
 use binder::declare_binder_interface;
-use binder::parcel::{Parcel, OwnedParcel};
+use binder::parcel::BorrowedParcel;
 use binder::{
     Binder, BinderFeatures, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode,
     FIRST_CALL_TRANSACTION,
@@ -179,8 +179,8 @@
 fn on_transact(
     service: &dyn ITest,
     code: TransactionCode,
-    _data: &Parcel,
-    reply: &mut Parcel,
+    _data: &BorrowedParcel<'_>,
+    reply: &mut BorrowedParcel<'_>,
 ) -> binder::Result<()> {
     match code.try_into()? {
         TestTransactionCode::Test => reply.write(&service.test()?),
@@ -218,24 +218,24 @@
     fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
         let binder = self.binder.clone();
         P::spawn(
-            move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
-            |reply| async move { reply?.into_parcel().read() }
+            move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())),
+            |reply| async move { reply?.read() }
         )
     }
 
     fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
         let binder = self.binder.clone();
         P::spawn(
-            move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
-            |reply| async move { reply?.into_parcel().read() }
+            move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())),
+            |reply| async move { reply?.read() }
         )
     }
 
     fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
         let binder = self.binder.clone();
         P::spawn(
-            move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
-            |reply| async move { reply?.into_parcel().read() }
+            move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())),
+            |reply| async move { reply?.read() }
         )
     }
 }
@@ -284,8 +284,8 @@
 fn on_transact_same_descriptor(
     _service: &dyn ITestSameDescriptor,
     _code: TransactionCode,
-    _data: &Parcel,
-    _reply: &mut Parcel,
+    _data: &BorrowedParcel<'_>,
+    _reply: &mut BorrowedParcel<'_>,
 ) -> binder::Result<()> {
     Ok(())
 }
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
index 66ba846..1fc761e 100644
--- a/libs/binder/rust/tests/serialization.rs
+++ b/libs/binder/rust/tests/serialization.rs
@@ -20,7 +20,7 @@
 use binder::declare_binder_interface;
 use binder::parcel::ParcelFileDescriptor;
 use binder::{
-    Binder, BinderFeatures, ExceptionCode, Interface, Parcel, Result, SpIBinder, Status,
+    Binder, BinderFeatures, BorrowedParcel, ExceptionCode, Interface, Result, SpIBinder, Status,
     StatusCode, TransactionCode,
 };
 
@@ -111,8 +111,8 @@
 fn on_transact(
     _service: &dyn ReadParcelTest,
     code: TransactionCode,
-    parcel: &Parcel,
-    reply: &mut Parcel,
+    parcel: &BorrowedParcel<'_>,
+    reply: &mut BorrowedParcel<'_>,
 ) -> Result<()> {
     match code {
         bindings::Transaction_TEST_BOOL => {
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index c986b82..8379675 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -33,10 +33,13 @@
 // using just a few large reads.
 static const size_t EVENT_BUFFER_SIZE = 100;
 
+static constexpr nsecs_t WAITING_FOR_VSYNC_TIMEOUT = ms2ns(300);
+
 DisplayEventDispatcher::DisplayEventDispatcher(
         const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
         ISurfaceComposer::EventRegistrationFlags eventRegistration)
-      : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
+      : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false),
+        mLastVsyncCount(0), mLastScheduleVsyncTime(0) {
     ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
 }
 
@@ -86,6 +89,7 @@
         }
 
         mWaitingForVsync = true;
+        mLastScheduleVsyncTime = systemTime(SYSTEM_TIME_MONOTONIC);
     }
     return OK;
 }
@@ -124,9 +128,21 @@
               this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
               vsyncEventData.id);
         mWaitingForVsync = false;
+        mLastVsyncCount = vsyncCount;
         dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
     }
 
+    if (mWaitingForVsync) {
+        const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+        const nsecs_t vsyncScheduleDelay = currentTime - mLastScheduleVsyncTime;
+        if (vsyncScheduleDelay > WAITING_FOR_VSYNC_TIMEOUT) {
+            ALOGW("Vsync time out! vsyncScheduleDelay=%" PRId64 "ms", ns2ms(vsyncScheduleDelay));
+            mWaitingForVsync = false;
+            dispatchVsync(currentTime, vsyncDisplayId /* displayId is not used */,
+                          ++mLastVsyncCount, vsyncEventData /* empty data */);
+        }
+    }
+
     return 1; // keep the callback
 }
 
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 92c89b8..8a3a476 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -80,6 +80,8 @@
     sp<Looper> mLooper;
     DisplayEventReceiver mReceiver;
     bool mWaitingForVsync;
+    uint32_t mLastVsyncCount;
+    nsecs_t mLastScheduleVsyncTime;
 
     std::vector<FrameRateOverride> mFrameRateOverrides;
 
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index a62d2b9..ecfaef8 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -40,6 +40,10 @@
         "libui",
         "libutils",
     ],
+
+    static_libs: [
+        "libtonemap",
+    ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
 }
@@ -97,7 +101,7 @@
         "skia/filters/GaussianBlurFilter.cpp",
         "skia/filters/KawaseBlurFilter.cpp",
         "skia/filters/LinearEffect.cpp",
-        "skia/filters/StretchShaderFactory.cpp"
+        "skia/filters/StretchShaderFactory.cpp",
     ],
 }
 
diff --git a/libs/renderengine/benchmark/Android.bp b/libs/renderengine/benchmark/Android.bp
index 5968399..baa5054 100644
--- a/libs/renderengine/benchmark/Android.bp
+++ b/libs/renderengine/benchmark/Android.bp
@@ -23,7 +23,10 @@
 
 cc_benchmark {
     name: "librenderengine_bench",
-    defaults: ["skia_deps", "surfaceflinger_defaults"],
+    defaults: [
+        "skia_deps",
+        "surfaceflinger_defaults",
+    ],
     srcs: [
         "main.cpp",
         "Codec.cpp",
@@ -32,6 +35,7 @@
     ],
     static_libs: [
         "librenderengine",
+        "libtonemap",
     ],
     cflags: [
         "-DLOG_TAG=\"RenderEngineBench\"",
@@ -50,5 +54,5 @@
         "libutils",
     ],
 
-    data: [ "resources/*"],
+    data: ["resources/*"],
 }
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 73dadef..53136e4 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -19,6 +19,7 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <SkString.h>
+#include <tonemap/tonemap.h>
 #include <utils/Trace.h>
 
 #include <optional>
@@ -32,6 +33,11 @@
 namespace renderengine {
 namespace skia {
 
+static aidl::android::hardware::graphics::common::Dataspace toAidlDataspace(
+        ui::Dataspace dataspace) {
+    return static_cast<aidl::android::hardware::graphics::common::Dataspace>(dataspace);
+}
+
 static void generateEOTF(ui::Dataspace dataspace, SkString& shader) {
     switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
         case HAL_DATASPACE_TRANSFER_ST2084:
@@ -127,159 +133,13 @@
         default:
             shader.append(R"(
                     float3 ScaleLuminance(float3 xyz) {
-                        return xyz * in_inputMaxLuminance;
+                        return xyz * in_libtonemap_inputMaxLuminance;
                     }
                 )");
             break;
     }
 }
 
-static void generateToneMapInterpolation(ui::Dataspace inputDataspace,
-                                         ui::Dataspace outputDataspace, SkString& shader) {
-    switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
-        case HAL_DATASPACE_TRANSFER_ST2084:
-        case HAL_DATASPACE_TRANSFER_HLG:
-            switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
-                case HAL_DATASPACE_TRANSFER_ST2084:
-                    shader.append(R"(
-                            float3 ToneMap(float3 xyz) {
-                                return xyz;
-                            }
-                        )");
-                    break;
-                case HAL_DATASPACE_TRANSFER_HLG:
-                    // PQ has a wider luminance range (10,000 nits vs. 1,000 nits) than HLG, so
-                    // we'll clamp the luminance range in case we're mapping from PQ input to HLG
-                    // output.
-                    shader.append(R"(
-                            float3 ToneMap(float3 xyz) {
-                                return clamp(xyz, 0.0, 1000.0);
-                            }
-                        )");
-                    break;
-                default:
-                    // Here we're mapping from HDR to SDR content, so interpolate using a Hermitian
-                    // polynomial onto the smaller luminance range.
-                    shader.append(R"(
-                            float3 ToneMap(float3 xyz) {
-                                float maxInLumi = in_inputMaxLuminance;
-                                float maxOutLumi = in_displayMaxLuminance;
-
-                                float nits = xyz.y;
-
-                                // if the max input luminance is less than what we can output then
-                                // no tone mapping is needed as all color values will be in range.
-                                if (maxInLumi <= maxOutLumi) {
-                                    return xyz;
-                                } else {
-
-                                    // three control points
-                                    const float x0 = 10.0;
-                                    const float y0 = 17.0;
-                                    float x1 = maxOutLumi * 0.75;
-                                    float y1 = x1;
-                                    float x2 = x1 + (maxInLumi - x1) / 2.0;
-                                    float y2 = y1 + (maxOutLumi - y1) * 0.75;
-
-                                    // horizontal distances between the last three control points
-                                    float h12 = x2 - x1;
-                                    float h23 = maxInLumi - x2;
-                                    // tangents at the last three control points
-                                    float m1 = (y2 - y1) / h12;
-                                    float m3 = (maxOutLumi - y2) / h23;
-                                    float m2 = (m1 + m3) / 2.0;
-
-                                    if (nits < x0) {
-                                        // scale [0.0, x0] to [0.0, y0] linearly
-                                        float slope = y0 / x0;
-                                        return xyz * slope;
-                                    } else if (nits < x1) {
-                                        // scale [x0, x1] to [y0, y1] linearly
-                                        float slope = (y1 - y0) / (x1 - x0);
-                                        nits = y0 + (nits - x0) * slope;
-                                    } else if (nits < x2) {
-                                        // scale [x1, x2] to [y1, y2] using Hermite interp
-                                        float t = (nits - x1) / h12;
-                                        nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
-                                                (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
-                                    } else {
-                                        // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
-                                        float t = (nits - x2) / h23;
-                                        nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
-                                                (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
-                                    }
-                                }
-
-                                // color.y is greater than x0 and is thus non-zero
-                                return xyz * (nits / xyz.y);
-                            }
-                        )");
-                    break;
-            }
-            break;
-        default:
-            switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
-                case HAL_DATASPACE_TRANSFER_ST2084:
-                case HAL_DATASPACE_TRANSFER_HLG:
-                    // Map from SDR onto an HDR output buffer
-                    // Here we use a polynomial curve to map from [0, displayMaxLuminance] onto
-                    // [0, maxOutLumi] which is hard-coded to be 3000 nits.
-                    shader.append(R"(
-                            float3 ToneMap(float3 xyz) {
-                                const float maxOutLumi = 3000.0;
-
-                                const float x0 = 5.0;
-                                const float y0 = 2.5;
-                                float x1 = in_displayMaxLuminance * 0.7;
-                                float y1 = maxOutLumi * 0.15;
-                                float x2 = in_displayMaxLuminance * 0.9;
-                                float y2 = maxOutLumi * 0.45;
-                                float x3 = in_displayMaxLuminance;
-                                float y3 = maxOutLumi;
-
-                                float c1 = y1 / 3.0;
-                                float c2 = y2 / 2.0;
-                                float c3 = y3 / 1.5;
-
-                                float nits = xyz.y;
-
-                                if (nits <= x0) {
-                                    // scale [0.0, x0] to [0.0, y0] linearly
-                                    float slope = y0 / x0;
-                                    return xyz * slope;
-                                } else if (nits <= x1) {
-                                    // scale [x0, x1] to [y0, y1] using a curve
-                                    float t = (nits - x0) / (x1 - x0);
-                                    nits = (1.0 - t) * (1.0 - t) * y0 + 2.0 * (1.0 - t) * t * c1 + t * t * y1;
-                                } else if (nits <= x2) {
-                                    // scale [x1, x2] to [y1, y2] using a curve
-                                    float t = (nits - x1) / (x2 - x1);
-                                    nits = (1.0 - t) * (1.0 - t) * y1 + 2.0 * (1.0 - t) * t * c2 + t * t * y2;
-                                } else {
-                                    // scale [x2, x3] to [y2, y3] using a curve
-                                    float t = (nits - x2) / (x3 - x2);
-                                    nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3;
-                                }
-
-                                // xyz.y is greater than x0 and is thus non-zero
-                                return xyz * (nits / xyz.y);
-                            }
-                        )");
-                    break;
-                default:
-                    // For completeness, this is tone-mapping from SDR to SDR, where this is just a
-                    // no-op.
-                    shader.append(R"(
-                            float3 ToneMap(float3 xyz) {
-                                return xyz;
-                            }
-                        )");
-                    break;
-            }
-            break;
-    }
-}
-
 // Normalizes from absolute light back to relative light (maps from [0, maxNits] back to [0, 1])
 static void generateLuminanceNormalizationForOOTF(ui::Dataspace outputDataspace, SkString& shader) {
     switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
@@ -300,7 +160,7 @@
         default:
             shader.append(R"(
                     float3 NormalizeLuminance(float3 xyz) {
-                        return xyz / in_displayMaxLuminance;
+                        return xyz / in_libtonemap_displayMaxLuminance;
                     }
                 )");
             break;
@@ -309,19 +169,22 @@
 
 static void generateOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace,
                          SkString& shader) {
-    // Input uniforms
-    shader.append(R"(
-            uniform float in_displayMaxLuminance;
-            uniform float in_inputMaxLuminance;
-        )");
+    shader.append(tonemap::getToneMapper()
+                          ->generateTonemapGainShaderSkSL(toAidlDataspace(inputDataspace),
+                                                          toAidlDataspace(outputDataspace))
+                          .c_str());
 
     generateLuminanceScalesForOOTF(inputDataspace, shader);
-    generateToneMapInterpolation(inputDataspace, outputDataspace, shader);
     generateLuminanceNormalizationForOOTF(outputDataspace, shader);
 
     shader.append(R"(
-            float3 OOTF(float3 xyz) {
-                return NormalizeLuminance(ToneMap(ScaleLuminance(xyz)));
+            float3 OOTF(float3 linearRGB, float3 xyz) {
+                float3 scaledLinearRGB = ScaleLuminance(linearRGB);
+                float3 scaledXYZ = ScaleLuminance(xyz);
+
+                float gain = libtonemap_LookupTonemapGain(scaledLinearRGB, scaledXYZ);
+
+                return NormalizeLuminance(scaledXYZ * gain);
             }
         )");
 }
@@ -399,7 +262,9 @@
         )");
     }
     shader.append(R"(
-        c.rgb = OETF(ToRGB(OOTF(ToXYZ(EOTF(c.rgb)))));
+        float3 linearRGB = EOTF(c.rgb);
+        float3 xyz = ToXYZ(linearRGB);
+        c.rgb = OETF(ToRGB(OOTF(linearRGB, xyz)));
     )");
     if (undoPremultipliedAlpha) {
         shader.append(R"(
@@ -465,11 +330,20 @@
                 colorTransform * mat4(outputColorSpace.getXYZtoRGB());
     }
 
-    effectBuilder.uniform("in_displayMaxLuminance") = maxDisplayLuminance;
-    // If the input luminance is unknown, use display luminance (aka, no-op any luminance changes)
-    // This will be the case for eg screenshots in addition to uncalibrated displays
-    effectBuilder.uniform("in_inputMaxLuminance") =
-            maxLuminance > 0 ? maxLuminance : maxDisplayLuminance;
+    tonemap::Metadata metadata{.displayMaxLuminance = maxDisplayLuminance,
+                               // If the input luminance is unknown, use display luminance (aka,
+                               // no-op any luminance changes)
+                               // This will be the case for eg screenshots in addition to
+                               // uncalibrated displays
+                               .contentMaxLuminance =
+                                       maxLuminance > 0 ? maxLuminance : maxDisplayLuminance};
+
+    const auto uniforms = tonemap::getToneMapper()->generateShaderSkSLUniforms(metadata);
+
+    for (const auto& uniform : uniforms) {
+        effectBuilder.uniform(uniform.name.c_str()).set(uniform.value.data(), uniform.value.size());
+    }
+
     return effectBuilder.makeShader(nullptr, false);
 }
 
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index d0e19dd..52b6c8f 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -23,7 +23,10 @@
 
 cc_test {
     name: "librenderengine_test",
-    defaults: ["skia_deps", "surfaceflinger_defaults"],
+    defaults: [
+        "skia_deps",
+        "surfaceflinger_defaults",
+    ],
     test_suites: ["device-tests"],
     srcs: [
         "RenderEngineTest.cpp",
@@ -36,6 +39,7 @@
         "libgmock",
         "librenderengine",
         "librenderengine_mocks",
+        "libtonemap",
     ],
 
     shared_libs: [
diff --git a/libs/tonemap/Android.bp b/libs/tonemap/Android.bp
new file mode 100644
index 0000000..231a342
--- /dev/null
+++ b/libs/tonemap/Android.bp
@@ -0,0 +1,37 @@
+// Copyright 2021 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.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_library_static {
+    name: "libtonemap",
+    vendor_available: true,
+
+    export_include_dirs: ["include"],
+    local_include_dirs: ["include"],
+
+    shared_libs: [
+        "android.hardware.graphics.common-V3-ndk",
+    ],
+    srcs: [
+        "tonemap.cpp",
+    ],
+}
diff --git a/libs/tonemap/OWNERS b/libs/tonemap/OWNERS
new file mode 100644
index 0000000..6d91da3
--- /dev/null
+++ b/libs/tonemap/OWNERS
@@ -0,0 +1,4 @@
+alecmouri@google.com
+jreck@google.com
+sallyqi@google.com
+scroggo@google.com
\ No newline at end of file
diff --git a/libs/tonemap/TEST_MAPPING b/libs/tonemap/TEST_MAPPING
new file mode 100644
index 0000000..00f83ba
--- /dev/null
+++ b/libs/tonemap/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "librenderengine_test"
+    },
+    {
+      "name": "libtonemap_test"
+    }
+  ]
+}
diff --git a/libs/tonemap/include/tonemap/tonemap.h b/libs/tonemap/include/tonemap/tonemap.h
new file mode 100644
index 0000000..d350e16
--- /dev/null
+++ b/libs/tonemap/include/tonemap/tonemap.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+
+#include <string>
+#include <vector>
+
+namespace android::tonemap {
+
+// Describes a shader uniform
+// The shader uniform is intended to be passed into a SkRuntimeShaderBuilder, i.e.:
+//
+// SkRuntimeShaderBuilder builder;
+// builder.uniform(<uniform name>).set(<uniform value>.data(), <uniform value>.size());
+struct ShaderUniform {
+    // The name of the uniform, used for binding into a shader.
+    // The shader must contain a uniform whose name matches this.
+    std::string name;
+
+    // The value for the uniform, which should be bound to the uniform identified by <name>
+    std::vector<uint8_t> value;
+};
+
+// Describes metadata which may be used for constructing the shader uniforms.
+// This metadata should not be used for manipulating the source code of the shader program directly,
+// as otherwise caching by other system of these shaders may break.
+struct Metadata {
+    float displayMaxLuminance = 0.0;
+    float contentMaxLuminance = 0.0;
+};
+
+class ToneMapper {
+public:
+    virtual ~ToneMapper() {}
+    // Constructs a tonemap shader whose shader language is SkSL
+    //
+    // The returned shader string *must* contain a function with the following signature:
+    // float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz);
+    //
+    // The arguments are:
+    // * linearRGB is the absolute nits of the RGB pixels in linear space
+    // * xyz is linearRGB converted into XYZ
+    //
+    // libtonemap_LookupTonemapGain() returns a float representing the amount by which to scale the
+    // absolute nits of the pixels. This function may be plugged into any existing SkSL shader, and
+    // is expected to look something like this:
+    //
+    // vec3 rgb = ...;
+    // // apply the EOTF based on the incoming dataspace to convert to linear nits.
+    // vec3 linearRGB = applyEOTF(rgb);
+    // // apply a RGB->XYZ matrix float3
+    // vec3 xyz = toXYZ(linearRGB);
+    // // Scale the luminance based on the content standard
+    // vec3 absoluteRGB = ScaleLuminance(linearRGB);
+    // vec3 absoluteXYZ = ScaleLuminance(xyz);
+    // float gain = libtonemap_LookupTonemapGain(absoluteRGB, absoluteXYZ);
+    // // Normalize the luminance back down to a [0, 1] range
+    // xyz = NormalizeLuminance(absoluteXYZ * gain);
+    // // apply a XYZ->RGB matrix and apply the output OETf.
+    // vec3 finalColor = applyOETF(ToRGB(xyz));
+    // ...
+    //
+    // Helper methods in this shader should be prefixed with "libtonemap_". Accordingly, libraries
+    // which consume this shader must *not* contain any methods prefixed with "libtonemap_" to
+    // guarantee that there are no conflicts in name resolution.
+    virtual std::string generateTonemapGainShaderSkSL(
+            aidl::android::hardware::graphics::common::Dataspace sourceDataspace,
+            aidl::android::hardware::graphics::common::Dataspace destinationDataspace) = 0;
+
+    // Constructs uniform descriptions that correspond to those that are generated for the tonemap
+    // shader. Uniforms must be prefixed with "in_libtonemap_". Libraries which consume this shader
+    // must not bind any new uniforms that begin with this prefix.
+    //
+    // Downstream shaders may assume the existence of the uniform in_libtonemap_displayMaxLuminance
+    // and in_libtonemap_inputMaxLuminance, in order to assist with scaling and normalizing
+    // luminance as described in the documentation for generateTonemapGainShaderSkSL(). That is,
+    // shaders plugging in a tone-mapping shader returned by generateTonemapGainShaderSkSL() may
+    // assume that there are predefined floats in_libtonemap_displayMaxLuminance and
+    // in_libtonemap_inputMaxLuminance inside of the body of the tone-mapping shader.
+    virtual std::vector<ShaderUniform> generateShaderSkSLUniforms(const Metadata& metadata) = 0;
+};
+
+// Retrieves a tonemapper instance.
+// This instance is globally constructed.
+ToneMapper* getToneMapper();
+
+} // namespace android::tonemap
\ No newline at end of file
diff --git a/libs/tonemap/tests/Android.bp b/libs/tonemap/tests/Android.bp
new file mode 100644
index 0000000..e58d519
--- /dev/null
+++ b/libs/tonemap/tests/Android.bp
@@ -0,0 +1,38 @@
+// Copyright 2021 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.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_test {
+    name: "libtonemap_test",
+    test_suites: ["device-tests"],
+    srcs: [
+        "tonemap_test.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.common-V3-ndk",
+    ],
+    static_libs: [
+        "libgmock",
+        "libgtest",
+        "libtonemap",
+    ],
+}
diff --git a/libs/tonemap/tests/tonemap_test.cpp b/libs/tonemap/tests/tonemap_test.cpp
new file mode 100644
index 0000000..7a7958f
--- /dev/null
+++ b/libs/tonemap/tests/tonemap_test.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <tonemap/tonemap.h>
+#include <cmath>
+
+namespace android {
+
+using testing::HasSubstr;
+
+struct TonemapTest : public ::testing::Test {};
+
+TEST_F(TonemapTest, generateShaderSkSLUniforms_containsDefaultUniforms) {
+    static const constexpr float kDisplayMaxLuminance = 1.f;
+    static const constexpr float kContentMaxLuminance = 2.f;
+    tonemap::Metadata metadata{.displayMaxLuminance = kDisplayMaxLuminance,
+                               .contentMaxLuminance = kContentMaxLuminance};
+    const auto uniforms = tonemap::getToneMapper()->generateShaderSkSLUniforms(metadata);
+
+    ASSERT_EQ(1, std::count_if(uniforms.cbegin(), uniforms.cend(), [](const auto& data) {
+                  return data.name == "in_libtonemap_displayMaxLuminance";
+              }));
+    ASSERT_EQ(1, std::count_if(uniforms.cbegin(), uniforms.cend(), [](const auto& data) {
+                  return data.name == "in_libtonemap_inputMaxLuminance";
+              }));
+
+    // Smoke check that metadata values are "real", specifically that they're non-zero and actually
+    // numbers. This is to help avoid shaders using these uniforms from dividing by zero or other
+    // catastrophic errors.
+    const auto& displayLum = std::find_if(uniforms.cbegin(), uniforms.cend(), [](const auto& data) {
+                                 return data.name == "in_libtonemap_displayMaxLuminance";
+                             })->value;
+
+    float displayLumFloat = 0.f;
+    std::memcpy(&displayLumFloat, displayLum.data(), displayLum.size());
+    EXPECT_FALSE(std::isnan(displayLumFloat));
+    EXPECT_GT(displayLumFloat, 0);
+
+    const auto& contentLum = std::find_if(uniforms.cbegin(), uniforms.cend(), [](const auto& data) {
+                                 return data.name == "in_libtonemap_inputMaxLuminance";
+                             })->value;
+
+    float contentLumFloat = 0.f;
+    std::memcpy(&contentLumFloat, contentLum.data(), contentLum.size());
+    EXPECT_FALSE(std::isnan(contentLumFloat));
+    EXPECT_GT(contentLumFloat, 0);
+}
+
+TEST_F(TonemapTest, generateTonemapGainShaderSkSL_containsEntryPoint) {
+    const auto shader =
+            tonemap::getToneMapper()
+                    ->generateTonemapGainShaderSkSL(aidl::android::hardware::graphics::common::
+                                                            Dataspace::BT2020_ITU_PQ,
+                                                    aidl::android::hardware::graphics::common::
+                                                            Dataspace::DISPLAY_P3);
+
+    // Other tests such as librenderengine_test will plug in the shader to check compilation.
+    EXPECT_THAT(shader, HasSubstr("float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz)"));
+}
+
+} // namespace android
diff --git a/libs/tonemap/tonemap.cpp b/libs/tonemap/tonemap.cpp
new file mode 100644
index 0000000..350bca4
--- /dev/null
+++ b/libs/tonemap/tonemap.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#include <tonemap/tonemap.h>
+
+#include <cstdint>
+#include <mutex>
+#include <type_traits>
+
+namespace android::tonemap {
+
+namespace {
+
+// Flag containing the variant of tone map algorithm to use.
+enum class ToneMapAlgorithm {
+    AndroidO, // Default algorithm in place since Android O,
+};
+
+static const constexpr auto kToneMapAlgorithm = ToneMapAlgorithm::AndroidO;
+
+static const constexpr auto kTransferMask =
+        static_cast<int32_t>(aidl::android::hardware::graphics::common::Dataspace::TRANSFER_MASK);
+static const constexpr auto kTransferST2084 =
+        static_cast<int32_t>(aidl::android::hardware::graphics::common::Dataspace::TRANSFER_ST2084);
+static const constexpr auto kTransferHLG =
+        static_cast<int32_t>(aidl::android::hardware::graphics::common::Dataspace::TRANSFER_HLG);
+
+template <typename T, std::enable_if_t<std::is_trivially_copyable<T>::value, bool> = true>
+std::vector<uint8_t> buildUniformValue(T value) {
+    std::vector<uint8_t> result;
+    result.resize(sizeof(value));
+    std::memcpy(result.data(), &value, sizeof(value));
+    return result;
+}
+
+class ToneMapperO : public ToneMapper {
+public:
+    std::string generateTonemapGainShaderSkSL(
+            aidl::android::hardware::graphics::common::Dataspace sourceDataspace,
+            aidl::android::hardware::graphics::common::Dataspace destinationDataspace) override {
+        const int32_t sourceDataspaceInt = static_cast<int32_t>(sourceDataspace);
+        const int32_t destinationDataspaceInt = static_cast<int32_t>(destinationDataspace);
+
+        std::string program;
+        // Define required uniforms
+        program.append(R"(
+                uniform float in_libtonemap_displayMaxLuminance;
+                uniform float in_libtonemap_inputMaxLuminance;
+            )");
+        switch (sourceDataspaceInt & kTransferMask) {
+            case kTransferST2084:
+            case kTransferHLG:
+                switch (destinationDataspaceInt & kTransferMask) {
+                    case kTransferST2084:
+                        program.append(R"(
+                                    float libtonemap_ToneMapTargetNits(vec3 xyz) {
+                                        return xyz.y;
+                                    }
+                                )");
+                        break;
+                    case kTransferHLG:
+                        // PQ has a wider luminance range (10,000 nits vs. 1,000 nits) than HLG, so
+                        // we'll clamp the luminance range in case we're mapping from PQ input to
+                        // HLG output.
+                        program.append(R"(
+                                    float libtonemap_ToneMapTargetNits(vec3 xyz) {
+                                        return clamp(xyz.y, 0.0, 1000.0);
+                                    }
+                                )");
+                        break;
+                    default:
+                        // Here we're mapping from HDR to SDR content, so interpolate using a
+                        // Hermitian polynomial onto the smaller luminance range.
+                        program.append(R"(
+                                    float libtonemap_ToneMapTargetNits(vec3 xyz) {
+                                        float maxInLumi = in_libtonemap_inputMaxLuminance;
+                                        float maxOutLumi = in_libtonemap_displayMaxLuminance;
+
+                                        float nits = xyz.y;
+
+                                        // if the max input luminance is less than what we can
+                                        // output then no tone mapping is needed as all color
+                                        // values will be in range.
+                                        if (maxInLumi <= maxOutLumi) {
+                                            return xyz.y;
+                                        } else {
+
+                                            // three control points
+                                            const float x0 = 10.0;
+                                            const float y0 = 17.0;
+                                            float x1 = maxOutLumi * 0.75;
+                                            float y1 = x1;
+                                            float x2 = x1 + (maxInLumi - x1) / 2.0;
+                                            float y2 = y1 + (maxOutLumi - y1) * 0.75;
+
+                                            // horizontal distances between the last three
+                                            // control points
+                                            float h12 = x2 - x1;
+                                            float h23 = maxInLumi - x2;
+                                            // tangents at the last three control points
+                                            float m1 = (y2 - y1) / h12;
+                                            float m3 = (maxOutLumi - y2) / h23;
+                                            float m2 = (m1 + m3) / 2.0;
+
+                                            if (nits < x0) {
+                                                // scale [0.0, x0] to [0.0, y0] linearly
+                                                float slope = y0 / x0;
+                                                return nits * slope;
+                                            } else if (nits < x1) {
+                                                // scale [x0, x1] to [y0, y1] linearly
+                                                float slope = (y1 - y0) / (x1 - x0);
+                                                nits = y0 + (nits - x0) * slope;
+                                            } else if (nits < x2) {
+                                                // scale [x1, x2] to [y1, y2] using Hermite interp
+                                                float t = (nits - x1) / h12;
+                                                nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) *
+                                                        (1.0 - t) * (1.0 - t) +
+                                                        (y2 * (3.0 - 2.0 * t) +
+                                                        h12 * m2 * (t - 1.0)) * t * t;
+                                            } else {
+                                                // scale [x2, maxInLumi] to [y2, maxOutLumi] using
+                                                // Hermite interp
+                                                float t = (nits - x2) / h23;
+                                                nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) *
+                                                        (1.0 - t) * (1.0 - t) + (maxOutLumi *
+                                                        (3.0 - 2.0 * t) + h23 * m3 *
+                                                        (t - 1.0)) * t * t;
+                                            }
+                                        }
+
+                                        return nits;
+                                    }
+                                )");
+                        break;
+                }
+                break;
+            default:
+                switch (destinationDataspaceInt & kTransferMask) {
+                    case kTransferST2084:
+                    case kTransferHLG:
+                        // Map from SDR onto an HDR output buffer
+                        // Here we use a polynomial curve to map from [0, displayMaxLuminance] onto
+                        // [0, maxOutLumi] which is hard-coded to be 3000 nits.
+                        program.append(R"(
+                                    float libtonemap_ToneMapTargetNits(vec3 xyz) {
+                                        const float maxOutLumi = 3000.0;
+
+                                        const float x0 = 5.0;
+                                        const float y0 = 2.5;
+                                        float x1 = in_libtonemap_displayMaxLuminance * 0.7;
+                                        float y1 = maxOutLumi * 0.15;
+                                        float x2 = in_libtonemap_displayMaxLuminance * 0.9;
+                                        float y2 = maxOutLumi * 0.45;
+                                        float x3 = in_libtonemap_displayMaxLuminance;
+                                        float y3 = maxOutLumi;
+
+                                        float c1 = y1 / 3.0;
+                                        float c2 = y2 / 2.0;
+                                        float c3 = y3 / 1.5;
+
+                                        float nits = xyz.y;
+
+                                        if (nits <= x0) {
+                                            // scale [0.0, x0] to [0.0, y0] linearly
+                                            float slope = y0 / x0;
+                                            return nits * slope;
+                                        } else if (nits <= x1) {
+                                            // scale [x0, x1] to [y0, y1] using a curve
+                                            float t = (nits - x0) / (x1 - x0);
+                                            nits = (1.0 - t) * (1.0 - t) * y0 +
+                                                    2.0 * (1.0 - t) * t * c1 + t * t * y1;
+                                        } else if (nits <= x2) {
+                                            // scale [x1, x2] to [y1, y2] using a curve
+                                            float t = (nits - x1) / (x2 - x1);
+                                            nits = (1.0 - t) * (1.0 - t) * y1 +
+                                                    2.0 * (1.0 - t) * t * c2 + t * t * y2;
+                                        } else {
+                                            // scale [x2, x3] to [y2, y3] using a curve
+                                            float t = (nits - x2) / (x3 - x2);
+                                            nits = (1.0 - t) * (1.0 - t) * y2 +
+                                                    2.0 * (1.0 - t) * t * c3 + t * t * y3;
+                                        }
+
+                                        return nits;
+                                    }
+                                )");
+                        break;
+                    default:
+                        // For completeness, this is tone-mapping from SDR to SDR, where this is
+                        // just a no-op.
+                        program.append(R"(
+                                    float libtonemap_ToneMapTargetNits(vec3 xyz) {
+                                        return xyz.y;
+                                    }
+                                )");
+                        break;
+                }
+                break;
+        }
+
+        program.append(R"(
+            float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz) {
+                if (xyz.y <= 0.0) {
+                    return 1.0;
+                }
+                return libtonemap_ToneMapTargetNits(xyz) / xyz.y;
+            }
+        )");
+        return program;
+    }
+
+    std::vector<ShaderUniform> generateShaderSkSLUniforms(const Metadata& metadata) override {
+        std::vector<ShaderUniform> uniforms;
+
+        uniforms.reserve(2);
+
+        uniforms.push_back({.name = "in_libtonemap_displayMaxLuminance",
+                            .value = buildUniformValue<float>(metadata.displayMaxLuminance)});
+        uniforms.push_back({.name = "in_libtonemap_inputMaxLuminance",
+                            .value = buildUniformValue<float>(metadata.contentMaxLuminance)});
+
+        return uniforms;
+    }
+};
+
+} // namespace
+
+ToneMapper* getToneMapper() {
+    static std::once_flag sOnce;
+    static std::unique_ptr<ToneMapper> sToneMapper;
+
+    std::call_once(sOnce, [&] {
+        switch (kToneMapAlgorithm) {
+            case ToneMapAlgorithm::AndroidO:
+                sToneMapper = std::unique_ptr<ToneMapper>(new ToneMapperO());
+                break;
+        }
+    });
+
+    return sToneMapper.get();
+}
+
+} // namespace android::tonemap
\ No newline at end of file
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 56b8374..6691575 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -79,6 +79,7 @@
         "libperfetto_client_experimental",
         "librenderengine",
         "libserviceutils",
+        "libtonemap",
         "libtrace_proto",
         "libaidlcommonsupport",
     ],
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 28c387e..dec7cc0 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -523,7 +523,7 @@
 }
 
 sp<Layer> BufferQueueLayer::createClone() {
-    LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
+    LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
     args.textureName = mTextureName;
     sp<BufferQueueLayer> layer = mFlinger->getFactory().createBufferQueueLayer(args);
     layer->setInitialValuesForClone(this);
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index dfdb5c0..c6e0727 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -62,6 +62,11 @@
     status_t setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format);
     sp<IGraphicBufferProducer> getProducer() const;
 
+    void setSizeForTest(uint32_t w, uint32_t h) {
+        mDrawingState.active_legacy.w = w;
+        mDrawingState.active_legacy.h = h;
+    }
+
 protected:
     void gatherBufferInfo() override;
 
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 4f0bbd2..b4ccb80 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -883,7 +883,7 @@
 }
 
 sp<Layer> BufferStateLayer::createClone() {
-    LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
+    LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
     args.textureName = mTextureName;
     sp<BufferStateLayer> layer = mFlinger->getFactory().createBufferStateLayer(args);
     layer->mHwcSlotGenerator = mHwcSlotGenerator;
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 8da2e24..0a8ebec 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -72,35 +72,28 @@
     return lbc;
 }
 
-status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
-                               uint32_t flags, const sp<IBinder>& parentHandle,
-                               LayerMetadata metadata, sp<IBinder>* handle,
-                               sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
-                               uint32_t* outTransformHint) {
+status_t Client::createSurface(const String8& name, uint32_t /* w */, uint32_t /* h */,
+                               PixelFormat /* format */, uint32_t flags,
+                               const sp<IBinder>& parentHandle, LayerMetadata metadata,
+                               sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* /* gbp */,
+                               int32_t* outLayerId, uint32_t* outTransformHint) {
     // We rely on createLayer to check permissions.
-    return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
-                                 parentHandle, outLayerId, nullptr, outTransformHint);
+    LayerCreationArgs args(mFlinger.get(), this, name.c_str(), flags, std::move(metadata));
+    return mFlinger->createLayer(args, outHandle, parentHandle, outLayerId, nullptr,
+                                 outTransformHint);
 }
 
-status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
-                                         PixelFormat format, uint32_t flags,
-                                         const sp<IGraphicBufferProducer>& parent,
-                                         LayerMetadata metadata, sp<IBinder>* handle,
-                                         sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
-                                         uint32_t* outTransformHint) {
-    if (mFlinger->authenticateSurfaceTexture(parent) == false) {
-        ALOGE("failed to authenticate surface texture");
-        return BAD_VALUE;
-    }
-
-    const auto& layer = (static_cast<MonitoredProducer*>(parent.get()))->getLayer();
-    if (layer == nullptr) {
-        ALOGE("failed to find parent layer");
-        return BAD_VALUE;
-    }
-
-    return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
-                                 nullptr, outLayerId, layer, outTransformHint);
+status_t Client::createWithSurfaceParent(const String8& /* name */, uint32_t /* w */,
+                                         uint32_t /* h */, PixelFormat /* format */,
+                                         uint32_t /* flags */,
+                                         const sp<IGraphicBufferProducer>& /* parent */,
+                                         LayerMetadata /* metadata */, sp<IBinder>* /* handle */,
+                                         sp<IGraphicBufferProducer>* /* gbp */,
+                                         int32_t* /* outLayerId */,
+                                         uint32_t* /* outTransformHint */) {
+    // This api does not make sense with blast since SF no longer tracks IGBP. This api should be
+    // removed.
+    return BAD_VALUE;
 }
 
 status_t Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle,
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 83b4a25..aefc014 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -38,6 +38,7 @@
     static_libs: [
         "libmath",
         "librenderengine",
+        "libtonemap",
         "libtrace_proto",
         "libaidlcommonsupport",
     ],
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 841e79f..3ccc229 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -36,8 +36,7 @@
 
 sp<Layer> ContainerLayer::createClone() {
     sp<ContainerLayer> layer = mFlinger->getFactory().createContainerLayer(
-            LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0,
-                              LayerMetadata()));
+            LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()));
     layer->setInitialValuesForClone(this);
     return layer;
 }
diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp
index 86c6b21..845176c 100644
--- a/services/surfaceflinger/EffectLayer.cpp
+++ b/services/surfaceflinger/EffectLayer.cpp
@@ -136,8 +136,7 @@
 
 sp<Layer> EffectLayer::createClone() {
     sp<EffectLayer> layer = mFlinger->getFactory().createEffectLayer(
-            LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0,
-                              LayerMetadata()));
+            LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()));
     layer->setInitialValuesForClone(this);
     return layer;
 }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a27c487..e606e55 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -87,11 +87,12 @@
 std::atomic<int32_t> Layer::sSequence{1};
 
 Layer::Layer(const LayerCreationArgs& args)
-      : mFlinger(args.flinger),
+      : sequence(args.sequence.value_or(sSequence++)),
+        mFlinger(args.flinger),
         mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)),
         mClientRef(args.client),
-        mWindowType(
-                static_cast<WindowInfo::Type>(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) {
+        mWindowType(static_cast<WindowInfo::Type>(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))),
+        mLayerCreationFlags(args.flags) {
     uint32_t layerFlags = 0;
     if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
     if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
@@ -99,8 +100,6 @@
     if (args.flags & ISurfaceComposerClient::eSkipScreenshot)
         layerFlags |= layer_state_t::eLayerSkipScreenshot;
 
-    mDrawingState.active_legacy.w = args.w;
-    mDrawingState.active_legacy.h = args.h;
     mDrawingState.flags = layerFlags;
     mDrawingState.active_legacy.transform.set(0, 0);
     mDrawingState.crop.makeInvalid();
@@ -185,12 +184,10 @@
 }
 
 LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
-                                     uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata)
+                                     uint32_t flags, LayerMetadata metadata)
       : flinger(flinger),
         client(std::move(client)),
         name(std::move(name)),
-        w(w),
-        h(h),
         flags(flags),
         metadata(std::move(metadata)) {
     IPCThreadState* ipc = IPCThreadState::self();
@@ -887,7 +884,7 @@
         uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect;
         std::string name = mName + "BackgroundColorLayer";
         mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer(
-                LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags,
+                LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags,
                                   LayerMetadata()));
 
         // add to child list
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 297ded0..84355ea 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -85,20 +85,18 @@
 } // namespace frametimeline
 
 struct LayerCreationArgs {
-    LayerCreationArgs(SurfaceFlinger*, sp<Client>, std::string name, uint32_t w, uint32_t h,
-                      uint32_t flags, LayerMetadata);
+    LayerCreationArgs(SurfaceFlinger*, sp<Client>, std::string name, uint32_t flags, LayerMetadata);
 
     SurfaceFlinger* flinger;
     const sp<Client> client;
     std::string name;
-    uint32_t w;
-    uint32_t h;
     uint32_t flags;
     LayerMetadata metadata;
 
     pid_t callingPid;
     uid_t callingUid;
     uint32_t textureName;
+    std::optional<uint32_t> sequence = std::nullopt;
 };
 
 class Layer : public virtual RefBase, compositionengine::LayerFE {
@@ -881,7 +879,7 @@
     // Layer serial number.  This gives layers an explicit ordering, so we
     // have a stable sort order when their layer stack and Z-order are
     // the same.
-    int32_t sequence{sSequence++};
+    const int32_t sequence;
 
     bool mPendingHWCDestroy{false};
 
@@ -1119,6 +1117,8 @@
     const std::vector<BlurRegion> getBlurRegions() const;
 
     bool mIsAtRoot = false;
+
+    uint32_t mLayerCreationFlags;
 };
 
 std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate);
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index 11fe6d0..a1e1455 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -112,12 +112,10 @@
         }
         drawLayers();
     } else {
-        uint32_t w = static_cast<uint32_t>(getWidth());
-        uint32_t h = static_cast<uint32_t>(getHeight());
         // In the "childrenOnly" case we reparent the children to a screenshot
         // layer which has no properties set and which does not draw.
         sp<ContainerLayer> screenshotParentLayer = mFlinger.getFactory().createContainerLayer(
-                {&mFlinger, nullptr, "Screenshot Parent"s, w, h, 0, LayerMetadata()});
+                {&mFlinger, nullptr, "Screenshot Parent"s, 0, LayerMetadata()});
 
         ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop);
         drawLayers();
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 6b2d745..df76f50 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -33,13 +33,7 @@
     mFlinger(flinger),
     mLayer(layer) {}
 
-MonitoredProducer::~MonitoredProducer() {
-    // Remove ourselves from SurfaceFlinger's list. We do this asynchronously
-    // because we don't know where this destructor is called from. It could be
-    // called with the mStateLock held, leading to a dead-lock (it actually
-    // happens).
-    mFlinger->removeGraphicBufferProducerAsync(onAsBinder());
-}
+MonitoredProducer::~MonitoredProducer() {}
 
 status_t MonitoredProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
     return mProducer->requestBuffer(slot, buf);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 98f2107..d05111e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -904,9 +904,8 @@
 }
 
 bool SurfaceFlinger::authenticateSurfaceTextureLocked(
-        const sp<IGraphicBufferProducer>& bufferProducer) const {
-    sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer));
-    return mGraphicBufferProducerList.count(surfaceTextureBinder.get()) > 0;
+        const sp<IGraphicBufferProducer>& /* bufferProducer */) const {
+    return false;
 }
 
 status_t SurfaceFlinger::getSupportedFrameTimestamps(
@@ -3344,20 +3343,15 @@
 }
 
 status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
-                                        const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
-                                        const wp<Layer>& parent, bool addToRoot,
-                                        uint32_t* outTransformHint) {
+                                        const sp<Layer>& lbc, const wp<Layer>& parent,
+                                        bool addToRoot, uint32_t* outTransformHint) {
     if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) {
         ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
               ISurfaceComposer::MAX_LAYERS);
         return NO_MEMORY;
     }
 
-    wp<IBinder> initialProducer;
-    if (gbc != nullptr) {
-        initialProducer = IInterface::asBinder(gbc);
-    }
-    setLayerCreatedState(handle, lbc, parent, initialProducer, addToRoot);
+    setLayerCreatedState(handle, lbc, parent, addToRoot);
 
     // Create a transaction includes the initial parent and producer.
     Vector<ComposerState> states;
@@ -3373,7 +3367,9 @@
         *outTransformHint = mActiveDisplayTransformHint;
     }
     // attach this layer to the client
-    client->attachLayer(handle, lbc);
+    if (client != nullptr) {
+        client->attachLayer(handle, lbc);
+    }
 
     return setTransactionState(FrameTimelineInfo{}, states, displays, 0 /* flags */, nullptr,
                                InputWindowCommands{}, -1 /* desiredPresentTime */,
@@ -3381,13 +3377,6 @@
                                0 /* Undefined transactionId */);
 }
 
-void SurfaceFlinger::removeGraphicBufferProducerAsync(const wp<IBinder>& binder) {
-    static_cast<void>(schedule([=] {
-        Mutex::Autolock lock(mStateLock);
-        mGraphicBufferProducerList.erase(binder);
-    }));
-}
-
 uint32_t SurfaceFlinger::getTransactionFlags() const {
     return mTransactionFlags;
 }
@@ -4273,17 +4262,14 @@
 
     sp<Layer> mirrorLayer;
     sp<Layer> mirrorFrom;
-    std::string layerName = "MirrorRoot";
-
     {
         Mutex::Autolock _l(mStateLock);
         mirrorFrom = fromHandle(mirrorFromHandle).promote();
         if (!mirrorFrom) {
             return NAME_NOT_FOUND;
         }
-
-        status_t result = createContainerLayer(client, std::move(layerName), -1, -1, 0,
-                                               LayerMetadata(), outHandle, &mirrorLayer);
+        LayerCreationArgs args(this, client, "MirrorRoot", 0, LayerMetadata());
+        status_t result = createContainerLayer(args, outHandle, &mirrorLayer);
         if (result != NO_ERROR) {
             return result;
         }
@@ -4292,22 +4278,13 @@
     }
 
     *outLayerId = mirrorLayer->sequence;
-    return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, false,
-                          nullptr /* outTransformHint */);
+    return addClientLayer(client, *outHandle, mirrorLayer /* layer */, nullptr /* parent */,
+                          false /* addAsRoot */, nullptr /* outTransformHint */);
 }
 
-status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
-                                     uint32_t h, PixelFormat format, uint32_t flags,
-                                     LayerMetadata metadata, sp<IBinder>* handle,
-                                     sp<IGraphicBufferProducer>* gbp,
+status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
                                      const sp<IBinder>& parentHandle, int32_t* outLayerId,
                                      const sp<Layer>& parentLayer, uint32_t* outTransformHint) {
-    if (int32_t(w|h) < 0) {
-        ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
-                int(w), int(h));
-        return BAD_VALUE;
-    }
-
     ALOG_ASSERT(parentLayer == nullptr || parentHandle == nullptr,
             "Expected only one of parentLayer or parentHandle to be non-null. "
             "Programmer error?");
@@ -4316,40 +4293,22 @@
 
     sp<Layer> layer;
 
-    std::string layerName{name.string()};
-
-    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
+    switch (args.flags & ISurfaceComposerClient::eFXSurfaceMask) {
         case ISurfaceComposerClient::eFXSurfaceBufferQueue:
         case ISurfaceComposerClient::eFXSurfaceBufferState: {
-            result = createBufferStateLayer(client, std::move(layerName), w, h, flags,
-                                            std::move(metadata), handle, &layer);
+            result = createBufferStateLayer(args, outHandle, &layer);
             std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
             if (pendingBufferCounter) {
                 std::string counterName = layer->getPendingBufferCounterName();
-                mBufferCountTracker.add((*handle)->localBinder(), counterName,
+                mBufferCountTracker.add((*outHandle)->localBinder(), counterName,
                                         pendingBufferCounter);
             }
         } break;
         case ISurfaceComposerClient::eFXSurfaceEffect:
-            // check if buffer size is set for color layer.
-            if (w > 0 || h > 0) {
-                ALOGE("createLayer() failed, w or h cannot be set for color layer (w=%d, h=%d)",
-                      int(w), int(h));
-                return BAD_VALUE;
-            }
-
-            result = createEffectLayer(client, std::move(layerName), w, h, flags,
-                                       std::move(metadata), handle, &layer);
+            result = createEffectLayer(args, outHandle, &layer);
             break;
         case ISurfaceComposerClient::eFXSurfaceContainer:
-            // check if buffer size is set for container layer.
-            if (w > 0 || h > 0) {
-                ALOGE("createLayer() failed, w or h cannot be set for container layer (w=%d, h=%d)",
-                      int(w), int(h));
-                return BAD_VALUE;
-            }
-            result = createContainerLayer(client, std::move(layerName), w, h, flags,
-                                          std::move(metadata), handle, &layer);
+            result = createContainerLayer(args, outHandle, &layer);
             break;
         default:
             result = BAD_VALUE;
@@ -4369,7 +4328,7 @@
     if (parentLayer != nullptr) {
         addToRoot = false;
     }
-    result = addClientLayer(client, *handle, *gbp, layer, parent, addToRoot, outTransformHint);
+    result = addClientLayer(args.client, *outHandle, layer, parent, addToRoot, outTransformHint);
     if (result != NO_ERROR) {
         return result;
     }
@@ -4379,9 +4338,7 @@
     return result;
 }
 
-status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, std::string name,
-                                                uint32_t w, uint32_t h, uint32_t flags,
-                                                LayerMetadata metadata, PixelFormat& format,
+status_t SurfaceFlinger::createBufferQueueLayer(LayerCreationArgs& args, PixelFormat& format,
                                                 sp<IBinder>* handle,
                                                 sp<IGraphicBufferProducer>* gbp,
                                                 sp<Layer>* outLayer) {
@@ -4397,7 +4354,6 @@
     }
 
     sp<BufferQueueLayer> layer;
-    LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
     args.textureName = getNewTexture();
     {
         // Grab the SF state lock during this since it's the only safe way to access
@@ -4407,7 +4363,7 @@
         layer = getFactory().createBufferQueueLayer(args);
     }
 
-    status_t err = layer->setDefaultBufferProperties(w, h, format);
+    status_t err = layer->setDefaultBufferProperties(0, 0, format);
     if (err == NO_ERROR) {
         *handle = layer->getHandle();
         *gbp = layer->getProducer();
@@ -4418,34 +4374,24 @@
     return err;
 }
 
-status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, std::string name,
-                                                uint32_t w, uint32_t h, uint32_t flags,
-                                                LayerMetadata metadata, sp<IBinder>* handle,
+status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
                                                 sp<Layer>* outLayer) {
-    LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
     args.textureName = getNewTexture();
-    sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
-    *handle = layer->getHandle();
-    *outLayer = layer;
-
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::createEffectLayer(const sp<Client>& client, std::string name, uint32_t w,
-                                           uint32_t h, uint32_t flags, LayerMetadata metadata,
-                                           sp<IBinder>* handle, sp<Layer>* outLayer) {
-    *outLayer = getFactory().createEffectLayer(
-            {this, client, std::move(name), w, h, flags, std::move(metadata)});
+    *outLayer = getFactory().createBufferStateLayer(args);
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::createContainerLayer(const sp<Client>& client, std::string name,
-                                              uint32_t w, uint32_t h, uint32_t flags,
-                                              LayerMetadata metadata, sp<IBinder>* handle,
+status_t SurfaceFlinger::createEffectLayer(LayerCreationArgs& args, sp<IBinder>* handle,
+                                           sp<Layer>* outLayer) {
+    *outLayer = getFactory().createEffectLayer(args);
+    *handle = (*outLayer)->getHandle();
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::createContainerLayer(LayerCreationArgs& args, sp<IBinder>* handle,
                                               sp<Layer>* outLayer) {
-    *outLayer = getFactory().createContainerLayer(
-            {this, client, std::move(name), w, h, flags, std::move(metadata)});
+    *outLayer = getFactory().createContainerLayer(args);
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
 }
@@ -5031,8 +4977,6 @@
      */
     colorizer.bold(result);
     StringAppendF(&result, "Visible layers (count = %zu)\n", mNumLayers.load());
-    StringAppendF(&result, "GraphicBufferProducers: %zu, max %zu\n",
-                  mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize);
     colorizer.reset(result);
 
     {
@@ -6794,11 +6738,10 @@
 }
 
 void SurfaceFlinger::setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer,
-                                          const wp<Layer> parent, const wp<IBinder>& producer,
-                                          bool addToRoot) {
+                                          const wp<Layer> parent, bool addToRoot) {
     Mutex::Autolock lock(mCreatedLayersLock);
     mCreatedLayers[handle->localBinder()] =
-            std::make_unique<LayerCreatedState>(layer, parent, producer, addToRoot);
+            std::make_unique<LayerCreatedState>(layer, parent, addToRoot);
 }
 
 auto SurfaceFlinger::getLayerCreatedState(const sp<IBinder>& handle) {
@@ -6859,19 +6802,6 @@
 
     layer->updateTransformHint(mActiveDisplayTransformHint);
 
-    if (state->initialProducer != nullptr) {
-        mGraphicBufferProducerList.insert(state->initialProducer);
-        LOG_ALWAYS_FATAL_IF(mGraphicBufferProducerList.size() > mMaxGraphicBufferProducerListSize,
-                            "Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers",
-                            mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize,
-                            mNumLayers.load());
-        if (mGraphicBufferProducerList.size() > mGraphicBufferProducerListSizeLogThreshold) {
-            ALOGW("Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers",
-                  mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize,
-                  mNumLayers.load());
-        }
-    }
-
     mInterceptor->saveSurfaceCreation(layer);
     return layer;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5c85382..f896c50 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -760,29 +760,23 @@
     /*
      * Layer management
      */
-    status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
-                         PixelFormat format, uint32_t flags, LayerMetadata metadata,
-                         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp,
+    status_t createLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
                          const sp<IBinder>& parentHandle, int32_t* outLayerId,
                          const sp<Layer>& parentLayer = nullptr,
                          uint32_t* outTransformHint = nullptr);
 
-    status_t createBufferQueueLayer(const sp<Client>& client, std::string name, uint32_t w,
-                                    uint32_t h, uint32_t flags, LayerMetadata metadata,
-                                    PixelFormat& format, sp<IBinder>* outHandle,
-                                    sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
+    status_t createBufferQueueLayer(LayerCreationArgs& args, PixelFormat& format,
+                                    sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
+                                    sp<Layer>* outLayer);
 
-    status_t createBufferStateLayer(const sp<Client>& client, std::string name, uint32_t w,
-                                    uint32_t h, uint32_t flags, LayerMetadata metadata,
-                                    sp<IBinder>* outHandle, sp<Layer>* outLayer);
+    status_t createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
+                                    sp<Layer>* outLayer);
 
-    status_t createEffectLayer(const sp<Client>& client, std::string name, uint32_t w, uint32_t h,
-                               uint32_t flags, LayerMetadata metadata, sp<IBinder>* outHandle,
+    status_t createEffectLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
                                sp<Layer>* outLayer);
 
-    status_t createContainerLayer(const sp<Client>& client, std::string name, uint32_t w,
-                                  uint32_t h, uint32_t flags, LayerMetadata metadata,
-                                  sp<IBinder>* outHandle, sp<Layer>* outLayer);
+    status_t createContainerLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
+                                  sp<Layer>* outLayer);
 
     status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
                          sp<IBinder>* outHandle, int32_t* outLayerId);
@@ -795,8 +789,7 @@
 
     // add a layer to SurfaceFlinger
     status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
-                            const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
-                            const wp<Layer>& parentLayer, bool addToRoot,
+                            const sp<Layer>& lbc, const wp<Layer>& parentLayer, bool addToRoot,
                             uint32_t* outTransformHint);
 
     // Traverse through all the layers and compute and cache its bounds.
@@ -1112,16 +1105,12 @@
     float mGlobalSaturationFactor = 1.0f;
     mat4 mClientColorMatrix;
 
-    // Can't be unordered_set because wp<> isn't hashable
-    std::set<wp<IBinder>> mGraphicBufferProducerList;
     size_t mMaxGraphicBufferProducerListSize = ISurfaceComposer::MAX_LAYERS;
     // If there are more GraphicBufferProducers tracked by SurfaceFlinger than
     // this threshold, then begin logging.
     size_t mGraphicBufferProducerListSizeLogThreshold =
             static_cast<size_t>(0.95 * static_cast<double>(MAX_LAYERS));
 
-    void removeGraphicBufferProducerAsync(const wp<IBinder>&);
-
     // protected by mStateLock (but we could use another lock)
     bool mLayersRemoved = false;
     bool mLayersAdded = false;
@@ -1336,19 +1325,12 @@
             GUARDED_BY(mStateLock);
     mutable Mutex mCreatedLayersLock;
     struct LayerCreatedState {
-        LayerCreatedState(const wp<Layer>& layer, const wp<Layer> parent,
-                          const wp<IBinder>& producer, bool addToRoot)
-              : layer(layer),
-                initialParent(parent),
-                initialProducer(producer),
-                addToRoot(addToRoot) {}
+        LayerCreatedState(const wp<Layer>& layer, const wp<Layer> parent, bool addToRoot)
+              : layer(layer), initialParent(parent), addToRoot(addToRoot) {}
         wp<Layer> layer;
         // Indicates the initial parent of the created layer, only used for creating layer in
         // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers.
         wp<Layer> initialParent;
-        // Indicates the initial graphic buffer producer of the created layer, only used for
-        // creating layer in SurfaceFlinger.
-        wp<IBinder> initialProducer;
         // Indicates whether the layer getting created should be added at root if there's no parent
         // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will
         // be added offscreen.
@@ -1359,7 +1341,7 @@
     // thread.
     std::unordered_map<BBinder*, std::unique_ptr<LayerCreatedState>> mCreatedLayers;
     void setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer,
-                              const wp<Layer> parent, const wp<IBinder>& producer, bool addToRoot);
+                              const wp<Layer> parent, bool addToRoot);
     auto getLayerCreatedState(const sp<IBinder>& handle);
     sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle) REQUIRES(mStateLock);
 
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 2082c42..28e8b8c 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -754,9 +754,7 @@
 }
 
 bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
-    bool isMatch(increment.surface_creation().name() == getUniqueName(LAYER_NAME, increment) &&
-                 increment.surface_creation().w() == SIZE_UPDATE &&
-                 increment.surface_creation().h() == SIZE_UPDATE);
+    bool isMatch(increment.surface_creation().name() == getUniqueName(LAYER_NAME, increment));
     if (isMatch && !foundSurface) {
         foundSurface = true;
     } else if (isMatch && foundSurface) {
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index f152ced..1ac5680 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -142,6 +142,7 @@
         "libtimestats",
         "libtimestats_atoms_proto",
         "libtimestats_proto",
+        "libtonemap",
         "libtrace_proto",
         "perfetto_trace_protos",
     ],
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 40ef6e7..52d8c35 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -535,6 +535,7 @@
 
     static void setupLatchedBuffer(CompositionTest* test, sp<BufferQueueLayer> layer) {
         // TODO: Eliminate the complexity of actually creating a buffer
+        layer->setSizeForTest(LayerProperties::WIDTH, LayerProperties::HEIGHT);
         status_t err =
                 layer->setDefaultBufferProperties(LayerProperties::WIDTH, LayerProperties::HEIGHT,
                                                   LayerProperties::FORMAT);
@@ -901,7 +902,6 @@
         FlingerLayerType layer = Base::template createLayerWithFactory<EffectLayer>(test, [test]() {
             return new EffectLayer(
                     LayerCreationArgs(test->mFlinger.flinger(), sp<Client>(), "test-layer",
-                                      LayerProperties::WIDTH, LayerProperties::HEIGHT,
                                       LayerProperties::LAYER_FLAGS, LayerMetadata()));
         });
 
@@ -940,7 +940,6 @@
         FlingerLayerType layer =
                 Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
                     LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-layer",
-                                           LayerProperties::WIDTH, LayerProperties::HEIGHT,
                                            LayerProperties::LAYER_FLAGS, LayerMetadata());
                     args.textureName = test->mFlinger.mutableTexturePool().back();
                     return new BufferQueueLayer(args);
@@ -952,7 +951,6 @@
     }
 
     static void cleanupInjectedLayers(CompositionTest* test) {
-        EXPECT_CALL(*test->mMessageQueue, postMessage(_)).Times(1);
         Base::cleanupInjectedLayers(test);
     }
 
@@ -990,7 +988,6 @@
 
     static FlingerLayerType createLayer(CompositionTest* test) {
         LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-container-layer",
-                               LayerProperties::WIDTH, LayerProperties::HEIGHT,
                                LayerProperties::LAYER_FLAGS, LayerMetadata());
         FlingerLayerType layer = new ContainerLayer(args);
         Base::template initLayerDrawingStateAndComputeBounds(test, layer);
diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
index 010c675..cd2fc74 100644
--- a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
@@ -114,8 +114,7 @@
 
 sp<BufferStateLayer> FpsReporterTest::createBufferStateLayer(LayerMetadata metadata = {}) {
     sp<Client> client;
-    LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT,
-                           LAYER_FLAGS, metadata);
+    LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS, metadata);
     return new BufferStateLayer(args);
 }
 
diff --git a/services/surfaceflinger/tests/unittests/GameModeTest.cpp b/services/surfaceflinger/tests/unittests/GameModeTest.cpp
index 3fa1a2c..d645942 100644
--- a/services/surfaceflinger/tests/unittests/GameModeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/GameModeTest.cpp
@@ -53,7 +53,7 @@
 
     sp<BufferStateLayer> createBufferStateLayer() {
         sp<Client> client;
-        LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0,
+        LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0,
                                LayerMetadata());
         return new BufferStateLayer(args);
     }
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index e388a6f..1e6e336 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -91,15 +91,14 @@
 
 sp<BufferStateLayer> RefreshRateSelectionTest::createBufferStateLayer() {
     sp<Client> client;
-    LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT,
-                           LAYER_FLAGS, LayerMetadata());
+    LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", LAYER_FLAGS,
+                           LayerMetadata());
     return new BufferStateLayer(args);
 }
 
 sp<EffectLayer> RefreshRateSelectionTest::createEffectLayer() {
     sp<Client> client;
-    LayerCreationArgs args(mFlinger.flinger(), client, "color-layer", WIDTH, HEIGHT, LAYER_FLAGS,
-                           LayerMetadata());
+    LayerCreationArgs args(mFlinger.flinger(), client, "color-layer", LAYER_FLAGS, LayerMetadata());
     return new EffectLayer(args);
 }
 
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index d021178..360f9c6 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -70,8 +70,8 @@
     std::string name() override { return "BufferStateLayer"; }
     sp<Layer> createLayer(TestableSurfaceFlinger& flinger) override {
         sp<Client> client;
-        LayerCreationArgs args(flinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT,
-                               LAYER_FLAGS, LayerMetadata());
+        LayerCreationArgs args(flinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS,
+                               LayerMetadata());
         return new BufferStateLayer(args);
     }
 };
@@ -81,7 +81,7 @@
     std::string name() override { return "EffectLayer"; }
     sp<Layer> createLayer(TestableSurfaceFlinger& flinger) override {
         sp<Client> client;
-        LayerCreationArgs args(flinger.flinger(), client, "color-layer", WIDTH, HEIGHT, LAYER_FLAGS,
+        LayerCreationArgs args(flinger.flinger(), client, "color-layer", LAYER_FLAGS,
                                LayerMetadata());
         return new EffectLayer(args);
     }
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index bd6a780..deeb785 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -57,7 +57,7 @@
 
     sp<BufferStateLayer> createBufferStateLayer() {
         sp<Client> client;
-        LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0,
+        LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0,
                                LayerMetadata());
         return new BufferStateLayer(args);
     }
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index bf69704..704340d 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -57,7 +57,7 @@
 
     sp<BufferStateLayer> createBufferStateLayer() {
         sp<Client> client;
-        LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0,
+        LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0,
                                LayerMetadata());
         return new BufferStateLayer(args);
     }
diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
index e4f7469..ade4fbb 100644
--- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
@@ -100,8 +100,7 @@
 sp<BufferStateLayer> TunnelModeEnabledReporterTest::createBufferStateLayer(
         LayerMetadata metadata = {}) {
     sp<Client> client;
-    LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT,
-                           LAYER_FLAGS, metadata);
+    LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS, metadata);
     return new BufferStateLayer(args);
 }
 
diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
index ba2e4db..8b48e1c 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
@@ -25,7 +25,7 @@
 class MockLayer : public Layer {
 public:
     MockLayer(SurfaceFlinger* flinger, std::string name)
-          : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 800, 600, 0, {})) {}
+          : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) {}
     explicit MockLayer(SurfaceFlinger* flinger) : MockLayer(flinger, "TestLayer") {}
 
     MOCK_CONST_METHOD0(getType, const char*());