Sunday, January 20, 2008

Using the service directory

Originally I wanted to play with Bluetooth which seemed easy but then - as usual with Android - unexpected complications occured. By the way, does anyone know, how to get the default Adapter activated? :-)

Playing with Bluetooth brought me back to services and I was surprised once again how well Android documentation keeps the secret that Android is a service-based platform. Actually, I found, that the Android system's architecture is pretty similar to that of the Symbian. The system is built in client-server fashion. System services (all located in the android.server package) run in their own virtual VMs. Whenever a client wants to talk to those services, they go through the service framework that I played with in this blog entry. The client side sees the services through client-side stubs whose name normally start with I (like IServiceManager). All the other classes on the client side are purely convenience methods, building on the functions offered by the interface class.

Android is superior to Symbian in that it has a proper service directory. This functionality was added to Symbian later, this is the ECom framework. General Symbian servers are not registered, however, in a service directory which is a major drawback of the platform. Android servers are nicely listed in Android's local service directory but of course this feature is not documented at all. :-)

I went after the service directory by decompiling the Android emulator's framework library with Pavel Kouznetsov's wonderful Jad tool. The android.jar is located under the root directory of the Android SDK. I found that the service directory is accessible via the android.os.ServiceManagerNative class.

IServiceManager sm = ServiceManagerNative.getDefault();

The android.os.IServiceManager is the service interface class through which the default service manager can be accessed. I put together a simple program to list these, you can download the program from here.

The display of this program is like this:

This is nice and good but how can one access one of those services? The example program demonstrates it by accessing a less known system service, the Statistics service.

The key lines are the following:

IServiceManager sm = ServiceManagerNative.getDefault();
IBinder statBinder = sm.getService( "statistics" );
IStatisticsService statService = IStatisticsService.Stub.asInterface( statBinder );


The service name "statistics" is the same name that was displayed by the previous program. Unfortunately, there seems to be no programmatic way to get from the IBinder (which is a client-side stub) to the IStatisticsService (or any other service interface class) without knowing, what is the real interface the binder supports. It is the programmer's responsibility to know the interface the service supports and obtain it correctly using the I class belonging to the service (like IStatisticsService this time).

Convenience classes using the service interface classes are more suitable for the application programmer to talk to services. Services may have other means to interact with applications, like Intent broadcasts. In the present state of Android with a lot of areas under development, consequently very poor or not-existing documentation, service interface classes may in many cases be the only way to activate features of the platform.

5 comments:

Rahul said...

i Want source code of Image+ListVIew in Android Platfofm
plz help me

Anonymous said...

Gabor, hi. Listen. Do you know hardware service name? I want to change screen brightness programmatically, but don't know how :(

Anonymous said...

the IServiceManager is neither available in android1.1 nor in 1.5.
Can you tell how to create a background service in any of these versions or what other jars do i need.

brian said...

This approach seems to be deprecated with android 2.0?


This example has dependencies within
android.os.* (ServiceManagerNative, IServiceManager) that no longer exist ?

Gabor Paller said...

The classes are probably still there, they are just not part of the public API. This can be worked around, but newer services are not registered in this service directory but accessed through intent resolution.

This whole service directory mechanism is a leftover from pre-1.0 Android.