|
Collectively, manufacturers market hundreds of models of mobile devices, presenting today's consumer with innumerable choices. While this may be great for the consumer, it presents a seemingly insurmountable problem for mobile application developers.
Because of the disparities among platform operating systems (OSs)and application run-time environments, and the variety of form factors, companies must determine which platform to support. Making the right selection is the key to minimizing risks when the application goes to market. Unfortunately, predicting mainstream technologies six to nine months in advance is difficult as the industry undergoes dramatic technological changes each year.
Developing applications for a single platform often doesn't leverage a company's capital investment. Aligning with a single carrier or channel partner adds to the overall risk. If the partnership fails, companies have to quickly port their applications to a new platform and begin the difficult process of developing new partnerships. Should a company decide to develop an application for multiple platforms, the cost of implementing the application for each platform can be excessive. Most would agree that obtaining expertise in platforms is a painstaking endeavor. The only reasonable way to mitigate these risks is to develop an approach that enables developers to implement mobile applications in a platform agnostic manner.
Competing platform OSs
The key challenge in developing middleware for mobile devices is the degrees of variability inherent in platform OSs and application run-time environments. Each platform provides access to essentially the same underlying hardware devices and facilities, but does so using different APIs. Some APIs provide high-level access while others provide a lower level. Also, some APIs are more feature rich providing wider interfaces, while others are feature poor providing narrower interfaces.
Platforms vary greatly in terms of execution models (see the table). Some platforms are single-threaded and provide absolute control to the application developer while others are multi-threaded and provide non-deterministic behavior and a lack of control. Some platforms are completely asynchronous where APIs provide results using callback functions. Other platforms are completely synchronous and force the calling function to block until the results are obtained. These factors taken together provide the greatest challenge to middleware developers.

Proposed middleware layer
How does the middleware developer distill a common API that can adapt to a wide range of platforms? Abstraction is a powerful technique for generalizing differences among platforms. Design-pattern advocates view architectural layers as a key strategy for implementing abstractions. Introducing a middleware layer lets application developers develop to a common API regardless of the underlying platform (Fig. 1). Essentially, the middleware layer separates system invariants (applications) from system variants (platforms).

1. Adding a middleware layer lets developers employ a common API regardless of the underlying platform.
The proposed middleware layer is comprised of two categories of object-oriented classes: the Task Management classes and assorted Platform Adaptor classes. The Task Manager provides a common execution run-time environment that supports an asynchronous, event-driven execution model. These facilities enable real-time applications to execute with the same run-time semantics regardless of the underlying platform.
The platform adaptor classes provide a common API to all the platform specific resources and hardware devices. These APIs include classes that allow developers to interface to the display and keypad to create rich user interfaces with a common look and feel across platforms.
Multitasking environment
When it comes to run-time environments, each platform provides a very different execution model. All platforms, with the exception of Brew, support multi-threading. Each multi-threading model, along with their respective thread synchronization mechanisms, is fundamentally different in terms of functionality and language specific features. For example, J2ME uses JAVA-styled synchronizers while Windows Mobile uses a UNIX-styled locking and signaling mechanism. The Task Manager must abstract the application developer from these disparate, low-level threading mechanisms and provide an easy-to-use Task Manager that will enable quick application development.
Perhaps the most fundamental problem with these threading models is that they don't provide a common framework for multi-tasking. Most mobile applications are non-trivial and real-time. As such, they require a rich environment for specifying tasks that can communicate asynchronously using events. A common multi-tasking framework can be implemented on either a single- or multi-threaded platform. On multi-threaded platforms, multitasking allows events to be processed in parallel and can therefore provide better real-time responsiveness to high priority events.
The Active Object design pattern has been used successfully to develop middleware systems such as the ACE, Rose RT, Symbian , and numerous other. Effectively, Active Objects implement tasks and provide the basic framework for multitasking. Each Active Object executes on a separate control thread (Fig. 2). On single-threaded platforms, the Active Object shares the common application thread. Active Objects are event driven. Events are sent to Active Objects from other Active Objects, the user interface, or callback services. Events are queued for the Active Object in a message queue. The Task Manager is an Active Object based system that serves as a mini-kernel. The Task Manager synchronizes the queuing and de-queuing of events as well as the scheduling of Active Objects to service events. Active Objects process events using run-to-completion semantics.

2. Active Objects implement tasks and provide a basic multitasking framework.
The benefits of Active Objects are:
- Active Objects decouple method invocation from execution using event queues and prioritization. This provides better real-time response to time-critical events.
- Synchronized event queues provide thread-safe communication between Active Objects and external events.
- Active Object member methods and data are bound to a single control thread. This ensures that an Active Object's members are only accessed by the object's dedicated thread, alleviating the need for synchronization mechanisms to protect member data.
The Task Manager is implemented using the Active Object model. Classes for implementing the Active Object task and event are provided. Additional classes are provided to implement services such as application construction/destruction and application global data. Compared to Rose RT, ACE, and other Active Object implementation, the Task Manager is lightweight and well suited for low-tier mobile devices.
To implement a task in the Task Manager, the app developer inherits from the Task class and overloads the run method. The developer implements additional event types by extending the Task Manager's Event type enumeration. The Event class is implemented using the Command design pattern. It provides methods for sending, replying to, and canceling events. A timeout feature returns an Event to its sender if the Event isn't processed in a specified time period.
Platform adaptors
Two key challenges in developing adaptable apps are the difference in platform APIs and the synchronicity models used by each platform for accessing system resources and devices. Platform APIs differ in terms of breadth and depth. In terms of breadth, some APIs are feature rich (wide) and others are feature poor (narrow). In terms of depth, some APIs provide high-level functions while others provide low-level functions. Developing an adaptor with a common API for a specific interface requires the middleware developer to balance the aspects of breadth and depth.
Synchronicity refers to the manner in which the platform provides the response to a resource/device request. Some platform APIs are synchronous. They require the Active Object to block until the request can be completed. Typically, responses using synchronous APIs are provided as return values using the call stack. In general, synchronous APIs aren't well suited for event-driven, real-time systems.
Other platform APIs are asynchronous. They require the Active Object to register for callbacks before the service is requested. When the request is completed, the platform passes the return values to the Active Object by calling the registered callback method. The callback is typically made on a platform-provided thread. On some platforms, ready events are passed to the Active Object, requiring the object to read the values from a buffer or device.
|