Android's Binder - Under the Hood

    Android's Binder is a just an abstraction on top linux concepts. Its a well defined protocol to facilitate IPC but the underlying mechanism is plain old linux concept. Under the hood, it just uses memory mapped pages to transfer data from one process to other.

    As and when an application process is created, it opens binder driver (/dev/binder) and one of the early operations is to memory map 128 KB by the driver. binder_proc is the data structure which book keeps all process specific data like mapped memory, size, total buffers, allocated buffers, free buffers etc. proc->buffer is the list of all buffers, proc->allocated_buffer is for used buffers and proc->free_buffers is for unused buffers. There are additional data structures which maps a handle to binder_proc and this is the essence of IPC.



     Any process wanting to invoke an API served by another process triggers a sequence of steps in the binder driver. The perquisites are for the data to be flattened etc. Binder driver gets the request as a BINDER_TRANSACTION ioctl and identifies the target process via the handle and basically picks up a free buffer in the memory corresponding to the target process (via its binder_proc). This buffer is then filled with flattened data provided by the source process. The buffer in addition to the user space payload has binder specific header data like source process id, source uid etc. In some cases, there might not be any more free buffers in the memory meant for target process and in such cases binder driver basically allocates a new page via binder_update_page_range and allocates a new buffer. This data in the new buffer serves as an entry point for a binder thread in the target process. A process can have a maximum of 16 binder threads and should all threads be busy, this new data wouldn't be processed and the source process would be blocked (assuming it was a blocking call and not a ONE_WAY transaction), but otherwise the target process can handle this data in an existing or a new binder thread and extract the header information like source identifier. In fact, this header info is the source to verify if the caller has the permission to invoke this API and this is how application permissions are verified in Android. As cool as this may seem, there are performance overheads to the entire operation and this is one of the reasons as to why why key dispatch mechanism was changed to use pipes (starting gingerbread) and this was supposed to help improve game interaction. Thanks to Arve Hjønnevåg for clarifying some of the binder's internals.

No comments: