Android from the foundation · Puzzle 5 of 6
Binder is the post office between processes
Processes can't touch each other's memory, so every call between them is packed into bytes and carried by the kernel's Binder driver, stamped with the caller's identity.
The problem
In puzzle 4, your "start B" letter went to the town hall. But in puzzle 1 we saw that one process can't touch another's memory. So how does a method call get from your house into the town hall at all?
See it
Your app wants the town hall to start a screen, but the town hall lives in another process. In your house sits a proxy: a counter that looks exactly like the town hall's service.
Step 1 of 6Objects can't leave a process; bytes can. The proxy packs the call's arguments into a flat envelope: a Parcel.
Step 2 of 6The kernel's Binder driver carries it, and stamps it with your app's UID. The receiver can't be fooled about who sent it. Predict: who picks it up at the town hall?
Step 3 of 6The town hall keeps a few couriers waiting for mail: its Binder threads. One takes the Parcel, unpacks it, and calls the real method.
Step 4 of 6The reply travels back the same way, and the proxy call in your app returns.
Step 5 of 6Each process's mailbox for incoming calls holds about 1 MB, shared by all calls in flight. A 3 MB bitmap in an Intent doesn't fit:
TransactionTooLargeException.Step 6 of 6
The building block
Binder is a driver in the Linux kernel (drivers/android/binderThe Binder driver in mainline Linux (now written in Rust) stamps the sender's user ID on every transaction. Android phones run Android's own kernel branches, which may still use the older C driver. 392 from_parent,
393 sender_euid: Kuid::current_euid(),transaction.rs, line 392 · Linux kernel ↗), and the kernel is the only code allowed into every process. On your side, a proxy looks like the service you're calling. It packs the arguments into a ParcelThe flat byte buffer that carries arguments across processes. 237 public final class Parcel {Parcel.java, line 237 · AOSP frameworks/base ↗. On the other side, a Binder thread unpacks it and calls the real method.
Two facts that come up all the time:
- Who's calling. Binder stamps every call with the caller's UID, and its PID (process number). The receiver reads it with
Binder.getCallingUid()Native: the UID the kernel stamped on the call. The caller can't fake it. 338 public static final native int getCallingUid();Binder.java, line 338 · AOSP frameworks/base ↗. That's how system_server checks permissions: the kernel guards files and memory (puzzle 1), and system_server guards everything else using this stamp. - Size. Each process's buffer for incoming calls is about 1 MB, shared by every call in flight.
The analogy
The post office. You hand your letter to the counter in your house (the proxy). The post office carries it, stamps your address on it, and a courier at the town hall's door (a Binder thread) brings it to the right desk.
Check yourself
Sources
What you now know
proxy → Parcel → Binder (kernel) stamps your UID → a Binder thread → the real method, and back. Every Intent and every system call travels this way, through a mailbox of about 1 MB.
Answer every question above correctly to unlock the next puzzle.