Plugins
Introduction
Plugins are external modules that are loaded at runtime.
Plugins have preference data and internal state known as keys and policy,
and also install a default system preferences file.
Plugin Key Defaults
We need to set system preferences when there is no user logged in or we
are very early in the boot sequence.
We do this with each plugin installing a text file with the plugin key
name, the value, and if the key is modifiable from the user sesison.
The plugin preferences are read from /etc/ohm/plugins/{name}
Comments are lines with first character # and then the
rest of the line is ignored.
Files are flat text with the following formal description,
plugin_prefix.key value public
There is a single space between the values, and all values are signed ints.
By making a key public, all the session users are allowed to change the
preference value, for instance the brightness on AC.
If a key is private then the public keyword is omitted, and any attempt
to change the key from the session will fail.
The public and private key concept is a way to enforce fine-grained
specific system policy on users when using PolicyKit rules for every
action would be too great an overhead.
Do not set internal state keys with their initial value here.
These should be added using ohm_plugin_conf_provide()
during load() and then the values populated in the
coldplug() method.
This ensures the correct ordering of coldplug.
System Start
The file /etc/ohm/modules.ini allows the system
builder to set the modules to be loaded at startup.
For instance, on a fast PC we may want to suggest different modules
to a embedded ARM.
Plugin Dependencies
Plugins can tell ohmd that other plugins are required
for certain functionality, for instance, the backlight unit on a mobile
phone may require the temperature module to be present, so it can do the
temperature shutdown checks.
This is done with ohm_plugin_require().
ohmd daemon will fail to load if any required plugin
is not present after the plugins have finished initializing.
Plugins can also tell ohmd that other plugins are suggested for certain
functionality, for instance, the backlight unit may work best when the
battery plugin is loaded so we can dim when we are low on power.
This is done with ohm_plugin_suggest().
ohmd daemon will print a message to the console if any
suggested plugin is not present.
Plugins can also tell ohmd that other plugins are
banned, for instance, a proprietary battery discharge plugin maybe
incompatible with the standard battery plugin.
This is done with ohm_plugin_prevent().
ohmd will fail to load if any prevented plugin is
manually loaded or loaded through a dependency of another plugin.
Plugins must also tell OHM that they will provide certain keys.
This is done using ohm_plugin_conf_provide() and
then OHM can check to see if the plugin is trying to provide keys
that are managed by another plugin.
This will stop the system doing odd things when two plugins try to write
to one key and is a good check when building policy.
In production code this check should be turned off using the command
line argument --no-checks as this speeds up the
initial coldplug considerably.
Plugin access to keys
To get key values from the global keystore, a plugin must use
ohm_plugin_conf_get_key() which will return false
if the key is not available.
Keys can be set using ohm_plugin_conf_set_key.
A plugin may want to be notified when a key changes.
In typical code, the key and the value would be passed to the plugin
and then the key name compared against a fixed list.
This is too slow for the plugin system in OHM, as many plugins may
have to be chained together for a policy action.
It was found that repeated strcmp()'s on all the
changed value keys was causing high load on embedded machines.
To register interest in a key change, a plugin must call
ohm_plugin_conf_interested() along with an integer ID
unique to the plugin.
The integer ID does not have to be unique among the other plugins.
When the key is changed in OHM by another plugin of the session user,
this is matched against a hash table for O(1) complexity, and then
a list iterated over sending the indervidual ID's to the plugins.
Matching integer ID's in plugins is much faster than matching strings,
for a small coldplug overhead.
See the example plugin code for more details.
Session Access to keys
Plugins have direct access to the keystore and can read and write any key
even if private.
The DBUS interface to the keystore is however limited to only setting
public keys to enforce security policy.
The DBUS interface should only be used to set preferences, it should
never be used to set or change policy - this is the job for the plugin.
The DBUS interface is protected from setting or creating keys to prevent
malicious users overwriting system prefrences that are not to be changed.
Session software can not load or unload plugins, as this would be a
system and security risk.
Default plugins
Some plugins are shipped by default and provide typical use cases.
Backlight Adjustment
Backlight brightness and state can be changed on most backlight hardware.
These are the optional DBUS methods for controlling the brightness of
the backlight.
Exported keys
Keys exported by this plugin:
Key
Description
backlight.value_ac
Brightness in percentage when on AC
backlight.value_battery
Brightness in percentage when on battery
backlight.value_idle
Brightness in percentage when idle
backlight.time_idle
The amount of time in seconds before the backlight is put
into idle mode, or zero to disable.
Idle mode is typically dimming for most backlight devices.
backlight.time_off
The amount of time in seconds before the backlight is turned
off, or zero to disable.