summaryrefslogtreecommitdiff
path: root/src/linux/up-backend.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2012-07-11 15:06:04 +0100
committerRichard Hughes <richard@hughsie.com>2012-07-11 18:11:39 +0100
commit44189f8129edff56668cad6846579adc0e64f8f3 (patch)
treecd59904458b38f983769ddcf64837eeb24422219 /src/linux/up-backend.c
parent7bad068a2d9fbbd509d0a53bcf6c2ffde6a4ef77 (diff)
Use systemd for suspend and hibernate
When running under systemd, call into systemd for suspend and hibernate instead of pm-utils. To capture resume events, install a small script that gets executed by systemd after resume and sends a dbus signal back to upower. To make this work, the upower backends gain a new signal, ::resuming, that they can optionally emit to signal that a resume happened. Backends opt in to this by returning TRUE from up_backend_emits_resuming(). In this case, upower doesn't assume the sleep command to block until resume, but instead waits for the ::resuming signal from the backend. The only backend that uses this mechanism is the linux backend when built with systemd support. Signed-off-by: Richard Hughes <richard@hughsie.com>
Diffstat (limited to 'src/linux/up-backend.c')
-rw-r--r--src/linux/up-backend.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/linux/up-backend.c b/src/linux/up-backend.c
index be01763..ddd4472 100644
--- a/src/linux/up-backend.c
+++ b/src/linux/up-backend.c
@@ -45,6 +45,17 @@
#include "up-device-idevice.h"
#endif /* HAVE_IDEVICE */
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+
+#define SD_HIBERNATE_COMMAND "gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.Hibernate 'true'"
+#define SD_SUSPEND_COMMAND "gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.Suspend 'true'"
+
+#endif
+
static void up_backend_class_init (UpBackendClass *klass);
static void up_backend_init (UpBackend *backend);
static void up_backend_finalize (GObject *object);
@@ -59,11 +70,13 @@ struct UpBackendPrivate
UpDeviceList *managed_devices;
UpDock *dock;
UpConfig *config;
+ DBusConnection *connection;
};
enum {
SIGNAL_DEVICE_ADDED,
SIGNAL_DEVICE_REMOVED,
+ SIGNAL_RESUMING,
SIGNAL_LAST
};
@@ -564,6 +577,11 @@ out:
const gchar *
up_backend_get_suspend_command (UpBackend *backend)
{
+#ifdef HAVE_SYSTEMD
+ if (sd_booted ())
+ return SD_SUSPEND_COMMAND;
+ else
+#endif
return UP_BACKEND_SUSPEND_COMMAND;
}
@@ -573,9 +591,24 @@ up_backend_get_suspend_command (UpBackend *backend)
const gchar *
up_backend_get_hibernate_command (UpBackend *backend)
{
+#ifdef HAVE_SYSTEMD
+ if (sd_booted ())
+ return SD_HIBERNATE_COMMAND;
+ else
+#endif
return UP_BACKEND_HIBERNATE_COMMAND;
}
+gboolean
+up_backend_emits_resuming (UpBackend *backend)
+{
+#ifdef HAVE_SYSTEMD
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
/**
* up_backend_get_powersave_command:
**/
@@ -609,10 +642,32 @@ up_backend_class_init (UpBackendClass *klass)
G_STRUCT_OFFSET (UpBackendClass, device_removed),
NULL, NULL, up_marshal_VOID__POINTER_POINTER,
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
+ signals [SIGNAL_RESUMING] =
+ g_signal_new ("resuming",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UpBackendClass, resuming),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
g_type_class_add_private (klass, sizeof (UpBackendPrivate));
}
+static DBusHandlerResult
+message_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ UpBackend *backend = user_data;
+
+ if (dbus_message_is_signal (message, "org.freedesktop.UPower", "Resuming")) {
+ g_debug ("received Resuming signal");
+ g_signal_emit (backend, signals[SIGNAL_RESUMING], 0);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
/**
* up_backend_init:
**/
@@ -624,6 +679,15 @@ up_backend_init (UpBackend *backend)
backend->priv->daemon = NULL;
backend->priv->device_list = NULL;
backend->priv->managed_devices = up_device_list_new ();
+
+#ifdef HAVE_SYSTEMD
+ if (sd_booted ()) {
+ DBusGConnection *bus;
+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+ backend->priv->connection = dbus_g_connection_get_connection (bus);
+ dbus_connection_add_filter (backend->priv->connection, message_filter, backend, NULL);
+ }
+#endif
}
/**
@@ -648,6 +712,9 @@ up_backend_finalize (GObject *object)
g_object_unref (backend->priv->managed_devices);
+ if (backend->priv->connection)
+ dbus_connection_remove_filter (backend->priv->connection, message_filter, backend);
+
G_OBJECT_CLASS (up_backend_parent_class)->finalize (object);
}