From 365bfd640807570beded283f7ca09a554c8ff39e Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 19 Aug 2021 23:24:30 +0200 Subject: [PATCH] Backport power profile changes Resolves: #1994476 --- ...er-saver-profile-when-low-on-battery.patch | 458 ++++++++++++++++++ gnome-settings-daemon.spec | 8 +- 2 files changed, 465 insertions(+), 1 deletion(-) create mode 100644 0001-power-Enable-power-saver-profile-when-low-on-battery.patch diff --git a/0001-power-Enable-power-saver-profile-when-low-on-battery.patch b/0001-power-Enable-power-saver-profile-when-low-on-battery.patch new file mode 100644 index 0000000..2092fec --- /dev/null +++ b/0001-power-Enable-power-saver-profile-when-low-on-battery.patch @@ -0,0 +1,458 @@ +From 8dd4c164f6ce166a5767588bd6fb8e4c3e8e1a09 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 16 Jul 2021 13:40:10 +0200 +Subject: [PATCH 1/4] 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. +--- + ...ttings-daemon.plugins.power.gschema.xml.in | 5 + + plugins/power/gsd-power-manager.c | 128 ++++++++++++++++++ + plugins/power/test.py | 32 +++++ + 3 files changed, 165 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 @@ + Power button action + 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). + ++ ++ true ++ Enable power-saver profile when battery is low ++ Automatically enable the "power-saver" profile using power-profiles-daemon if the battery is low. ++ + + +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index 95cec9c3..1f125a6f 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; ++ guint32 power_saver_cookie; ++ + /* Sound */ + guint32 critical_alert_timeout_id; + +@@ -1927,6 +1935,67 @@ idle_configure (GsdPowerManager *manager) + } + } + ++static void ++hold_profile_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ GsdPowerManager *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; ++ } ++ ++ if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(u)"))) { ++ g_variant_get (result, "(u)", &manager->power_saver_cookie); ++ g_debug ("Holding power-saver profile with cookie %u", manager->power_saver_cookie); ++ } else { ++ g_warning ("Calling HoldProfile() did not return a uint32"); ++ } ++} ++ ++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_debug ("Starting hold of power-saver profile"); ++ ++ g_dbus_proxy_call (manager->power_profiles_proxy, ++ "HoldProfile", ++ g_variant_new("(sss)", ++ "power-saver", ++ "Power saver profile when low on battery", ++ GSD_POWER_DBUS_NAME), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, manager->cancellable, hold_profile_cb, manager); ++} ++ ++static void ++disable_power_saver (GsdPowerManager *manager) ++{ ++ if (!manager->power_profiles_proxy || manager->power_saver_cookie == 0) ++ return; ++ ++ g_debug ("Releasing power-saver profile"); ++ ++ g_dbus_proxy_call (manager->power_profiles_proxy, ++ "ReleaseProfile", ++ g_variant_new ("(u)", manager->power_saver_cookie), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, dbus_call_log_error, "ReleaseProfile failed"); ++ manager->power_saver_cookie = 0; ++} ++ + static void + main_battery_or_ups_low_changed (GsdPowerManager *manager, + gboolean is_low) +@@ -1935,6 +2004,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 +2151,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 +2395,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 +2713,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 +2987,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); +diff --git a/plugins/power/test.py b/plugins/power/test.py +index bb5861a4..f554400e 100755 +--- a/plugins/power/test.py ++++ b/plugins/power/test.py +@@ -76,6 +76,13 @@ class PowerPluginBase(gsdtestcase.GSDTestCase): + 'gnome_screensaver', stdout=subprocess.PIPE) + gsdtestcase.set_nonblock(self.screensaver.stdout) + ++ # start mock power-profiles-daemon ++ try: ++ (self.ppd, self.obj_ppd) = self.spawn_server_template('power_profiles_daemon') ++ self.addCleanup(self.stop_process, self.ppd) ++ except ModuleNotFoundError: ++ self.ppd = None ++ + self.session_log = OutputChecker() + self.session = subprocess.Popen(['gnome-session', '-f', + '-a', os.path.join(self.workdir, 'autostart'), +@@ -1302,5 +1309,30 @@ class PowerPluginTest8(PowerPluginBase): + + self.assertEqual(exc.exception.get_dbus_message(), 'No usable backlight could be found!') + ++ def test_power_saver_on_low_battery(self): ++ '''Check that the power-saver profile gets held when low on battery''' ++ ++ if not self.ppd: ++ self.skipTest("power-profiles-daemon dbusmock support is not available") ++ ++ obj_props = dbus.Interface(self.obj_ppd, dbus.PROPERTIES_IFACE) ++ ++ self.set_composite_battery_discharging() ++ time.sleep(0.5) ++ holds = obj_props.Get('net.hadess.PowerProfiles', 'ActiveProfileHolds') ++ self.assertEqual(len(holds), 0) ++ ++ self.set_composite_battery_critical() ++ time.sleep(0.5) ++ holds = obj_props.Get('net.hadess.PowerProfiles', 'ActiveProfileHolds') ++ self.assertEqual(len(holds), 1) ++ self.assertEqual(holds[0]['Profile'], 'power-saver') ++ self.assertEqual(holds[0]['ApplicationId'], 'org.gnome.SettingsDaemon.Power') ++ ++ self.set_composite_battery_discharging() ++ time.sleep(0.5) ++ holds = obj_props.Get('net.hadess.PowerProfiles', 'ActiveProfileHolds') ++ self.assertEqual(len(holds), 0) ++ + # avoid writing to stderr + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) +-- +2.31.1 + + +From 74ed476d1a37a43eeba8c8bee8f5be5d499b0805 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 28 Jul 2021 16:40:24 +0200 +Subject: [PATCH 2/4] power: Dim screen faster if power saver mode is on + +As done on other platforms, aggressively dim the screen after a +short period when the user has selected to enter power saver mode. + +The same aggressive screen dim will be used if the battery is low and +power-profiles-daemon is not available. If it is available, then it +fixes a screen dim happening when the battery was low which might +have been unwanted. + +See https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/232 + +Prior art: +https://support.apple.com/en-us/HT205234 +--- + plugins/power/gsd-power-manager.c | 46 +++++++++++++++++++++++++++++-- + 1 file changed, 44 insertions(+), 2 deletions(-) + +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index 1f125a6f..cfef9718 100644 +--- a/plugins/power/gsd-power-manager.c ++++ b/plugins/power/gsd-power-manager.c +@@ -192,6 +192,7 @@ struct _GsdPowerManager + /* Power Profiles */ + GDBusProxy *power_profiles_proxy; + guint32 power_saver_cookie; ++ gboolean power_saver_enabled; + + /* Sound */ + guint32 critical_alert_timeout_id; +@@ -1780,6 +1781,20 @@ clear_idle_watch (GnomeIdleMonitor *monitor, + *id = 0; + } + ++static gboolean ++is_power_save_active (GsdPowerManager *manager) ++{ ++ /* ++ * If we have power-profiles-daemon, then we follow its setting, ++ * otherwise we go into power-save mode when the battery is low. ++ */ ++ if (manager->power_profiles_proxy && ++ g_dbus_proxy_get_name_owner (manager->power_profiles_proxy)) ++ return manager->power_saver_enabled; ++ else ++ return manager->battery_is_low; ++} ++ + static void + idle_configure (GsdPowerManager *manager) + { +@@ -1903,8 +1918,8 @@ idle_configure (GsdPowerManager *manager) + /* Don't dim when the screen lock is active */ + } else if (!on_battery) { + /* Don't dim when charging */ +- } else if (manager->battery_is_low) { +- /* Aggressively blank when battery is low */ ++ } else if (is_power_save_active (manager)) { ++ /* Try to save power by dimming agressively */ + timeout_dim = SCREENSAVER_TIMEOUT_BLANK; + } else { + if (g_settings_get_boolean (manager->settings, "idle-dim")) { +@@ -2165,6 +2180,27 @@ power_profiles_proxy_signal_cb (GDBusProxy *proxy, + manager->power_saver_cookie = 0; + } + ++static void ++update_active_power_profile (GsdPowerManager *manager) ++{ ++ g_autoptr(GVariant) v = NULL; ++ const char *active_profile; ++ gboolean power_saver_enabled; ++ ++ v = g_dbus_proxy_get_cached_property (manager->power_profiles_proxy, "ActiveProfile"); ++ if (v) { ++ active_profile = g_variant_get_string (v, NULL); ++ power_saver_enabled = g_strcmp0 (active_profile, "power-saver") == 0; ++ if (power_saver_enabled != manager->power_saver_enabled) { ++ manager->power_saver_enabled = power_saver_enabled; ++ idle_configure (manager); ++ } ++ } else { ++ /* p-p-d might have disappeared from the bus */ ++ idle_configure (manager); ++ } ++} ++ + static void + power_profiles_proxy_ready_cb (GObject *source_object, + GAsyncResult *res, +@@ -2179,9 +2215,15 @@ power_profiles_proxy_ready_cb (GObject *source_object, + return; + } + ++ g_signal_connect_swapped (manager->power_profiles_proxy, ++ "g-properties-changed", ++ G_CALLBACK (update_active_power_profile), ++ manager); + g_signal_connect (manager->power_profiles_proxy, "g-signal", + G_CALLBACK (power_profiles_proxy_signal_cb), + manager); ++ ++ update_active_power_profile (manager); + } + + static void +-- +2.31.1 + + +From 89e25ed7871258aa6df7f824e226a7b8a28f23f3 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 29 Jul 2021 12:05:40 +0200 +Subject: [PATCH 3/4] power: Respect dim screen settings when not on battery + +The dim screen settings in the UI was not well respected as it only +worked on discharging laptops. + +Closes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/837 +--- + plugins/power/gsd-power-manager.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index cfef9718..e7b9752f 100644 +--- a/plugins/power/gsd-power-manager.c ++++ b/plugins/power/gsd-power-manager.c +@@ -1916,8 +1916,6 @@ idle_configure (GsdPowerManager *manager) + timeout_dim = 0; + if (manager->screensaver_active) { + /* Don't dim when the screen lock is active */ +- } else if (!on_battery) { +- /* Don't dim when charging */ + } else if (is_power_save_active (manager)) { + /* Try to save power by dimming agressively */ + timeout_dim = SCREENSAVER_TIMEOUT_BLANK; +-- +2.31.1 + + +From f91abc0033b9cf17fd0e171cb7d652f88edac294 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Mon, 9 Aug 2021 17:57:11 +0200 +Subject: [PATCH 4/4] power: When dimming the screen, dim it quicker by default + +Now that we respect the "dim when idle" setting[1], dim quicker to try +and save more power. 4/5 of the timeout to the screensaver was always a +bit too undecided as a fraction, even when using the dimming as a +warning that the screen was going to go to the screensaver (see commit +7bc750a5). + +[1]: Except in power-saver mode where we always dim aggressively +--- + plugins/power/gsd-power-constants.h | 2 +- + plugins/power/gsdpowerconstants.py | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/plugins/power/gsd-power-constants.h b/plugins/power/gsd-power-constants.h +index 91e2296a..8bf9c641 100644 +--- a/plugins/power/gsd-power-constants.h ++++ b/plugins/power/gsd-power-constants.h +@@ -25,7 +25,7 @@ + #define IDLE_DIM_BLANK_DISABLED_MIN 60 /* seconds */ + + /* Which fraction of the idle-delay is the idle-dim delay */ +-#define IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER 4.0/5.0 ++#define IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER 1.0/2.0 + + /* The dim delay under which we do not bother dimming */ + #define MINIMUM_IDLE_DIM_DELAY 10 /* seconds */ +diff --git a/plugins/power/gsdpowerconstants.py b/plugins/power/gsdpowerconstants.py +index a07798ee..26fa5bfc 100644 +--- a/plugins/power/gsdpowerconstants.py ++++ b/plugins/power/gsdpowerconstants.py +@@ -8,7 +8,7 @@ + + SCREENSAVER_TIMEOUT_BLANK = 15; + IDLE_DIM_BLANK_DISABLED_MIN = 60; +-IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER = 4.0/5.0; ++IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER = 1.0/2.0; + MINIMUM_IDLE_DIM_DELAY = 10; + POWER_UP_TIME_ON_AC = 15; + GSD_MOCK_DEFAULT_BRIGHTNESS = 50; +-- +2.31.1 + diff --git a/gnome-settings-daemon.spec b/gnome-settings-daemon.spec index 519513f..77c2e58 100644 --- a/gnome-settings-daemon.spec +++ b/gnome-settings-daemon.spec @@ -11,7 +11,7 @@ Name: gnome-settings-daemon Version: 40.0.1 -Release: 2%{?dist} +Release: 3%{?dist} Summary: The daemon sharing settings from GNOME to GTK+/KDE applications License: GPLv2+ @@ -66,6 +66,8 @@ Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_versi Requires: gtk3%{?_isa} >= %{gtk3_version} Requires: libgweather%{?_isa} >= %{libgweather_version} +Patch00001: 0001-power-Enable-power-saver-profile-when-low-on-battery.patch + %description A daemon to share settings from GNOME to other applications. It also handles global keybindings, as well as a number of desktop-wide settings. @@ -184,6 +186,10 @@ cp %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/glib-2.0/schemas %{_libdir}/pkgconfig/gnome-settings-daemon.pc %changelog +* Thu Aug 19 2021 Carlos Garnacho - 40.0.1-3 +- Backport power saving changes + Resolves: #1994476 + * Mon Aug 09 2021 Mohan Boddu - 40.0.1-2 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688