Android from the foundation · Puzzle 16 of 16
How big can a Binder call be?
In puzzle 13, a call crossed Binder as bytes packed in a Parcel. The receiving process has only so much room for them.
The problem
In puzzle 13, your call crossed into system_server packed into a Parcel. An Intent can carry data along with it, like a photo. But the Parcel has to wait somewhere in system_server until one of its Binder threads is free. How much room is there?
See it
Calls into system_server wait in its Binder buffer, an area of its memory set up by the kernel, until a Binder thread is free.
Step 1 of 4Its size is fixed: about 1 MB (a megabyte, about a million bytes), shared by every call in progress, from every app. Predict: your app sends an Intent carrying a 3 MB photo. What happens?
Step 2 of 4It doesn't fit, so the call fails with
TransactionTooLargeException. A transaction is one Binder call.Step 3 of 4The fix: save the photo to a file and send only its name, a few bytes. Your other screen reads the file itself: same app, same UID, so the sandbox allows it.
Step 4 of 4
The building block
Calls into a process wait in its Binder buffer: an area of that process's memory, set up by the kernel when the process first uses Binder. Its size is fixed then, so it can't grow later: about 1 MB.
That 1 MB is shared by every call in progress into that process, from every app. So a call can fail even when it's well under 1 MB, if many other calls are waiting at the same moment.
A call that doesn't fit fails with TransactionTooLargeException (a transaction is one Binder call). The fix is never a bigger Parcel: save the data somewhere both sides can reach, like a file, and send its name, or a number that identifies it. Inside your own app this just works: all its screens run as the same UID, so the sandbox lets every one of them read the file. (Sharing with another app needs system_server's help: a later puzzle.)
Splitting the data into many smaller calls doesn't help either: they all go through the same shared 1 MB, and the receiver would have to glue the pieces back together.
The analogy
The town hall's mailbox has one fixed size, shared by everyone's letters. A parcel that doesn't fit the slot comes back. So you leave the parcel at home and send a note that says where it is.
Check yourself
Sources
- Android reference: TransactionTooLargeException ("The Binder transaction buffer has a limited fixed size, currently 1MB, which is shared by all transactions in progress for the process.")
- Android reference: Parcel
What you now know
Calls into a process wait in its Binder buffer: about 1 MB, shared by every call in progress. A call that doesn't fit fails with TransactionTooLargeException. Send where the data is, not the data.
Answer every question above correctly to unlock the next puzzle.