2
* @file powersavemode.c
3
* Power saving mode module -- this handles the power saving mode
6
* Copyright © 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
8
* @author David Weinehall <david.weinehall@nokia.com>
10
* mce is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU Lesser General Public License
12
* version 2.1 as published by the Free Software Foundation.
14
* mce is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
* Lesser General Public License for more details.
19
* You should have received a copy of the GNU Lesser General Public
20
* License along with mce. If not, see <http://www.gnu.org/licenses/>.
23
#include "powersavemode.h"
26
#include "../mce-log.h"
27
#include "../mce-gconf.h"
28
#include "../mce-dbus.h"
30
#include <mce/dbus-names.h>
35
#define MODULE_NAME "powersavemode"
37
/** Functionality provided by this module */
38
static const gchar *const provides[] = { MODULE_NAME, NULL };
40
/** Module information */
41
G_MODULE_EXPORT module_info_struct module_info = {
42
/** Name of the module */
44
/** Module provides */
46
/** Module priority */
50
/** Battery charge level */
51
static gint battery_level = 100;
53
static charger_state_t charger_state = CHARGER_STATE_UNDEF;
55
/** GConf callback ID for power saving mode setting */
56
static guint psm_gconf_cb_id = 0;
57
/** Power saving mode from GConf */
58
static gboolean power_saving_mode = DEFAULT_POWER_SAVING_MODE;
60
/** GConf callback ID for forced power saving mode setting */
61
static guint force_psm_gconf_cb_id = 0;
62
/** Forced power saving mode from GConf */
63
static gboolean force_psm = FALSE;
65
/** GConf callback ID for power saving mode threshold */
66
static guint psm_threshold_gconf_cb_id = 0;
67
/** Power saving mode threshold from GConf */
68
static gint psm_threshold = DEFAULT_PSM_THRESHOLD;
70
/** Active power saving mode */
71
static gboolean active_power_saving_mode = FALSE;
73
/** Device thermal state */
74
static thermal_state_t thermal_state = THERMAL_STATE_UNDEF;
79
* @param method_call A DBusMessage to reply to;
80
* pass NULL to send a signal instead
81
* @return TRUE on success, FALSE on failure
83
static gboolean send_psm_state(DBusMessage *const method_call)
85
DBusMessage *msg = NULL;
86
gboolean status = FALSE;
89
"Sending PSM state: %s",
90
active_power_saving_mode ? "TRUE" : "FALSE");
92
/* If method_call is set, send a reply,
93
* otherwise, send a signal
95
if (method_call != NULL) {
96
msg = dbus_new_method_reply(method_call);
99
msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF,
103
/* Append the power saving mode */
104
if (dbus_message_append_args(msg,
105
DBUS_TYPE_BOOLEAN, &active_power_saving_mode,
106
DBUS_TYPE_INVALID) == FALSE) {
108
"Failed to append %sargument to D-Bus message "
110
method_call ? "reply " : "",
111
method_call ? MCE_REQUEST_IF :
113
method_call ? MCE_PSM_STATE_GET :
115
dbus_message_unref(msg);
119
/* Send the message */
120
status = dbus_send_message(msg);
127
* Update the power saving mode
129
static void update_power_saving_mode(void)
131
gint new_power_saving_mode;
133
/* XXX: later on we should make overheating another
134
* trigger for power saving mode too
136
if (((((battery_level <= psm_threshold) &&
137
(power_saving_mode == TRUE)) ||
138
(force_psm == TRUE)) &&
139
(charger_state != CHARGER_STATE_ON)) ||
140
(thermal_state == THERMAL_STATE_OVERHEATED)) {
141
/* If the battery charge level is lower than the threshold,
142
* and the user has enable power saving mode,
143
* or if the device is overheated,
144
* activate low power mode
146
new_power_saving_mode = TRUE;
148
new_power_saving_mode = FALSE;
151
if (active_power_saving_mode != new_power_saving_mode) {
152
active_power_saving_mode = new_power_saving_mode;
153
(void)execute_datapipe(&power_saving_mode_pipe,
154
GINT_TO_POINTER(active_power_saving_mode),
155
USE_INDATA, CACHE_INDATA);
156
send_psm_state(NULL);
161
* Datapipe trigger for the battery charge level
163
* @param data A pointer representation of the battery charge level in percent
165
static void battery_level_trigger(gconstpointer const data)
167
battery_level = GPOINTER_TO_INT(data);
169
update_power_saving_mode();
173
* Datapipe trigger for the charger state
175
* @param data A pointer representation of the charger state
177
static void charger_state_trigger(gconstpointer const data)
179
charger_state = GPOINTER_TO_INT(data);
181
update_power_saving_mode();
185
* Datapipe trigger for the thermal state
187
* @param data THERMAL_STATE_OK if the device temperature is normal,
188
* THERMAL_STATE_OVERHEATED if the device is overheated
190
static void thermal_state_trigger(gconstpointer const data)
192
thermal_state = GPOINTER_TO_INT(data);
194
update_power_saving_mode();
198
* GConf callback for power saving related settings
201
* @param id Connection ID from gconf_client_notify_add()
202
* @param entry The modified GConf entry
205
static void psm_gconf_cb(GConfClient *const gcc, const guint id,
206
GConfEntry *const entry, gpointer const data)
208
const GConfValue *gcv = gconf_entry_get_value(entry);
216
"GConf Key `%s' has been unset",
217
gconf_entry_get_key(entry));
221
if (id == psm_gconf_cb_id) {
222
power_saving_mode = gconf_value_get_bool(gcv);
223
update_power_saving_mode();
224
} else if (id == force_psm_gconf_cb_id) {
225
force_psm = gconf_value_get_bool(gcv);
226
update_power_saving_mode();
227
} else if (id == psm_threshold_gconf_cb_id) {
228
psm_threshold = gconf_value_get_int(gcv);
229
update_power_saving_mode();
232
"Spurious GConf value received; confused!");
240
* D-Bus callback for the get PSM mode method call
242
* @param msg The D-Bus message
243
* @return TRUE on success, FALSE on failure
245
static gboolean psm_state_get_dbus_cb(DBusMessage *const msg)
247
gboolean status = FALSE;
249
mce_log(LL_DEVEL, "Received PSM state get request from %s",
250
mce_dbus_get_message_sender_ident(msg));
252
/* Try to send a reply that contains the current PSM state */
253
if (send_psm_state(msg) == FALSE)
262
/** Array of dbus message handlers */
263
static mce_dbus_handler_t psm_dbus_handlers[] =
265
/* signals - outbound (for Introspect purposes only) */
267
.interface = MCE_SIGNAL_IF,
268
.name = MCE_PSM_STATE_SIG,
269
.type = DBUS_MESSAGE_TYPE_SIGNAL,
271
" <arg name=\"psm_active\" type=\"b\"/>\n"
275
.interface = MCE_REQUEST_IF,
276
.name = MCE_PSM_STATE_GET,
277
.type = DBUS_MESSAGE_TYPE_METHOD_CALL,
278
.callback = psm_state_get_dbus_cb,
280
" <arg direction=\"out\" name=\"power_saving_mode_active\" type=\"b\"/>\n"
288
/** Add dbus handlers
290
static void mce_psm_init_dbus(void)
292
mce_dbus_handler_register_array(psm_dbus_handlers);
295
/** Remove dbus handlers
297
static void mce_psm_quit_dbus(void)
299
mce_dbus_handler_unregister_array(psm_dbus_handlers);
303
* Init function for the power saving mode module
305
* @todo XXX status needs to be set on error!
307
* @param module Unused
308
* @return NULL on success, a string with an error message on failure
310
G_MODULE_EXPORT const gchar *g_module_check_init(GModule *module);
311
const gchar *g_module_check_init(GModule *module)
315
/* Append triggers/filters to datapipes */
316
append_output_trigger_to_datapipe(&battery_level_pipe,
317
battery_level_trigger);
318
append_output_trigger_to_datapipe(&charger_state_pipe,
319
charger_state_trigger);
320
append_output_trigger_to_datapipe(&thermal_state_pipe,
321
thermal_state_trigger);
323
/* Power saving mode setting */
324
/* Since we've set a default, error handling is unnecessary */
325
mce_gconf_notifier_add(MCE_GCONF_EM_PATH,
330
mce_gconf_get_bool(MCE_GCONF_PSM_PATH,
333
/* Forced power saving mode setting */
334
/* Since we've set a default, error handling is unnecessary */
335
mce_gconf_notifier_add(MCE_GCONF_EM_PATH,
336
MCE_GCONF_FORCED_PSM_PATH,
338
&force_psm_gconf_cb_id);
340
mce_gconf_get_bool(MCE_GCONF_FORCED_PSM_PATH,
343
/* Power saving mode threshold */
344
/* Since we've set a default, error handling is unnecessary */
345
mce_gconf_notifier_add(MCE_GCONF_EM_PATH,
346
MCE_GCONF_PSM_THRESHOLD_PATH,
348
&psm_threshold_gconf_cb_id);
350
mce_gconf_get_int(MCE_GCONF_PSM_THRESHOLD_PATH,
353
/* Add dbus handlers */
360
* Exit function for the power saving mode module
362
* @todo D-Bus unregistration
364
* @param module Unused
366
G_MODULE_EXPORT void g_module_unload(GModule *module);
367
void g_module_unload(GModule *module)
371
/* Remove gconf notifications */
372
mce_gconf_notifier_remove(psm_gconf_cb_id),
375
mce_gconf_notifier_remove(force_psm_gconf_cb_id),
376
force_psm_gconf_cb_id = 0;
378
mce_gconf_notifier_remove(psm_threshold_gconf_cb_id),
379
psm_threshold_gconf_cb_id = 0;
381
/* Remove dbus handlers */
384
/* Remove triggers/filters from datapipes */
385
remove_output_trigger_from_datapipe(&thermal_state_pipe,
386
thermal_state_trigger);
387
remove_output_trigger_from_datapipe(&battery_level_pipe,
388
battery_level_trigger);
389
remove_output_trigger_from_datapipe(&charger_state_pipe,
390
charger_state_trigger);