Binder Introduction
Binder is an inter-process communication (IPC) mechanism implemented and used extensively by Android. However, if you are an Android application developer you probably seldom use Binder directly. This is because the programming interfaces exposed by Android framework hide the details of Binder so well that it is almost invisible to application developers. However, if you plan to learn the internals of Android system, it is critical to have a deep understanding of Binder. Android is a huge system with so many components working together and Binder is the link between them, so without a good understanding of Binder, it will be very difficult for you to apprehend an architectural view of Android. So I even think Binder is the first system you should tackle before diving into other subsystems.
Let’s use the example of launching an Activity
in Android to further understand the importance of Binder. Application developers simply need to call startActivity
to launch a new Activity
instance and you probably learned how to do that in you first Android lesson. But under the hood the application needs to initiate a sequence of complex interactions with different system servers to make that happen. The ActivityTaskManagerService
(ATMS), which is the core component of managing an application's activities, runs in a privileged system process called system_server
, so the application needs to first send a request to ATMS using Binder. The application also needs to request WindowManagerService
, who also runs in system_server
, to allocate a window for the new Activity
instance. Besides, the application also needs to request SurfaceFlinger
, who runs in its own process, to allocate a Surface
for the new Activity
. PackageManagerService
and InputManagerService
are also involved heavily during this Activity
launching process. All these steps involve interactions with Binder. It may already sound complicated, but in fact this only covers a small part of the interactions with Binder during Activity
launching.
Binder has a even longer history than Android itself. The current Binder implementation in Android is a descendant of the OpenBinder project at Be Inc. However the Android Binder code base is written from scratch instead of basing off OpenBinder. I don’t have a definite answer about the motivation of porting Binder to Android instead of using other existing IPC mechanisms in Linux. But according to a discussion on LKML [1] back in 2009, it is probably because many Android OS engineers at Google came from OpenBinder project. No matter what the actual decision making process was, Binder is proven to be a great success in Android. The implementation of Binder had little change ever since the first version of Android and it is used ubiquitously in Android.
HamKing sample project
There is a popular Shake Shack store located at 8th Ave and 44th Street in downtown Manhattan. I have been there several times with my former colleges. There was always a long line inside and outside the store. So after you order your food they will give you one buzzer which will ring you up when the food is ready. With this buzzer at hand, you can chat with your friends or even go out for a walk while waiting for you order. What a smart way to increase work efficiency!
So I created a sample Android project called HamKing to mimic this pipeline and I will refer to it extensively during this Binder series as a context. You can get the code base from [2]. There are three modules in the code base: client
, server
and api
. The client
module mimics a Shake Shack customer and the server
module mimics the Shake Shack store itself. Both modules references the api
module which defines the communication contract between the two apps. The client
and server
module will be built into two separate APKs that run in two isolated processes. So in order to communicate with each other, the two apps need to use Binder.
The client app can request a new order by clicking the “START ORDER” button at the bottom and view the details of the orders at home page. An order has three states: “preparing”, “ready” and “picked”. When the order is in “ready” state, the client can fetch the order from server app; after this the order will be moved to “picked” state. I cannot make a real burger in the app so I use a Bitmap
to represent the fully made burger. The server side app also displays all pending orders on home page.
The communication contract is defined by several .aidl
files in api
module. Android Interface Definition Language is the standard language for Binder contract definition. In an .aidl
file you only need to write down the service interface using a succinct syntax. The build pipeline will auto-generate the boilerplate code of initiating and handling Binder calls via the aidl
tool.
IHamKingInterface
mimics the services provided by a Shake Shack store. A client can start a new order via requestOrder
and cancel an order via cancelOrder
. After an order is ready, the client can use pickupOrder
to fetch the "burger".
ClientInfo.aidl
defines a model class called ClientInfo
which is not a Binder service. It will be compiled into a Java class called ClientInfo
which implements the Parcelable
interface. The name
field is the full name of the customer like "John Smith".
ICreditCard
mimics the services provided by a credit card. The client hands over an instance of such a service to the server while requesting an order.
OrderInfo
is a model class representing an order. Clients don't specify the mOrderId
when requesting an order. Server will fill it up and send it back to the client while processing the order request. The mProteinType
can be one of "beef", "pork", "tofu" and "none". The mSauces
can be chosen from "ketchup", "hot sauce" and "write sauce". mBurgerImage
Bitmap is used to mimic an actual burger. The server will fill it up with a random Bitmap
when the order is ready.
IOrderSession
is a handle of an active order session. Think is as the buzzer in a real Shake Shack store. If you think about it, you are registering part of your brain as a "listener" to the buzzer while waiting for you order, so when the buzzer rings up your brain will run a "callback" to pickup the order. IOrderListener
mimics the part of your brain that listens for the buzzer.
I hope this gives you sufficient explanation of the HamKing project. Play with it and read through the source code if you plan to follow me on this Binder series because it will be referenced extensively during this series. Besides, I will also reference the source code in Android OS very often. In this series I will only use the android-11.0.0_r3
release which is the latest release as of writing. Android Code Search [3] is a fantastic online AOSP code browsing tool and I suggest you to browse AOSP source code there. For the Linux kernel source code I will reference the v5.10
release [4]. Elixir cross reference is a good online code browsing tool for Linux kernel [5].
In this series, I will post source code from different places very often. The original source code tend to be very long, so readers can get lost easily if I post them as is. So in most cases, the source code you see in the articles won’t be in its original shape, because I have removed and changed lines to make the code more easy to understand.
External links
[1] https://lkml.org/lkml/2009/6/25/3
[2] https://github.com/androidonekb/HamKing
[3] https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3: