Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package upower for openSUSE:Factory checked in at 2026-02-20 17:40:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/upower (Old) and /work/SRC/openSUSE:Factory/.upower.new.1977 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "upower" Fri Feb 20 17:40:13 2026 rev:97 rq:1333725 version:1.91.1 Changes: -------- --- /work/SRC/openSUSE:Factory/upower/upower.changes 2026-02-12 17:24:55.229063173 +0100 +++ /work/SRC/openSUSE:Factory/.upower.new.1977/upower.changes 2026-02-20 17:40:22.985782763 +0100 @@ -1,0 +2,15 @@ +Fri Feb 13 11:04:02 UTC 2026 - Dominique Leuenberger <[email protected]> + +- Update to version 1.91.1: + + Fix: a resource leak + + Fix: a NULL exception caused by a Non-NULL GError pointer + + Fix client API: crashing when printing the error message from + a NULL GError pointer + + Fix: ACPI reports -NaN capacity value + + Feature: Skip CriticalPowerAction when performing battery + recalibration + + Deprecate: capacity_level and luminosity property + + CI: Add a tartan LLVM static analysis + + Feature: History supports voltage item + +------------------------------------------------------------------- Old: ---- upower-1.91.0.obscpio New: ---- upower-1.91.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ upower.spec ++++++ --- /var/tmp/diff_new_pack.rPwAkx/_old 2026-02-20 17:40:24.565848609 +0100 +++ /var/tmp/diff_new_pack.rPwAkx/_new 2026-02-20 17:40:24.569848775 +0100 @@ -1,8 +1,7 @@ # # spec file for package upower # -# Copyright (c) 2026 SUSE LLC -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -29,7 +28,7 @@ %define idevice disabled %endif Name: upower -Version: 1.91.0 +Version: 1.91.1 Release: 0 Summary: Power Device Enumeration Framework License: GPL-2.0-or-later ++++++ _service ++++++ --- /var/tmp/diff_new_pack.rPwAkx/_old 2026-02-20 17:40:24.617850775 +0100 +++ /var/tmp/diff_new_pack.rPwAkx/_new 2026-02-20 17:40:24.625851109 +0100 @@ -3,7 +3,7 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://gitlab.freedesktop.org/upower/upower.git</param> - <param name="revision">v1.91.0</param> + <param name="revision">v1.91.1</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> <param name="versionrewrite-pattern">(v)?([^+]+)(\+0)?(\+[1-9][0-9]*)?</param> <param name="versionrewrite-replacement">\2\4</param> ++++++ upower-1.91.0.obscpio -> upower-1.91.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/NEWS new/upower-1.91.1/NEWS --- old/upower-1.91.0/NEWS 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/NEWS 2026-02-10 13:01:59.000000000 +0100 @@ -1,3 +1,16 @@ +Version 1.91.1 +-------------- +Released: 2026-02-10 + +- Fix: a resource leak (!294) +- Fix: a NULL exception caused by a Non-NULL GError pointer (!295, #331) +- Fix client API: crashing when printing the error message from a NULL GError pointer (!304) +- Fix: ACPI reports -NaN capacity value (!306) +- Feature: Skip CriticalPowerAction when performing battery recalibration (!285, #312) +- Deprecate: capacity_level and luminosity property (!293, !297 ) +- CI: Add a tartan LLVM static analysis (!300) +- Feature: History supports voltage item (!299) + Version 1.91.0 -------------- Released: 2025-11-25 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/README.md new/upower-1.91.1/README.md --- old/upower-1.91.0/README.md 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/README.md 2026-02-10 13:01:59.000000000 +0100 @@ -51,3 +51,15 @@ 3. `sudo systemctl restart upower.service` 4. Grab logs using `journalctl -u upower.service` or similar + +## Using tartan + +[Tartan](https://gitlab.freedesktop.org/tartan/tartan/-/wikis/home) is a LLVM static +analysis plugin built to analyze GLib code. It can be installed and then run using: + +```shell +mkdir build +cd build +meson setup .. +SCANBUILD=../contrib/tartan.sh ninja scan-build +``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/contrib/tartan.sh new/upower-1.91.1/contrib/tartan.sh --- old/upower-1.91.0/contrib/tartan.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/upower-1.91.1/contrib/tartan.sh 2026-02-10 13:01:59.000000000 +0100 @@ -0,0 +1,11 @@ +#!/bin/sh + +/usr/bin/scan-build-20 \ + -load-plugin /usr/lib64/tartan/20.1/libtartan.so \ + -disable-checker core.CallAndMessage \ + -disable-checker core.NullDereference \ + -disable-checker deadcode.DeadStores \ + -disable-checker unix.Malloc \ + -enable-checker tartan.GErrorChecker \ + --exclude meson-private \ + --status-bugs -v "$@" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/dbus/org.freedesktop.UPower.Device.xml new/upower-1.91.1/dbus/org.freedesktop.UPower.Device.xml --- old/upower-1.91.0/dbus/org.freedesktop.UPower.Device.xml 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/dbus/org.freedesktop.UPower.Device.xml 2026-02-10 13:01:59.000000000 +0100 @@ -158,7 +158,7 @@ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> <arg name="type" direction="in" type="s"> <doc:doc><doc:summary>The type of history. - Valid types are <doc:tt>rate</doc:tt> or <doc:tt>charge</doc:tt>.</doc:summary></doc:doc> + Valid types are <doc:tt>rate</doc:tt>, <doc:tt>charge</doc:tt> and <doc:tt>voltage</doc:tt>.</doc:summary></doc:doc> </arg> <arg name="timespan" direction="in" type="u"> <doc:doc><doc:summary>The amount of data to return in seconds, or 0 for all.</doc:summary></doc:doc> @@ -186,7 +186,7 @@ <doc:item> <doc:term>value</doc:term> <doc:definition> - The data value, for instance the rate in W or the charge in %. + The data value, for instance the rate in W, the charge in % and the voltage in V. </doc:definition> </doc:item> <doc:item> @@ -572,11 +572,18 @@ </property> <property name="Luminosity" type="d" access="read"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> <doc:doc> <doc:description> <doc:para> Luminosity being recorded by the meter. </doc:para> + <doc:para> + DEPRECATED + </doc:para> + <doc:para> + This property is deprecated since the code it depends on was removed in 0.99.12 + </doc:para> </doc:description> </doc:doc> </property> @@ -967,9 +974,6 @@ <doc:para> This property is deprecated since it is duplicated from the 'BatteryLevel' property. </doc:para> - <doc:para> - Since 1.91.0 - </doc:para> </doc:description> </doc:doc> </property> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/etc/UPower.conf new/upower-1.91.1/etc/UPower.conf --- old/upower-1.91.0/etc/UPower.conf 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/etc/UPower.conf 2026-02-10 13:01:59.000000000 +0100 @@ -88,6 +88,15 @@ # Default is false AllowRiskyCriticalPowerAction=false +# If the user performs the battery recalibration, the battery behavior +# will be set to "force discharge" and the user expects the battery will +# be fully discharged. However, upower performs the +# CriticalPowerAction earlier than the battery was fully discharged. +# ExpectBatteryRecalibration allows upower to ignore the +# CriticalPowerAction when the user attempts to perform the battery recalibration. +# Default is false +ExpectBatteryRecalibration=false + # The action to take when "TimeAction" or "PercentageAction" above has been # reached for the batteries (UPS or laptop batteries) supplying the computer # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/libupower-glib/up-client.c new/upower-1.91.1/libupower-glib/up-client.c --- old/upower-1.91.0/libupower-glib/up-client.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/libupower-glib/up-client.c 2026-02-10 13:01:59.000000000 +0100 @@ -106,8 +106,6 @@ GPtrArray *array; guint i; - g_return_val_if_fail (UP_IS_CLIENT (client), NULL); - if (up_exported_daemon_call_enumerate_devices_sync (client->priv->proxy, &devices, cancellable, @@ -148,6 +146,8 @@ g_autoptr(GError) error = NULL; GPtrArray *ret = NULL; + g_return_val_if_fail (UP_IS_CLIENT (client), NULL); + ret = up_client_get_devices_full (client, NULL, &error); if (!ret) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -192,6 +192,8 @@ { g_autoptr(GTask) task = NULL; + g_return_if_fail (UP_IS_CLIENT (client)); + task = g_task_new (client, cancellable, callback, user_data); g_task_set_source_tag (task, (gpointer) G_STRFUNC); @@ -479,7 +481,7 @@ "If the laptop lid is closed", NULL, FALSE, - G_PARAM_READABLE | G_PARAM_DEPRECATED)); + G_PARAM_READABLE)); /** * UpClient:lid-is-present: * @@ -493,7 +495,7 @@ "If a laptop lid is present", NULL, FALSE, - G_PARAM_READABLE | G_PARAM_DEPRECATED)); + G_PARAM_READABLE)); /** * UpClient::device-added: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/libupower-glib/up-client.h new/upower-1.91.1/libupower-glib/up-client.h --- old/upower-1.91.0/libupower-glib/up-client.h 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/libupower-glib/up-client.h 2026-02-10 13:01:59.000000000 +0100 @@ -94,9 +94,7 @@ GAsyncResult *res, GError **error); const gchar *up_client_get_daemon_version (UpClient *client); -G_DEPRECATED gboolean up_client_get_lid_is_closed (UpClient *client); -G_DEPRECATED gboolean up_client_get_lid_is_present (UpClient *client); gboolean up_client_get_on_battery (UpClient *client); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/libupower-glib/up-device.c new/upower-1.91.1/libupower-glib/up-device.c --- old/upower-1.91.0/libupower-glib/up-device.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/libupower-glib/up-device.c 2026-02-10 13:01:59.000000000 +0100 @@ -350,9 +350,8 @@ if (up_exported_device_get_voltage_max_design (priv->proxy_device) > 0) g_string_append_printf (string, " voltage-max-design: %g V\n", up_exported_device_get_voltage_max_design (priv->proxy_device)); - /* Suppress the warning about the deprecated property CapacityLevel */ - /* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. - * since 1.91.0 */ + /* Eliminate the display of the deprecation warning specific to the CapacityLevel property. */ + /* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" capacity_level = up_exported_device_get_capacity_level (priv->proxy_device); @@ -377,8 +376,12 @@ g_string_append_printf (string, " charge-cycles: %s\n", "N/A"); } if (kind == UP_DEVICE_KIND_KEYBOARD) { + /* DEPRECATED. This property is deprecated since the code it depends on was removed in 0.99.12. */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" if (up_exported_device_get_luminosity (priv->proxy_device) > 0) g_string_append_printf (string, " luminosity: %g lx\n", up_exported_device_get_luminosity (priv->proxy_device)); + #pragma GCC diagnostic pop } if (kind == UP_DEVICE_KIND_BATTERY || kind == UP_DEVICE_KIND_UPS) { @@ -427,6 +430,7 @@ if (up_exported_device_get_has_history (priv->proxy_device)) { up_device_to_text_history (device, string, "charge"); up_device_to_text_history (device, string, "rate"); + up_device_to_text_history (device, string, "voltage"); } return g_string_free (string, FALSE); @@ -458,7 +462,7 @@ /** * up_device_get_history_sync: * @device: a #UpDevice instance. - * @type: The type of history, known values are "rate" and "charge". + * @type: The type of history. Known values are "rate", "charge" and "voltage". * @timespec: the amount of time to look back into time. * @resolution: the resolution of data. * @cancellable: a #GCancellable or %NULL @@ -694,7 +698,11 @@ up_exported_device_set_voltage (device->priv->proxy_device, g_value_get_double (value)); break; case PROP_LUMINOSITY: + /* DEPRECATED. This property is deprecated since the code it depends on was removed in 0.99.12. */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" up_exported_device_set_luminosity (device->priv->proxy_device, g_value_get_double (value)); + #pragma GCC diagnostic pop break; case PROP_TIME_TO_EMPTY: up_exported_device_set_time_to_empty (device->priv->proxy_device, g_value_get_int64 (value)); @@ -741,9 +749,8 @@ case PROP_VOLTAGE_MAX_DESIGN: up_exported_device_set_voltage_max_design (device->priv->proxy_device, g_value_get_double (value)); break; - /* Suppress the warning about the deprecated property CapacityLevel */ - /* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. - * since 1.91.0 */ + /* Eliminate the display of the deprecation warning specific to the CapacityLevel property. */ + /* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" case PROP_CAPACITY_LEVEL: @@ -841,7 +848,11 @@ g_value_set_double (value, up_exported_device_get_voltage (device->priv->proxy_device)); break; case PROP_LUMINOSITY: + /* DEPRECATED. This property is deprecated since the code it depends on was removed in 0.99.12. */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" g_value_set_double (value, up_exported_device_get_luminosity (device->priv->proxy_device)); + #pragma GCC diagnostic pop break; case PROP_TIME_TO_EMPTY: g_value_set_int64 (value, up_exported_device_get_time_to_empty (device->priv->proxy_device)); @@ -885,9 +896,8 @@ case PROP_VOLTAGE_MAX_DESIGN: g_value_set_double (value, up_exported_device_get_voltage_max_design (device->priv->proxy_device)); break; - /* Suppress the warning about the deprecated property CapacityLevel */ - /* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. - * since 1.91.0 */ + /* Eliminate the display of the deprecation warning specific to the CapacityLevel property. */ + /* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" case PROP_CAPACITY_LEVEL: @@ -1193,13 +1203,16 @@ * * The current luminosity of the device. * + * NOTE: As of 1.91.1, this property is deprecated since the code it + * depends on was removed in 0.99.12. + * * Since: 0.9.19 **/ g_object_class_install_property (object_class, PROP_LUMINOSITY, g_param_spec_double ("luminosity", NULL, NULL, 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | G_PARAM_DEPRECATED)); /** * UpDevice:time-to-empty: * @@ -1404,14 +1417,12 @@ * * DEPRECATED. * This property is deprecated since it is duplicated from the 'BatteryLevel' property. - * - * Since 1.91.0 **/ g_object_class_install_property (object_class, PROP_CAPACITY_LEVEL, g_param_spec_string ("capacity-level", NULL, NULL, NULL, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | G_PARAM_DEPRECATED)); } static void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/meson.build new/upower-1.91.1/meson.build --- old/upower-1.91.0/meson.build 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/meson.build 2026-02-10 13:01:59.000000000 +0100 @@ -1,5 +1,5 @@ project('upower', 'c', - version: '1.91.0', + version: '1.91.1', license: 'GPLv2+', default_options: [ 'buildtype=debugoptimized', @@ -10,7 +10,7 @@ soversion = 3 current = 1 -revision = 1 +revision = 2 libversion = '@0@.@1@.@2@'.format(soversion, current, revision) gnome = import('gnome') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/rules/95-upower-hid.hwdb new/upower-1.91.1/rules/95-upower-hid.hwdb --- old/upower-1.91.0/rules/95-upower-hid.hwdb 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/rules/95-upower-hid.hwdb 2026-02-10 13:01:59.000000000 +0100 @@ -93,10 +93,10 @@ UPOWER_BATTERY_TYPE=ups UPOWER_VENDOR=Phoenixtec Power Co., Ltd -# iDowell +# iDowell, Goldenmate usb:v075Dp0300* UPOWER_BATTERY_TYPE=ups - UPOWER_VENDOR=iDowell + UPOWER_VENDOR=iDowell, Goldenmate # Cyber Power Systems usb:v0764p0005* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/linux/integration-test.py new/upower-1.91.1/src/linux/integration-test.py --- old/upower-1.91.0/src/linux/integration-test.py 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/linux/integration-test.py 2026-02-10 13:01:59.000000000 +0100 @@ -738,6 +738,42 @@ ) self.stop_daemon() + def test_nan_percentage_battery_capacity(self): + """ACPI returns NaN for capacity""" + + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "capacity", + "-NaN", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "voltage_now", + "12000000", + ], + [], + ) + + self.start_daemon() + devs = self.proxy.EnumerateDevices() + self.assertEqual(len(devs), 1) + bat0_up = devs[0] + + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 0.0) + + # don't assert if nan percentage is reported + self.stop_daemon() + def test_multiple_batteries(self): """Multiple batteries""" @@ -3508,6 +3544,106 @@ ) self.stop_daemon() + + os.unlink(config.name) + + def test_critical_action_is_ignored_when_performing_battery_recalibration(self): + """check that critical action is ignored when performing battery recalibration""" + + ac0 = self.testbed.add_device( + "power_supply", + "AC0", + None, + ["type", "Mains", "online", "1"], + [], + ) + + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + "charge_behaviour", + "[auto] inhibit-charge force-discharge", + ], + [], + ) + + config = tempfile.NamedTemporaryFile(delete=False, mode="w") + config.write("[UPower]\n") + config.write("UsePercentageForPolicy=true\n") + config.write("PercentageAction=5\n") + config.write("AllowRiskyCriticalPowerAction=true\n") + config.write("ExpectBatteryRecalibration=true\n") + config.close() + + self.start_daemon(cfgfile=config.name, warns=True) + + devs = self.proxy.EnumerateDevices() + self.assertEqual(len(devs), 2) + bat0_up = devs[1] + + # check warning message when CriticalPowerAction=Suspend and AllowRiskyCriticalPowerAction=true + self.daemon_log.check_line( + 'The "ExpectBatteryRecalibration" setting is considered risky:' + " abrupt power loss due to battery exhaustion may lead to data" + " corruption. The system will unexpected down when the AC is disconnected." + " Use AllowRiskyCriticalPowerAction=false to disable support for" + " risky settings.", + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) + + # simulate that battery has 0% + self.testbed.set_attribute( + bat0, "charge_behaviour", "auto inhibit-charge [force-discharge]" + ) + self.testbed.set_attribute(bat0, "energy_now", "0") + self.testbed.uevent(bat0, "change") + time.sleep(0.5) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + + self.daemon_log.check_line( + "ExpectBatteryRecalibration is enabled and the AC is connected, so the battery level is not critical", + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) + + self.testbed.set_attribute(bat0, "status", "Not charging") + self.testbed.uevent(bat0, "change") + + self.daemon_log.check_line( + "ExpectBatteryRecalibration is enabled and the AC is connected, so the battery level is not critical", + timeout=UP_DAEMON_ACTION_DELAY + 1.0, + ) + + self.testbed.set_attribute( + bat0, "charge_behaviour", "[auto] inhibit-charge force-discharge" + ) + self.testbed.set_attribute(bat0, "energy_now", "800000") + self.testbed.set_attribute(bat0, "status", "Charging") + self.testbed.uevent(bat0, "change") + + time.sleep(0.5) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + + self.stop_daemon() os.unlink(config.name) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/linux/up-device-supply-battery.c new/upower-1.91.1/src/linux/up-device-supply-battery.c --- old/upower-1.91.0/src/linux/up-device-supply-battery.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/linux/up-device-supply-battery.c 2026-02-10 13:01:59.000000000 +0100 @@ -513,6 +513,8 @@ if (!self->ignore_system_percentage) { values.percentage = g_udev_device_get_sysfs_attr_as_double_uncached (native, "capacity"); + if (isnan (values.percentage)) + values.percentage = 0.0f; values.percentage = CLAMP(values.percentage, 0.0f, 100.0f); } @@ -711,9 +713,8 @@ if (start != G_MAXUINT) { g_string_printf (start_str, "%d", CLAMP (start, 0, 100)); if (!g_file_set_contents_full (start_filename, start_str->str, start_str->len, - G_FILE_SET_CONTENTS_ONLY_EXISTING, 0644, error)) { + G_FILE_SET_CONTENTS_ONLY_EXISTING, 0644, NULL)) err_count++; - } } else { g_debug ("Ignore charge_control_start_threshold setting"); } @@ -721,9 +722,8 @@ if (end != G_MAXUINT) { g_string_printf (end_str, "%d", CLAMP (end, 0, 100)); if (!g_file_set_contents_full (end_filename, end_str->str, end_str->len, - G_FILE_SET_CONTENTS_ONLY_EXISTING, 0644, error)) { + G_FILE_SET_CONTENTS_ONLY_EXISTING, 0644, NULL)) err_count++; - } } else { g_debug ("Ignore charge_control_end_threshold setting"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/linux/up-device-supply.c new/upower-1.91.1/src/linux/up-device-supply.c --- old/upower-1.91.0/src/linux/up-device-supply.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/linux/up-device-supply.c 2026-02-10 13:01:59.000000000 +0100 @@ -331,7 +331,9 @@ up_device_supply_sibling_discovered_guess_type (UpDevice *device, GObject *sibling) { - GUdevDevice *input, *native_device, *parent_device, *parent_sibling; + GUdevDevice *input, *native_device; + g_autoptr (GUdevDevice) parent_device = NULL; + g_autoptr (GUdevDevice) parent_sibling = NULL; UpDeviceKind cur_type, new_type; gboolean is_same_parent = FALSE; char *new_model_name; @@ -492,9 +494,10 @@ "type", new_type, "model", new_model_name, NULL); - g_free (new_model_name); - } else + } else { g_object_set (device, "type", new_type, NULL); + } + g_free (new_model_name); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/up-config.c new/upower-1.91.1/src/up-config.c --- old/upower-1.91.0/src/up-config.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/up-config.c 2026-02-10 13:01:59.000000000 +0100 @@ -247,6 +247,7 @@ up_config_init (UpConfig *config) { gboolean allow_risky_critical_action = FALSE; + gboolean expect_battery_recalibration = FALSE; g_autofree gchar *critical_action = NULL; g_autoptr (GError) error = NULL; g_autofree gchar *filename = NULL; @@ -308,6 +309,17 @@ " risky settings.", critical_action); } } + + expect_battery_recalibration = up_config_get_boolean (config, "ExpectBatteryRecalibration"); + if (expect_battery_recalibration) { + if (allow_risky_critical_action) { + g_warning ("The \"ExpectBatteryRecalibration\" setting is considered risky:" + " abrupt power loss due to battery exhaustion may lead to data" + " corruption. The system will unexpected down when the AC is disconnected." + " Use AllowRiskyCriticalPowerAction=false to disable support for" + " risky settings."); + } + } } /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/up-daemon.c new/upower-1.91.1/src/up-daemon.c --- old/upower-1.91.0/src/up-daemon.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/up-daemon.c 2026-02-10 13:01:59.000000000 +0100 @@ -769,6 +769,8 @@ gdouble percentage, gint64 time_to_empty) { + gboolean can_risky = FALSE; + gboolean expect_battery_recalibration = FALSE; gboolean use_percentage = TRUE; UpDeviceLevel default_level = UP_DEVICE_LEVEL_NONE; @@ -791,6 +793,21 @@ default_level = UP_DEVICE_LEVEL_DISCHARGING; } + /* Check if the battery is performing the battery recalibration and + * AC is online, the battery level is UP_DEVICE_LEVEL_NONE. */ + can_risky = up_config_get_boolean (daemon->priv->config, + "AllowRiskyCriticalPowerAction"); + expect_battery_recalibration = up_config_get_boolean (daemon->priv->config, + "ExpectBatteryRecalibration"); + + if (can_risky && kind == UP_DEVICE_KIND_BATTERY) { + if (expect_battery_recalibration && + up_daemon_get_on_ac_local (daemon, NULL)) { + g_debug ("ExpectBatteryRecalibration is enabled and the AC is connected, so the battery level is not critical"); + return UP_DEVICE_LEVEL_NONE; + } + } + if (power_supply && !daemon->priv->use_percentage_for_policy && time_to_empty > 0.0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/up-device.c new/upower-1.91.1/src/up-device.c --- old/upower-1.91.0/src/up-device.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/up-device.c 2026-02-10 13:01:59.000000000 +0100 @@ -213,6 +213,7 @@ up_history_set_rate_data (priv->history, up_exported_device_get_energy_rate (skeleton)); up_history_set_time_full_data (priv->history, up_exported_device_get_time_to_full (skeleton)); up_history_set_time_empty_data (priv->history, up_exported_device_get_time_to_empty (skeleton)); + up_history_set_voltage_data (priv->history, up_exported_device_get_voltage (skeleton)); } static void @@ -669,6 +670,8 @@ type = UP_HISTORY_TYPE_TIME_FULL; else if (g_strcmp0 (type_string, "time-empty") == 0) type = UP_HISTORY_TYPE_TIME_EMPTY; + else if (g_strcmp0 (type_string, "voltage") == 0) + type = UP_HISTORY_TYPE_VOLTAGE; /* something recognized */ if (type != UP_HISTORY_TYPE_UNKNOWN) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/up-history.c new/upower-1.91.1/src/up-history.c --- old/upower-1.91.0/src/up-history.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/up-history.c 2026-02-10 13:01:59.000000000 +0100 @@ -45,11 +45,13 @@ gint64 time_full_last; gint64 time_empty_last; gdouble percentage_last; + gdouble voltage_last; UpDeviceState state; GPtrArray *data_rate; GPtrArray *data_charge; GPtrArray *data_time_full; GPtrArray *data_time_empty; + GPtrArray *data_voltage; GSource *save_source; guint max_data_age; gchar *dir; @@ -254,6 +256,8 @@ array_data = history->priv->data_time_full; else if (type == UP_HISTORY_TYPE_TIME_EMPTY) array_data = history->priv->data_time_empty; + else if (type == UP_HISTORY_TYPE_VOLTAGE) + array_data = history->priv->data_voltage; /* not recognized */ if (array_data == NULL) @@ -549,6 +553,7 @@ gchar *filename_charge = NULL; gchar *filename_time_full = NULL; gchar *filename_time_empty = NULL; + gchar *filename_voltage = NULL; /* we have an ID? */ if (history->priv->id == NULL) { @@ -561,6 +566,7 @@ filename_charge = up_history_get_filename (history, "charge"); filename_time_full = up_history_get_filename (history, "time-full"); filename_time_empty = up_history_get_filename (history, "time-empty"); + filename_voltage = up_history_get_filename (history, "voltage"); /* save to disk */ ret = up_history_array_to_file (history, history->priv->data_rate, filename_rate); @@ -575,11 +581,15 @@ ret = up_history_array_to_file (history, history->priv->data_time_empty, filename_time_empty); if (!ret) goto out; + ret = up_history_array_to_file (history, history->priv->data_voltage, filename_voltage); + if (!ret) + goto out; out: g_free (filename_rate); g_free (filename_charge); g_free (filename_time_full); g_free (filename_time_empty); + g_free (filename_voltage); return ret; } @@ -693,6 +703,11 @@ up_history_array_from_file (history->priv->data_time_empty, filename); g_free (filename); + /* load voltage history from disk */ + filename = up_history_get_filename (history, "voltage"); + up_history_array_from_file (history->priv->data_voltage, filename); + g_free (filename); + /* save a marker so we don't use incomplete percentages */ item = up_history_item_new (); up_history_item_set_time_to_present (item); @@ -700,6 +715,7 @@ g_ptr_array_add (history->priv->data_charge, g_object_ref (item)); g_ptr_array_add (history->priv->data_time_full, g_object_ref (item)); g_ptr_array_add (history->priv->data_time_empty, g_object_ref (item)); + g_ptr_array_add (history->priv->data_voltage, g_object_ref (item)); g_object_unref (item); up_history_schedule_save (history); @@ -871,6 +887,37 @@ } /** + * up_history_set_voltage_data: + **/ +gboolean +up_history_set_voltage_data (UpHistory *history, gdouble voltage) +{ + UpHistoryItem *item; + + g_return_val_if_fail (UP_IS_HISTORY (history), FALSE); + + if (history->priv->id == NULL) + return FALSE; + if (history->priv->state == UP_DEVICE_STATE_UNKNOWN) + return FALSE; + if (history->priv->voltage_last == voltage) + return FALSE; + + /* add to array and schedule save file */ + item = up_history_item_new (); + up_history_item_set_time_to_present (item); + up_history_item_set_value (item, voltage); + up_history_item_set_state (item, history->priv->state); + g_ptr_array_add (history->priv->data_voltage, item); + up_history_schedule_save (history); + + /* save last value */ + history->priv->voltage_last = voltage; + + return TRUE; +} + +/** * up_history_is_device_id_equal: **/ gboolean @@ -907,6 +954,7 @@ history->priv->data_charge = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); history->priv->data_time_full = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); history->priv->data_time_empty = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + history->priv->data_voltage = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); history->priv->max_data_age = UP_HISTORY_DEFAULT_MAX_DATA_AGE; if (g_getenv ("UPOWER_HISTORY_DIR")) @@ -937,6 +985,7 @@ g_ptr_array_unref (history->priv->data_charge); g_ptr_array_unref (history->priv->data_time_full); g_ptr_array_unref (history->priv->data_time_empty); + g_ptr_array_unref (history->priv->data_voltage); g_free (history->priv->id); g_free (history->priv->dir); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/up-history.h new/upower-1.91.1/src/up-history.h --- old/upower-1.91.0/src/up-history.h 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/up-history.h 2026-02-10 13:01:59.000000000 +0100 @@ -55,6 +55,7 @@ UP_HISTORY_TYPE_RATE, UP_HISTORY_TYPE_TIME_FULL, UP_HISTORY_TYPE_TIME_EMPTY, + UP_HISTORY_TYPE_VOLTAGE, UP_HISTORY_TYPE_UNKNOWN } UpHistoryType; @@ -81,6 +82,8 @@ gint64 time); gboolean up_history_set_time_empty_data (UpHistory *history, gint64 time); +gboolean up_history_set_voltage_data (UpHistory *history, + gdouble voltage); void up_history_set_max_data_age (UpHistory *history, guint max_data_age); gboolean up_history_save_data (UpHistory *history); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upower-1.91.0/src/up-self-test.c new/upower-1.91.1/src/up-self-test.c --- old/upower-1.91.0/src/up-self-test.c 2025-11-25 09:39:56.000000000 +0100 +++ new/upower-1.91.1/src/up-self-test.c 2026-02-10 13:01:59.000000000 +0100 @@ -139,6 +139,9 @@ filename = g_build_filename (history_dir, "history-rate-test.dat", NULL); g_unlink (filename); g_free (filename); + filename = g_build_filename (history_dir, "history-voltage-test.dat", NULL); + g_unlink (filename); + g_free (filename); } static void @@ -178,18 +181,21 @@ up_history_set_rate_data (history, 0.99f); up_history_set_time_empty_data (history, 12346); up_history_set_time_full_data (history, 54322); + up_history_set_voltage_data (history, 3.7f); g_usleep (2 * G_USEC_PER_SEC); up_history_set_charge_data (history, 90); up_history_set_rate_data (history, 1.00f); up_history_set_time_empty_data (history, 12345); up_history_set_time_full_data (history, 54321); + up_history_set_voltage_data (history, 3.9f); g_usleep (2 * G_USEC_PER_SEC); up_history_set_charge_data (history, 95); up_history_set_rate_data (history, 1.01f); up_history_set_time_empty_data (history, 12344); up_history_set_time_full_data (history, 54320); + up_history_set_voltage_data (history, 4.1f); /* get data for last 10 seconds */ array = up_history_get_data (history, UP_HISTORY_TYPE_CHARGE, 10, 100); ++++++ upower.obsinfo ++++++ --- /var/tmp/diff_new_pack.rPwAkx/_old 2026-02-20 17:40:25.077869946 +0100 +++ /var/tmp/diff_new_pack.rPwAkx/_new 2026-02-20 17:40:25.117871613 +0100 @@ -1,5 +1,5 @@ name: upower -version: 1.91.0 -mtime: 1764059996 -commit: d79841fe402fd23b18bcbf460bffab46fa14e740 +version: 1.91.1 +mtime: 1770724919 +commit: 57f59b584e066dddafaa11cb8137b32e6e3d15c7
