Overview of Android binder IPC implementation

pchethan 25,768 views 26 slides Jun 25, 2014
Slide 1
Slide 1 of 26
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26

About This Presentation

No description available for this slideshow.


Slide Content

Android Binder IPC Chethan Palakshamurthy

Outline What is Binder IPC? High level design Communication between participants Low level design Creation of proxy and native binders

Index What is Binder IPC?

Binder IPC The features of Binder are comparable to functionality provided by any mature traditional client/server architecture or IPC mechanisms. Symbian IPC, Linux D-Bus are couple of the examples. Binder takes a different approach with the constructs used, to better support Android Interface Definition Language (AIDL) and its implementation The main feature of Binder is that, instead of sharing enumerated command/request ids, the client and server sides share a common abstract service interface There exist two objects which implement the same interface. (1) Local proxy – for use by application in the same process and (2) Remote service object – which has the actual service implementation, resides in service’s process Invoking an API on the local proxy object, translates to a call on the remote object

Index What is Binder IPC? High level design

Binder IPC – High level design Service Manager Service Register/ Deregister by service name Application Get Service Request Service Async response 0..* 1 1 0..* 0..* 0..* Via Kernel Driver IServiceManager IAbcService

Binder IPC – High level view Binder framework uses a kernel driver for IPC - /dev/binder Clients to the driver are App (Service user) Services Service Manager (Also a service – a special one) Driver assigns and maintains IDs or handles (and much more info) of each. Service manager (Id = 0) Registers itself with binder driver, as ‘Manager’ on device startup Manages a list of services. Services Services register themselves with SVC manager on service startup Provide an abstract service interface

Binder IPC – Using a service First, application gets IServiceManager handle. Using the globally known identifier – 0. There are helper functions to get this object App invokes IServiceManager :: GetService to get a handle of IAbcService for a service “ Abc ” IServiceManager object is implemented by framework and is part of binder library Invokes IAbcService :: PerformSomething call The call gets translated to PerformSomething call on the service object Service provider needs to implement the IAbcService

Binder IPC – High level design Service Object Application Local Proxy Object ProxyAbcService Remote Native Object NativeAbcService IAbcService :: PerformSomething () Driver IAbcService :: PerformSomething () IAbcService App process Service process

Index What is Binder IPC? High level design Communication

Binder IPC Design – Messaging … Service Manager Application Service 1 Service 2 Service N Kernel Driver fd =/dev/binder “Media.Player” Id: 0 2. ioctl ( fd , params { fd,params { cmd =ADDSERVICE, service=“Media.Player” target=0}) //on startup of process 4. ioctl ( fd , params { cmd =CREATE, target=1}) 3. ioctl ( fd , params { cmd =GET, srv =“ media.player ” target=0 outHandle =})

Binder IPC Design - Messaging Service manager opens ‘/dev/binder’ and registers itself (handle = 0) as manager using ioctl Media Player Service, on process startup, creates an object instance ( MediaPlayerService ) and registers it (instance as handle, say 0x70FF) along with a name, with SVC Mgr. By calling ioctl with target handle = 0, in parameter Driver knows ‘0’. It directs it to SVC Mgr. Seeing ADD_SERVICE in param , SVC Mgr, registers the service along with provided handle. Now, SVC manager knows “Media.Player”. Driver knows media player service handle – 0x70FF. Application asks SVC Mgr for “Media.Player” service By calling ioctl with target handle = 0, cmd =“GET_SERVICE”, name=“Media.Player” SVC Mgr returns the handle associated with “Media.Player”, in ioctl out params .

Binder IPC Design - Messaging Application asks the service to create one instance of media player. (Media Player Service supports multiple player instances) By calling ioctl with target handle = ‘0x70FF’ (say) Media Player Service on seeing command ‘CREATE’ creates a player instance and embeds the instance handle in the reply.

Binder IPC Design – Send/Receive Impl . Each client of the driver has 1 or more threads. A thread on the server waits on a loop on an ioctl waiting for a service request. The driver puts the thread to sleep using wait_event_interruptible . When an app calls ioctl on its end targeting a service, the driver wakes up a thread of that service ioctl on service end, comes out of the wait, services the request Now, if it’s a sync request, app makes another ioctl call waiting for reply. The services sends a reply parcel back by calling ioctl , waking up the app; and goes back to sleep with another ioctl call (typically in a loop) If the request is Async , service calls ioctl sometime later. But this time, one of the threads waiting with ioctl will pick it up

Binder IPC Design – Send/Receive - Sync App SVC1::Thread1 ioctl ( fd,params ) ioctl blocks the thread and puts into sleep Kern Driver ioctl ( fd , params ) Thread is resumed, as ioctl returns Process( params ) ioctl ( fd , ..) //reply calls ioctl again to go back to waiting mode, suspending the thread ioctl ( fd,params ) Sending request mesg Waiting for reply Process Reply data

Binder IPC Design – Async call from Service SVC App::Thread1 ioctl ( fd,params ) ioctl blocks the thread and puts into sleep Kern Driver ioctl ( fd , params ) Thread is resumed, ioctl returns Process( params ) ioctl ( fd , params ) //reply calls ioctl again to go back to waiting mode, suspending the thread Sending request mesg Waiting for reply Process Reply data ioctl ( fd,params )

Index What is Binder IPC? High level design Communication Low level design

Binder IPC – LLD Application or service do not call ioctl directly. There are layers of objects before an application intent gets translated to an ioctl . Some important ones are - Local proxy object  Implements a service specific abstract interface E.g., BpMediaPlayerService (B=binder, p=proxy) Each API implementation creates `Parcels` that encapsulate command/request ID etc. Forwards Parcel to proxy helper. Proxy Helper  Flattens & converts the parcels into ioctl parameter objects and makes the ioctl call. BpBinder , IPCThreadState

Binder IPC – LLD Remote helper  Receives and unflattens the ioctl parameters Delegates parcel to remote native object. IPCThreadState , BBinder Remote native object Does the exact opposite of local proxy object Receives the parcel and calls the appropriate service object BnMediaPlayerService Service Object Has the ‘real’ implementation of the service E.g., MediaPlayerService : BnMediaPlayerService (B=binder, n=proxy) MediaPlayerService

Binder IPC – LLD IABCInterface Application Local Proxy object Remote Helper Binder Driver Proxy Helper <<Extends>> <<realize>> IPC Message IPC Message Remote Native object Google Service Implementer Transact(Parcel*) onTransact (Parcel*) Service Object <<realize>>

Binder IPC – LLD Application Binder Driver BpMediaPlayerService setDataSource (…) Transact(SET_DATA_SOURCE_URL, Parcel*) BpBinder MediaPlayerService ::Client BnMediaPlayerService setDataSource (…) OnTransact (SET_DATA_SOURCE_URL, Parcel*) BBinder ioctl resume ioctl Thread transact() IPCThreadState transact() IMediaPlayerService

Index What is Binder IPC? High level design Communication Low level design Creation of proxy and native binders

Binder IPC – Creation of proxy and native binders Getting Service Manager object Use sp< IServiceManager > defaultServiceManager () to get handle. This function creates a BpBinder (0) and wraps it with BpServiceManager BpBinder is the helper object which can send IPC to the desired handle. In this case handle = 0. BpServiceManager translates manager calls to IPC using BpBinder object That is, a service proxy object wraps a BpBinder Wrapping is done with interface_cast <>

Binder IPC – Creation of proxy and native binders Getting service object App gets a desired service using sp< IBinder > IServiceManager :: GetService (“Media.Player”) When GetService calls ioctl , it gets a virtual handle to MediaPlayerService . A BpBinder (handle) is created and wrapped with BpMediaPlayerService Thus sp< BpMediaPlayerService > is obtained for App’s use.

Binder IPC – Creation of proxy and native binders Creating a media player instance sp< BpMediaPlayerService >.create(…) create() sends ioctl message to MediaPlayerService instance on Media server process create API is invoked on MediaPlayerService instance. Based on parameters, the service creates a media player instance - BnMediaPlayer . The instance handle is returned embedded in the ioctl call as a ‘cookie’ Driver notes the cookie (in binder node inside driver) and in future transactions to Media Player, it sends the cookie, along with any msg from Application. On app side, sp< BpMediaPlayerService >.create() method again creates a BpBinder with that handle of MediaPlayer

Binder IPC – Creation of proxy and native binders Calling API on media player instance sp< BpMediaPlayer >. setDataSource (…) The implementation creates a Parcel and passes it on to BpBinder The IPC message is delivered to the media server. The driver adds the ‘proxy’ pointer along with the message The binder framework on the media server on receiving the cookie, fetches the native service instance and passes on the Parcel. The instance eventually calls setDataSource on itself.