From 68b9975ad98b94a28ce2e2ca21316e603d464f1a Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 13 Oct 2013 02:46:32 +0200 Subject: daemon: Add CriticalPowerAction Paraphrasing from the configuration option: The action to take when "TimeAction" or "PercentageAction" above has been reached for the batteries (UPS or laptop batteries) supplying the computer. This is done 20 seconds after the warning-level variable got set to UP_DEVICE_LEVEL_ACTION has been set, to give the opportunity to front-ends to display a (short) warning. This is only implemented for the Linux backend, using logind. --- etc/UPower.conf | 12 +++++++ src/dummy/up-backend.c | 12 +++++++ src/freebsd/up-backend.c | 12 +++++++ src/linux/Makefile.am | 2 ++ src/linux/up-backend.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ src/openbsd/up-backend.c | 11 +++++++ src/up-backend.h | 1 + src/up-daemon.c | 28 ++++++++++++++++ 8 files changed, 163 insertions(+) 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 @@ -132,6 +132,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) +{ + 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); -- cgit v1.2.1