Wednesday, November 13, 2013

Monday, November 11, 2013

How an Android bound service works...

As i was delving into how an Android bound service works from a developer's perspective i came out with the following write-up which i would like to share with you.
The following diagram depicts the whole flow nicely.
Thus in the onServiceConnected we get a reference to the proxy of the Service through which we can call the methods of the remote service as if they were the local methods. What happens in the background is described here.
If the data that are being passed while calling any of the Service methods through the proxy reference (which we have got in the onserviceConnected callback)are basic data types, then the proxy first converts them into parcelable data. If we want to pass an user defined data types (any objects of an UDT), we have to derive that class from Parcelable interface so that the proxy can write them to the IPC layer.
Then we basically call the the transact on a member variable called mRemote where we pass those parcelable in data as well as the parcelable out data as the second and the third parameter respectively. We also pass something like Stub.Transaction_add (if the function in the AIDL interface was called, say add). At this point the interprocess communication is initiated with the transact method. The parcelled data is sent to the JNI interface which then sends it to the Binder kernel driver. The Binder kernel driver will send the client process to sleep and map the data and the code from the client process to the server process. Then the parcel is sent upwards from the binder kernel to the C++ middleware and then to the JNI and on java API wrapper layer the method onTransact of the stub is called.
@Override public boolean onTransact ( int code , android . os . Par c e l  data
, android . os . Par c e l  r eply , int f l a g s ) throws android . os . RemoteException
{
switch ( code )
{
case TRANSACTION_add:
data . e n f o r c e I n t e r f a c e (DESCRIPTOR) ;
int _ar g 0 ;
_ar g 0 = data . r e adInt ( ) ;
int _ar g 1 ;
_ ar g 1 = data . r e adInt ( ) ;
int _ r e s u l t = this . add ( _arg0 , _ar g1 ) ;
13 r epl y . wr i teNoExcept ion ( ) ;
14 r epl y . wr i t e I n t ( _r e s u l t ) ;
return true ;
}
}

The code is read first due to the accurate signature and the number of arguments. Then the arguments are extracted and the business logic gets executed. The result is written to a reply parcel and which is then again routed through the Binder driver which then wakes up the client and writes the reply parcel to the proxy.  The reply is unmarshalled by the proxy and then sent to the client application.
Hope this helps the android learners....

Share