AOSP Framework & Internals
5 min read

Binder Driver Architecture

Learn about Binder Driver Architecture.

Why Double Copying Fails at Scale

Every time an application asks for the current location or updates the screen, it must talk to a system service. These services live in completely separate memory spaces to prevent one crash from taking down the whole operating system. Sharing data requires moving it across that strict boundary securely. Traditional Linux inter-process communication mechanisms like pipes or sockets force you to copy data twice. First, the sending process copies data from its user space into kernel space. Second, the receiving process copies that same data from kernel space into its own user space.

When you have hundreds of processes talking constantly, these double copies consume massive CPU cycles. Memory bandwidth becomes a major bottleneck for the entire system. A phone running on a battery simply cannot afford this overhead. Android needed a custom solution built specifically for high-frequency process communication. The platform required a way to move data across boundaries without the heavy cost of the second copy.

How Memory Mapping Eliminates the Second Copy

If we want to avoid copying data twice, we need a way for two isolated processes to share memory safely. Giving processes direct access to each other's memory breaks the security model. The Binder kernel driver solves this by operating entirely inside the Linux kernel and managing the memory itself. When a process starts, it opens the Binder driver and maps a chunk of physical memory into its virtual address space.

The kernel driver maps that exact same physical memory into kernel space. When a sender wants to transmit a message, it passes the data to the kernel. The kernel then copies that data directly from the sender's user space into the receiver's mapped buffer.

You are about to see a flowchart comparing the standard data flow with the Binder data flow. This visualization helps you understand exactly where the system eliminates the second memory copy. Look for how the Binder kernel driver writes directly into the shared memory block, allowing the receiver to access it instantly.

Notice how the Standard IPC path forces the kernel to actively push data into the receiver. In the Binder path, the kernel only writes to the mapped buffer once. The receiver simply reads what is already waiting in its memory space. This shared memory approach drastically reduces bus traffic and CPU usage. By default, the framework allocates a one megabyte buffer for each process to handle these incoming transactions. This single-copy trick makes communication incredibly fast, but speed alone does not solve the problem of keeping different parts of the operating system secure from each other.

Enforcing Security Through Split Nodes

If every component uses the same communication channel, a malicious vendor hardware driver might try to talk directly to a core system service. Project Treble required a strict separation between vendor code and the Android framework. The architecture needed physical boundaries to enforce these security rules. Google solved this by splitting the single Binder channel into three distinct device nodes.

Processes talk to the driver using standard system calls like open and ioctl. Standard applications use /dev/binder to talk to the system server. Vendor daemons use /dev/vndbinder to talk to each other. The framework uses /dev/hwbinder to communicate with hardware abstraction layers.

Interview Note: Interviewers will often ask you why Android split the Binder nodes. The answer is always about isolating vendor implementations from framework code to enforce security policies.

This architectural split prevents vendor code from bypassing security rules. Bad actors cannot access core framework APIs directly because SELinux policies prevent them from opening the wrong device node. A vendor camera daemon can talk to hardware via its dedicated node, but it cannot reach the Activity Manager. Fast and secure communication is great until the process you are talking to suddenly crashes.

Tracking Objects Across Boundaries

When two processes talk frequently, one process often holds a reference to an object in the other process. If the remote process dies unexpectedly, the caller could hang forever waiting for a response. The system cannot afford to leak memory or leave threads permanently blocked. Binder natively understands object references and handles this lifecycle management for you.

The kernel driver maintains a reference count for every shared object crossing a process boundary. When a call comes in, the driver automatically wakes up an idle thread from a pool in the receiving process. If a process holding a remote object crashes, the kernel driver detects the dead connection. The driver immediately triggers a death notification to any process holding a reference to that destroyed object.

ActivityManager relies on these death notifications to know when an application crashes so it can clean up the application state. The system removes stale references safely without leaking memory or stalling the user interface. This lifecycle tracking makes remote calls feel exactly like local function calls. You can now see how data moves through the kernel securely, but what actually happens when you ask the system to start a new activity?