// SPDX-License-Identifier: GPL-2.0

// Copyright (C) 2025 Google LLC.

//! This module defines the `Thread` type, which represents a userspace thread that is using
//! binder.
//!
//! The `Process` object stores all of the threads in an rb tree.

use kernel::{
    bindings,
    fs::{File, LocalFile},
    list::{AtomicTracker, List, ListArc, ListLinks, TryNewListArc},
    prelude::*,
    security,
    seq_file::SeqFile,
    seq_print,
    sync::atomic::{ordering::Relaxed, Atomic},
    sync::poll::{PollCondVar, PollTable},
    sync::{aref::ARef, Arc, SpinLock},
    task::Task,
    uaccess::{UserPtr, UserSlice, UserSliceReader},
    uapi,
};

use crate::{
    allocation::{Allocation, AllocationView, BinderObject, BinderObjectRef, NewAllocation},
    defs::*,
    error::BinderResult,
    process::{GetWorkOrRegister, Process},
    ptr_align,
    stats::GLOBAL_STATS,
    transaction::{Transaction, TransactionInfo},
    BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverCode, DeliverToRead,
};

use core::mem::size_of;

fn is_aligned(value: usize, to: usize) -> bool {
    value % to == 0
}

/// Stores the layout of the scatter-gather entries. This is used during the `translate_objects`
/// call and is discarded when it returns.
struct ScatterGatherState {
    /// A struct that tracks the amount of unused buffer space.
    unused_buffer_space: UnusedBufferSpace,
    /// Scatter-gather entries to copy.
    sg_entries: KVec<ScatterGatherEntry>,
    /// Indexes into `sg_entries` corresponding to the last binder_buffer_object that
    /// was processed and all of its ancestors. The array is in sorted order.
    ancestors: KVec<usize>,
}

/// This entry specifies an additional buffer that should be copied using the scatter-gather
/// mechanism.
struct ScatterGatherEntry {
    /// The index in the offset array of the BINDER_TYPE_PTR that this entry originates from.
    obj_index: usize,
    /// Offset in target buffer.
    offset: usize,
    /// User address in source buffer.
    sender_uaddr: usize,
    /// Number of bytes to copy.
    length: usize,
    /// The minimum offset of the next fixup in this buffer.
    fixup_min_offset: usize,
    /// The offsets within this buffer that contain pointers which should be translated.
    pointer_fixups: KVec<PointerFixupEntry>,
}

/// This entry specifies that a fixup should happen at `target_offset` of the
/// buffer.
enum PointerFixupEntry {
    /// A fixup for a `binder_buffer_object`.
    Fixup {
        /// The translated pointer to write.
        pointer_value: u64,
        /// The offset at which the value should be written. The offset is relative
        /// to the original buffer.
        target_offset: usize,
    },
    /// A skip for a `binder_fd_array_object`.
    Skip {
        /// The number of bytes to skip.
        skip: usize,
        /// The offset at which the skip should happen. The offset is relative
        /// to the original buffer.
        target_offset: usize,
    },
}

/// Return type of `apply_and_validate_fixup_in_parent`.
struct ParentFixupInfo {
    /// The index of the parent buffer in `sg_entries`.
    parent_sg_index: usize,
    /// The number of ancestors of the buffer.
    ///
    /// The buffer is considered an ancestor of itself, so this is always at
    /// least one.
    num_ancestors: usize,
    /// New value of `fixup_min_offset` if this fixup is applied.
    new_min_offset: usize,
    /// The offset of the fixup in the target buffer.
    target_offset: usize,
}

impl ScatterGatherState {
    /// Called when a `binder_buffer_object` or `binder_fd_array_object` tries
    /// to access a region in its parent buffer. These accesses have various
    /// restrictions, which this method verifies.
    ///
    /// The `parent_offset` and `length` arguments describe the offset and
    /// length of the access in the parent buffer.
    ///
    /// # Detailed restrictions
    ///
    /// Obviously the fixup must be in-bounds for the parent buffer.
    ///
    /// For safety reasons, we only allow fixups inside a buffer to happen
    /// at increasing offsets; additionally, we only allow fixup on the last
    /// buffer object that was verified, or one of its parents.
    ///
    /// Example of what is allowed:
    ///
    /// A
    ///   B (parent = A, offset = 0)
    ///   C (parent = A, offset = 16)
    ///     D (parent = C, offset = 0)
    ///   E (parent = A, offset = 32) // min_offset is 16 (C.parent_offset)
    ///
    /// Examples of what is not allowed:
    ///
    /// Decreasing offsets within the same parent:
    /// A
    ///   C (parent = A, offset = 16)
    ///   B (parent = A, offset = 0) // decreasing offset within A
    ///
    /// Arcerring to a parent that wasn't the last object or any of its parents:
    /// A
    ///   B (parent = A, offset = 0)
    ///   C (parent = A, offset = 0)
    ///   C (parent = A, offset = 16)
    ///     D (parent = B, offset = 0) // B is not A or any of A's parents
    fn validate_parent_fixup(
        &self,
        parent: usize,
        parent_offset: usize,
        length: usize,
    ) -> Result<ParentFixupInfo> {
        // Using `position` would also be correct, but `rposition` avoids
        // quadratic running times.
        let ancestors_i = self
            .ancestors
            .iter()
            .copied()
            .rposition(|sg_idx| self.sg_entries[sg_idx].obj_index == parent)
            .ok_or(EINVAL)?;
        let sg_idx = self.ancestors[ancestors_i];
        let sg_entry = match self.sg_entries.get(sg_idx) {
            Some(sg_entry) => sg_entry,
            None => {
                pr_err!(
                    "self.ancestors[{}] is {}, but self.sg_entries.len() is {}",
                    ancestors_i,
                    sg_idx,
                    self.sg_entries.len()
                );
                return Err(EINVAL);
            }
        };
        if sg_entry.fixup_min_offset > parent_offset {
            pr_warn!(
                "validate_parent_fixup: fixup_min_offset={}, parent_offset={}",
                sg_entry.fixup_min_offset,
                parent_offset
            );
            return Err(EINVAL);
        }
        let new_min_offset = parent_offset.checked_add(length).ok_or(EINVAL)?;
        if new_min_offset > sg_entry.length {
            pr_warn!(
                "validate_parent_fixup: new_min_offset={}, sg_entry.length={}",
                new_min_offset,
                sg_entry.length
            );
            return Err(EINVAL);
        }
        let target_offset = sg_entry.offset.checked_add(parent_offset).ok_or(EINVAL)?;
        // The `ancestors_i + 1` operation can't overflow since the output of the addition is at
        // most `self.ancestors.len()`, which also fits in a usize.
        Ok(ParentFixupInfo {
            parent_sg_index: sg_idx,
            num_ancestors: ancestors_i + 1,
            new_min_offset,
            target_offset,
        })
    }
}

/// Keeps track of how much unused buffer space is left. The initial amount is the number of bytes
/// requested by the user using the `buffers_size` field of `binder_transaction_data_sg`. Each time
/// we translate an object of type `BINDER_TYPE_PTR`, some of the unused buffer space is consumed.
struct UnusedBufferSpace {
    /// The start of the remaining space.
    offset: usize,
    /// The end of the remaining space.
    limit: usize,
}
impl UnusedBufferSpace {
    /// Claim the next `size` bytes from the unused buffer space. The offset for the claimed chunk
    /// into the buffer is returned.
    fn claim_next(&mut self, size: usize) -> Result<usize> {
        // We require every chunk to be aligned.
        let size = ptr_align(size).ok_or(EINVAL)?;
        let new_offset = self.offset.checked_add(size).ok_or(EINVAL)?;

        if new_offset <= self.limit {
            let offset = self.offset;
            self.offset = new_offset;
            Ok(offset)
        } else {
            Err(EINVAL)
        }
    }
}

pub(crate) enum PushWorkRes {
    Ok,
    FailedDead(DLArc<dyn DeliverToRead>),
}

impl PushWorkRes {
    fn is_ok(&self) -> bool {
        match self {
            PushWorkRes::Ok => true,
            PushWorkRes::FailedDead(_) => false,
        }
    }
}

/// The fields of `Thread` protected by the spinlock.
struct InnerThread {
    /// Determines the looper state of the thread. It is a bit-wise combination of the constants
    /// prefixed with `LOOPER_`.
    looper_flags: u32,

    /// Determines whether the looper should return.
    looper_need_return: bool,

    /// Determines if thread is dead.
    is_dead: bool,

    /// Work item used to deliver error codes to the thread that started a transaction. Stored here
    /// so that it can be reused.
    reply_work: DArc<ThreadError>,

    /// Work item used to deliver error codes to the current thread. Stored here so that it can be
    /// reused.
    return_work: DArc<ThreadError>,

    /// Determines whether the work list below should be processed. When set to false, `work_list`
    /// is treated as if it were empty.
    process_work_list: bool,
    /// List of work items to deliver to userspace.
    work_list: List<DTRWrap<dyn DeliverToRead>>,
    current_transaction: Option<DArc<Transaction>>,

    /// Extended error information for this thread.
    extended_error: ExtendedError,
}

const LOOPER_REGISTERED: u32 = 0x01;
const LOOPER_ENTERED: u32 = 0x02;
const LOOPER_EXITED: u32 = 0x04;
const LOOPER_INVALID: u32 = 0x08;
const LOOPER_WAITING: u32 = 0x10;
const LOOPER_WAITING_PROC: u32 = 0x20;
const LOOPER_POLL: u32 = 0x40;

impl InnerThread {
    fn new() -> Result<Self> {
        fn next_err_id() -> u32 {
            static EE_ID: Atomic<u32> = Atomic::new(0);
            EE_ID.fetch_add(1, Relaxed)
        }

        Ok(Self {
            looper_flags: 0,
            looper_need_return: false,
            is_dead: false,
            process_work_list: false,
            reply_work: ThreadError::try_new()?,
            return_work: ThreadError::try_new()?,
            work_list: List::new(),
            current_transaction: None,
            extended_error: ExtendedError::new(next_err_id(), BR_OK, 0),
        })
    }

    fn pop_work(&mut self) -> Option<DLArc<dyn DeliverToRead>> {
        if !self.process_work_list {
            return None;
        }

        let ret = self.work_list.pop_front();
        self.process_work_list = !self.work_list.is_empty();
        ret
    }

    fn push_work(&mut self, work: DLArc<dyn DeliverToRead>) -> PushWorkRes {
        if self.is_dead {
            PushWorkRes::FailedDead(work)
        } else {
            self.work_list.push_back(work);
            self.process_work_list = true;
            PushWorkRes::Ok
        }
    }

    fn push_reply_work(&mut self, code: u32) {
        if let Ok(work) = ListArc::try_from_arc(self.reply_work.clone()) {
            work.set_error_code(code);
            self.push_work(work);
        } else {
            pr_warn!("Thread reply work is already in use.");
        }
    }

    fn push_return_work(&mut self, reply: u32) {
        if let Ok(work) = ListArc::try_from_arc(self.return_work.clone()) {
            work.set_error_code(reply);
            self.push_work(work);
        } else {
            pr_warn!("Thread return work is already in use.");
        }
    }

    /// Used to push work items that do not need to be processed immediately and can wait until the
    /// thread gets another work item.
    fn push_work_deferred(&mut self, work: DLArc<dyn DeliverToRead>) {
        self.work_list.push_back(work);
    }

    /// Fetches the transaction this thread can reply to. If the thread has a pending transaction
    /// (that it could respond to) but it has also issued a transaction, it must first wait for the
    /// previously-issued transaction to complete.
    ///
    /// The `thread` parameter should be the thread containing this `ThreadInner`.
    fn pop_transaction_to_reply(&mut self, thread: &Thread) -> Result<DArc<Transaction>> {
        let transaction = self.current_transaction.take().ok_or(EINVAL)?;
        if core::ptr::eq(thread, transaction.from.as_ref()) {
            self.current_transaction = Some(transaction);
            return Err(EINVAL);
        }
        // Find a new current transaction for this thread.
        self.current_transaction = transaction.find_from(thread).cloned();
        Ok(transaction)
    }

    fn pop_transaction_replied(&mut self, transaction: &DArc<Transaction>) -> bool {
        match self.current_transaction.take() {
            None => false,
            Some(old) => {
                if !Arc::ptr_eq(transaction, &old) {
                    self.current_transaction = Some(old);
                    return false;
                }
                self.current_transaction = old.clone_next();
                true
            }
        }
    }

    fn looper_enter(&mut self) {
        self.looper_flags |= LOOPER_ENTERED;
        if self.looper_flags & LOOPER_REGISTERED != 0 {
            self.looper_flags |= LOOPER_INVALID;
        }
    }

    fn looper_register(&mut self, valid: bool) {
        self.looper_flags |= LOOPER_REGISTERED;
        if !valid || self.looper_flags & LOOPER_ENTERED != 0 {
            self.looper_flags |= LOOPER_INVALID;
        }
    }

    fn looper_exit(&mut self) {
        self.looper_flags |= LOOPER_EXITED;
    }

    /// Determines whether the thread is part of a pool, i.e., if it is a looper.
    fn is_looper(&self) -> bool {
        self.looper_flags & (LOOPER_ENTERED | LOOPER_REGISTERED) != 0
    }

    /// Determines whether the thread should attempt to fetch work items from the process queue.
    /// This is generally case when the thread is registered as a looper and not part of a
    /// transaction stack. But if there is local work, we want to return to userspace before we
    /// deliver any remote work.
    fn should_use_process_work_queue(&self) -> bool {
        self.current_transaction.is_none() && !self.process_work_list && self.is_looper()
    }

    fn poll(&mut self) -> u32 {
        self.looper_flags |= LOOPER_POLL;
        if self.process_work_list || self.looper_need_return {
            bindings::POLLIN
        } else {
            0
        }
    }
}

/// This represents a thread that's used with binder.
#[pin_data]
pub(crate) struct Thread {
    pub(crate) id: i32,
    pub(crate) process: Arc<Process>,
    pub(crate) task: ARef<Task>,
    #[pin]
    inner: SpinLock<InnerThread>,
    #[pin]
    work_condvar: PollCondVar,
    /// Used to insert this thread into the process' `ready_threads` list.
    ///
    /// INVARIANT: May never be used for any other list than the `self.process.ready_threads`.
    #[pin]
    links: ListLinks,
    #[pin]
    links_track: AtomicTracker,
}

kernel::list::impl_list_arc_safe! {
    impl ListArcSafe<0> for Thread {
        tracked_by links_track: AtomicTracker;
    }
}
kernel::list::impl_list_item! {
    impl ListItem<0> for Thread {
        using ListLinks { self.links };
    }
}

impl Thread {
    pub(crate) fn new(id: i32, process: Arc<Process>) -> Result<Arc<Self>> {
        let inner = InnerThread::new()?;

        Arc::pin_init(
            try_pin_init!(Thread {
                id,
                process,
                task: ARef::from(&**kernel::current!()),
                inner <- kernel::new_spinlock!(inner, "Thread::inner"),
                work_condvar <- kernel::new_poll_condvar!("Thread::work_condvar"),
                links <- ListLinks::new(),
                links_track <- AtomicTracker::new(),
            }),
            GFP_KERNEL,
        )
    }

    #[inline(never)]
    pub(crate) fn debug_print(self: &Arc<Self>, m: &SeqFile, print_all: bool) -> Result<()> {
        let inner = self.inner.lock();

        if print_all || inner.current_transaction.is_some() || !inner.work_list.is_empty() {
            seq_print!(
                m,
                "  thread {}: l {:02x} need_return {}\n",
                self.id,
                inner.looper_flags,
                inner.looper_need_return,
            );
        }

        let mut t_opt = inner.current_transaction.as_ref();
        while let Some(t) = t_opt {
            if Arc::ptr_eq(&t.from, self) {
                t.debug_print_inner(m, "    outgoing transaction ");
                t_opt = t.from_parent.as_ref();
            } else if Arc::ptr_eq(&t.to, &self.process) {
                t.debug_print_inner(m, "    incoming transaction ");
                t_opt = t.find_from(self);
            } else {
                t.debug_print_inner(m, "    bad transaction ");
                t_opt = None;
            }
        }

        for work in &inner.work_list {
            work.debug_print(m, "    ", "    pending transaction ")?;
        }
        Ok(())
    }

    pub(crate) fn get_extended_error(&self, data: UserSlice) -> Result {
        let mut writer = data.writer();
        let ee = self.inner.lock().extended_error;
        writer.write(&ee)?;
        Ok(())
    }

    pub(crate) fn set_current_transaction(&self, transaction: DArc<Transaction>) {
        self.inner.lock().current_transaction = Some(transaction);
    }

    pub(crate) fn has_current_transaction(&self) -> bool {
        self.inner.lock().current_transaction.is_some()
    }

    /// Attempts to fetch a work item from the thread-local queue. The behaviour if the queue is
    /// empty depends on `wait`: if it is true, the function waits for some work to be queued (or a
    /// signal); otherwise it returns indicating that none is available.
    // #[export_name] is a temporary workaround so that ps output does not become unreadable from
    // mangled symbol names.
    #[export_name = "rust_binder_waitlcl"]
    fn get_work_local(self: &Arc<Self>, wait: bool) -> Result<Option<DLArc<dyn DeliverToRead>>> {
        {
            let mut inner = self.inner.lock();
            if inner.looper_need_return {
                return Ok(inner.pop_work());
            }
        }

        // Try once if the caller does not want to wait.
        if !wait {
            return self.inner.lock().pop_work().ok_or(EAGAIN).map(Some);
        }

        // Loop waiting only on the local queue (i.e., not registering with the process queue).
        let mut inner = self.inner.lock();
        loop {
            if let Some(work) = inner.pop_work() {
                return Ok(Some(work));
            }

            inner.looper_flags |= LOOPER_WAITING;
            let signal_pending = self.work_condvar.wait_interruptible_freezable(&mut inner);
            inner.looper_flags &= !LOOPER_WAITING;

            if signal_pending {
                return Err(EINTR);
            }
            if inner.looper_need_return {
                return Ok(None);
            }
        }
    }

    /// Attempts to fetch a work item from the thread-local queue, falling back to the process-wide
    /// queue if none is available locally.
    ///
    /// This must only be called when the thread is not participating in a transaction chain. If it
    /// is, the local version (`get_work_local`) should be used instead.
    // #[export_name] is a temporary workaround so that ps output does not become unreadable from
    // mangled symbol names.
    #[export_name = "rust_binder_wait"]
    fn get_work(self: &Arc<Self>, wait: bool) -> Result<Option<DLArc<dyn DeliverToRead>>> {
        // Try to get work from the thread's work queue, using only a local lock.
        {
            let mut inner = self.inner.lock();
            if let Some(work) = inner.pop_work() {
                return Ok(Some(work));
            }
            if inner.looper_need_return {
                drop(inner);
                return Ok(self.process.get_work());
            }
        }

        // If the caller doesn't want to wait, try to grab work from the process queue.
        //
        // We know nothing will have been queued directly to the thread queue because it is not in
        // a transaction and it is not in the process' ready list.
        if !wait {
            return self.process.get_work().ok_or(EAGAIN).map(Some);
        }

        // Get work from the process queue. If none is available, atomically register as ready.
        let reg = match self.process.get_work_or_register(self) {
            GetWorkOrRegister::Work(work) => return Ok(Some(work)),
            GetWorkOrRegister::Register(reg) => reg,
        };

        let mut inner = self.inner.lock();
        loop {
            if let Some(work) = inner.pop_work() {
                return Ok(Some(work));
            }

            inner.looper_flags |= LOOPER_WAITING | LOOPER_WAITING_PROC;
            let signal_pending = self.work_condvar.wait_interruptible_freezable(&mut inner);
            inner.looper_flags &= !(LOOPER_WAITING | LOOPER_WAITING_PROC);

            if signal_pending || inner.looper_need_return {
                // We need to return now. We need to pull the thread off the list of ready threads
                // (by dropping `reg`), then check the state again after it's off the list to
                // ensure that something was not queued in the meantime. If something has been
                // queued, we just return it (instead of the error).
                drop(inner);
                drop(reg);

                let res = match self.inner.lock().pop_work() {
                    Some(work) => Ok(Some(work)),
                    None if signal_pending => Err(EINTR),
                    None => Ok(None),
                };
                return res;
            }
        }
    }

    /// Push the provided work item to be delivered to user space via this thread.
    ///
    /// Returns whether the item was successfully pushed. This can only fail if the thread is dead.
    pub(crate) fn push_work(&self, work: DLArc<dyn DeliverToRead>) -> PushWorkRes {
        let sync = work.should_sync_wakeup();

        let res = self.inner.lock().push_work(work);

        if res.is_ok() {
            if sync {
                self.work_condvar.notify_sync();
            } else {
                self.work_condvar.notify_one();
            }
        }

        res
    }

    /// Attempts to push to given work item to the thread if it's a looper thread (i.e., if it's
    /// part of a thread pool) and is alive. Otherwise, push the work item to the process instead.
    pub(crate) fn push_work_if_looper(&self, work: DLArc<dyn DeliverToRead>) -> BinderResult {
        let mut inner = self.inner.lock();
        if inner.is_looper() && !inner.is_dead {
            inner.push_work(work);
            Ok(())
        } else {
            drop(inner);
            self.process.push_work(work)
        }
    }

    pub(crate) fn push_work_deferred(&self, work: DLArc<dyn DeliverToRead>) {
        self.inner.lock().push_work_deferred(work);
    }

    pub(crate) fn push_return_work(&self, reply: u32) {
        self.inner.lock().push_return_work(reply);
    }

    fn translate_object(
        &self,
        obj_index: usize,
        offset: usize,
        object: BinderObjectRef<'_>,
        view: &mut AllocationView<'_>,
        allow_fds: bool,
        sg_state: &mut ScatterGatherState,
    ) -> BinderResult {
        match object {
            BinderObjectRef::Binder(obj) => {
                let strong = obj.hdr.type_ == BINDER_TYPE_BINDER;
                // SAFETY: `binder` is a `binder_uintptr_t`; any bit pattern is a valid
                // representation.
                let ptr = unsafe { obj.__bindgen_anon_1.binder } as _;
                let cookie = obj.cookie as _;
                let flags = obj.flags as _;
                let node = self
                    .process
                    .as_arc_borrow()
                    .get_node(ptr, cookie, flags, strong, self)?;
                security::binder_transfer_binder(&self.process.cred, &view.alloc.process.cred)?;
                view.transfer_binder_object(offset, obj, strong, node)?;
            }
            BinderObjectRef::Handle(obj) => {
                let strong = obj.hdr.type_ == BINDER_TYPE_HANDLE;
                // SAFETY: `handle` is a `u32`; any bit pattern is a valid representation.
                let handle = unsafe { obj.__bindgen_anon_1.handle } as _;
                let node = self.process.get_node_from_handle(handle, strong)?;
                security::binder_transfer_binder(&self.process.cred, &view.alloc.process.cred)?;
                view.transfer_binder_object(offset, obj, strong, node)?;
            }
            BinderObjectRef::Fd(obj) => {
                if !allow_fds {
                    return Err(EPERM.into());
                }

                // SAFETY: `fd` is a `u32`; any bit pattern is a valid representation.
                let fd = unsafe { obj.__bindgen_anon_1.fd };
                let file = LocalFile::fget(fd)?;
                // SAFETY: The binder driver never calls `fdget_pos` and this code runs from an
                // ioctl, so there are no active calls to `fdget_pos` on this thread.
                let file = unsafe { LocalFile::assume_no_fdget_pos(file) };
                security::binder_transfer_file(
                    &self.process.cred,
                    &view.alloc.process.cred,
                    &file,
                )?;

                let mut obj_write = BinderFdObject::default();
                obj_write.hdr.type_ = BINDER_TYPE_FD;
                // This will be overwritten with the actual fd when the transaction is received.
                obj_write.__bindgen_anon_1.fd = u32::MAX;
                obj_write.cookie = obj.cookie;
                view.write::<BinderFdObject>(offset, &obj_write)?;

                const FD_FIELD_OFFSET: usize =
                    core::mem::offset_of!(uapi::binder_fd_object, __bindgen_anon_1.fd);

                let field_offset = offset + FD_FIELD_OFFSET;
                crate::trace::trace_transaction_fd_send(view.alloc.debug_id, fd, field_offset);

                view.alloc.info_add_fd(file, field_offset, false)?;
            }
            BinderObjectRef::Ptr(obj) => {
                let obj_length = obj.length.try_into().map_err(|_| EINVAL)?;
                let alloc_offset = match sg_state.unused_buffer_space.claim_next(obj_length) {
                    Ok(alloc_offset) => alloc_offset,
                    Err(err) => {
                        pr_warn!(
                            "Failed to claim space for a BINDER_TYPE_PTR. (offset: {}, limit: {}, size: {})",
                            sg_state.unused_buffer_space.offset,
                            sg_state.unused_buffer_space.limit,
                            obj_length,
                        );
                        return Err(err.into());
                    }
                };

                let sg_state_idx = sg_state.sg_entries.len();
                sg_state.sg_entries.push(
                    ScatterGatherEntry {
                        obj_index,
                        offset: alloc_offset,
                        sender_uaddr: obj.buffer as _,
                        length: obj_length,
                        pointer_fixups: KVec::new(),
                        fixup_min_offset: 0,
                    },
                    GFP_KERNEL,
                )?;

                let buffer_ptr_in_user_space = (view.alloc.ptr + alloc_offset) as u64;

                if obj.flags & uapi::BINDER_BUFFER_FLAG_HAS_PARENT == 0 {
                    sg_state.ancestors.clear();
                    sg_state.ancestors.push(sg_state_idx, GFP_KERNEL)?;
                } else {
                    // Another buffer also has a pointer to this buffer, and we need to fixup that
                    // pointer too.

                    let parent_index = usize::try_from(obj.parent).map_err(|_| EINVAL)?;
                    let parent_offset = usize::try_from(obj.parent_offset).map_err(|_| EINVAL)?;

                    let info = sg_state.validate_parent_fixup(
                        parent_index,
                        parent_offset,
                        size_of::<u64>(),
                    )?;

                    sg_state.ancestors.truncate(info.num_ancestors);
                    sg_state.ancestors.push(sg_state_idx, GFP_KERNEL)?;

                    let parent_entry = match sg_state.sg_entries.get_mut(info.parent_sg_index) {
                        Some(parent_entry) => parent_entry,
                        None => {
                            pr_err!(
                                "validate_parent_fixup returned index out of bounds for sg.entries"
                            );
                            return Err(EINVAL.into());
                        }
                    };

                    parent_entry.fixup_min_offset = info.new_min_offset;
                    parent_entry.pointer_fixups.push(
                        PointerFixupEntry::Fixup {
                            pointer_value: buffer_ptr_in_user_space,
                            target_offset: info.target_offset,
                        },
                        GFP_KERNEL,
                    )?;
                }

                let mut obj_write = BinderBufferObject::default();
                obj_write.hdr.type_ = BINDER_TYPE_PTR;
                obj_write.flags = obj.flags;
                obj_write.buffer = buffer_ptr_in_user_space;
                obj_write.length = obj.length;
                obj_write.parent = obj.parent;
                obj_write.parent_offset = obj.parent_offset;
                view.write::<BinderBufferObject>(offset, &obj_write)?;
            }
            BinderObjectRef::Fda(obj) => {
                if !allow_fds {
                    return Err(EPERM.into());
                }
                let parent_index = usize::try_from(obj.parent).map_err(|_| EINVAL)?;
                let parent_offset = usize::try_from(obj.parent_offset).map_err(|_| EINVAL)?;
                let num_fds = usize::try_from(obj.num_fds).map_err(|_| EINVAL)?;
                let fds_len = num_fds.checked_mul(size_of::<u32>()).ok_or(EINVAL)?;

                if !is_aligned(parent_offset, size_of::<u32>()) {
                    return Err(EINVAL.into());
                }

                let info = sg_state.validate_parent_fixup(parent_index, parent_offset, fds_len)?;
                view.alloc.info_add_fd_reserve(num_fds)?;

                sg_state.ancestors.truncate(info.num_ancestors);
                let parent_entry = match sg_state.sg_entries.get_mut(info.parent_sg_index) {
                    Some(parent_entry) => parent_entry,
                    None => {
                        pr_err!(
                            "validate_parent_fixup returned index out of bounds for sg.entries"
                        );
                        return Err(EINVAL.into());
                    }
                };

                if !is_aligned(parent_entry.sender_uaddr, size_of::<u32>()) {
                    return Err(EINVAL.into());
                }

                parent_entry.fixup_min_offset = info.new_min_offset;
                parent_entry
                    .pointer_fixups
                    .push(
                        PointerFixupEntry::Skip {
                            skip: fds_len,
                            target_offset: info.target_offset,
                        },
                        GFP_KERNEL,
                    )
                    .map_err(|_| ENOMEM)?;

                let fda_uaddr = parent_entry
                    .sender_uaddr
                    .checked_add(parent_offset)
                    .ok_or(EINVAL)?;

                let mut fda_bytes = KVec::new();
                UserSlice::new(UserPtr::from_addr(fda_uaddr as _), fds_len)
                    .read_all(&mut fda_bytes, GFP_KERNEL)?;

                if fds_len != fda_bytes.len() {
                    pr_err!("UserSlice::read_all returned wrong length in BINDER_TYPE_FDA");
                    return Err(EINVAL.into());
                }

                for i in (0..fds_len).step_by(size_of::<u32>()) {
                    let fd = {
                        let mut fd_bytes = [0u8; size_of::<u32>()];
                        fd_bytes.copy_from_slice(&fda_bytes[i..i + size_of::<u32>()]);
                        u32::from_ne_bytes(fd_bytes)
                    };

                    let file = LocalFile::fget(fd)?;
                    // SAFETY: The binder driver never calls `fdget_pos` and this code runs from an
                    // ioctl, so there are no active calls to `fdget_pos` on this thread.
                    let file = unsafe { LocalFile::assume_no_fdget_pos(file) };
                    security::binder_transfer_file(
                        &self.process.cred,
                        &view.alloc.process.cred,
                        &file,
                    )?;

                    // The `validate_parent_fixup` call ensuers that this addition will not
                    // overflow.
                    view.alloc.info_add_fd(file, info.target_offset + i, true)?;
                }
                drop(fda_bytes);

                let mut obj_write = BinderFdArrayObject::default();
                obj_write.hdr.type_ = BINDER_TYPE_FDA;
                obj_write.num_fds = obj.num_fds;
                obj_write.parent = obj.parent;
                obj_write.parent_offset = obj.parent_offset;
                view.write::<BinderFdArrayObject>(offset, &obj_write)?;
            }
        }
        Ok(())
    }

    fn apply_sg(&self, alloc: &mut Allocation, sg_state: &mut ScatterGatherState) -> BinderResult {
        for sg_entry in &mut sg_state.sg_entries {
            let mut end_of_previous_fixup = sg_entry.offset;
            let offset_end = sg_entry.offset.checked_add(sg_entry.length).ok_or(EINVAL)?;

            let mut reader =
                UserSlice::new(UserPtr::from_addr(sg_entry.sender_uaddr), sg_entry.length).reader();
            for fixup in &mut sg_entry.pointer_fixups {
                let (fixup_len, fixup_offset) = match fixup {
                    PointerFixupEntry::Fixup { target_offset, .. } => {
                        (size_of::<u64>(), *target_offset)
                    }
                    PointerFixupEntry::Skip {
                        skip,
                        target_offset,
                    } => (*skip, *target_offset),
                };

                let target_offset_end = fixup_offset.checked_add(fixup_len).ok_or(EINVAL)?;
                if fixup_offset < end_of_previous_fixup || offset_end < target_offset_end {
                    pr_warn!(
                        "Fixups oob {} {} {} {}",
                        fixup_offset,
                        end_of_previous_fixup,
                        offset_end,
                        target_offset_end
                    );
                    return Err(EINVAL.into());
                }

                let copy_off = end_of_previous_fixup;
                let copy_len = fixup_offset - end_of_previous_fixup;
                if let Err(err) = alloc.copy_into(&mut reader, copy_off, copy_len) {
                    pr_warn!("Failed copying into alloc: {:?}", err);
                    return Err(err.into());
                }
                if let PointerFixupEntry::Fixup { pointer_value, .. } = fixup {
                    let res = alloc.write::<u64>(fixup_offset, pointer_value);
                    if let Err(err) = res {
                        pr_warn!("Failed copying ptr into alloc: {:?}", err);
                        return Err(err.into());
                    }
                }
                if let Err(err) = reader.skip(fixup_len) {
                    pr_warn!("Failed skipping {} from reader: {:?}", fixup_len, err);
                    return Err(err.into());
                }
                end_of_previous_fixup = target_offset_end;
            }
            let copy_off = end_of_previous_fixup;
            let copy_len = offset_end - end_of_previous_fixup;
            if let Err(err) = alloc.copy_into(&mut reader, copy_off, copy_len) {
                pr_warn!("Failed copying remainder into alloc: {:?}", err);
                return Err(err.into());
            }
        }
        Ok(())
    }

    /// This method copies the payload of a transaction into the target process.
    ///
    /// The resulting payload will have several different components, which will be stored next to
    /// each other in the allocation. Furthermore, various objects can be embedded in the payload,
    /// and those objects have to be translated so that they make sense to the target transaction.
    pub(crate) fn copy_transaction_data(
        &self,
        to_process: Arc<Process>,
        info: &mut TransactionInfo,
        debug_id: usize,
        allow_fds: bool,
        txn_security_ctx_offset: Option<&mut usize>,
    ) -> BinderResult<NewAllocation> {
        let mut secctx = if let Some(offset) = txn_security_ctx_offset {
            let secid = self.process.cred.get_secid();
            let ctx = match security::SecurityCtx::from_secid(secid) {
                Ok(ctx) => ctx,
                Err(err) => {
                    pr_warn!("Failed to get security ctx for id {}: {:?}", secid, err);
                    return Err(err.into());
                }
            };
            Some((offset, ctx))
        } else {
            None
        };

        let data_size = info.data_size;
        let aligned_data_size = ptr_align(data_size).ok_or(EINVAL)?;
        let offsets_size = info.offsets_size;
        let buffers_size = info.buffers_size;
        let aligned_secctx_size = match secctx.as_ref() {
            Some((_offset, ctx)) => ptr_align(ctx.len()).ok_or(EINVAL)?,
            None => 0,
        };

        if !is_aligned(offsets_size, size_of::<u64>()) {
            return Err(EINVAL.into());
        }
        if !is_aligned(buffers_size, size_of::<u64>()) {
            return Err(EINVAL.into());
        }

        // This guarantees that at least `sizeof(usize)` bytes will be allocated.
        let len = usize::max(
            aligned_data_size
                .checked_add(offsets_size)
                .and_then(|sum| sum.checked_add(buffers_size))
                .and_then(|sum| sum.checked_add(aligned_secctx_size))
                .ok_or(ENOMEM)?,
            size_of::<u64>(),
        );
        let secctx_off = aligned_data_size + offsets_size + buffers_size;
        let mut alloc = match to_process.buffer_alloc(debug_id, len, info) {
            Ok(alloc) => alloc,
            Err(err) => {
                pr_warn!(
                    "Failed to allocate buffer. len:{}, is_oneway:{}",
                    len,
                    info.is_oneway(),
                );
                return Err(err);
            }
        };

        let mut buffer_reader = UserSlice::new(info.data_ptr, data_size).reader();
        let mut end_of_previous_object = 0;
        let mut sg_state = None;

        // Copy offsets if there are any.
        if offsets_size > 0 {
            let mut offsets_reader = UserSlice::new(info.offsets_ptr, offsets_size).reader();

            let offsets_start = aligned_data_size;
            let offsets_end = aligned_data_size + offsets_size;

            // This state is used for BINDER_TYPE_PTR objects.
            let sg_state = sg_state.insert(ScatterGatherState {
                unused_buffer_space: UnusedBufferSpace {
                    offset: offsets_end,
                    limit: offsets_end + buffers_size,
                },
                sg_entries: KVec::new(),
                ancestors: KVec::new(),
            });

            // Traverse the objects specified.
            let mut view = AllocationView::new(&mut alloc, data_size);
            for (index, index_offset) in (offsets_start..offsets_end)
                .step_by(size_of::<u64>())
                .enumerate()
            {
                let offset = offsets_reader.read::<u64>()?;
                view.alloc.write(index_offset, &offset)?;
                let offset: usize = offset.try_into().map_err(|_| EINVAL)?;

                if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) {
                    pr_warn!("Got transaction with invalid offset.");
                    return Err(EINVAL.into());
                }

                // Copy data between two objects.
                if end_of_previous_object < offset {
                    view.copy_into(
                        &mut buffer_reader,
                        end_of_previous_object,
                        offset - end_of_previous_object,
                    )?;
                }

                let mut object = BinderObject::read_from(&mut buffer_reader)?;

                match self.translate_object(
                    index,
                    offset,
                    object.as_ref(),
                    &mut view,
                    allow_fds,
                    sg_state,
                ) {
                    Ok(()) => end_of_previous_object = offset + object.size(),
                    Err(err) => {
                        pr_warn!("Error while translating object.");
                        return Err(err);
                    }
                }

                // Update the indexes containing objects to clean up.
                let offset_after_object = index_offset + size_of::<u64>();
                view.alloc
                    .set_info_offsets(offsets_start..offset_after_object);
            }
        }

        // Copy remaining raw data.
        alloc.copy_into(
            &mut buffer_reader,
            end_of_previous_object,
            data_size - end_of_previous_object,
        )?;

        if let Some(sg_state) = sg_state.as_mut() {
            if let Err(err) = self.apply_sg(&mut alloc, sg_state) {
                pr_warn!("Failure in apply_sg: {:?}", err);
                return Err(err);
            }
        }

        if let Some((off_out, secctx)) = secctx.as_mut() {
            if let Err(err) = alloc.write(secctx_off, secctx.as_bytes()) {
                pr_warn!("Failed to write security context: {:?}", err);
                return Err(err.into());
            }
            **off_out = secctx_off;
        }
        Ok(alloc)
    }

    fn unwind_transaction_stack(self: &Arc<Self>) {
        let mut thread = self.clone();
        while let Ok(transaction) = {
            let mut inner = thread.inner.lock();
            inner.pop_transaction_to_reply(thread.as_ref())
        } {
            let reply = Err(BR_DEAD_REPLY);
            if !transaction.from.deliver_single_reply(reply, &transaction) {
                break;
            }

            thread = transaction.from.clone();
        }
    }

    pub(crate) fn deliver_reply(
        &self,
        reply: Result<DLArc<Transaction>, u32>,
        transaction: &DArc<Transaction>,
    ) {
        if self.deliver_single_reply(reply, transaction) {
            transaction.from.unwind_transaction_stack();
        }
    }

    /// Delivers a reply to the thread that started a transaction. The reply can either be a
    /// reply-transaction or an error code to be delivered instead.
    ///
    /// Returns whether the thread is dead. If it is, the caller is expected to unwind the
    /// transaction stack by completing transactions for threads that are dead.
    fn deliver_single_reply(
        &self,
        reply: Result<DLArc<Transaction>, u32>,
        transaction: &DArc<Transaction>,
    ) -> bool {
        if let Ok(transaction) = &reply {
            crate::trace::trace_transaction(true, transaction, Some(&self.task));
            transaction.set_outstanding(&mut self.process.inner.lock());
        }

        {
            let mut inner = self.inner.lock();
            if !inner.pop_transaction_replied(transaction) {
                return false;
            }

            if inner.is_dead {
                return true;
            }

            match reply {
                Ok(work) => {
                    inner.push_work(work);
                }
                Err(code) => inner.push_reply_work(code),
            }
        }

        // Notify the thread now that we've released the inner lock.
        self.work_condvar.notify_sync();
        false
    }

    /// Determines if the given transaction is the current transaction for this thread.
    fn is_current_transaction(&self, transaction: &DArc<Transaction>) -> bool {
        let inner = self.inner.lock();
        match &inner.current_transaction {
            None => false,
            Some(current) => Arc::ptr_eq(current, transaction),
        }
    }

    /// Determines the current top of the transaction stack. It fails if the top is in another
    /// thread (i.e., this thread belongs to a stack but it has called another thread). The top is
    /// [`None`] if the thread is not currently participating in a transaction stack.
    fn top_of_transaction_stack(&self) -> Result<Option<DArc<Transaction>>> {
        let inner = self.inner.lock();
        if let Some(cur) = &inner.current_transaction {
            if core::ptr::eq(self, cur.from.as_ref()) {
                pr_warn!("got new transaction with bad transaction stack");
                return Err(EINVAL);
            }
            Ok(Some(cur.clone()))
        } else {
            Ok(None)
        }
    }

    // No inlining avoids allocating stack space for `BinderTransactionData` for the entire
    // duration of `transaction()`.
    #[inline(never)]
    fn read_transaction_info(
        &self,
        cmd: u32,
        reader: &mut UserSliceReader,
        info: &mut TransactionInfo,
    ) -> Result<()> {
        let td = match cmd {
            BC_TRANSACTION | BC_REPLY => {
                reader.read::<BinderTransactionData>()?.with_buffers_size(0)
            }
            BC_TRANSACTION_SG | BC_REPLY_SG => reader.read::<BinderTransactionDataSg>()?,
            _ => return Err(EINVAL),
        };

        // SAFETY: Above `read` call initializes all bytes, so this union read is ok.
        let trd_data_ptr = unsafe { &td.transaction_data.data.ptr };

        info.is_reply = matches!(cmd, BC_REPLY | BC_REPLY_SG);
        info.from_pid = self.process.task.pid();
        info.from_tid = self.id;
        info.code = td.transaction_data.code;
        info.flags = td.transaction_data.flags;
        info.data_ptr = UserPtr::from_addr(trd_data_ptr.buffer as usize);
        info.data_size = td.transaction_data.data_size as usize;
        info.offsets_ptr = UserPtr::from_addr(trd_data_ptr.offsets as usize);
        info.offsets_size = td.transaction_data.offsets_size as usize;
        info.buffers_size = td.buffers_size as usize;
        // SAFETY: Above `read` call initializes all bytes, so this union read is ok.
        info.target_handle = unsafe { td.transaction_data.target.handle };
        Ok(())
    }

    #[inline(never)]
    fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Result<()> {
        let mut info = TransactionInfo::zeroed();
        self.read_transaction_info(cmd, reader, &mut info)?;

        let ret = if info.is_reply {
            self.reply_inner(&mut info)
        } else if info.is_oneway() {
            self.oneway_transaction_inner(&mut info)
        } else {
            self.transaction_inner(&mut info)
        };

        if let Err(err) = ret {
            if err.reply != BR_TRANSACTION_COMPLETE {
                info.reply = err.reply;
            }

            self.push_return_work(err.reply);
            if let Some(source) = &err.source {
                info.errno = source.to_errno();
                info.reply = err.reply;

                {
                    let mut ee = self.inner.lock().extended_error;
                    ee.command = err.reply;
                    ee.param = source.to_errno();
                }

                pr_warn!(
                    "{}:{} transaction to {} failed: {source:?}",
                    info.from_pid,
                    info.from_tid,
                    info.to_pid
                );
            }
        }

        Ok(())
    }

    fn transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
        let node_ref = self.process.get_transaction_node(info.target_handle)?;
        info.to_pid = node_ref.node.owner.task.pid();
        security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?;
        // TODO: We need to ensure that there isn't a pending transaction in the work queue. How
        // could this happen?
        let top = self.top_of_transaction_stack()?;
        let list_completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
        let completion = list_completion.clone_arc();
        let transaction = Transaction::new(node_ref, top, self, info)?;

        // Check that the transaction stack hasn't changed while the lock was released, then update
        // it with the new transaction.
        {
            let mut inner = self.inner.lock();
            if !transaction.is_stacked_on(&inner.current_transaction) {
                pr_warn!("Transaction stack changed during transaction!");
                return Err(EINVAL.into());
            }
            inner.current_transaction = Some(transaction.clone_arc());
            // We push the completion as a deferred work so that we wait for the reply before
            // returning to userland.
            inner.push_work_deferred(list_completion);
        }

        if let Err(e) = transaction.submit(info) {
            completion.skip();
            // Define `transaction` first to drop it after `inner`.
            let transaction;
            let mut inner = self.inner.lock();
            transaction = inner.current_transaction.take().unwrap();
            inner.current_transaction = transaction.clone_next();
            Err(e)
        } else {
            Ok(())
        }
    }

    fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
        let orig = self.inner.lock().pop_transaction_to_reply(self)?;
        if !orig.from.is_current_transaction(&orig) {
            return Err(EINVAL.into());
        }

        info.to_tid = orig.from.id;
        info.to_pid = orig.from.process.task.pid();

        // We need to complete the transaction even if we cannot complete building the reply.
        let out = (|| -> BinderResult<_> {
            let completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
            let process = orig.from.process.clone();
            let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
            let reply = Transaction::new_reply(self, process, info, allow_fds)?;
            self.inner.lock().push_work(completion);
            orig.from.deliver_reply(Ok(reply), &orig);
            Ok(())
        })()
        .map_err(|mut err| {
            // At this point we only return `BR_TRANSACTION_COMPLETE` to the caller, and we must let
            // the sender know that the transaction has completed (with an error in this case).
            pr_warn!(
                "Failure {:?} during reply - delivering BR_FAILED_REPLY to sender.",
                err
            );
            let reply = Err(BR_FAILED_REPLY);
            orig.from.deliver_reply(reply, &orig);
            err.reply = BR_TRANSACTION_COMPLETE;
            err
        });

        out
    }

    fn oneway_transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
        let node_ref = self.process.get_transaction_node(info.target_handle)?;
        info.to_pid = node_ref.node.owner.task.pid();
        security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?;
        let transaction = Transaction::new(node_ref, None, self, info)?;
        let code = if self.process.is_oneway_spam_detection_enabled() && info.oneway_spam_suspect {
            BR_ONEWAY_SPAM_SUSPECT
        } else {
            BR_TRANSACTION_COMPLETE
        };
        let list_completion = DTRWrap::arc_try_new(DeliverCode::new(code))?;
        let completion = list_completion.clone_arc();
        self.inner.lock().push_work(list_completion);
        match transaction.submit(info) {
            Ok(()) => Ok(()),
            Err(err) => {
                completion.skip();
                Err(err)
            }
        }
    }

    fn write(self: &Arc<Self>, req: &mut BinderWriteRead) -> Result {
        let write_start = req.write_buffer.wrapping_add(req.write_consumed);
        let write_len = req.write_size.saturating_sub(req.write_consumed);
        let mut reader =
            UserSlice::new(UserPtr::from_addr(write_start as _), write_len as _).reader();

        while reader.len() >= size_of::<u32>() && self.inner.lock().return_work.is_unused() {
            let before = reader.len();
            let cmd = reader.read::<u32>()?;
            crate::trace::trace_command(cmd);
            GLOBAL_STATS.inc_bc(cmd);
            self.process.stats.inc_bc(cmd);
            match cmd {
                BC_TRANSACTION | BC_TRANSACTION_SG | BC_REPLY | BC_REPLY_SG => {
                    self.transaction(cmd, &mut reader)?;
                }
                BC_FREE_BUFFER => {
                    let buffer = self.process.buffer_get(reader.read()?);
                    if let Some(buffer) = buffer {
                        if buffer.looper_need_return_on_free() {
                            self.inner.lock().looper_need_return = true;
                        }
                        drop(buffer);
                    }
                }
                BC_INCREFS => {
                    self.process
                        .as_arc_borrow()
                        .update_ref(reader.read()?, true, false)?
                }
                BC_ACQUIRE => {
                    self.process
                        .as_arc_borrow()
                        .update_ref(reader.read()?, true, true)?
                }
                BC_RELEASE => {
                    self.process
                        .as_arc_borrow()
                        .update_ref(reader.read()?, false, true)?
                }
                BC_DECREFS => {
                    self.process
                        .as_arc_borrow()
                        .update_ref(reader.read()?, false, false)?
                }
                BC_INCREFS_DONE => self.process.inc_ref_done(&mut reader, false)?,
                BC_ACQUIRE_DONE => self.process.inc_ref_done(&mut reader, true)?,
                BC_REQUEST_DEATH_NOTIFICATION => self.process.request_death(&mut reader, self)?,
                BC_CLEAR_DEATH_NOTIFICATION => self.process.clear_death(&mut reader, self)?,
                BC_DEAD_BINDER_DONE => self.process.dead_binder_done(reader.read()?, self),
                BC_REGISTER_LOOPER => {
                    let valid = self.process.register_thread();
                    self.inner.lock().looper_register(valid);
                }
                BC_ENTER_LOOPER => self.inner.lock().looper_enter(),
                BC_EXIT_LOOPER => self.inner.lock().looper_exit(),
                BC_REQUEST_FREEZE_NOTIFICATION => self.process.request_freeze_notif(&mut reader)?,
                BC_CLEAR_FREEZE_NOTIFICATION => self.process.clear_freeze_notif(&mut reader)?,
                BC_FREEZE_NOTIFICATION_DONE => self.process.freeze_notif_done(&mut reader)?,

                // Fail if given an unknown error code.
                // BC_ATTEMPT_ACQUIRE and BC_ACQUIRE_RESULT are no longer supported.
                _ => return Err(EINVAL),
            }
            // Update the number of write bytes consumed.
            req.write_consumed += (before - reader.len()) as u64;
        }

        Ok(())
    }

    fn read(self: &Arc<Self>, req: &mut BinderWriteRead, wait: bool) -> Result {
        let read_start = req.read_buffer.wrapping_add(req.read_consumed);
        let read_len = req.read_size.saturating_sub(req.read_consumed);
        let mut writer = BinderReturnWriter::new(
            UserSlice::new(UserPtr::from_addr(read_start as _), read_len as _).writer(),
            self,
        );
        let (in_pool, has_transaction, thread_todo, use_proc_queue) = {
            let inner = self.inner.lock();
            (
                inner.is_looper(),
                inner.current_transaction.is_some(),
                !inner.work_list.is_empty(),
                inner.should_use_process_work_queue(),
            )
        };

        crate::trace::trace_wait_for_work(use_proc_queue, has_transaction, thread_todo);

        let getter = if use_proc_queue {
            Self::get_work
        } else {
            Self::get_work_local
        };

        // Reserve some room at the beginning of the read buffer so that we can send a
        // BR_SPAWN_LOOPER if we need to.
        let mut has_noop_placeholder = false;
        if req.read_consumed == 0 {
            if let Err(err) = writer.write_code(BR_NOOP) {
                pr_warn!("Failure when writing BR_NOOP at beginning of buffer.");
                return Err(err);
            }
            has_noop_placeholder = true;
        }

        // Loop doing work while there is room in the buffer.
        let initial_len = writer.len();
        while writer.len() >= size_of::<uapi::binder_transaction_data_secctx>() + 4 {
            match getter(self, wait && initial_len == writer.len()) {
                Ok(Some(work)) => match work.into_arc().do_work(self, &mut writer) {
                    Ok(true) => {}
                    Ok(false) => break,
                    Err(err) => {
                        return Err(err);
                    }
                },
                Ok(None) => {
                    break;
                }
                Err(err) => {
                    // Propagate the error if we haven't written anything else.
                    if err != EINTR && err != EAGAIN {
                        pr_warn!("Failure in work getter: {:?}", err);
                    }
                    if initial_len == writer.len() {
                        return Err(err);
                    } else {
                        break;
                    }
                }
            }
        }

        req.read_consumed += read_len - writer.len() as u64;

        // Write BR_SPAWN_LOOPER if the process needs more threads for its pool.
        if has_noop_placeholder && in_pool && self.process.needs_thread() {
            let mut writer =
                UserSlice::new(UserPtr::from_addr(req.read_buffer as _), req.read_size as _)
                    .writer();
            writer.write(&BR_SPAWN_LOOPER)?;
        }
        Ok(())
    }

    pub(crate) fn write_read(self: &Arc<Self>, data: UserSlice, wait: bool) -> Result {
        let (mut reader, mut writer) = data.reader_writer();
        let mut req = reader.read::<BinderWriteRead>()?;

        // Go through the write buffer.
        let mut ret = Ok(());
        if req.write_size > 0 {
            ret = self.write(&mut req);
            crate::trace::trace_write_done(ret);
            if let Err(err) = ret {
                pr_warn!(
                    "Write failure {:?} in pid:{}",
                    err,
                    self.process.pid_in_current_ns()
                );
                req.read_consumed = 0;
                writer.write(&req)?;
                self.inner.lock().looper_need_return = false;
                return ret;
            }
        }

        // Go through the work queue.
        if req.read_size > 0 {
            ret = self.read(&mut req, wait);
            crate::trace::trace_read_done(ret);
            if ret.is_err() && ret != Err(EINTR) {
                pr_warn!(
                    "Read failure {:?} in pid:{}",
                    ret,
                    self.process.pid_in_current_ns()
                );
            }
        }

        // Write the request back so that the consumed fields are visible to the caller.
        writer.write(&req)?;

        self.inner.lock().looper_need_return = false;

        ret
    }

    pub(crate) fn poll(&self, file: &File, table: PollTable<'_>) -> (bool, u32) {
        table.register_wait(file, &self.work_condvar);
        let mut inner = self.inner.lock();
        (inner.should_use_process_work_queue(), inner.poll())
    }

    /// Make the call to `get_work` or `get_work_local` return immediately, if any.
    pub(crate) fn exit_looper(&self) {
        let mut inner = self.inner.lock();
        let should_notify = inner.looper_flags & LOOPER_WAITING != 0;
        if should_notify {
            inner.looper_need_return = true;
        }
        drop(inner);

        if should_notify {
            self.work_condvar.notify_one();
        }
    }

    pub(crate) fn notify_if_poll_ready(&self, sync: bool) {
        // Determine if we need to notify. This requires the lock.
        let inner = self.inner.lock();
        let notify = inner.looper_flags & LOOPER_POLL != 0 && inner.should_use_process_work_queue();
        drop(inner);

        // Now that the lock is no longer held, notify the waiters if we have to.
        if notify {
            if sync {
                self.work_condvar.notify_sync();
            } else {
                self.work_condvar.notify_one();
            }
        }
    }

    pub(crate) fn release(self: &Arc<Self>) {
        self.inner.lock().is_dead = true;

        //self.work_condvar.clear();
        self.unwind_transaction_stack();

        // Cancel all pending work items.
        while let Ok(Some(work)) = self.get_work_local(false) {
            work.into_arc().cancel();
        }
    }
}

#[pin_data]
struct ThreadError {
    error_code: Atomic<u32>,
    #[pin]
    links_track: AtomicTracker,
}

impl ThreadError {
    fn try_new() -> Result<DArc<Self>> {
        DTRWrap::arc_pin_init(pin_init!(Self {
            error_code: Atomic::new(BR_OK),
            links_track <- AtomicTracker::new(),
        }))
        .map(ListArc::into_arc)
    }

    fn set_error_code(&self, code: u32) {
        self.error_code.store(code, Relaxed);
    }

    fn is_unused(&self) -> bool {
        self.error_code.load(Relaxed) == BR_OK
    }
}

impl DeliverToRead for ThreadError {
    fn do_work(
        self: DArc<Self>,
        _thread: &Thread,
        writer: &mut BinderReturnWriter<'_>,
    ) -> Result<bool> {
        let code = self.error_code.load(Relaxed);
        self.error_code.store(BR_OK, Relaxed);
        writer.write_code(code)?;
        Ok(true)
    }

    fn cancel(self: DArc<Self>) {}

    fn should_sync_wakeup(&self) -> bool {
        false
    }

    fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
        seq_print!(
            m,
            "{}transaction error: {}\n",
            prefix,
            self.error_code.load(Relaxed)
        );
        Ok(())
    }
}

kernel::list::impl_list_arc_safe! {
    impl ListArcSafe<0> for ThreadError {
        tracked_by links_track: AtomicTracker;
    }
}
