9 Start Level API Specification

9.1 Introduction

This specification describes how to enable a management agent to control the relative starting and stopping order of bundles in an OSGi framework.

The management agent can set the start levels for bundles and set the active start level of the Framework, which will start and stop the appropriate bundles. Only bundles that have a start level less or equal to this active start level must be active. The purpose of the Start Level API is to allow the management agent to control, in detail, what bundles will be started and stopped and when this occurs.

9.1.1 Essentials

  • Ordering - A management agent should be able to order the startup and shutdown sequences of bundles.

  • Levels - The management agent should support a virtually unlimited number of levels.

9.1.2 Entities

  • Bundle Start Level - The adapter on a bundle that is used by a management agent to order the startup and shutdown sequences of bundles.

  • Framework Start Level - The adapter that is used to set the framework start levels.

  • Management Agent - A bundle that is provided by the Operator to implement an Operator specific policy.

  • Framework Event - See Events.

  • Framework Listener - See Listeners.

Figure 9.1 Class Diagram org.osgi.framework.startlevel package

Class Diagram org.osgi.framework.startlevel package

9.2 Start Level API

The Start Level API provides the following functions:

  • Controls the beginning start level of the OSGi Framework.

  • Is used to modify the active start level of the Framework.

  • Can be used to assign a specific start level to a bundle.

  • Can set the initial start level for newly installed bundles.

Defining the order in which bundles are started and stopped is useful for the following:

  • Safe mode - The management agent can implement a safe mode. In this mode, only fully trusted bundles are started. Safe mode might be necessary when a bundle causes a failure at startup that disrupts normal operation and prevents correction of the problem.

  • Splash screen - If the total startup time is long, it might be desirable to show a splash screen during initialization. This improves the user's perception of the boot time of the device. The startup ordering can ensure that the right bundle is started first.

  • Handling erratic bundles - Problems can occur because bundles require services to be available when they are activated (this is a programming error). By controlling the start order, the management agent can prevent these problems.

  • High priority bundles - Certain tasks such as metering need to run as quickly as possible and cannot have a long startup delay. These bundles can be started first.

Start levels are not intended to be used for ensuring that dependencies are met when a bundle is started. Any of the life cycle actions (install/update/uninstall) can cause a dependency to become unavailable regardless of start levels.

9.2.1 Adaptations

This specification provides two adaptations of a Bundle object to a:

  • BundleStartLevel - Used to get and set the start level on a specific bundle.

  • FrameworkStartLevel - Used to get and control the framework start level. This adaptation must return null for any other bundle than the system bundle (bundle 0).

9.2.2 Bundle Start Level Bundle Adaptation

The adaptation provides the following methods:

9.2.3 Framework Start Level Bundle Adaptation

The Framework Start Level adaptation is only possible for the system bundle. Other bundles must return null for this adaptation. The adaptation provides the following methods:

9.3 The Concept of a Start Level

A start level is defined as a non-negative integer. A start level of 0 (zero) is the state in which the Framework has either not been launched or has completed shutdown (these two states are considered equivalent). In this state, no bundles are running. Progressively higher integral values represent progressively higher start levels. For example, 2 is a higher start level than 1. The Framework must support all positive int values (Integer.MAX_VALUE) for start levels.

The Framework has an active start level that is used to decide which bundles can be started. All bundles must be assigned a bundle start level. This is the minimum start level to start a bundle. The bundle start level can be set with the setStartLevel(int) method on the BundleStartLevel object. When a bundle is installed, it is initially assigned the bundle start level returned by getInitialBundleStartLevel() on a FrameworkStartLevel object. The initial bundle start level to be used when bundles are installed can be set with setInitialBundleStartLevel(int).

In addition, a bundle can be persistently marked as started or stopped with the Bundle start and stop methods. A bundle cannot run unless it is marked started, regardless of the bundle's start level.

9.3.1 Changing the Active Start Level

A management agent can influence the active start level with the setStartLevel(int) method. The Framework must then increase or decrease the active start level by 1 until the requested start level is reached. The process of starting or stopping bundles, which is initiated by the setStartLevel(int) method, must take place asynchronously.

This means that the active start level (the one that is active at a certain moment in time) must be changed to a new start level, called the requested start level. The active and requested levels differ during a certain period when the Framework starts and stops the appropriate bundles. Moving from the active start level to the requested start level must take place in increments of one (1).

If the requested start level is higher than the active start level, the Framework must increase the start level by one and then start all bundles that meet the following criteria:

  • Bundles that are persistently marked started, and

  • Bundles that have a bundle start level equal to the new active start level.

The Framework continues increasing the active start level and starting the appropriate bundles until it has started all bundles with a bundle start level that equals the requested start level.

The Framework must not increase to the next active start level until all started bundles have returned from their BundleActivator.start method normally or with an exception. A FrameworkEvent.ERROR must be broadcast when the BundleActivator.start method throws an exception.

If the requested start level is lower than the active start level, the Framework must stop all bundles that have a bundle start level that is equal to the active start level. The Framework must then decrease the active start level by 1. If the active start level is still higher than the requested start level, it should continue stopping the appropriate bundles and decreasing the active start level until the requested start level is reached. A FrameworkEvent.ERROR must be broadcast when the BundleActivator.stop method throws an exception.

If the requested start level is the active start level, the Framework will not start or stop any bundles.

When the requested start level is reached and all bundles satisfy the condition that their bundle start level <= active start level in order to be started, then the FrameworkEvent.STARTLEVEL_CHANGED event must be sent to all registered FrameworkListener objects. If the requested start level and active start level are equal, then this event may arrive before the setStartLevel method has returned.

It must therefore always be true that:

  • A bundle is started, or will be started soon, if the start level is less or equal to the active start level.

  • A bundle is stopped, or will be stopped soon, when it has a start level more than the active start level.

These steps are depicted in the flow chart in Figure 9.2.

Figure 9.2 Move to requested start level R, active level is A, B is a bundle's start level

Move to requested start level R, active level is A, B is a bundle's start level

If the Framework is currently involved in changing the active start level, it must first reach the previously requested start level before it is allowed to continue with a newly requested start level. For example, assume the active start level is 5 and the Framework is requested to transition to start level 3. Before start level 3 is reached, another request is made to transition to start level 7. In this case, the OSGi Framework must first complete the transition to start level 3 before it transitions to start level 7.

9.3.2 Startup Sequence

At startup, the Framework must have an active start level of zero. It must then move the active start level to the beginning start level. The beginning start level is specified with an argument when starting the Framework or through some other means, which is left undefined here. If no beginning start level is given, the Framework must assume a beginning start level of one (1).

The Framework must launch and then set the requested start level to the beginning start level. It must then follow the procedure described in Changing the Active Start Level to make the active start level equal the beginning start level, with the exception of the FrameworkEvent.START_LEVEL_CHANGED event broadcast. During launching, the Framework must broadcast a FrameworkEvent.STARTED event when the beginning start level is reached.

9.3.3 Shutdown Sequence

When the Framework shuts down, the requested start level must be set to zero. The Framework must then follow the process described in Changing the Active Start Level to make the active start level equal to zero.

9.3.4 Changing a Bundle's Start Level

Bundles are assigned an initial start level when they are installed. The default value for the initial start level is set to one, but can be changed with the setInitialBundleStartLevel(int) method on the FrameworkStartLevel object. A bundle's start level will not change when the setInitialBundleStartLevel(int) method later modifies the default initial start level.

Once installed, the start level of a bundle can be changed with setStartLevel(int). When a bundle's start level is changed and the bundle is marked persistently to be started, then the OSGi Framework must compare the new bundle start level to the active start level. For example, assume that the active start level is 5 and a bundle with start level 5 is started. If the bundle's start level subsequently is changed to 6 then this bundle must be stopped by the OSGi Framework but it must still be marked persistently to be started.

9.3.5 Starting a Bundle

If a bundle is started by calling the Bundle.start method, then the OSGi Framework must mark the bundle as persistently started. The OSGi Framework must not actually start a bundle when the active start level is less than the bundle's start level. In that case, the state must not change.

9.3.6 Exceptions in the Bundle Activator

If the BundleActivator.start or stop method throws an Exception, then the handling of this Exception is different depending who invoked the start or stop method.

If the bundle is started/stopped due to a change in the active start level or the bundle's start level, then the Exception must be wrapped in a BundleException and broadcast as a FrameworkEvent.ERROR event. Otherwise, a new BundleException must be created containing the exception and this BundleException is then thrown to the caller.

9.3.7 System Bundle

The System Bundle is defined to have a start level of zero. The start level of the System Bundle cannot be changed.

9.4 Example Applications

The Start Level API allows a management agent to implement many different startup schemes. The following sections show some examples.

9.4.1 Safe Mode Startup Scheme

A management agent can implement a safe mode in which it runs trusted bundles at level 1 and runs itself on level 2. When the management agent gets control, it constructs a list of all applications to be started. This list can be constructed from BundleContext.getBundles(). The management agent checks each bundle to determine if it is not started but is marked to be started persistently by calling the isPersistentlyStarted() method of the Start Level API.

Before it starts each bundle, the management agent persistently records the bundle to be started and then starts the bundle. This continues until all bundles are started. When all bundles are successfully started, the management agent persistently records that all bundles started without problems.

If the OSGi framework is restarted, the management agent should inspect the persistently recorded information. If the persistently recorded information indicates a bundle failure, the management agent should try to restart the system without that application bundle since that bundle failed. Alternatively, it could contact its Remote Manager and ask for assistance.

9.4.2 Splash Screen Startup Scheme

A splash screen is a popup containing startup information about an application. The popup provides feedback to the end user indicating that the system is still initializing. The Start Level API can be used by a bundle to pop-up a splash screen before any other bundle is started, and remove it once all bundles have been started. The splash-screen bundle would start at start level 1 and all other bundles would start at start level 2 or higher.

class SplashScreen implements 
    BundleActivator, FrameworkListener {
    Screen         screen;
    public void start(BundleContext context) {
        context.addFrameworkListener( this );
        screen = createSplash();
        screen.open();
    }
    public void stop(BundleContext context) {
        screen.close();
    }
    public void frameworkEvent( FrameworkEvent event ) {
        if ( event.getType() == FrameworkEvent.STARTED )
            screen.close();
    }
    Screen createSplash() { ... }
}

9.5 Security

The Start Level API requires Adapt Permission with action ADAPT for the following type:

  • org.osgi.framework.startlevel.BundleStartLevel

  • org.osgi.framework.startlevel.FrameworkStartLevel

The Start Level methods that mutate state require an additional Admin Permission with the action:

  • EXECUTE - For bundles that must be able to modify a bundle's start level

  • STARTLEVEL - For modifying the Framework's active start level.