summaryrefslogtreecommitdiff
path: root/src/up-daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/up-daemon.c')
-rw-r--r--src/up-daemon.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/up-daemon.c b/src/up-daemon.c
index b645137..70ca495 100644
--- a/src/up-daemon.c
+++ b/src/up-daemon.c
@@ -45,6 +45,7 @@ struct UpDaemonPrivate
GHashTable *poll_timeouts;
gboolean poll_paused;
GHashTable *idle_signals;
+ GSource *poll_source;
int critical_action_lock_fd;
/* Display battery properties */
@@ -751,10 +752,19 @@ static void
up_daemon_device_changed_cb (UpDevice *device, GParamSpec *pspec, UpDaemon *daemon)
{
UpDeviceKind type;
+ const char *prop;
g_return_if_fail (UP_IS_DAEMON (daemon));
g_return_if_fail (UP_IS_DEVICE (device));
+ prop = g_param_spec_get_name (pspec);
+ if (!daemon->priv->poll_paused &&
+ ((g_strcmp0 (prop, "poll-timeout") == 0) ||
+ (g_strcmp0 (prop, "last-refresh") == 0))) {
+ g_source_set_ready_time (daemon->priv->poll_source, 0);
+ return;
+ }
+
/* refresh battery devices when AC state changes */
g_object_get (device,
"type", &type,
@@ -767,6 +777,76 @@ up_daemon_device_changed_cb (UpDevice *device, GParamSpec *pspec, UpDaemon *daem
up_daemon_update_warning_level (daemon);
}
+static gboolean
+up_daemon_poll_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
+{
+ UpDaemon *daemon = UP_DAEMON (user_data);
+ UpDaemonPrivate *priv = daemon->priv;
+ g_autoptr(GPtrArray) array = NULL;
+ guint i;
+ UpDevice *device;
+ gint64 ready_time = G_MAXINT64;
+ gint64 now = g_source_get_time (priv->poll_source);
+ gint max_dispatch_timeout = 0;
+
+ g_source_set_ready_time (priv->poll_source, -1);
+ g_assert (callback == NULL);
+
+ if (daemon->priv->poll_paused)
+ return G_SOURCE_CONTINUE;
+
+ /* Find the earliest device that needs a refresh. */
+ array = up_device_list_get_array (priv->power_devices);
+ for (i = 0; i < array->len; i += 1) {
+ gint timeout;
+ gint64 last_refresh;
+ gint64 poll_time;
+ gint64 dispatch_time;
+ device = (UpDevice *) g_ptr_array_index (array, i);
+ g_object_get (device,
+ "poll-timeout", &timeout,
+ "last-refresh", &last_refresh,
+ NULL);
+
+ if (timeout <= 0)
+ continue;
+
+ poll_time = last_refresh + timeout * G_USEC_PER_SEC;
+
+ /* Allow dispatching early if another device got dispatched.
+ * i.e. device polling will synchronize eventually.
+ */
+ dispatch_time = poll_time - MIN(timeout, max_dispatch_timeout) * G_USEC_PER_SEC / 2;
+
+ if (now >= dispatch_time) {
+ g_debug ("up_daemon_poll_dispatch: refreshing %s", up_exported_device_get_native_path (UP_EXPORTED_DEVICE (device)));
+ up_device_refresh_internal (device, UP_REFRESH_POLL);
+ max_dispatch_timeout = MAX(max_dispatch_timeout, timeout);
+
+ /* We'll wake up again immediately and then
+ * calculate the correct time to re-poll. */
+ }
+
+ ready_time = MIN(ready_time, poll_time);
+ }
+
+ if (ready_time == G_MAXINT64)
+ ready_time = -1;
+
+ /* Set the ready time (if it was not modified externally) */
+ if (g_source_get_ready_time (priv->poll_source) == -1)
+ g_source_set_ready_time (priv->poll_source, ready_time);
+
+ return G_SOURCE_CONTINUE;
+}
+
+GSourceFuncs poll_source_funcs = {
+ .prepare = NULL,
+ .check = NULL,
+ .dispatch = up_daemon_poll_dispatch,
+ .finalize = NULL,
+};
+
typedef struct {
guint id;
guint timeout;
@@ -1029,6 +1109,9 @@ up_daemon_device_added_cb (UpBackend *backend, UpDevice *device, UpDaemon *daemo
g_signal_connect (device, "notify",
G_CALLBACK (up_daemon_device_changed_cb), daemon);
+ /* Ensure we poll the new device if needed */
+ g_source_set_ready_time (daemon->priv->poll_source, 0);
+
/* emit */
object_path = up_device_get_object_path (device);
g_debug ("emitting added: %s", object_path);
@@ -1130,6 +1213,13 @@ up_daemon_init (UpDaemon *daemon)
daemon->priv->config = up_config_new ();
daemon->priv->power_devices = up_device_list_new ();
daemon->priv->display_device = up_device_new (daemon, NULL);
+ daemon->priv->poll_source = g_source_new (&poll_source_funcs, sizeof (GSource));
+
+ g_source_set_callback (daemon->priv->poll_source, NULL, daemon, NULL);
+ g_source_set_name (daemon->priv->poll_source, "up-device-poll");
+ g_source_attach (daemon->priv->poll_source, NULL);
+ /* g_source_destroy removes the last reference */
+ g_source_unref (daemon->priv->poll_source);
daemon->priv->use_percentage_for_policy = up_config_get_boolean (daemon->priv->config, "UsePercentageForPolicy");
load_percentage_policy (daemon, FALSE);
@@ -1205,6 +1295,7 @@ up_daemon_finalize (GObject *object)
g_clear_pointer (&priv->poll_timeouts, g_hash_table_destroy);
g_clear_pointer (&priv->idle_signals, g_hash_table_destroy);
+ g_clear_pointer (&daemon->priv->poll_source, g_source_destroy);
g_object_unref (priv->power_devices);
g_object_unref (priv->display_device);