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
 

Reply via email to