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.
This commit is contained in:
Bastien Nocera 2013-10-13 02:46:32 +02:00
parent 28438a7672
commit 68b9975ad9
8 changed files with 163 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -67,6 +67,8 @@ EXTRA_DIST = $(libupshared_la_SOURCES) \
libupshared_la_CFLAGS = \
$(WARNINGFLAGS_C)
libupshared_la_LIBADD = $(GIO_LIBS)
clean-local :
rm -f *~

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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);