Sunday, February 26, 2006

OSGi Device Management

The biggest chunk of functionality for the OSGi Mobile Service Platform is the Device Management Tree (DMT) Admin. The Dmt Admin API is a matchmaker between management applications (both remote management servers as well as local applications) and the components that are available on a device. The Dmt Admin maintains a conceptual tree structure of interior and leaf nodes. Interior nodes have children, and leaf nodes have a primitive value like an integer, float, string, time, date etc. Plug-ins map this conceptual tree to actual hardware registers or other value sources. The conceptual tree is closely modeled after the OMA Device Management specification.

In the past two days I have written my first plug-in for the Mobile Expert Group. This group is considering using the Dmt Admin for their R4 specification but they want to make the API simpler for Java applications. I had to write a prototype to make a change request.

Initially the task to write a plug-in looks daunting. The interface that must be implemented has 22 methods, and they look quite, well, not simple. Fortunately, as I found out, most methods do not require an implementation to make the plug-in work. Actually, I was quite surprised how easy it was to implement a simple leaf node. You only have to write a Plugin service that is registered with the Framework when you start up. This plug-in service is asked for a session object that you must implement. This session is used to access the plug-in.

My first attempt was to create a plug-in that maintained the position. The OSGi R4 specification has a Position object that lends itself very well to this concept. A Position object contains six fields: longitude, latitude, altitude, track, and speed. Each of the values is a Measurement object that contains three fields: value, error, and Unit. Overall, a Position is mapped to a sub-tree of eighteen nodes. Not big, but also not trivial.

A key problem of writing a plug-in is to map the URIs (which are String[] objects for the plug-in) to your function. My first attempt was hard-coding this relation, but that became very cumbersome amazingly quickly. I must admit that I am allergic to any redundancy in code, but even less sensitive people should have been affronted. I developed this allergy 10 years ago when working on an application with thousands of fields that were hardcode in hundreds of places.

So for my first attempt used some tables to minimize the redundancy, but the results were still not very satisfactory. Intricate knowledge of the tree was necessary in too many different places.

Looking at the code I remembered having a class that makes any Java object look like a Map, very similar in vein to Java beans. Could I use this? The properties of a bean also form a tree. Properties that result in primitive types like String, byte[] can be mapped to leaf nodes and the remaining properties are treated as interior nodes. This turned out to be a very interesting architecture. I threw away all the code I had written and the plug-in became almost completely generic. Virtually all the code needed for my plug-in was now provided by the Position and Measurement classes. That is the way I like it! Even better, the only change I had to make to my bean inspector was to be able to reason about the tree, even in the absence of instances. The original class only worked with instances.

What the prototype showed me was that, with a little bit of help, it is almost trivial to write a Dmt Admin plug-in. As proof, hereby a class that implements a (non-transactional) plug-in for locales. The remaining code is completely agnostic of the problem domain area.

public class TinyPlugin extends TestPlugin {
  TinyPlugin(BundleContext context) { super("./Tiny", context);}

  public Locale[] getLocales() { return Locale.getAvailableLocales(); }

  public String getDefaultLocale() {
return Locale.getDefault().toString();
  }
     
  public void setDefaultLocale(String locale) {
    String parts[] = locale.split("_");
    Locale l = new Locale(parts[0],
parts.length > 1 ? parts[1] : "",
     parts.length > 2 ? parts[2] : "");
     Locale.setDefault(l);
  }
}

Tree:
     ./Tiny
          Locales
          defaultLocale

This class (together with a library of generic code) implements a full Dmt Admin plug-in. It will be hard to make a similar plug-in with less code. And as you probably have found out in this article, I am a staunch believer in small is beautiful (and robust).

     Peter Kriens
     OSGi Evangelist

No comments:

Post a Comment