summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kellner <christian@kellner.me>2017-02-10 15:19:51 +0100
committerBastien Nocera <hadess@hadess.net>2017-03-25 18:04:59 +0100
commit01cd65c1a7c88cf66e36b8da2d9cca2d0f23050d (patch)
tree4d2cc85b8bd97da4d0a07e4cba00c3a6b95a9dfa
parenta69d151907ade8b1ea5c1dea992c81b3b546d529 (diff)
linux: Refresh devices after waking up from sleep
The battery levels might have changed drastically compared to before sleep. Since we poll batteries at set intervals, it can take quite some time for the new level to be picked up by the polling code. Listen to the "PrepareForSleep" signal emitted by logind, that gets emitted on suspend and wake up. Pause polling globally on suspend, and refresh all devices manually and resume polling when waking up. https://bugs.freedesktop.org/show_bug.cgi?id=99763
-rw-r--r--src/linux/up-backend.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/linux/up-backend.c b/src/linux/up-backend.c
index 2ba201a..edd7775 100644
--- a/src/linux/up-backend.c
+++ b/src/linux/up-backend.c
@@ -62,6 +62,7 @@ struct UpBackendPrivate
UpDeviceList *managed_devices;
UpConfig *config;
GDBusProxy *logind_proxy;
+ guint logind_sleep_id;
};
enum {
@@ -460,6 +461,57 @@ up_backend_take_action (UpBackend *backend)
}
/**
+ * up_backend_prepare_for_sleep:
+ *
+ * Callback for logind's PrepareForSleep signal. It receives
+ * a boolean that indicates if we are about to sleep (TRUE)
+ * or waking up (FALSE).
+ * In case of the waking up we refresh the devices so we are
+ * up to date, especially w.r.t. battery levels, since they
+ * might have changed drastically.
+ **/
+static void
+up_backend_prepare_for_sleep (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ UpBackend *backend = user_data;
+ gboolean will_sleep;
+ GPtrArray *array;
+ guint i;
+
+ if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(b)"))) {
+ g_warning ("logind PrepareForSleep has unexpected parameter(s)");
+ return;
+ }
+
+ g_variant_get (parameters, "(b)", &will_sleep);
+
+ if (will_sleep) {
+ up_daemon_pause_poll (backend->priv->daemon);
+ return;
+ }
+
+ /* we are waking up, lets refresh all battery devices */
+ g_debug ("Woke up from sleep; about to refresh devices");
+ array = up_device_list_get_array (backend->priv->device_list);
+
+ for (i = 0; i < array->len; i++) {
+ UpDevice *device = UP_DEVICE (g_ptr_array_index (array, i));
+ up_device_refresh_internal (device);
+ }
+
+ g_ptr_array_unref (array);
+
+ up_daemon_resume_poll (backend->priv->daemon);
+}
+
+
+/**
* up_backend_class_init:
* @klass: The UpBackendClass
**/
@@ -491,6 +543,9 @@ up_backend_class_init (UpBackendClass *klass)
static void
up_backend_init (UpBackend *backend)
{
+ GDBusConnection *bus;
+ guint sleep_id;
+
backend->priv = UP_BACKEND_GET_PRIVATE (backend);
backend->priv->config = up_config_new ();
backend->priv->managed_devices = up_device_list_new ();
@@ -502,6 +557,19 @@ up_backend_init (UpBackend *backend)
LOGIND_DBUS_INTERFACE,
NULL,
NULL);
+
+ bus = g_dbus_proxy_get_connection (backend->priv->logind_proxy);
+ sleep_id = g_dbus_connection_signal_subscribe (bus,
+ LOGIND_DBUS_NAME,
+ LOGIND_DBUS_INTERFACE,
+ "PrepareForSleep",
+ LOGIND_DBUS_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ up_backend_prepare_for_sleep,
+ backend,
+ NULL);
+ backend->priv->logind_sleep_id = sleep_id;
}
/**
@@ -511,6 +579,7 @@ static void
up_backend_finalize (GObject *object)
{
UpBackend *backend;
+ GDBusConnection *bus;
g_return_if_fail (UP_IS_BACKEND (object));
@@ -523,6 +592,11 @@ 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);
+
+ bus = g_dbus_proxy_get_connection (backend->priv->logind_proxy);
+ g_dbus_connection_signal_unsubscribe (bus,
+ backend->priv->logind_sleep_id);
+
g_clear_object (&backend->priv->logind_proxy);
g_object_unref (backend->priv->managed_devices);