Author |
Marius Vollmer |
Status |
Draft |
Version |
2013-11-27 |
Approver |
Olli Finni |
Copyright © Nokia. All rights reserved.
This material, including documentation and any related computer programs, is protected by copyright controlled by Nokia. All rights are reserved. Copying, including reproducing, storing, adapting or translating, any or all of this material requires the prior written consent of Nokia. This material also contains confidential information, which may not be disclosed to others without the prior written consent of Nokia.
Nokia is a registered trademark of Nokia. Other company and product names mentioned herein may be trademarks or tradenames of their respective owners.
Introduction
The Context Framework, part of the Data Domain, provides a uniform, high level API to numerous context properties of the device. While many of these context properties are available without the context framework, each of them has its own specific way of accessing it. The context framework collects them all behind a uniform API, and applications thus have easy access to all of the context properties.
The following lists some typical context properties:
-
Connectivity status of the device; whether it is connected to the Internet and by what means.
-
Location; the name of the current city.
-
Builtin sensors; orientation in space.
-
Current use; idle, plays media, web browsing.
-
Combined properties; current weather based on location and online weather database.
More concretely, the information in the status bar of a device is provided exclusively by the Context Framework.
Applications access context properties by using the ContextProperty
class that is implemented in api:libcontextsubscriber.
The context framework is modular: context properties from multiple
independent components are directly combined in the
libcontextsubscriber
API and applications can access them without
needing to know who is ultimately providing them.
A component that wants to directly provide context properties needs to implement the relevant interfaces defined by the context framework. Currently, the only supported way to do that is to use the api:libcontextprovider library.
In addition to information from multiple sources, the context framework is a provider of context properties itself: there is a context daemon that collects information from low-level and legacy interfaces. This context daemon is a good default location for implementing context properties and for absorbing properties from existing subsystems that have aqcuired them for historical reasons and would rather get rid of them.
The concrete list of properties is ultimately defined by their providers, but the context framework is the central authority: the ‘official’ list of context properties of the Maemo platform is defined and documented by the context framework.
To summarize, the context framework contributes value to the Maemo platform in the following ways:
-
It implements and documents a high-level, uniform API to a set of context properties that are provided by multiple components.
-
It defines and documents the concrete list of properties of the Maemo platform. This includes harmonizing the context ontology with other industry efforts.
-
It implements context properties that do not naturally belong to other subsystems and coordinates the implementation of context properties that do belong in specific subsystems.
-
It provides a debugging and exploration tool for inspecting and controlling context properties.
Thus, the Context Framework does not drive the behavior of the system, it only provides the information that is needed for other components to decide for themselves. To makes this reasonably easy, the context properties are at a high level of abstraction and express the coarse grained states of the device. For example, the properties tell you whether it is completely idle, in passive use playing some media, or in active use. They don’t give a real-time view of CPU load.
Architecture
Concepts
Context properties are collected from all providers that have
registered themselves with the
context-providers
interface. For each
provider, this registration information includes the list of its
properties with type information and a short description for each, and
the D-Bus bus name where the provider can be reached. Providers can
be both on the session and on the system bus, and the registration
information indicates which bus it is.
This registration information is read by the libcontextsubscriber
library and used by its ContextProperty
class to connect a requested
property name to the right bus name.
The registration information is compiled into a cache that is
optimized for use by libcontextsubscriber
. When the set of
registered properties changes, the cache is recompiled by a command
line utility provided by the context framework. This will then
trigger all libcontextsubscriber clients to reload the registry
information, and existing ContextProperty
instances to be updated.
(Note that the cache only caches property declarations, it does not ever contain the values of context properties.)
When providers are installed from packages, recompilation of the cache happens automatically. Triggers in the Context Framework packages are used to run the command line utility at the right times.
The libcontextsubscriber
library gracefully handles start, stop and
restart of providers. During system startup some applications may
start to use the Context Framework before all providers are
available. Properties become dynamically available as providers become
available, and removed when providers are no longer available.
Communication between a ContextProperty
and the provider happens
using a private D-Bus interface. This interface allows for bulk
retrieval of property values, bulk subscriptions, and bulk change
notification.
The values of properties are represented to clients as a QVariant
value. Properties can have a special null value when they are not
available, either because they are not provided by any provider, or
because the provider is not able to deliver a value. In other words,
the types of all context properties are "maybe types": subscribers
might get a value or not. In general, the null value means that the
real value of the property is unknown.
The null value is different from the empty string or the empty list. For example, the "Location.City" property, which denotes the name of the current city as a string, will be null when the name of the city is unknown (either because the current location of the device is unknown or because the database that maps from locations to city names is not reachable), but it will be the empty string when the current location is known to be outside of any city.
The absence of a value can have many reasons: no provider is available for this property, the provider has not yet delivered a value, or the provider is deliberately not delivering a value, which it can in turn have many reasons. For example, necessary hardware might not be present or its use might be disallowed by the current power management policy, or a needed online database might not reachable.
The Context Framework makes no attempt to distinguish these different reasons. Subscribers should make good use of a value when they get it, but they must not fail catastrophically when no value is available, or when it takes longer than expected for it to become available.
It is expected that eventually the statusbar plugins, such as the battery charge monitor and the connectivity indicators, exclusively use the context properties to retrieve the information they display.
Context providers need to implement the private D-Bus interface. This is done with the api:libcontextprovider library. This library is used by the context daemon itself, which can serve as an extended example.
The Connectivity Framework and the Sensor Framework are expected to be context providers as described above. Additional context properties, such as those related to the Location Framework, are implemented by the context daemon contained in the Context Framework.
The contextd
Context Daemon will implement all context properties
that don’t have a native provider. It will at least implement
properties for the information contained in HAL and for location
related information. It is expected that contextd
runs the
necessary reverse geocoding operations at a reasonable frequency. It
will also perform Content Framework queries to retrieve the values of
certain properties.
If necessary for security reasons, the contextd
might need to be
split into multiple instances.
System context
The context framework decouples context subscribers from context providers.
Structural view
The following figure summarizes the components of the Context Framework.
There are two fundamental options for exporting information via the context framework:
-
The context daemon can use existing platform interfaces, such as HAL, to collect this information, process it, and export it as a context property.
This applies to: HAL, Location subsystem, Kernel. -
The principal producer of the information, such as the
icd2
daemon in the Connectivity subsystem, can use the libcontextprovider API and export the information directly to applications without using the context daemon as a middle man.
This applies to: Sensor Framework, possibly Connectivity subsystem (needs agreeement), possibly Telephony subsystem (needs agreement)
Provided Interfaces
libcontextsubscriber
A C++ API for listening to context properties.
libcontextprovider
A C++ and C API for providing values of context properties.
context-properties
The canonical list of context properties in the Maemo platform. When a context property from the list is available, it must conform to its description there.
context-providers
The interface to register providers of context properties. A provider must use the api:libcontextprovider API.
Development support
No special features are needed in the Context Framework components to
make them work in a Scratchbox environment. Availability of
individual properties depends on the ability of their providers to run
in Scratchbox. The contextd
Context Daemon runs but might not be
able to provide all properties.
The Context Framework provides a graphical tool called the Context Commander to watch all available context properties. This can be used to test context providers during development.
In addition, the Context Commander can be used to force context properties of selected applications to arbitrary values. This can be used to test the reaction of applications to context changes.
The Context Commander runs on the device and either show its UI on the device itself or exports it to an external X11 server. This way, the testing can be done without disturbing the display of the device itself.
When started, the Context Commander takes control of all subscribers with their cooperation: when the "org.freedesktop.ContextKit.Commander" name appears on the session D-Bus, all ContextProperty instances redirect their subcription requests to it.
There are vague ideas about integrating the Context Commander into Eclipse.
Licenses
The components of the Context Framework will be developed publically, under the umbrella of the freedesktop.org organization. All source code is licensed with LGPL 2.1, including the daemon and context commander.
Non-free source code can safely interact with the Context Framework components.
User Data, Settings, and Configurability
The Context Framework does not store user data and is not configurable.
Configurability
See above.
Packages
contextkit
- Languages
-
C, C++
- License
-
LGPL 2.1
- Provided interfaces
-
libcontextsubscriber, libcontextprovider, context-providers, context-properties,
- Used interfaces
-
libdbus, libgee, libglib, libcdb, libqt4-dbus, libqt4-xml, libqtcore4
- Binary packages
-
libcontextsubscriber0, libcontextsubscriber0-dbg, libcontextsubscriber-dev, libcontextsubscriber-doc, libcontextprovider0, libcontextprovider0-dbg, libcontextprovider-dev, libcontextprovider-doc, contextkit, contextkit-doc, context-dbg
- Sources
context-commander
- Languages
-
C++
- License
-
LGPL 2.1
- Provided interfaces
-
none
- Used interfaces
-
libcontextsubscriber, libqt4-dbus, libqt4-gui, libqt4-core
- Binary packages
-
context-commander
- Sources
context-provider-example
- Languages
-
C
- License
-
LGPL 2.1
- Provided interfaces
-
Context.Example.* properties.
- Used interfaces
-
libcontextprovider, sysfs files for accelerometer and ambient light sensor
- Binary packages
-
context-provider-example
- Sources
-
https://dvcs.projects.maemo.org/git/?p=ContextProviderExample
context-subscriber-example
- Languages
-
C++
- License
-
LGPL 2.1
- Provided interfaces
-
none.
- Used interfaces
-
Context.Example.* properties, libcontextsubscriber, libqt4-gui, libqt4-core
- Binary packages
-
context-subscriber-example
- Sources
-
https://dvcs.projects.maemo.org/git/?p=ContextSubscriberExample
Performance
General
The Context Framework makes no real-time guarantees and does not rely on any.
It is careful not to cause significant additional communication that wouldn’t be needed anyway to communicate contextual information to the interested parties.
We expect 5 to 10 providers, about 20 subscribers, each subscribed to an average of 5 properties. Property values can become arbitrarily big, but are expected to be mostly small, in the order of 10 bytes. The occasional big property value is expected to change correspondingly infrequently.
Memory
OneNAND |
All files are stored on the OneNAND, in their FHS mandated places |
200 KiB |
eMMC |
Not used |
0 |
RAM/Idle |
A couple of bytes per subscription plus a couple more per provided property |
200 KiB |
RAM/Peak |
The biggest property values might reach a KiB |
500 KiB |
Runtime
The Context Framework allows subscribers and providers to directly connect to each other (incurring only the usual D-Bus daemon overhead). Context properties are expected to change only infrequently and providers are urged to throttle the rate of change.
The contextd daemon is started on the first subscription to one of its properties. This is expected to happen on every boot since it provides properties that are used by other daemons, such as the context engine.
Power consumption
Providers of context properties know at any time whether someone in the system is subscribed to them. This allows them to avoid expensive operations for producing values that are not needed.
The documentation for subscribers urges them to take the cost of producing property values into consideration. The subscriber API offers an easy way to temporarily suspend a subscription.
Sometimes, increased granularity of control over a property is needed: instead of just switching it on and off, the subscriber might want to request different levels of quality. For example, some subscribers might need a higher update frequency than others and are willing to pay the associated price in power consumption.
The recommended way to implement this increased control is to offer multiple properties that deliver the same value but with different qualities-of-service. For example, there could be both "Location.HighResCoordinates" and "Location.LowResCoordinates" properties that both deliver the current geographical coordinates. Subscribing to "Location.HighResCoordinates", however, would cause the location to be updated more frequently and maybe even activate a GPS device, if available.
Security Impact
Different context properties might need to have different access restrictions. A context provider can implement these access restriction in whatever way works, but should preferrably use the existing features of the Security Framework.
The Security Framework can control access per D-Bus bus connection. Thus, a given context provider should only implement properties with the same access rights and leave it to the Security Framework to allow or disallow connections to the provider as a whole.
The Context Daemon needs to follow the same rules, of course.
The libcontextsubscriber library listens for a special D-Bus bus name to appear and then allows the service behind that name to override all values of context properties. The library protects this special name with a security token so that only specially certified software can own this name. The context commander might or might not be certified in this way; instead of certifying it, it might be preferrable to require developers to explicitly disable the name protection (via a developer certificate or a general device unlocking ceremony) before they can use the context commander.
Open Items
-
The D-Bus interface needs to be reviewed and maybe redesigned. It might make sense to use one object path per property instead of one object path per subscriber like we do now.
-
Integration with Content Framework needs to be addressed. Snapshots of the current context need to be imported into the content database (as document tags, say) and content queries might be run periodically to provide contextual information (such as the ten most recently accessed documents).
-
The current plan for localization of context properties requires context providers to do it. They thusly need access to the current device language and rumour has it that everything about l10n is different in Harmattan.
Appendices
The Context Framework for Context Providers
The advantages of the Context Framework for application writers should be clear: they can access a rich set of useful contextual information with a simple API.
The ultimate providers of this information, however, might feel that the context framework itself does not add significant value: after all, they already implement APIs to access all that information anyway. Hooking into the Context Framework means a duplication of effort and the requirement to express everything as a value (instead of a general query/response API) might be unwelcome.
However, the unified API and central maintenance of the list of core properties carries a lot of value:
-
It makes using more contextual information trivial once you have used your first property.
-
It makes it possible to expose present and future context information in all kinds of places with a single effort. Once the context framework has been integrated into the Web runtime, into Python, or into any language that people care about, no additional effort is needed by anyone to track future developments of the context properties.
-
It decouples context providers from consumers. The context framework makes it possible to move the implementation of a property from one component to another without having to restart the consumers.
-
It makes it worthwhile to develop sophisticated tools such as the context commander and support for easy automated testing of context subscribers and providers.
-
It might allow some context providers to exit the "API business" altogether.
If a piece of information is available in a corner of the system but needed somewhere else, it is only human to see this as a nuisance and cobble together a few D-Bus methods to access that information.
The context framework provides a good alternative in those cases.
It is thus our opinion that the context framework provides enough value to justify pushing it into other peoples subsystems, even if that means duplicated efforts.
Moreover, the effort needed to integrate with the context framework is low.
Relation to Policy Engine
The policy engine has the role in the Maemo platform to decide system global behavior and controls the various distributed enforcement points accordingly. This job will likely be done by OHMng.
The policy engine can be both a subscriber to and provider of context properties. The policy engine will base its decisions (partly) on the current values of context properties and will publish (part of) its decisions as context properties.
Most facts that need to be gathered as input for the policy engine can be communicted to it via the context framework. If necessary, non-public context properties can be defined that (while visible to everyone who knows where to look) are not maintained as part of the list of core properties.
Decisions of the policy engine can be communicated to cooperating applications and potentially even to enforcement points. The set of values representable as context properties is quite rich so that hopefully all facts and decisions can be represented with them.