The Android IPC system
The information below comes from a number of sources, including my own experiments with the Android IPC and some disparate internet sources.
The overall architecture of the Android IPC system is shown in the diagram below. It consists of four major blocks; one in kernel space, and the other three in user space. The dashed lines represent the logical RPC calls. The solid lines represent the actual data flow.
BinderDriver
: This is the core of IPC system. It passes data between aServiceProvider
(s) and aServiceUser
(s). This kernel component is provided by Android.ServiceProvider
: Provides some kind of service. It parses the received RPC data from theBinderDriver
and does the real work. Application developers will either make use of existing service providers (such as theCamera
orAudioFlinger
), or in some cases will write their own.ServiceManager
: This is a special singleton ServiceProvider that provides service manager services for other service providers. This component is provided by Android.ServiceUser
: This is the client. It remote calls theServiceProvider
by generating an RPC and sending it to theBinderDriver
. Application developers typically write their ownServiceUser
as part of their application.
Here is a typical flow of events for a fictitious MultServiceProvider
(a service provider that multiplies two numbers for a client) and a MultServiceUser
client which doesn’t know how to do multiplication (maybe because the numbers are quaternions) and needs to use the MultServiceProvider
:
ServiceManager
runs first (at power-up) and registers a special node (node O) with theBinderDriver
.- The
MultServiceProvider
gets anIServiceManager
proxy object for the special node O by calling the globaldefaultServiceManager()
function. - The
MultServiceProvider
then callsdefaultServiceManager()->addService("Multiplier", new MultServiceProvider())
to add itself as a service provider and then waits in an infinite loop for someone to request its services. TheaddService
RPC call is routed to theServiceManager
through theBinderDriver
. - The
BinderDriver
notices that the RPC is for theServiceManager
to add a new service, so besides routing the RPC to theServiceManager
it generates another node (let’s call it node M), for the newMultServiceProvider
. - The
ServiceManager
reads the data from theBinderDriver
and processes theIServiceManager::addService
RPC call. - The
MultServiceUser
client process gets anIServiceManager
proxy object for the special node O (again by usingdefaultServiceManager()
). - The client does an
IServiceManager::getService("Multiplier")
RPC call to get theMultServiceProvider
. This call is routed to theServiceManager
through theBinderDriver
. - The
ServiceManager
reads the RPC data from theBinderDriver
, processes theIServiceManager::getService
request and returns back the node representing theMultServiceProvider
. MultServiceUser
callsMultServiceProvider::multiply(a, b)
. This call is routed to theMultServiceProvider
by theBinderDriver
.- The
MultServiceProvider
handles theMultServiceProvider::multiply
RPC call and sends the product of the 2 numbers in a reply to theBinderDriver
. - The
BinderDriver
routes the reply back to the client. - The client reads the data from the
BinderDriver
which contains the result of “a * b”.
In a future post I hope to discuss the whole architecture in more detail, with concrete code examples for how to use IBinder
, IInterface
, BBinder
, BpInterface
, BnInterface
, etc… to create a ServiceProvider
and a ServiceUser
all in native C++ code on Android.