Each optional or managed feature on Symbian OS is given a 32-bit unique
identifier and represented by a TUid
. The names of Symbian
OS features and their UID assignments are defined in the
featureUIDs.h
header file. For example:
namespace NFeature
{
const TUid KFax = {0x10279806}; // Sample only! Refer to true
const TUid KPrint = {0x10279807}; // featureUIDs.h header file for
const TUid KBluetooth = {0x10279808}; // actual names and UIDs (plus
const TUid KInfrared = {0x10279809}; // proper in-code documentation
const TUid KMmc = {0x1027980a}; // about each feature).
const TUid KUsb = {0x1027980b};
// . . .
}
These names or UIDs are the argument values for the Feature Registry query functions. The granularity of features is generally quite coarse. Seldom will a feature correspond to a single API method or aspect of its behaviour. Other approaches (beyond what is provided by the Feature Registry) are generally required to detect these minor variations. Strong guarantees of backward compatibility mean that existing functionality associated with a feature or identifier may not change or be removed where the feature is supported at all. Functionality can, however, grow in later releases.
It is recommended that licensees define their feature IDs in a
similarly way i.e. in a file named UIxFeatureUIDs.h
containing a
namespace for their platform features.
A feature ID is a globally unique identifier (UID) consisting of a 32-bit number. The UID can be allocated on behalf of licensees and third parties from Symbian Signed. There are two steps in setting up a a Feature ID:
allocate the UID
define the UID in feature management source files.
For new features designed to be optional, and introduced into Symbian OS from version 9.3 onwards, obtain a new UID from Symbian Signed.
To maintain forward compatibility, there is a small range of IDs that represent features that are considered to be supported on the platform by default. Such features are always present but may be removed. The feature IDs in this range are controlled by the System Design Authority group within Symbian.
The Feature and UID must then be defined in a number of ROM-build files and header files to complete the introduction of the managed feature. The procedure is managed by the handset vendors.
Feature queries are made using the
RFeatureRegistry
class declared in the header file
featreg.h
, supplied by featreg.dll
and linked through
featreg.lib
.
A single feature Query API is provided by class
RFeatureRegistryNotify
, declared in
featreg.h
, supplied by featreg.dll
and linked through
featreg.lib
.
To inquire whether a single feature is supported on the device, use
the following static function of class RFeatureRegistry
:
static TInt QuerySupportS(TUid aFeatureUid);
This function returns a positive value if the feature is supported, zero if the feature is not supported, otherwise (in the exceptional case) a negative, system-wide error code if support cannot be determined.
You can choose to deal with the error returns locally. For example, by considering the feature not supported:
TBool haveUsb = RFeatureRegistry::QuerySupportS(NFeature::KUsb) > 0;
Alternatively you can choose to Leave on exceptional error returns:
TBool haveUsb =
User::LeaveIfError(RFeatureRegistry::QuerySupportS(NFeature::KUsb)) > 0;
The Feature Registry maintains an additional 32-bit data word per
feature, which can be obtained using an overload of the
QuerySupportS
function:
static TInt QuerySupportS(TUid aFeatureUid, TUint32& aInfo);
The contents of this extra word are reserved for future use.
The most efficient way to find out if more than one function is
supported is to open and query an instance of the
RFeatureRegistry
class using the following non-static
methods of the RFeatureRegistry
class:
inline RFeatureRegistry();
TInt Open();
TInt QuerySupport(TUid aFeatureUid);
TInt QuerySupport(TUid aFeatureUid, TUint32& aInfo);
void Close();
To query several features in a non-leaving context (and treating exceptional results as if the feature is not supported):
TBool iHaveUsb;
TBool iHaveBluetooth;
...
RFeatureRegistry featReg;
const TBool opened = (featReg.Open() == KErrNone);
iHaveUsb = opened && (featReg.QuerySupport(NFeature::KUsb) > 0);
iHaveBluetooth = opened && (featReg.QuerySupport(NFeature::KBluetooth) > 0);
// can always call Close(), even if Open() failed:
featReg.Close();
Or if choosing to Leave on exceptional returns:
RFeatureRegistry featReg;
User::LeaveIfError(featReg.Open());
CleanupClosePushL(featReg); // don’t forget this
iHaveUsb = User::LeaveIfError(featReg.QuerySupport(NFeature::KUsb)) > 0;
iHaveBluetooth =
User::LeaveIfError(featReg.QuerySupport(NFeature::KBluetooth)) > 0;
CleanupStack::PopAndDestroy(&featReg); // this calls Close()
RFeatureRegistry
also has an overload of
non-static QuerySupport, which can return the extra word of data stored with
each feature.
An important point about the above non-static APIs is that they only
guarantee to return the state of features at the time
Open()
was called. To ensure that future run-time feature
changes are detected, close the instance immediately after querying it, and
re-open it next time queries are to be made. This also frees up resources held
by the open instance.
Note: Querying features can have an impact on performance. Therefore, if you are querying frequently (for example, in a loop) it is recommended that you cache the query return. However, if the feature is seldom used (once or twice between switching the device on and off), caching is unnecessary.
When deciding when and how often to query, you must plan carefully as feature queries will result in a performance overhead. It is recommended that you always query and cache the return value if it is to be used many times in quick succession, particularly in loops. However, if the feature is seldom used (once or twice between switching the device on and off), caching is unnecessary.
This issue only occurs within Symbian and licensee organisations,
and does not apply to external developers. This issue only happens in debug
builds; in release builds, the error value KErrCorrupt
is
returned instead of a panic. “1” is the enumeration for
EFeatRegBadConfig
, declared in the exported header file
featregpan.h
.
This is a serious problem. Your UI-provider or system integration team must ensure that the Feature Registry has a valid configuration file for the environment you are using, be it an emulator or a target device or reference board.
If the error KErrNoMemory
is returned, this
means there is insufficient memory to complete the query. If more memory
becomes available subsequent queries may succeed.
If the error KErrCorrupt
is returned, this is
serious. Your UI-provider or system integration team must ensure that the
Feature Registry has a valid configuration file for the environment you are
using, be it an emulator or a target device or reference board. Refer to the
Single feature queries and
Multiple feature queries sections
for example code on how to allow client programs to continue under such
circumstances.
Where optional features are removed from a device, all effort is made to make the failure of any attempt to use the missing features as graceful as possible. Unless individual features are documented to give particular, safe responses when not supported by a device (through a stub DLL, for example), their use as a means to discover the feature cannot be considered safe unless expressly documented as such. In addition, optional features supplied as plug-ins may be more efficiently detected using the Feature Registry. Finally, even if it works now, there is no guarantee that attempts to use a removed feature in future will not have serious consequences including exceptions, leaves or panics.
A Notify API is provided by the
RFeatureRegistryNotify
class, declared in
featreg.h
, supplied by featreg.dll
and linked through
featreg.lib
.
The RFeatureRegistryNotify
class has the
following member functions that allow you to subscribe for notification of
changes in the Feature Registry:
inline RFeatureRegistryNotify();
TInt Open();
void Subscribe(TRequestStatus &aNotifyStatus);
void Cancel();
void Close();
To use the API requires an instance of the
RFeatureRegistryNotify
class to be Opened and Subscribed to. It
will usually be employed in Active Objects in an Active Scheduler. At any time
while the instance is open, call Cancel()
to ensure the
object is not subscribed for notification. If it previously was subscribed, the
asynchronous Subscribe()
request is completed with
KErrCancel
.
When a Subscribe()
request completes successfully, will
know that the Feature Registry has changed. You must re-query the features you
are interested in, to determine whether the change affected affects you.
To ensure changes are not missed, always re-subscribe before querying the Feature Registry.
Note:
Most clients do not require run-time notification of feature changes. The vast majority of features are not removable, and most applications can be restarted if a feature needs to be rediscovered. The potential use of this API are long-running system tasks that monitor a variety of features, and applications that use software that becomes supported or unsupported as add-on devices are attached and detached (that is, plug and play devices).
While the class RFeatureRegistryNotify
is
currently marked as internal to Symbian, the intention is to reclassify it as
publishedAll in a later release of Symbian OS. Therefore, contrary
to expectations, this class can be used as described.
It is not expected that many clients will require run-time notification of feature changes. The vast majority of features are not removable, and most applications can be restarted if a feature needs to be rediscovered. This API is likely to be used by long-running system tasks that monitor a variety of features, and applications that use software that becomes supported or unsupported as add-on devices are attached and detached (that is, plug and play devices).
No. Notification is for any change in the Feature Registry. The recipient must determine if the status of any feature they are interested in has changed.
No. The current implementation of Feature Registry is a constant ROM-based configuration file. The API is provided for forward compatibility. Applications can be written now anticipating run-time feature changes in a future implementation. Alternatively, applications can be written in the future once run-time updates do occur, and the API will be present – but will never notify – on older devices so there will be no compatibility issues.
This information only applies to Symbian and licensees. Yes, but it
is a side-effect of the current implementation, is @internalComponent and not
guaranteed to work into the future. Running featregsetup.exe
(a
binary included with the component) currently forces notification.