99
102
#define DKP_DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_TYPE_DAEMON, DkpDaemonPrivate))
104
/* if using more memory compared to usable swap, disable hibernate */
105
#define DKP_DAEMON_SWAP_WATERLINE 80.0f /* % */
107
/* refresh all the devices after this much time when on-battery has changed */
108
#define DKP_DAEMON_ON_BATTERY_REFRESH_DEVICES_DELAY 3 /* seconds */
110
static gboolean dkp_daemon_device_add (DkpDaemon *daemon, GUdevDevice *d, gboolean emit_event);
111
static void dkp_daemon_device_remove (DkpDaemon *daemon, GUdevDevice *d);
102
114
* dkp_daemon_set_lid_is_closed:
105
dkp_daemon_set_lid_is_closed (DkpDaemon *daemon, gboolean lid_is_closed)
117
dkp_daemon_set_lid_is_closed (DkpDaemon *daemon, gboolean lid_is_closed, gboolean notify)
107
119
gboolean ret = FALSE;
108
static gboolean initialized = FALSE;
110
121
g_return_val_if_fail (DKP_IS_DAEMON (daemon), FALSE);
120
131
/* Do not emit an event on startup. Otherwise, e. g.
121
132
* gnome-power-manager would pick up a "lid is closed" change
122
133
* event when dk-p gets D-BUS activated, and thus would
123
134
* immediately suspend the machine on startup. FD#22574 */
124
135
egg_debug ("not emitting lid change event for daemon startup");
127
137
g_signal_emit (daemon, signals[CHANGED_SIGNAL], 0);
204
214
case PROP_CAN_SUSPEND:
205
/* TODO: for now assume we can always suspend */
206
g_value_set_boolean (value, TRUE);
215
g_value_set_boolean (value, daemon->priv->can_suspend);
209
218
case PROP_CAN_HIBERNATE:
210
/* TODO for now assume we can always hibernate */
211
g_value_set_boolean (value, TRUE);
219
g_value_set_boolean (value, daemon->priv->can_hibernate);
214
222
case PROP_ON_BATTERY:
353
* dkp_daemon_check_state:
356
dkp_daemon_check_state (DkpDaemon *daemon)
358
gchar *contents = NULL;
359
GError *error = NULL;
361
const gchar *filename = "/sys/power/state";
363
/* see what kernel can do */
364
ret = g_file_get_contents (filename, &contents, NULL, &error);
366
egg_warning ("failed to open %s: %s", filename, error->message);
367
g_error_free (error);
371
/* does the kernel advertise this */
372
daemon->priv->can_suspend = (g_strstr_len (contents, -1, "mem") != NULL);
373
daemon->priv->can_hibernate = (g_strstr_len (contents, -1, "disk") != NULL);
380
* dkp_daemon_check_swap:
383
dkp_daemon_check_swap (DkpDaemon *daemon)
385
gchar *contents = NULL;
386
gchar **lines = NULL;
387
GError *error = NULL;
394
gfloat percentage = 0.0f;
395
const gchar *filename = "/proc/meminfo";
397
/* get memory data */
398
ret = g_file_get_contents (filename, &contents, NULL, &error);
400
egg_warning ("failed to open %s: %s", filename, error->message);
401
g_error_free (error);
405
/* process each line */
406
lines = g_strsplit (contents, "\n", -1);
407
for (i=1; lines[i] != NULL; i++) {
408
tokens = g_strsplit_set (lines[i], ": ", -1);
409
len = g_strv_length (tokens);
411
if (g_strcmp0 (tokens[0], "SwapFree") == 0)
412
swap_free = atoi (tokens[len-2]);
413
else if (g_strcmp0 (tokens[0], "Active") == 0)
414
active = atoi (tokens[len-2]);
419
/* work out how close to the line we are */
420
if (swap_free > 0 && active > 0)
421
percentage = (active * 100) / swap_free;
422
egg_debug ("total swap available %i kb, active memory %i kb (%.1f%%)", swap_free, active, percentage);
345
430
* dkp_daemon_init:
348
433
dkp_daemon_init (DkpDaemon *daemon)
350
437
daemon->priv = DKP_DAEMON_GET_PRIVATE (daemon);
351
438
daemon->priv->polkit = dkp_polkit_new ();
352
439
daemon->priv->lid_is_present = FALSE;
353
440
daemon->priv->lid_is_closed = FALSE;
441
daemon->priv->can_suspend = FALSE;
442
daemon->priv->can_hibernate = FALSE;
444
/* check if we have support */
445
dkp_daemon_check_state (daemon);
447
/* do we have enough swap? */
448
if (daemon->priv->can_hibernate) {
449
waterline = dkp_daemon_check_swap (daemon);
450
if (waterline > DKP_DAEMON_SWAP_WATERLINE) {
451
egg_debug ("not enough swap to enable hibernate");
452
daemon->priv->can_hibernate = FALSE;
372
473
g_object_unref (daemon->priv->proxy);
373
474
if (daemon->priv->connection != NULL)
374
475
dbus_g_connection_unref (daemon->priv->connection);
375
if (daemon->priv->devkit_client != NULL)
376
g_object_unref (daemon->priv->devkit_client);
476
if (daemon->priv->gudev_client != NULL)
477
g_object_unref (daemon->priv->gudev_client);
377
478
if (daemon->priv->power_devices != NULL)
378
479
g_object_unref (daemon->priv->power_devices);
379
480
if (daemon->priv->managed_devices != NULL)
516
* dkp_daemon_get_number_devices_of_type:
519
dkp_daemon_get_number_devices_of_type (DkpDaemon *daemon, DkpDeviceType type)
523
const GPtrArray *array;
524
DkpDeviceType type_tmp;
527
/* ask each device */
528
array = dkp_device_list_get_array (daemon->priv->power_devices);
529
for (i=0; i<array->len; i++) {
530
device = (DkpDevice *) g_ptr_array_index (array, i);
531
g_object_get (device,
534
if (type == type_tmp)
418
541
* dkp_daemon_get_low_battery_local:
420
543
* As soon as _all_ batteries are low, this is true
623
* dkp_daemon_refresh_battery_devices:
626
dkp_daemon_refresh_battery_devices (DkpDaemon *daemon)
629
const GPtrArray *array;
633
/* refresh all devices in array */
634
array = dkp_device_list_get_array (daemon->priv->power_devices);
635
for (i=0; i<array->len; i++) {
636
device = (DkpDevice *) g_ptr_array_index (array, i);
637
/* only refresh battery devices */
638
g_object_get (device,
641
if (type == DKP_DEVICE_TYPE_BATTERY)
642
dkp_device_refresh_internal (device);
649
* dkp_daemon_refresh_battery_devices_cb:
652
dkp_daemon_refresh_battery_devices_cb (DkpDaemon *daemon)
654
egg_debug ("doing the delayed refresh");
655
dkp_daemon_refresh_battery_devices (daemon);
500
660
* dkp_daemon_device_changed:
503
dkp_daemon_device_changed (DkpDaemon *daemon, DevkitDevice *d, gboolean synthesized)
663
dkp_daemon_device_changed (DkpDaemon *daemon, GUdevDevice *d, gboolean synthesized)
506
666
DkpDevice *device;
509
670
/* first, change the device and add it if it doesn't exist */
512
673
device = DKP_DEVICE (object);
513
674
egg_debug ("changed %s", dkp_device_get_object_path (device));
514
675
dkp_device_changed (device, d, synthesized);
677
/* refresh battery devices when AC state changes */
678
g_object_get (device,
681
if (type == DKP_DEVICE_TYPE_LINE_POWER) {
682
/* refresh now, and again in a little while */
683
dkp_daemon_refresh_battery_devices (daemon);
684
g_timeout_add_seconds (DKP_DAEMON_ON_BATTERY_REFRESH_DEVICES_DELAY,
685
(GSourceFunc) dkp_daemon_refresh_battery_devices_cb, daemon);
516
egg_debug ("treating change event as add on %s", devkit_device_get_native_path (d));
689
egg_debug ("treating change event as add on %s", g_udev_device_get_sysfs_path (d));
517
690
dkp_daemon_device_add (daemon, d, TRUE);
680
853
/* does device exist in db? */
681
854
object = dkp_device_list_lookup (daemon->priv->power_devices, d);
682
855
if (object == NULL) {
683
egg_debug ("ignoring remove event on %s", devkit_device_get_native_path (d));
856
egg_debug ("ignoring remove event on %s", g_udev_device_get_sysfs_path (d));
685
858
device = DKP_DEVICE (object);
686
859
dkp_device_removed (device);
694
* dkp_daemon_device_event_signal_handler:
867
* dkp_daemon_uevent_signal_handler_cb:
697
dkp_daemon_device_event_signal_handler (DevkitClient *client, const char *action,
698
DevkitDevice *device, gpointer user_data)
870
dkp_daemon_uevent_signal_handler_cb (GUdevClient *client, const gchar *action,
871
GUdevDevice *device, gpointer user_data)
700
873
DkpDaemon *daemon = DKP_DAEMON (user_data);
702
875
if (g_strcmp0 (action, "add") == 0) {
703
egg_debug ("add %s", devkit_device_get_native_path (device));
876
egg_debug ("add %s", g_udev_device_get_sysfs_path (device));
704
877
dkp_daemon_device_add (daemon, device, TRUE);
705
878
} else if (g_strcmp0 (action, "remove") == 0) {
706
egg_debug ("remove %s", devkit_device_get_native_path (device));
879
egg_debug ("remove %s", g_udev_device_get_sysfs_path (device));
707
880
dkp_daemon_device_remove (daemon, device);
708
881
} else if (g_strcmp0 (action, "change") == 0) {
709
egg_debug ("change %s", devkit_device_get_native_path (device));
882
egg_debug ("change %s", g_udev_device_get_sysfs_path (device));
710
883
dkp_daemon_device_changed (daemon, device, FALSE);
712
egg_warning ("unhandled action '%s' on %s", action, devkit_device_get_native_path (device));
885
egg_warning ("unhandled action '%s' on %s", action, g_udev_device_get_sysfs_path (device));
752
925
GError *error_local = NULL;
753
PolKitCaller *caller;
926
PolkitSubject *subject;
754
927
gchar *stdout = NULL;
755
928
gchar *stderr = NULL;
757
caller = dkp_polkit_get_caller (daemon->priv->polkit, context);
930
subject = dkp_polkit_get_subject (daemon->priv->polkit, context);
761
if (!dkp_polkit_check_auth (daemon->priv->polkit, caller, "org.freedesktop.devicekit.power.suspend", context))
934
if (!dkp_polkit_check_auth (daemon->priv->polkit, subject, "org.freedesktop.devicekit.power.suspend", context))
764
937
ret = g_spawn_command_line_sync ("/usr/sbin/pm-suspend", &stdout, &stderr, NULL, &error_local);
790
963
GError *error_local = NULL;
791
PolKitCaller *caller;
964
PolkitSubject *subject;
792
965
gchar *stdout = NULL;
793
966
gchar *stderr = NULL;
795
caller = dkp_polkit_get_caller (daemon->priv->polkit, context);
968
subject = dkp_polkit_get_subject (daemon->priv->polkit, context);
799
if (!dkp_polkit_check_auth (daemon->priv->polkit, caller, "org.freedesktop.devicekit.power.hibernate", context))
972
if (!dkp_polkit_check_auth (daemon->priv->polkit, subject, "org.freedesktop.devicekit.power.hibernate", context))
802
975
ret = g_spawn_command_line_sync ("/usr/sbin/pm-hibernate", &stdout, &stderr, NULL, &error_local);
858
1031
for (i=0; subsystems[i] != NULL; i++)
859
1032
egg_debug ("registering subsystem : %s", subsystems[i]);
861
daemon->priv->devkit_client = devkit_client_new (subsystems);
862
if (!devkit_client_connect (daemon->priv->devkit_client, &error)) {
863
egg_warning ("Couldn't open connection to DeviceKit daemon: %s", error->message);
864
g_error_free (error);
867
g_signal_connect (daemon->priv->devkit_client, "device-event",
868
G_CALLBACK (dkp_daemon_device_event_signal_handler), daemon);
1034
daemon->priv->gudev_client = g_udev_client_new (subsystems);
1035
g_signal_connect (daemon->priv->gudev_client, "uevent",
1036
G_CALLBACK (dkp_daemon_uevent_signal_handler_cb), daemon);
896
devices = devkit_client_enumerate_by_subsystem (daemon->priv->devkit_client, subsystems, &error);
898
egg_warning ("Cannot enumerate devices: %s", error->message);
899
g_error_free (error);
900
g_object_unref (daemon);
904
for (l = devices; l != NULL; l = l->next) {
905
DevkitDevice *device = l->data;
906
dkp_daemon_device_add (daemon, device, FALSE);
908
g_list_foreach (devices, (GFunc) g_object_unref, NULL);
909
g_list_free (devices);
1065
/* add all subsystems */
1066
for (i=0; subsystems[i] != NULL; i++) {
1067
devices = g_udev_client_query_by_subsystem (daemon->priv->gudev_client, subsystems[i]);
1068
for (l = devices; l != NULL; l = l->next) {
1070
dkp_daemon_device_add (daemon, device, FALSE);
1072
g_list_foreach (devices, (GFunc) g_object_unref, NULL);
1073
g_list_free (devices);
911
1076
daemon->priv->on_battery = (dkp_daemon_get_on_battery_local (daemon) &&
912
1077
!dkp_daemon_get_on_ac_local (daemon));