[gnome-settings-daemon/wip/hadess/power-saver-on-low-battery] power: Enable power-saver profile when low on battery




commit 3e74dc38a777f4adf7eb478cd09fe31e9b6f257b
Author: Bastien Nocera <hadess hadess net>
Date:   Fri Jul 16 13:40:10 2021 +0200

    power: Enable power-saver profile when low on battery
    
    When low on battery, and if the feature is enabled, hold the power
    profile to "power-saver" until the battery is sufficiently recharged.

 ...me.settings-daemon.plugins.power.gschema.xml.in |   5 +
 plugins/power/gsd-power-manager.c                  | 117 +++++++++++++++++++++
 2 files changed, 122 insertions(+)
---
diff --git a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in 
b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in
index 93c704e9..04b287bd 100644
--- a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in
+++ b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in
@@ -41,5 +41,10 @@
       <summary>Power button action</summary>
       <description>The action to take when the system power button is pressed. This action is hard-coded 
(and the setting ignored) on virtual machines (power off) and tablets (suspend).</description>
     </key>
+    <key name="power-saver-profile-on-low-battery" type="b">
+      <default>true</default>
+      <summary>Enable power-saver profile when battery is low</summary>
+      <description>Automatically enable the "power-saver" profile using power-profiles-daemon if the battery 
is low.</description>
+    </key>
   </schema>
 </schemalist>
diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c
index 95cec9c3..dc7ac622 100644
--- a/plugins/power/gsd-power-manager.c
+++ b/plugins/power/gsd-power-manager.c
@@ -59,6 +59,10 @@
 #define UPOWER_DBUS_INTERFACE                   "org.freedesktop.UPower"
 #define UPOWER_DBUS_INTERFACE_KBDBACKLIGHT      "org.freedesktop.UPower.KbdBacklight"
 
+#define PPD_DBUS_NAME                           "net.hadess.PowerProfiles"
+#define PPD_DBUS_PATH                           "/net/hadess/PowerProfiles"
+#define PPD_DBUS_INTERFACE                      "net.hadess.PowerProfiles"
+
 #define GSD_POWER_SETTINGS_SCHEMA               "org.gnome.settings-daemon.plugins.power"
 
 #define GSD_POWER_DBUS_NAME                     GSD_DBUS_NAME ".Power"
@@ -185,6 +189,10 @@ struct _GsdPowerManager
         gdouble                  ambient_last_absolute;
         gint64                   ambient_last_time;
 
+        /* Power Profiles */
+        GDBusProxy              *power_profiles_proxy;
+        guint                    power_saver_cookie;
+
         /* Sound */
         guint32                  critical_alert_timeout_id;
 
@@ -1927,6 +1935,56 @@ idle_configure (GsdPowerManager *manager)
         }
 }
 
+static void
+hold_profile_cb (GObject      *source_object,
+                 GAsyncResult *res,
+                 gpointer      user_data)
+{
+        GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
+        g_autoptr(GError) error = NULL;
+        g_autoptr(GVariant) result = NULL;
+
+        result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+                                           res,
+                                           &error);
+        if (result == NULL) {
+                g_warning ("Couldn't hold power-saver profile: %s", error->message);
+                return;
+        }
+
+        manager->power_saver_cookie = g_variant_get_uint32 (result);
+        g_debug ("Holding power-saver profile with cookie %u", manager->power_saver_cookie);
+}
+
+static void
+enable_power_saver (GsdPowerManager *manager)
+{
+        if (!manager->power_profiles_proxy)
+                return;
+        if (!g_settings_get_boolean (manager->settings, "power-saver-profile-on-low-battery"))
+                return;
+
+        g_dbus_proxy_call (manager->power_profiles_proxy,
+                           "HoldProfile",
+                           g_variant_new ("(u)", manager->power_saver_cookie),
+                           G_DBUS_CALL_FLAGS_NONE,
+                           -1, manager->cancellable, hold_profile_cb, NULL);
+}
+
+static void
+disable_power_saver (GsdPowerManager *manager)
+{
+        if (!manager->power_profiles_proxy || !manager->power_saver_cookie)
+                return;
+
+        g_dbus_proxy_call (manager->power_profiles_proxy,
+                           "ReleaseProfile",
+                           g_variant_new ("(u)", manager->power_saver_cookie),
+                           G_DBUS_CALL_FLAGS_NONE,
+                           -1, NULL, NULL, NULL);
+        manager->power_saver_cookie = 0;
+}
+
 static void
 main_battery_or_ups_low_changed (GsdPowerManager *manager,
                                  gboolean         is_low)
@@ -1935,6 +1993,10 @@ main_battery_or_ups_low_changed (GsdPowerManager *manager,
                 return;
         manager->battery_is_low = is_low;
         idle_configure (manager);
+        if (is_low)
+                enable_power_saver (manager);
+        else
+                disable_power_saver (manager);
 }
 
 static gboolean
@@ -2078,6 +2140,39 @@ screensaver_signal_cb (GDBusProxy *proxy,
                 handle_wake_up_screen (GSD_POWER_MANAGER (user_data));
 }
 
+static void
+power_profiles_proxy_signal_cb (GDBusProxy  *proxy,
+                               const gchar *sender_name,
+                               const gchar *signal_name,
+                               GVariant    *parameters,
+                               gpointer     user_data)
+{
+        GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
+
+        if (g_strcmp0 (signal_name, "ProfileReleased") != 0)
+                return;
+        manager->power_saver_cookie = 0;
+}
+
+static void
+power_profiles_proxy_ready_cb (GObject             *source_object,
+                              GAsyncResult        *res,
+                              gpointer             user_data)
+{
+        g_autoptr(GError) error = NULL;
+        GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
+
+        manager->power_profiles_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+        if (manager->power_profiles_proxy == NULL) {
+                g_debug ("Could not connect to power-profiles-daemon: %s", error->message);
+                return;
+        }
+
+        g_signal_connect (manager->power_profiles_proxy, "g-signal",
+                          G_CALLBACK (power_profiles_proxy_signal_cb),
+                          manager);
+}
+
 static void
 power_keyboard_proxy_ready_cb (GObject             *source_object,
                                GAsyncResult        *res,
@@ -2289,6 +2384,14 @@ engine_settings_key_changed_cb (GSettings *settings,
                 idle_configure (manager);
                 return;
         }
+        if (g_str_equal (key, "power-saver-profile-on-low-battery")) {
+                if (manager->battery_is_low &&
+                    g_settings_get_boolean (settings, key))
+                        enable_power_saver (manager);
+                else
+                        disable_power_saver (manager);
+                return;
+        }
 }
 
 static void
@@ -2599,6 +2702,17 @@ on_rr_screen_acquired (GObject      *object,
         g_signal_connect (manager->up_client, "notify::on-battery",
                           G_CALLBACK (up_client_on_battery_cb), manager);
 
+        /* connect to power-profiles-daemon */
+        g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+                                  G_DBUS_PROXY_FLAGS_NONE,
+                                  NULL,
+                                  PPD_DBUS_NAME,
+                                  PPD_DBUS_PATH,
+                                  PPD_DBUS_INTERFACE,
+                                  manager->cancellable,
+                                  power_profiles_proxy_ready_cb,
+                                  manager);
+
         /* connect to UPower for keyboard backlight control */
         manager->kbd_brightness_now = -1;
         g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
@@ -2862,6 +2976,9 @@ gsd_power_manager_stop (GsdPowerManager *manager)
 
         g_clear_object (&manager->screensaver_proxy);
 
+        disable_power_saver (manager);
+        g_clear_object (&manager->power_profiles_proxy);
+
         play_loop_stop (&manager->critical_alert_timeout_id);
 
         g_clear_object (&manager->idle_monitor);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]