~nemo-mobile-team/nemo-mobile/mce

« back to all changes in this revision

Viewing changes to modules/powersavemode.c

  • Committer: David Greaves
  • Author(s): David Greaves
  • Date: 2015-10-21 16:13:02 UTC
  • Revision ID: git-v1:426c4b5f971755305d27ac6ae6178075ad054316
Migration to git.merproject.org

Signed-off-by: David Greaves <david.greaves@jolla.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * @file powersavemode.c
3
 
 * Power saving mode module -- this handles the power saving mode
4
 
 * for MCE
5
 
 * <p>
6
 
 * Copyright © 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
7
 
 * <p>
8
 
 * @author David Weinehall <david.weinehall@nokia.com>
9
 
 *
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.
13
 
 *
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.
18
 
 *
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/>.
21
 
 */
22
 
 
23
 
#include "powersavemode.h"
24
 
 
25
 
#include "../mce.h"
26
 
#include "../mce-log.h"
27
 
#include "../mce-gconf.h"
28
 
#include "../mce-dbus.h"
29
 
 
30
 
#include <mce/dbus-names.h>
31
 
 
32
 
#include <gmodule.h>
33
 
 
34
 
/** Module name */
35
 
#define MODULE_NAME             "powersavemode"
36
 
 
37
 
/** Functionality provided by this module */
38
 
static const gchar *const provides[] = { MODULE_NAME, NULL };
39
 
 
40
 
/** Module information */
41
 
G_MODULE_EXPORT module_info_struct module_info = {
42
 
        /** Name of the module */
43
 
        .name = MODULE_NAME,
44
 
        /** Module provides */
45
 
        .provides = provides,
46
 
        /** Module priority */
47
 
        .priority = 250
48
 
};
49
 
 
50
 
/** Battery charge level */
51
 
static gint battery_level = 100;
52
 
/** Charger state */
53
 
static charger_state_t charger_state = CHARGER_STATE_UNDEF;
54
 
 
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;
59
 
 
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;
64
 
 
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;
69
 
 
70
 
/** Active power saving mode */
71
 
static gboolean active_power_saving_mode = FALSE;
72
 
 
73
 
/** Device thermal state */
74
 
static thermal_state_t thermal_state = THERMAL_STATE_UNDEF;
75
 
 
76
 
/**
77
 
 * Send the PSM state
78
 
 *
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
82
 
 */
83
 
static gboolean send_psm_state(DBusMessage *const method_call)
84
 
{
85
 
        DBusMessage *msg = NULL;
86
 
        gboolean status = FALSE;
87
 
 
88
 
        mce_log(LL_DEBUG,
89
 
                "Sending PSM state: %s",
90
 
                active_power_saving_mode ? "TRUE" : "FALSE");
91
 
 
92
 
        /* If method_call is set, send a reply,
93
 
         * otherwise, send a signal
94
 
         */
95
 
        if (method_call != NULL) {
96
 
                msg = dbus_new_method_reply(method_call);
97
 
        } else {
98
 
                /* psm_state_ind */
99
 
                msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF,
100
 
                                      MCE_PSM_STATE_SIG);
101
 
        }
102
 
 
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) {
107
 
                mce_log(LL_CRIT,
108
 
                        "Failed to append %sargument to D-Bus message "
109
 
                        "for %s.%s",
110
 
                        method_call ? "reply " : "",
111
 
                        method_call ? MCE_REQUEST_IF :
112
 
                                      MCE_SIGNAL_IF,
113
 
                        method_call ? MCE_PSM_STATE_GET :
114
 
                                      MCE_PSM_STATE_SIG);
115
 
                dbus_message_unref(msg);
116
 
                goto EXIT;
117
 
        }
118
 
 
119
 
        /* Send the message */
120
 
        status = dbus_send_message(msg);
121
 
 
122
 
EXIT:
123
 
        return status;
124
 
}
125
 
 
126
 
/**
127
 
 * Update the power saving mode
128
 
 */
129
 
static void update_power_saving_mode(void)
130
 
{
131
 
        gint new_power_saving_mode;
132
 
 
133
 
        /* XXX: later on we should make overheating another
134
 
         *      trigger for power saving mode too
135
 
         */
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
145
 
                 */
146
 
                new_power_saving_mode = TRUE;
147
 
        } else {
148
 
                new_power_saving_mode = FALSE;
149
 
        }
150
 
 
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);
157
 
        }
158
 
}
159
 
 
160
 
/**
161
 
 * Datapipe trigger for the battery charge level
162
 
 *
163
 
 * @param data A pointer representation of the battery charge level in percent
164
 
 */
165
 
static void battery_level_trigger(gconstpointer const data)
166
 
{
167
 
        battery_level = GPOINTER_TO_INT(data);
168
 
 
169
 
        update_power_saving_mode();
170
 
}
171
 
 
172
 
/**
173
 
 * Datapipe trigger for the charger state
174
 
 *
175
 
 * @param data A pointer representation of the charger state
176
 
 */
177
 
static void charger_state_trigger(gconstpointer const data)
178
 
{
179
 
        charger_state = GPOINTER_TO_INT(data);
180
 
 
181
 
        update_power_saving_mode();
182
 
}
183
 
 
184
 
/**
185
 
 * Datapipe trigger for the thermal state
186
 
 *
187
 
 * @param data THERMAL_STATE_OK if the device temperature is normal,
188
 
 *             THERMAL_STATE_OVERHEATED if the device is overheated
189
 
 */
190
 
static void thermal_state_trigger(gconstpointer const data)
191
 
{
192
 
        thermal_state = GPOINTER_TO_INT(data);
193
 
 
194
 
        update_power_saving_mode();
195
 
}
196
 
 
197
 
/**
198
 
 * GConf callback for power saving related settings
199
 
 *
200
 
 * @param gcc Unused
201
 
 * @param id Connection ID from gconf_client_notify_add()
202
 
 * @param entry The modified GConf entry
203
 
 * @param data Unused
204
 
 */
205
 
static void psm_gconf_cb(GConfClient *const gcc, const guint id,
206
 
                         GConfEntry *const entry, gpointer const data)
207
 
{
208
 
        const GConfValue *gcv = gconf_entry_get_value(entry);
209
 
 
210
 
        (void)gcc;
211
 
        (void)data;
212
 
 
213
 
        /* Key is unset */
214
 
        if (gcv == NULL) {
215
 
                mce_log(LL_DEBUG,
216
 
                        "GConf Key `%s' has been unset",
217
 
                        gconf_entry_get_key(entry));
218
 
                goto EXIT;
219
 
        }
220
 
 
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();
230
 
        } else {
231
 
                mce_log(LL_WARN,
232
 
                        "Spurious GConf value received; confused!");
233
 
        }
234
 
 
235
 
EXIT:
236
 
        return;
237
 
}
238
 
 
239
 
/**
240
 
 * D-Bus callback for the get PSM mode method call
241
 
 *
242
 
 * @param msg The D-Bus message
243
 
 * @return TRUE on success, FALSE on failure
244
 
 */
245
 
static gboolean psm_state_get_dbus_cb(DBusMessage *const msg)
246
 
{
247
 
        gboolean status = FALSE;
248
 
 
249
 
        mce_log(LL_DEVEL, "Received PSM state get request from %s",
250
 
               mce_dbus_get_message_sender_ident(msg));
251
 
 
252
 
        /* Try to send a reply that contains the current PSM state */
253
 
        if (send_psm_state(msg) == FALSE)
254
 
                goto EXIT;
255
 
 
256
 
        status = TRUE;
257
 
 
258
 
EXIT:
259
 
        return status;
260
 
}
261
 
 
262
 
/** Array of dbus message handlers */
263
 
static mce_dbus_handler_t psm_dbus_handlers[] =
264
 
{
265
 
        /* signals - outbound (for Introspect purposes only) */
266
 
        {
267
 
                .interface = MCE_SIGNAL_IF,
268
 
                .name      = MCE_PSM_STATE_SIG,
269
 
                .type      = DBUS_MESSAGE_TYPE_SIGNAL,
270
 
                .args      =
271
 
                        "    <arg name=\"psm_active\" type=\"b\"/>\n"
272
 
        },
273
 
        /* method calls */
274
 
        {
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,
279
 
                .args      =
280
 
                        "    <arg direction=\"out\" name=\"power_saving_mode_active\" type=\"b\"/>\n"
281
 
        },
282
 
        /* sentinel */
283
 
        {
284
 
                .interface = 0
285
 
        }
286
 
};
287
 
 
288
 
/** Add dbus handlers
289
 
 */
290
 
static void mce_psm_init_dbus(void)
291
 
{
292
 
        mce_dbus_handler_register_array(psm_dbus_handlers);
293
 
}
294
 
 
295
 
/** Remove dbus handlers
296
 
 */
297
 
static void mce_psm_quit_dbus(void)
298
 
{
299
 
        mce_dbus_handler_unregister_array(psm_dbus_handlers);
300
 
}
301
 
 
302
 
/**
303
 
 * Init function for the power saving mode module
304
 
 *
305
 
 * @todo XXX status needs to be set on error!
306
 
 *
307
 
 * @param module Unused
308
 
 * @return NULL on success, a string with an error message on failure
309
 
 */
310
 
G_MODULE_EXPORT const gchar *g_module_check_init(GModule *module);
311
 
const gchar *g_module_check_init(GModule *module)
312
 
{
313
 
        (void)module;
314
 
 
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);
322
 
 
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,
326
 
                               MCE_GCONF_PSM_PATH,
327
 
                               psm_gconf_cb,
328
 
                               &psm_gconf_cb_id);
329
 
 
330
 
        mce_gconf_get_bool(MCE_GCONF_PSM_PATH,
331
 
                           &power_saving_mode);
332
 
 
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,
337
 
                               psm_gconf_cb,
338
 
                               &force_psm_gconf_cb_id);
339
 
 
340
 
        mce_gconf_get_bool(MCE_GCONF_FORCED_PSM_PATH,
341
 
                           &force_psm);
342
 
 
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,
347
 
                               psm_gconf_cb,
348
 
                               &psm_threshold_gconf_cb_id);
349
 
 
350
 
        mce_gconf_get_int(MCE_GCONF_PSM_THRESHOLD_PATH,
351
 
                          &psm_threshold);
352
 
 
353
 
        /* Add dbus handlers */
354
 
        mce_psm_init_dbus();
355
 
 
356
 
        return NULL;
357
 
}
358
 
 
359
 
/**
360
 
 * Exit function for the power saving mode module
361
 
 *
362
 
 * @todo D-Bus unregistration
363
 
 *
364
 
 * @param module Unused
365
 
 */
366
 
G_MODULE_EXPORT void g_module_unload(GModule *module);
367
 
void g_module_unload(GModule *module)
368
 
{
369
 
        (void)module;
370
 
 
371
 
        /* Remove gconf notifications  */
372
 
        mce_gconf_notifier_remove(psm_gconf_cb_id),
373
 
                psm_gconf_cb_id = 0;
374
 
 
375
 
        mce_gconf_notifier_remove(force_psm_gconf_cb_id),
376
 
                force_psm_gconf_cb_id = 0;
377
 
 
378
 
        mce_gconf_notifier_remove(psm_threshold_gconf_cb_id),
379
 
                psm_threshold_gconf_cb_id = 0;
380
 
 
381
 
        /* Remove dbus handlers */
382
 
        mce_psm_quit_dbus();
383
 
 
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);
391
 
 
392
 
        return;
393
 
}