summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/UPower.conf12
-rw-r--r--src/dummy/up-backend.c12
-rw-r--r--src/freebsd/up-backend.c12
-rw-r--r--src/linux/Makefile.am2
-rw-r--r--src/linux/up-backend.c85
-rw-r--r--src/openbsd/up-backend.c11
-rw-r--r--src/up-backend.h1
-rw-r--r--src/up-daemon.c28
8 files changed, 163 insertions, 0 deletions
diff --git a/etc/UPower.conf b/etc/UPower.conf
index 331743a..801f52f 100644
--- a/etc/UPower.conf
+++ b/etc/UPower.conf
@@ -76,3 +76,15 @@ PercentageAction=2
TimeLow=1200
TimeCritical=300
TimeAction=120
+
+# The action to take when "TimeAction" or "PercentageAction" above has been
+# reached for the batteries (UPS or laptop batteries) supplying the computer
+#
+# Possible values are:
+# PowerOff
+# Hibernate
+# HybridSleep
+#
+# If HybridSleep isn't available, Hibernate will be used
+# If Hibernate isn't available, PowerOff will be used
+CriticalPowerAction=HybridSleep
diff --git a/src/dummy/up-backend.c b/src/dummy/up-backend.c
index 5435dbe..d9d4a59 100644
--- a/src/dummy/up-backend.c
+++ b/src/dummy/up-backend.c
@@ -133,6 +133,18 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
}
/**
+ * up_backend_take_action:
+ * @backend: The %UpBackend class instance
+ *
+ * Act upon the %UP_DEVICE_LEVEL_ACTION warning-level.
+ **/
+void
+up_backend_take_action (UpBackend *backend)
+{
+ g_debug ("Not taking any action, dummy backend is used");
+}
+
+/**
* up_backend_class_init:
* @klass: The UpBackendClass
**/
diff --git a/src/freebsd/up-backend.c b/src/freebsd/up-backend.c
index 74a0b77..1466bbf 100644
--- a/src/freebsd/up-backend.c
+++ b/src/freebsd/up-backend.c
@@ -295,6 +295,18 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
return TRUE;
}
+/**
+ * up_backend_take_action:
+ * @backend: The %UpBackend class instance
+ *
+ * Act upon the %UP_DEVICE_LEVEL_ACTION warning-level.
+ **/
+void
+up_backend_take_action (UpBackend *backend)
+{
+ /* FIXME: Implement */
+}
+
/* Return value: a percentage value */
gfloat
up_backend_get_used_swap (UpBackend *backend)
diff --git a/src/linux/Makefile.am b/src/linux/Makefile.am
index 35e00eb..7242e1f 100644
--- a/src/linux/Makefile.am
+++ b/src/linux/Makefile.am
@@ -67,6 +67,8 @@ EXTRA_DIST = $(libupshared_la_SOURCES) \
libupshared_la_CFLAGS = \
$(WARNINGFLAGS_C)
+libupshared_la_LIBADD = $(GIO_LIBS)
+
clean-local :
rm -f *~
diff --git a/src/linux/up-backend.c b/src/linux/up-backend.c
index 41f6033..b49d748 100644
--- a/src/linux/up-backend.c
+++ b/src/linux/up-backend.c
@@ -53,6 +53,10 @@ static void up_backend_class_init (UpBackendClass *klass);
static void up_backend_init (UpBackend *backend);
static void up_backend_finalize (GObject *object);
+#define LOGIND_DBUS_NAME "org.freedesktop.login1"
+#define LOGIND_DBUS_PATH "/org/freedesktop/login1"
+#define LOGIND_DBUS_INTERFACE "org.freedesktop.login1.Manager"
+
#define UP_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_BACKEND, UpBackendPrivate))
struct UpBackendPrivate
@@ -64,6 +68,7 @@ struct UpBackendPrivate
UpDock *dock;
UpConfig *config;
DBusConnection *connection;
+ GDBusProxy *logind_proxy;
};
enum {
@@ -348,6 +353,77 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
return TRUE;
}
+static gboolean
+check_action_result (GVariant *result)
+{
+ if (result) {
+ const char *s;
+
+ g_variant_get (result, "(s)", &s);
+ if (g_strcmp0 (s, "yes") != 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * up_backend_take_action:
+ * @backend: The %UpBackend class instance
+ *
+ * Act upon the %UP_DEVICE_LEVEL_ACTION warning-level.
+ **/
+void
+up_backend_take_action (UpBackend *backend)
+{
+ struct {
+ const gchar *method;
+ const gchar *can_method;
+ } actions[] = {
+ { "HybridSleep", "CanHybridSleep" },
+ { "Hibernate", "CanHibernate" },
+ { "PowerOff", NULL },
+ };
+ guint i;
+
+ g_return_if_fail (backend->priv->logind_proxy != NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (actions); i++) {
+ gboolean action_available = FALSE;
+ GVariant *result;
+
+ if (actions[i].can_method) {
+ /* Check whether we can use the method */
+ result = g_dbus_proxy_call_sync (backend->priv->logind_proxy,
+ actions[i].can_method,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL);
+ action_available = check_action_result (result);
+ g_variant_unref (result);
+
+ if (!action_available)
+ continue;
+ } else {
+ action_available = TRUE;
+ }
+
+ /* Take action */
+ g_debug ("About to call logind method %s", actions[i].method);
+ g_dbus_proxy_call (backend->priv->logind_proxy,
+ actions[i].method,
+ g_variant_new ("(b)", FALSE),
+ G_DBUS_CALL_FLAGS_NONE,
+ G_MAXINT,
+ NULL,
+ NULL,
+ NULL);
+
+ return;
+ }
+
+ g_assert_not_reached ();
+}
+
/**
* up_backend_class_init:
* @klass: The UpBackendClass
@@ -383,6 +459,14 @@ up_backend_init (UpBackend *backend)
backend->priv = UP_BACKEND_GET_PRIVATE (backend);
backend->priv->config = up_config_new ();
backend->priv->managed_devices = up_device_list_new ();
+ backend->priv->logind_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ 0,
+ NULL,
+ LOGIND_DBUS_NAME,
+ LOGIND_DBUS_PATH,
+ LOGIND_DBUS_INTERFACE,
+ NULL,
+ NULL);
}
/**
@@ -404,6 +488,7 @@ up_backend_finalize (GObject *object)
g_object_unref (backend->priv->device_list);
if (backend->priv->gudev_client != NULL)
g_object_unref (backend->priv->gudev_client);
+ g_clear_object (&backend->priv->logind_proxy);
g_object_unref (backend->priv->managed_devices);
diff --git a/src/openbsd/up-backend.c b/src/openbsd/up-backend.c
index b6bd001..d10a6c2 100644
--- a/src/openbsd/up-backend.c
+++ b/src/openbsd/up-backend.c
@@ -148,6 +148,17 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
return TRUE;
}
+/**
+ * up_backend_take_action:
+ * @backend: The %UpBackend class instance
+ *
+ * Act upon the %UP_DEVICE_LEVEL_ACTION warning-level.
+ **/
+void
+up_backend_take_action (UpBackend *backend)
+{
+ /* FIXME: Implement */
+}
/**
* OpenBSD specific code
diff --git a/src/up-backend.h b/src/up-backend.h
index 06ab7ea..71b074c 100644
--- a/src/up-backend.h
+++ b/src/up-backend.h
@@ -69,6 +69,7 @@ void up_backend_test (gpointer user_data);
gboolean up_backend_coldplug (UpBackend *backend,
UpDaemon *daemon);
+void up_backend_take_action (UpBackend *backend);
G_END_DECLS
diff --git a/src/up-daemon.c b/src/up-daemon.c
index 549d732..1edfdee 100644
--- a/src/up-daemon.c
+++ b/src/up-daemon.c
@@ -81,6 +81,7 @@ struct UpDaemonPrivate
gboolean during_coldplug;
guint battery_poll_id;
guint battery_poll_count;
+ guint action_timeout_id;
gboolean use_percentage_for_policy;
guint low_percentage;
@@ -104,6 +105,8 @@ G_DEFINE_TYPE (UpDaemon, up_daemon, G_TYPE_OBJECT)
#define UP_DAEMON_ON_BATTERY_REFRESH_DEVICES_DELAY 1 /* seconds */
#define UP_DAEMON_POLL_BATTERY_NUMBER_TIMES 5
+#define UP_DAEMON_ACTION_DELAY 20 /* seconds */
+
/**
* up_daemon_get_on_battery_local:
*
@@ -502,6 +505,13 @@ up_daemon_set_on_battery (UpDaemon *daemon, gboolean on_battery)
up_daemon_emit_properties_changed (daemon, "OnBattery", g_variant_new_boolean (on_battery));
}
+static gboolean
+take_action_timeout_cb (UpDaemon *daemon)
+{
+ up_backend_take_action (daemon->priv->backend);
+ return G_SOURCE_REMOVE;
+}
+
/**
* up_daemon_set_warning_level:
**/
@@ -514,6 +524,22 @@ up_daemon_set_warning_level (UpDaemon *daemon, UpDeviceLevel warning_level)
g_object_notify (G_OBJECT (daemon), "warning-level");
up_daemon_emit_properties_changed (daemon, "WarningLevel", g_variant_new_uint32 (warning_level));
+
+ if (daemon->priv->warning_level == UP_DEVICE_LEVEL_ACTION) {
+ if (daemon->priv->action_timeout_id == 0) {
+ g_debug ("About to take action in %d seconds", UP_DAEMON_ACTION_DELAY);
+ daemon->priv->action_timeout_id = g_timeout_add_seconds (UP_DAEMON_ACTION_DELAY,
+ (GSourceFunc) take_action_timeout_cb,
+ daemon);
+ } else {
+ g_debug ("Not taking action, timeout id already set");
+ }
+ } else {
+ if (daemon->priv->action_timeout_id > 0) {
+ g_debug ("Removing timeout as action level changed");
+ g_source_remove (daemon->priv->action_timeout_id);
+ }
+ }
}
UpDeviceLevel
@@ -976,6 +1002,8 @@ up_daemon_finalize (GObject *object)
if (priv->battery_poll_id != 0)
g_source_remove (priv->battery_poll_id);
+ if (priv->action_timeout_id != 0)
+ g_source_remove (priv->action_timeout_id);
if (priv->proxy != NULL)
g_object_unref (priv->proxy);