An Introduction To Xlets

The conventional model for Java applications doesn't work very well in a digital TV environment. The basic Java application model assumes that only one application is executing in a given virtual machine, and that the application itself is in complete control of its lifecycle (which can include killing the Java VM that it's running in). This is less than ideal for a digital TV receiver, where several applications may be running at the same time, and where there is a need to enforce some separation between the applications. Luckily, we already have a good starting point that gives us something pretty close to what we need: applets. Unlike a normal application, these can be started by something other than a command line (in the case of applets, this is the web browser), and several of them can execute in the same web page at the same time.

Of course, the digital TV world is not the same as the Web, and so some changes had to be made in order for this kind of concept to work well in a digital TV receiver. The result is known as Xlets. These are a concept similar to applets, that have been introduced by Sun in the JavaTV specification and adopted as the Java application format for MHP and related digital TV standards. Like applets, the Xlet interface allows an external source (the application manager in the case of a digital TV receiver) to start and stop an application, as well as controlling it in other ways. The Xlet interface is found in the javax.tv.xlet package:

public interface Xlet {

  public void initXlet(XletContext ctx)
    throws XletStateChangeException;

  public void startXlet()
    throws XletStateChangeException;

  public void pauseXlet();
  public void destroyXlet(boolean unconditional)
    throws XletStateChangeException;
}

If you compare this to the java.applet.Applet class, you'll notice some similarities. Like the applet class, the Xlet has methods that allow the application manager to initialize it, start, and stop it. There are some major differences, however, between Xlets and applets.

The biggest of these is that an Xlet can also be paused and resumed. The reason for this is very simple - in an environment like a digital TV receiver several applications may be running at the same time, hardware restrictions mean that only one of those applications may be visible at any time. In this scenario, non-visible applications must be paused in order to keep resources free for the application which is visible.

An Xlet is also much simpler than an applet - broadcasters and box manufacturers are paranoid, and so Xlets are in some way more limited in what they can do when interacting with their environment. Some of the other tasks that can be carried out via the Applet class are supported in standards like MHP or JavaTV, but other APIs must be used to do them.

So, an Xlet has four main states - Loaded, Paused, Started, and Destroyed. If we examine the lifecycle of an Xlet, we can see where these states fit into the overall picture:

State diagram for an Xlet.

State diagram for an Xlet

  1. The application manager loads the Xlet's main class file (as signalled by the broadcaster) and creates an instance of the Xlet by calling the default constructor. This can happen at any point after the application is signalled. Once this has happened, the Xlet is in the Loaded state.
  2. When the user chooses to start the Xlet (or the AIT or other application signalling indicates that the Xlet should start automatically), the application manager in the receiver calls the initXlet() method, passing in a new XletContext object for the Xlet.

    The Xlet may use this XletContext to initialize itself, and to preload any large assets such as images that may require some time to load from the object carousel. When the initialization is complete, the Xlet is in the Paused state and is ready to start immediately.

  3. Once the initXlet() method returns, the application manager calls the startXlet() method. This will move the Xlet from the Paused state into the Started state, and the Xlet will be able to interact with the user.
  4. During the execution of the Xlet, the application manager may call the pauseXlet() method. This will cause the application to move from the Started state back to the Paused state. The application will later be moved back to the Started state by calling the startXlet() method again. This may happen several times during the Xlet's life.
  5. At the end of the Xlet's life, the application manager will call the destroyXlet() method, which will cause the Xlet to move into the Destroyed state and free all its resources. After this point, this instance of the Xlet cannot be started again.

It's important to remember that an Xlet is not a standard Java application. There are many important differences between the two. An Xlet is conceptually much closer to an applet. Like an applet, there may be more than one Xlet running at any one time, which means that Xlets should not take certain actions that will globally affect the Java virtual machine. For instance, an Xlet should never, ever, EVER call the System.exit() method because it may not be the only application running in the VM at the time. Some more do's and don'ts are listed below.

Xlet Contexts

As we have already mentioned, each Xlet has a context associated with it - an instance of the javax.tv.xlet.XletContext class. This is similar to the AppletContext class that is associated with an applet. In both cases the context is used to provide a way for the application to get more information about its environment and to communicate any changes in its state to its environment.

public interface XletContext {
  public static final String ARGS = "javax.tv.xlet.args"

  public void notifyDestroyed();
  public void notifyPaused();
  public void resumeRequest();
  
  public Object getXletProperty(String key);
}

The notifyDestroyed() and notifyPaused() methods allow an Xlet to notify the receiver that it is about to terminate or pause itself. The Xlet can use these to make sure that the receiver knows the state of every application and can take appropriate action. These methods should be called immediately before the Xlet enters the Paused or Destroyed states, because the receiver may take action that the application is otherwise unprepared for.

An application can request that it be moved from the Paused state back to the Started state using the resumeRequest(). This may happen when a given event has occurred, for instance a certain time is reached or a certain event is detected in the MPEG stream. This effectively allows an application to 'sleep' for a while. Having said that, this method does only request that an application is started again - the receiver software may choose to ignore this request due to resource limitations, display issues or simply because it's feeling cruel.

The diagrams below show exactly what happens when an Xlet requests a change of state via its Xlet context. In this case, the Xlet will pause itself and then requests to resume.

The Xlet calls notifyPaused() on the Xlet context.

The Xlet calls notifyPaused() on the Xlet context.

The Xlet context notifies the application manager that the Xlet has paused.

The Xlet context notifies the application manager that the Xlet has paused.

The application manager updates its internal state.

The application manager updates its internal state.

The Xlet calls requestResume() when it wants to resume.

The Xlet calls requestResume() when it wants to resume.

The Xlet context passes the request to the application manager.

The Xlet context passes the request to the application manager.

The application manager notifies the Xlet that it can resume.

The application manager notifies the Xlet that it can resume.

The Xlet resumes.

The Xlet resumes.

  1. First, the Xlet notifies its Xlet context that it has paused, by calling the XletContext.notifyPaused() method.
  2. The Xlet context then passes this information on to the application manager in the middleware.
  3. The application manager then updates its internal state to reflect that the application has paused, and the Xlet goes to sleep.
  4. When the application wants to resume operation (e.g. because a certain time has been reached, or because the user has pressed a key), it calls the XletContext.requestResume() method.
  5. As before, the Xlet context passes this request on to the application manager.
  6. The application manager will then decide whether to restart the application or not. If it does, then it will update its internal state to reflect this change and then call the startXlet() method on the Xlet. Like all other operations that control the lifecycle of the Xlet, this method is called directly from the application manager and does not go via the xlet context.
  7. The Xlet will then resume operation.

The getXletProperty() method allows the Xlet to access properties that are defined for it in the information signalled by the broadcaster. At present, only one property is defined by JavaTV and MHP. The property name given by XletContext.ARGS enables an application to access any arguments that are given to it in the application signalling (the AIT), since the Xlet model does not directly allow for command-line arguments to be passed to it. MHP also defines the following Xlet properties, which are also used by OCAP:

  • dvb.app.id - the application ID of the application, as indicated in the application signalling
  • dvb.org.id - the organization ID of the application, as indicated in the application signalling
  • dvb.caller.parameters - the parameters passed to this application if it was started by a mechanism other than application signalling.

The main difference between the XletContext.ARGS property and the dvb.caller.parameters property is that the former refers to parameters passed in via application signalling while the latter refers to parameters passed in via the MHP application listing and launching API. In the latter case, the XletContext.ARGS property will still carry the arguments as they are signalled. For applications that have not been started via the MHP application listing and launching API, dvb.caller.parameters will contain an empty string.

As well as these Xlet properties, a number of system properties are available to the application. These can be read using the standard System.getProperty() method. The table below shows which properties are available to JavaTV, OCAP and MHP applications.

System properties that are supported in an MHP receiver.
System Property JavaTV OCAP MHP
path.separator


Path separator in filenames (will always be '/' in MHP)
Supported Supported Supported
dvb.persistent.root


Root directory for persistent storage
Supported Supported
dvb.returnchannel.timeout


Timeout period (in seconds) for return channel connections
Supported Supported
mhp.profile.enhanced_broadcast


Indicates whether the enhanced broadcast profile is supported (will always be "YES" since this is the minimum profile)
Supported Supported
mhp.profile.interactive_broadcast


Indicates whether the interactive broadcast profile is supported ("YES" if it is, "NO" or null otherwise)
Supported Supported
mhp.profile.internet_access


Indicates whether the Internet access profile is supported ("YES" if it is, "NO" or null otherwise)
Supported Supported
mhp.eb.version.major


Major version number of the supported enhanced broadcast profile, or null if not supported
Supported Supported
mhp.eb.version.minor


Minor version number of the supported enhanced broadcast profile, or null if not supported
Supported Supported
mhp.eb.version.micro


Micro version number of the supported enhanced broadcast profile, or null if not supported
Supported Supported
mhp.ib.version.major


Major version number of the supported interactive broadcast profile, or null if not supported
Supported Supported
mhp.ib.version.minor


Minor version number of the supported interactive broadcast profile, or null if not supported
Supported Supported
mhp.ib.version.micro


Micro version number of the supported interactive broadcast profile, or null if not supported
Supported Supported
mhp.ia.version.major


Major version number of the supported Internet access profile, or null if not supported
Supported Supported
mhp.ia.version.minor


Minor version number of the supported Internet access profile, or null if not supported
Supported Supported
mhp.ia.version.micro


Micro version number of the supported Internet access profile, or null if not supported
Supported Supported
mhp.option.ip.multicast


Has a value of "SUPPORTED" if the system supports IP multicast in transport streams
Supported
mhp.option.dsmcc.uu


Has a value of "SUPPORTED" if the system supports DSM-CC User-To-User protocol over the return channel
Supported
mhp.option.dvb.html


Has a value of "SUPPORTED" if the system supports DVB-HTML applications
Supported
mhp.stored.services


Flag showing how much memory is reserved for stored services and applications (if any memory is reserved). This does not reflect how much of that memory is actually free. (MHP 1.1. only)
Supported
mhp.smartcard.reader


Has a value of "SUPPORTED" if the system has a smart card reader accessible using the smart card API (MHP 1.1. only)
Supported
mhp.option.memorycard


Has a value of "SUPPORTED" if the system supports memory card devices
Supported
mhp.option.opentype


Has a value of "SUPPORTED" if the system supports OpenType font technology
Supported
mhp.option.highdef


Has a value of "SUPPORTED" if the system supports high-definition TV
Supported
given by org.havi.ui.HVersion. HAVI_SPECIFICATION_VENDOR


Vendor name of the HAVi specification. Will always be "DVB" for MHP systems
Supported Supported
given by org.havi.ui.HVersion. HAVI_SPECIFICATION_NAME


Name of the HAVI specification that is implemented. Will always be "MHP" for MHP systems
Supported Supported
given by org.havi.ui.HVersion. HAVI_SPECIFICATION_VERSION


Version of the HAVi specification that is implemented. This will be the same as the version number of the MHP specification that is implemented by the receiver
Supported Supported
given by org.havi.ui.HVersion. HAVI_IMPLEMENTATION_VENDOR


Name of the vendor for the HAVi implementation (e.g. the middleware vendor)
Supported Supported
given by org.havi.ui.HVersion. HAVI_IMPLEMENTATION_VERSION


Version of the HAVi implementation
Supported Supported
given by org.havi.ui.HVersion. HAVI_IMPLEMENTATION__NAME


Name of the HAVi implementation
Supported Supported

Do's and don'ts for application developers

We've already seen that applications should not call the System.exit() method. But there are a few other things that Xlets should do, depending on their state:

  • The destroyXlet() method should remember to kill all application threads and cancel any existing asynchronous requests that are currently outstanding in the service information and (in the case of MHP applications) section filtering APIs.
  • The destroyXlet() (and ideally the pauseXlet()) methods should free any graphics contexts that the application has created. The middleware will maintain references to these unless they are disposed of properly with a call to java.awt.Graphics.dispose()
  • The application should remember that it may be paused or destroyed at any time, and should make sure that it can always clean up after itself.
  • The application should respect the restrictions that may be imposed on the core Java APIs. Both MHP and OCAP define a number of restrictions on classes in java.lang and other packages that application developers should be aware of.
  • Resource issues are especially important in an digital TV environment, as we will see later. An application should cooperate with other Xlets where possible on resource issues, and especially should not keep scarce resources longer than it has to.
  • Remember that your application should be as reliable as possible. If a method throws an exception, catch it. Exceptions get thrown for a reason.