mirror of
https://gitlab.freedesktop.org/upower/upower.git
synced 2026-05-07 17:48:06 +02:00
Compare commits
25 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25303ba527 | ||
|
|
17f9e8dc5a | ||
|
|
61654b84af | ||
|
|
20a844b41e | ||
|
|
d75f2dbee4 | ||
|
|
f4764ee174 | ||
|
|
c098e60a59 | ||
|
|
57f59b584e | ||
|
|
988624350b | ||
|
|
09a8e63bae | ||
|
|
f61735aa6d | ||
|
|
eff769c65f | ||
|
|
37f7086983 | ||
|
|
8e424217f5 | ||
|
|
7d486c500c | ||
|
|
09c8bbb0f7 | ||
|
|
1c052a378f | ||
|
|
bf3d20378f | ||
|
|
f6e63cfc40 | ||
|
|
0f57b6bf73 | ||
|
|
38ab5417b7 | ||
|
|
d9f42cfc9d | ||
|
|
4722fcfaac | ||
|
|
1ba5f3a55e | ||
|
|
c5df437cc1 |
23 changed files with 434 additions and 51 deletions
22
NEWS
22
NEWS
|
|
@ -1,3 +1,25 @@
|
||||||
|
Version 1.91.2
|
||||||
|
--------------
|
||||||
|
Released: 2026-04-01
|
||||||
|
|
||||||
|
- Feature: Skip the systemd inhibitor when performing CriticalPowerAction (!309)
|
||||||
|
- Feature: Introduce "Auto" CriticalPowerAction using systemd-logind Sleep() (!309)
|
||||||
|
- Fix: Test CanPowerOff() availability before calling PowerOff() (!311)
|
||||||
|
- Fix: Add charge limit support for systems providing only charge_control_end_threshold (!310, #342, #285)
|
||||||
|
|
||||||
|
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
|
Version 1.91.0
|
||||||
--------------
|
--------------
|
||||||
Released: 2025-11-25
|
Released: 2025-11-25
|
||||||
|
|
|
||||||
12
README.md
12
README.md
|
|
@ -51,3 +51,15 @@ logs. There are two ways of doing so:
|
||||||
|
|
||||||
3. `sudo systemctl restart upower.service`
|
3. `sudo systemctl restart upower.service`
|
||||||
4. Grab logs using `journalctl -u upower.service` or similar
|
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
|
||||||
|
```
|
||||||
|
|
|
||||||
11
contrib/tartan.sh
Executable file
11
contrib/tartan.sh
Executable file
|
|
@ -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 "$@"
|
||||||
|
|
@ -158,7 +158,7 @@ method return sender=:1.386 -> dest=:1.477 reply_serial=2
|
||||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||||
<arg name="type" direction="in" type="s">
|
<arg name="type" direction="in" type="s">
|
||||||
<doc:doc><doc:summary>The type of history.
|
<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>
|
||||||
<arg name="timespan" direction="in" type="u">
|
<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>
|
<doc:doc><doc:summary>The amount of data to return in seconds, or 0 for all.</doc:summary></doc:doc>
|
||||||
|
|
@ -186,7 +186,7 @@ method return sender=:1.386 -> dest=:1.477 reply_serial=2
|
||||||
<doc:item>
|
<doc:item>
|
||||||
<doc:term>value</doc:term>
|
<doc:term>value</doc:term>
|
||||||
<doc:definition>
|
<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:definition>
|
||||||
</doc:item>
|
</doc:item>
|
||||||
<doc:item>
|
<doc:item>
|
||||||
|
|
@ -572,11 +572,18 @@ method return sender=:1.386 -> dest=:1.477 reply_serial=2
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
<property name="Luminosity" type="d" access="read">
|
<property name="Luminosity" type="d" access="read">
|
||||||
|
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
|
||||||
<doc:doc>
|
<doc:doc>
|
||||||
<doc:description>
|
<doc:description>
|
||||||
<doc:para>
|
<doc:para>
|
||||||
Luminosity being recorded by the meter.
|
Luminosity being recorded by the meter.
|
||||||
</doc:para>
|
</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:description>
|
||||||
</doc:doc>
|
</doc:doc>
|
||||||
</property>
|
</property>
|
||||||
|
|
@ -967,9 +974,6 @@ method return sender=:1.386 -> dest=:1.477 reply_serial=2
|
||||||
<doc:para>
|
<doc:para>
|
||||||
This property is deprecated since it is duplicated from the 'BatteryLevel' property.
|
This property is deprecated since it is duplicated from the 'BatteryLevel' property.
|
||||||
</doc:para>
|
</doc:para>
|
||||||
<doc:para>
|
|
||||||
Since 1.91.0
|
|
||||||
</doc:para>
|
|
||||||
</doc:description>
|
</doc:description>
|
||||||
</doc:doc>
|
</doc:doc>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,15 @@ TimeAction=120
|
||||||
# Default is false
|
# Default is false
|
||||||
AllowRiskyCriticalPowerAction=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
|
# The action to take when "TimeAction" or "PercentageAction" above has been
|
||||||
# reached for the batteries (UPS or laptop batteries) supplying the computer
|
# reached for the batteries (UPS or laptop batteries) supplying the computer
|
||||||
#
|
#
|
||||||
|
|
@ -95,10 +104,11 @@ AllowRiskyCriticalPowerAction=false
|
||||||
# PowerOff
|
# PowerOff
|
||||||
# Hibernate
|
# Hibernate
|
||||||
# HybridSleep
|
# HybridSleep
|
||||||
|
# Auto (The CriticalPowerAction will be determined by the system)
|
||||||
# Suspend (AllowRiskyCriticalPowerAction should be true to use this option but risky)
|
# Suspend (AllowRiskyCriticalPowerAction should be true to use this option but risky)
|
||||||
# Ignore (AllowRiskyCriticalPowerAction should be true to use this option but risky)
|
# Ignore (AllowRiskyCriticalPowerAction should be true to use this option but risky)
|
||||||
#
|
#
|
||||||
# If Suspend isn't available or AllowRiskyCriticalPowerAction=false, HybridSleep will be used
|
# If Suspend isn't available or AllowRiskyCriticalPowerAction=false, HybridSleep will be used
|
||||||
# If HybridSleep isn't available, Hibernate will be used
|
# If HybridSleep isn't available, Hibernate will be used
|
||||||
# If Hibernate isn't available, PowerOff will be used
|
# If Hibernate isn't available, PowerOff will be used
|
||||||
CriticalPowerAction=HybridSleep
|
CriticalPowerAction=Auto
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,6 @@ up_client_get_devices_full (UpClient *client,
|
||||||
GPtrArray *array;
|
GPtrArray *array;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
g_return_val_if_fail (UP_IS_CLIENT (client), NULL);
|
|
||||||
|
|
||||||
if (up_exported_daemon_call_enumerate_devices_sync (client->priv->proxy,
|
if (up_exported_daemon_call_enumerate_devices_sync (client->priv->proxy,
|
||||||
&devices,
|
&devices,
|
||||||
cancellable,
|
cancellable,
|
||||||
|
|
@ -148,6 +146,8 @@ up_client_get_devices2 (UpClient *client)
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
GPtrArray *ret = NULL;
|
GPtrArray *ret = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (UP_IS_CLIENT (client), NULL);
|
||||||
|
|
||||||
ret = up_client_get_devices_full (client, NULL, &error);
|
ret = up_client_get_devices_full (client, NULL, &error);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
|
@ -192,6 +192,8 @@ up_client_get_devices_async (UpClient *client,
|
||||||
{
|
{
|
||||||
g_autoptr(GTask) task = NULL;
|
g_autoptr(GTask) task = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (UP_IS_CLIENT (client));
|
||||||
|
|
||||||
task = g_task_new (client, cancellable, callback, user_data);
|
task = g_task_new (client, cancellable, callback, user_data);
|
||||||
g_task_set_source_tag (task, (gpointer) G_STRFUNC);
|
g_task_set_source_tag (task, (gpointer) G_STRFUNC);
|
||||||
|
|
||||||
|
|
@ -479,7 +481,7 @@ up_client_class_init (UpClientClass *klass)
|
||||||
"If the laptop lid is closed",
|
"If the laptop lid is closed",
|
||||||
NULL,
|
NULL,
|
||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_READABLE | G_PARAM_DEPRECATED));
|
G_PARAM_READABLE));
|
||||||
/**
|
/**
|
||||||
* UpClient:lid-is-present:
|
* UpClient:lid-is-present:
|
||||||
*
|
*
|
||||||
|
|
@ -493,7 +495,7 @@ up_client_class_init (UpClientClass *klass)
|
||||||
"If a laptop lid is present",
|
"If a laptop lid is present",
|
||||||
NULL,
|
NULL,
|
||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_READABLE | G_PARAM_DEPRECATED));
|
G_PARAM_READABLE));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UpClient::device-added:
|
* UpClient::device-added:
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,7 @@ GPtrArray *up_client_get_devices_finish (UpClient *client,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GError **error);
|
GError **error);
|
||||||
const gchar *up_client_get_daemon_version (UpClient *client);
|
const gchar *up_client_get_daemon_version (UpClient *client);
|
||||||
G_DEPRECATED
|
|
||||||
gboolean up_client_get_lid_is_closed (UpClient *client);
|
gboolean up_client_get_lid_is_closed (UpClient *client);
|
||||||
G_DEPRECATED
|
|
||||||
gboolean up_client_get_lid_is_present (UpClient *client);
|
gboolean up_client_get_lid_is_present (UpClient *client);
|
||||||
gboolean up_client_get_on_battery (UpClient *client);
|
gboolean up_client_get_on_battery (UpClient *client);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -350,9 +350,8 @@ up_device_to_text (UpDevice *device)
|
||||||
if (up_exported_device_get_voltage_max_design (priv->proxy_device) > 0)
|
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));
|
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 */
|
/* 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.
|
/* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. */
|
||||||
* since 1.91.0 */
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
capacity_level = up_exported_device_get_capacity_level (priv->proxy_device);
|
capacity_level = up_exported_device_get_capacity_level (priv->proxy_device);
|
||||||
|
|
@ -377,8 +376,12 @@ up_device_to_text (UpDevice *device)
|
||||||
g_string_append_printf (string, " charge-cycles: %s\n", "N/A");
|
g_string_append_printf (string, " charge-cycles: %s\n", "N/A");
|
||||||
}
|
}
|
||||||
if (kind == UP_DEVICE_KIND_KEYBOARD) {
|
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)
|
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));
|
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 ||
|
if (kind == UP_DEVICE_KIND_BATTERY ||
|
||||||
kind == UP_DEVICE_KIND_UPS) {
|
kind == UP_DEVICE_KIND_UPS) {
|
||||||
|
|
@ -427,6 +430,7 @@ up_device_to_text (UpDevice *device)
|
||||||
if (up_exported_device_get_has_history (priv->proxy_device)) {
|
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, "charge");
|
||||||
up_device_to_text_history (device, string, "rate");
|
up_device_to_text_history (device, string, "rate");
|
||||||
|
up_device_to_text_history (device, string, "voltage");
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_string_free (string, FALSE);
|
return g_string_free (string, FALSE);
|
||||||
|
|
@ -458,7 +462,7 @@ up_device_refresh_sync (UpDevice *device, GCancellable *cancellable, GError **er
|
||||||
/**
|
/**
|
||||||
* up_device_get_history_sync:
|
* up_device_get_history_sync:
|
||||||
* @device: a #UpDevice instance.
|
* @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.
|
* @timespec: the amount of time to look back into time.
|
||||||
* @resolution: the resolution of data.
|
* @resolution: the resolution of data.
|
||||||
* @cancellable: a #GCancellable or %NULL
|
* @cancellable: a #GCancellable or %NULL
|
||||||
|
|
@ -694,7 +698,11 @@ up_device_set_property (GObject *object, guint prop_id, const GValue *value, GPa
|
||||||
up_exported_device_set_voltage (device->priv->proxy_device, g_value_get_double (value));
|
up_exported_device_set_voltage (device->priv->proxy_device, g_value_get_double (value));
|
||||||
break;
|
break;
|
||||||
case PROP_LUMINOSITY:
|
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));
|
up_exported_device_set_luminosity (device->priv->proxy_device, g_value_get_double (value));
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
break;
|
break;
|
||||||
case PROP_TIME_TO_EMPTY:
|
case PROP_TIME_TO_EMPTY:
|
||||||
up_exported_device_set_time_to_empty (device->priv->proxy_device, g_value_get_int64 (value));
|
up_exported_device_set_time_to_empty (device->priv->proxy_device, g_value_get_int64 (value));
|
||||||
|
|
@ -741,9 +749,8 @@ up_device_set_property (GObject *object, guint prop_id, const GValue *value, GPa
|
||||||
case PROP_VOLTAGE_MAX_DESIGN:
|
case PROP_VOLTAGE_MAX_DESIGN:
|
||||||
up_exported_device_set_voltage_max_design (device->priv->proxy_device, g_value_get_double (value));
|
up_exported_device_set_voltage_max_design (device->priv->proxy_device, g_value_get_double (value));
|
||||||
break;
|
break;
|
||||||
/* Suppress the warning about the deprecated property CapacityLevel */
|
/* 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.
|
/* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. */
|
||||||
* since 1.91.0 */
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
case PROP_CAPACITY_LEVEL:
|
case PROP_CAPACITY_LEVEL:
|
||||||
|
|
@ -841,7 +848,11 @@ up_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpe
|
||||||
g_value_set_double (value, up_exported_device_get_voltage (device->priv->proxy_device));
|
g_value_set_double (value, up_exported_device_get_voltage (device->priv->proxy_device));
|
||||||
break;
|
break;
|
||||||
case PROP_LUMINOSITY:
|
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));
|
g_value_set_double (value, up_exported_device_get_luminosity (device->priv->proxy_device));
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
break;
|
break;
|
||||||
case PROP_TIME_TO_EMPTY:
|
case PROP_TIME_TO_EMPTY:
|
||||||
g_value_set_int64 (value, up_exported_device_get_time_to_empty (device->priv->proxy_device));
|
g_value_set_int64 (value, up_exported_device_get_time_to_empty (device->priv->proxy_device));
|
||||||
|
|
@ -885,9 +896,8 @@ up_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpe
|
||||||
case PROP_VOLTAGE_MAX_DESIGN:
|
case PROP_VOLTAGE_MAX_DESIGN:
|
||||||
g_value_set_double (value, up_exported_device_get_voltage_max_design (device->priv->proxy_device));
|
g_value_set_double (value, up_exported_device_get_voltage_max_design (device->priv->proxy_device));
|
||||||
break;
|
break;
|
||||||
/* Suppress the warning about the deprecated property CapacityLevel */
|
/* 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.
|
/* DEPRECATED. This property is deprecated since it is duplicated from the 'BatteryLevel' property. */
|
||||||
* since 1.91.0 */
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
case PROP_CAPACITY_LEVEL:
|
case PROP_CAPACITY_LEVEL:
|
||||||
|
|
@ -1193,13 +1203,16 @@ up_device_class_init (UpDeviceClass *klass)
|
||||||
*
|
*
|
||||||
* The current luminosity of the device.
|
* 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
|
* Since: 0.9.19
|
||||||
**/
|
**/
|
||||||
g_object_class_install_property (object_class,
|
g_object_class_install_property (object_class,
|
||||||
PROP_LUMINOSITY,
|
PROP_LUMINOSITY,
|
||||||
g_param_spec_double ("luminosity", NULL, NULL,
|
g_param_spec_double ("luminosity", NULL, NULL,
|
||||||
0.0, G_MAXDOUBLE, 0.0,
|
0.0, G_MAXDOUBLE, 0.0,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE | G_PARAM_DEPRECATED));
|
||||||
/**
|
/**
|
||||||
* UpDevice:time-to-empty:
|
* UpDevice:time-to-empty:
|
||||||
*
|
*
|
||||||
|
|
@ -1404,14 +1417,12 @@ up_device_class_init (UpDeviceClass *klass)
|
||||||
*
|
*
|
||||||
* DEPRECATED.
|
* DEPRECATED.
|
||||||
* This property is deprecated since it is duplicated from the 'BatteryLevel' property.
|
* This property is deprecated since it is duplicated from the 'BatteryLevel' property.
|
||||||
*
|
|
||||||
* Since 1.91.0
|
|
||||||
**/
|
**/
|
||||||
g_object_class_install_property (object_class,
|
g_object_class_install_property (object_class,
|
||||||
PROP_CAPACITY_LEVEL,
|
PROP_CAPACITY_LEVEL,
|
||||||
g_param_spec_string ("capacity-level",
|
g_param_spec_string ("capacity-level",
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE | G_PARAM_DEPRECATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
project('upower', 'c',
|
project('upower', 'c',
|
||||||
version: '1.91.0',
|
version: '1.91.2',
|
||||||
license: 'GPLv2+',
|
license: 'GPLv2+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'buildtype=debugoptimized',
|
'buildtype=debugoptimized',
|
||||||
|
|
@ -10,7 +10,7 @@ project('upower', 'c',
|
||||||
|
|
||||||
soversion = 3
|
soversion = 3
|
||||||
current = 1
|
current = 1
|
||||||
revision = 1
|
revision = 2
|
||||||
libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
|
libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
|
||||||
|
|
||||||
gnome = import('gnome')
|
gnome = import('gnome')
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
install_data(
|
||||||
|
'org.freedesktop.upower.rules',
|
||||||
|
install_tag: 'runtime',
|
||||||
|
install_dir: join_paths(datadir, 'polkit-1', 'rules.d'),
|
||||||
|
)
|
||||||
|
|
||||||
if polkit.found()
|
if polkit.found()
|
||||||
#newer polkit has the ITS rules included
|
#newer polkit has the ITS rules included
|
||||||
if polkit.version().version_compare('>0.113')
|
if polkit.version().version_compare('>0.113')
|
||||||
|
|
|
||||||
31
policy/org.freedesktop.upower.rules
Normal file
31
policy/org.freedesktop.upower.rules
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2026 Kate Hsuan <hpa@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if ((action.id == "org.freedesktop.login1.power-off-ignore-inhibit" ||
|
||||||
|
action.id == "org.freedesktop.login1.reboot-ignore-inhibit" ||
|
||||||
|
action.id == "org.freedesktop.login1.halt-ignore-inhibit" ||
|
||||||
|
action.id == "org.freedesktop.login1.suspend-ignore-inhibit" ||
|
||||||
|
action.id == "org.freedesktop.login1.hibernate-ignore-inhibit") &&
|
||||||
|
subject.user == "root") {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -4,4 +4,8 @@ SUBSYSTEM=="power_supply", ATTR{charge_control_start_threshold}!="", \
|
||||||
IMPORT{builtin}="hwdb 'battery:$kernel:$attr{model_name}:$attr{[dmi/id]modalias}'", \
|
IMPORT{builtin}="hwdb 'battery:$kernel:$attr{model_name}:$attr{[dmi/id]modalias}'", \
|
||||||
GOTO="battery_end"
|
GOTO="battery_end"
|
||||||
|
|
||||||
|
SUBSYSTEM=="power_supply", ATTR{charge_control_end_threshold}!="", \
|
||||||
|
IMPORT{builtin}="hwdb 'battery:$kernel:$attr{model_name}:$attr{[dmi/id]modalias}'", \
|
||||||
|
GOTO="battery_end"
|
||||||
|
|
||||||
LABEL="battery_end"
|
LABEL="battery_end"
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,10 @@ usb:v06DApFFFF*
|
||||||
UPOWER_BATTERY_TYPE=ups
|
UPOWER_BATTERY_TYPE=ups
|
||||||
UPOWER_VENDOR=Phoenixtec Power Co., Ltd
|
UPOWER_VENDOR=Phoenixtec Power Co., Ltd
|
||||||
|
|
||||||
# iDowell
|
# iDowell, Goldenmate
|
||||||
usb:v075Dp0300*
|
usb:v075Dp0300*
|
||||||
UPOWER_BATTERY_TYPE=ups
|
UPOWER_BATTERY_TYPE=ups
|
||||||
UPOWER_VENDOR=iDowell
|
UPOWER_VENDOR=iDowell, Goldenmate
|
||||||
|
|
||||||
# Cyber Power Systems
|
# Cyber Power Systems
|
||||||
usb:v0764p0005*
|
usb:v0764p0005*
|
||||||
|
|
|
||||||
|
|
@ -738,6 +738,42 @@ class Tests(dbusmock.DBusTestCase):
|
||||||
)
|
)
|
||||||
self.stop_daemon()
|
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):
|
def test_multiple_batteries(self):
|
||||||
"""Multiple batteries"""
|
"""Multiple batteries"""
|
||||||
|
|
||||||
|
|
@ -2328,10 +2364,10 @@ class Tests(dbusmock.DBusTestCase):
|
||||||
with open(f"/sys/class/power_supply/{battery_name}/charge_types") as fp:
|
with open(f"/sys/class/power_supply/{battery_name}/charge_types") as fp:
|
||||||
self.assertEqual(fp.read(), "Standard")
|
self.assertEqual(fp.read(), "Standard")
|
||||||
|
|
||||||
# Battery 2 switches to "Fast"
|
# Battery 2 switches to "Standard"
|
||||||
battery_name = bat2_up.split("_")[-1]
|
battery_name = bat2_up.split("_")[-1]
|
||||||
with open(f"/sys/class/power_supply/{battery_name}/charge_types") as fp:
|
with open(f"/sys/class/power_supply/{battery_name}/charge_types") as fp:
|
||||||
self.assertEqual(fp.read(), "Fast")
|
self.assertEqual(fp.read(), "Standard")
|
||||||
|
|
||||||
def test_battery_charge_limit_multiple_batteries_get_charge_threshold_settings_supported(
|
def test_battery_charge_limit_multiple_batteries_get_charge_threshold_settings_supported(
|
||||||
self,
|
self,
|
||||||
|
|
@ -3511,6 +3547,106 @@ class Tests(dbusmock.DBusTestCase):
|
||||||
|
|
||||||
os.unlink(config.name)
|
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)
|
||||||
|
|
||||||
def test_low_battery_changes_history_save_interval(self):
|
def test_low_battery_changes_history_save_interval(self):
|
||||||
"""check that we save the history more quickly on low battery"""
|
"""check that we save the history more quickly on low battery"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -566,10 +566,15 @@ up_backend_get_critical_action (UpBackend *backend)
|
||||||
const gchar *method;
|
const gchar *method;
|
||||||
const gchar *can_method;
|
const gchar *can_method;
|
||||||
} actions[] = {
|
} actions[] = {
|
||||||
|
/*
|
||||||
|
* The fallback order is
|
||||||
|
* Suspend -> HybridSleep -> Hibernate -> PowerOff -> Sleep -> Ignore
|
||||||
|
*/
|
||||||
{ "Suspend", "CanSuspend" },
|
{ "Suspend", "CanSuspend" },
|
||||||
{ "HybridSleep", "CanHybridSleep" },
|
{ "HybridSleep", "CanHybridSleep" },
|
||||||
{ "Hibernate", "CanHibernate" },
|
{ "Hibernate", "CanHibernate" },
|
||||||
{ "PowerOff", NULL },
|
{ "PowerOff", "CanPowerOff" },
|
||||||
|
{ "Sleep", "CanSleep"},
|
||||||
{ "Ignore", NULL },
|
{ "Ignore", NULL },
|
||||||
};
|
};
|
||||||
g_autofree gchar *action = NULL;
|
g_autofree gchar *action = NULL;
|
||||||
|
|
@ -592,6 +597,12 @@ up_backend_get_critical_action (UpBackend *backend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if "Auto", use "Sleep()" */
|
||||||
|
if (!g_strcmp0 (action, "Auto")) {
|
||||||
|
g_free (action);
|
||||||
|
action = g_strdup_printf ("Sleep");
|
||||||
|
}
|
||||||
|
|
||||||
if (action != NULL) {
|
if (action != NULL) {
|
||||||
for (i = 0; i < G_N_ELEMENTS (actions); i++)
|
for (i = 0; i < G_N_ELEMENTS (actions); i++)
|
||||||
if (g_str_equal (actions[i].method, action))
|
if (g_str_equal (actions[i].method, action))
|
||||||
|
|
@ -633,6 +644,9 @@ up_backend_get_critical_action (UpBackend *backend)
|
||||||
void
|
void
|
||||||
up_backend_take_action (UpBackend *backend)
|
up_backend_take_action (UpBackend *backend)
|
||||||
{
|
{
|
||||||
|
GVariant *res = NULL;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
g_autofree gchar *action = NULL;
|
||||||
const char *method;
|
const char *method;
|
||||||
|
|
||||||
method = up_backend_get_critical_action (backend);
|
method = up_backend_get_critical_action (backend);
|
||||||
|
|
@ -646,14 +660,43 @@ up_backend_take_action (UpBackend *backend)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_strcmp0 (method, "Sleep"))
|
||||||
|
action = g_strdup ("Sleep");
|
||||||
|
else
|
||||||
|
action = g_strdup_printf ("%sWithFlags", method);
|
||||||
|
|
||||||
|
/* flag 16 is SD_LOGIND_SKIP_INHIBITORS */
|
||||||
|
res = g_dbus_proxy_call_sync (backend->priv->logind_proxy,
|
||||||
|
action,
|
||||||
|
g_variant_new ("(t)", 16),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
/* if the new API doesn't work, use old one */
|
||||||
|
if (error != NULL) {
|
||||||
|
g_autofree gchar *action_old = NULL;
|
||||||
|
g_debug ("The new power action API doesn't work, using old one.");
|
||||||
|
|
||||||
|
if (!g_strcmp0 (method, "Sleep")) {
|
||||||
|
/* Sleep() is not available, so PowerOff instead */
|
||||||
|
g_debug ("Sleep() is not available, using PowerOff instead");
|
||||||
|
action_old = g_strdup ("PowerOff");
|
||||||
|
} else {
|
||||||
|
action_old = g_strdup (method);
|
||||||
|
}
|
||||||
g_dbus_proxy_call (backend->priv->logind_proxy,
|
g_dbus_proxy_call (backend->priv->logind_proxy,
|
||||||
method,
|
action_old,
|
||||||
g_variant_new ("(b)", FALSE),
|
g_variant_new ("(b)", FALSE),
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
G_MAXINT,
|
-1,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
}
|
||||||
|
if (res != NULL)
|
||||||
|
g_variant_unref (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -302,12 +302,12 @@ up_device_battery_charge_find_available_charge_types_for_charging (UpDevice *dev
|
||||||
UpDeviceSupplyBattery *self = UP_DEVICE_SUPPLY_BATTERY (device);
|
UpDeviceSupplyBattery *self = UP_DEVICE_SUPPLY_BATTERY (device);
|
||||||
UpDeviceSupplyBatteryChargeTypes charge_types = self->supported_charge_types;
|
UpDeviceSupplyBatteryChargeTypes charge_types = self->supported_charge_types;
|
||||||
|
|
||||||
if (charge_types & UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_FAST)
|
|
||||||
return UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_FAST;
|
|
||||||
|
|
||||||
if (charge_types & UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_STANDARD)
|
if (charge_types & UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_STANDARD)
|
||||||
return UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_STANDARD;
|
return UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_STANDARD;
|
||||||
|
|
||||||
|
if (charge_types & UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_FAST)
|
||||||
|
return UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_FAST;
|
||||||
|
|
||||||
if (charge_types & UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_ADAPTIVE)
|
if (charge_types & UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_ADAPTIVE)
|
||||||
return UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_ADAPTIVE;
|
return UP_DEVICE_SUPPLY_BATTERY_CHARGE_TYPES_ADAPTIVE;
|
||||||
|
|
||||||
|
|
@ -513,6 +513,8 @@ up_device_supply_battery_refresh (UpDevice *device,
|
||||||
|
|
||||||
if (!self->ignore_system_percentage) {
|
if (!self->ignore_system_percentage) {
|
||||||
values.percentage = g_udev_device_get_sysfs_attr_as_double_uncached (native, "capacity");
|
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);
|
values.percentage = CLAMP(values.percentage, 0.0f, 100.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -711,9 +713,8 @@ up_device_supply_battery_set_battery_charge_thresholds(UpDevice *device, guint s
|
||||||
if (start != G_MAXUINT) {
|
if (start != G_MAXUINT) {
|
||||||
g_string_printf (start_str, "%d", CLAMP (start, 0, 100));
|
g_string_printf (start_str, "%d", CLAMP (start, 0, 100));
|
||||||
if (!g_file_set_contents_full (start_filename, start_str->str, start_str->len,
|
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++;
|
err_count++;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
g_debug ("Ignore charge_control_start_threshold setting");
|
g_debug ("Ignore charge_control_start_threshold setting");
|
||||||
}
|
}
|
||||||
|
|
@ -721,9 +722,8 @@ up_device_supply_battery_set_battery_charge_thresholds(UpDevice *device, guint s
|
||||||
if (end != G_MAXUINT) {
|
if (end != G_MAXUINT) {
|
||||||
g_string_printf (end_str, "%d", CLAMP (end, 0, 100));
|
g_string_printf (end_str, "%d", CLAMP (end, 0, 100));
|
||||||
if (!g_file_set_contents_full (end_filename, end_str->str, end_str->len,
|
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++;
|
err_count++;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
g_debug ("Ignore charge_control_end_threshold setting");
|
g_debug ("Ignore charge_control_end_threshold setting");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,9 @@ static void
|
||||||
up_device_supply_sibling_discovered_guess_type (UpDevice *device,
|
up_device_supply_sibling_discovered_guess_type (UpDevice *device,
|
||||||
GObject *sibling)
|
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;
|
UpDeviceKind cur_type, new_type;
|
||||||
gboolean is_same_parent = FALSE;
|
gboolean is_same_parent = FALSE;
|
||||||
char *new_model_name;
|
char *new_model_name;
|
||||||
|
|
@ -492,10 +494,11 @@ up_device_supply_sibling_discovered_guess_type (UpDevice *device,
|
||||||
"type", new_type,
|
"type", new_type,
|
||||||
"model", new_model_name,
|
"model", new_model_name,
|
||||||
NULL);
|
NULL);
|
||||||
g_free (new_model_name);
|
} else {
|
||||||
} else
|
|
||||||
g_object_set (device, "type", new_type, NULL);
|
g_object_set (device, "type", new_type, NULL);
|
||||||
}
|
}
|
||||||
|
g_free (new_model_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,7 @@ static void
|
||||||
up_config_init (UpConfig *config)
|
up_config_init (UpConfig *config)
|
||||||
{
|
{
|
||||||
gboolean allow_risky_critical_action = FALSE;
|
gboolean allow_risky_critical_action = FALSE;
|
||||||
|
gboolean expect_battery_recalibration = FALSE;
|
||||||
g_autofree gchar *critical_action = NULL;
|
g_autofree gchar *critical_action = NULL;
|
||||||
g_autoptr (GError) error = NULL;
|
g_autoptr (GError) error = NULL;
|
||||||
g_autofree gchar *filename = NULL;
|
g_autofree gchar *filename = NULL;
|
||||||
|
|
@ -308,6 +309,17 @@ up_config_init (UpConfig *config)
|
||||||
" risky settings.", critical_action);
|
" 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -769,6 +769,8 @@ up_daemon_compute_warning_level (UpDaemon *daemon,
|
||||||
gdouble percentage,
|
gdouble percentage,
|
||||||
gint64 time_to_empty)
|
gint64 time_to_empty)
|
||||||
{
|
{
|
||||||
|
gboolean can_risky = FALSE;
|
||||||
|
gboolean expect_battery_recalibration = FALSE;
|
||||||
gboolean use_percentage = TRUE;
|
gboolean use_percentage = TRUE;
|
||||||
UpDeviceLevel default_level = UP_DEVICE_LEVEL_NONE;
|
UpDeviceLevel default_level = UP_DEVICE_LEVEL_NONE;
|
||||||
|
|
||||||
|
|
@ -791,6 +793,21 @@ up_daemon_compute_warning_level (UpDaemon *daemon,
|
||||||
default_level = UP_DEVICE_LEVEL_DISCHARGING;
|
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 &&
|
if (power_supply &&
|
||||||
!daemon->priv->use_percentage_for_policy &&
|
!daemon->priv->use_percentage_for_policy &&
|
||||||
time_to_empty > 0.0)
|
time_to_empty > 0.0)
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,7 @@ update_history (UpDevice *device)
|
||||||
up_history_set_rate_data (priv->history, up_exported_device_get_energy_rate (skeleton));
|
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_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_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
|
static void
|
||||||
|
|
@ -669,6 +670,8 @@ up_device_get_history (UpExportedDevice *skeleton,
|
||||||
type = UP_HISTORY_TYPE_TIME_FULL;
|
type = UP_HISTORY_TYPE_TIME_FULL;
|
||||||
else if (g_strcmp0 (type_string, "time-empty") == 0)
|
else if (g_strcmp0 (type_string, "time-empty") == 0)
|
||||||
type = UP_HISTORY_TYPE_TIME_EMPTY;
|
type = UP_HISTORY_TYPE_TIME_EMPTY;
|
||||||
|
else if (g_strcmp0 (type_string, "voltage") == 0)
|
||||||
|
type = UP_HISTORY_TYPE_VOLTAGE;
|
||||||
|
|
||||||
/* something recognized */
|
/* something recognized */
|
||||||
if (type != UP_HISTORY_TYPE_UNKNOWN) {
|
if (type != UP_HISTORY_TYPE_UNKNOWN) {
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,13 @@ struct UpHistoryPrivate
|
||||||
gint64 time_full_last;
|
gint64 time_full_last;
|
||||||
gint64 time_empty_last;
|
gint64 time_empty_last;
|
||||||
gdouble percentage_last;
|
gdouble percentage_last;
|
||||||
|
gdouble voltage_last;
|
||||||
UpDeviceState state;
|
UpDeviceState state;
|
||||||
GPtrArray *data_rate;
|
GPtrArray *data_rate;
|
||||||
GPtrArray *data_charge;
|
GPtrArray *data_charge;
|
||||||
GPtrArray *data_time_full;
|
GPtrArray *data_time_full;
|
||||||
GPtrArray *data_time_empty;
|
GPtrArray *data_time_empty;
|
||||||
|
GPtrArray *data_voltage;
|
||||||
GSource *save_source;
|
GSource *save_source;
|
||||||
guint max_data_age;
|
guint max_data_age;
|
||||||
gchar *dir;
|
gchar *dir;
|
||||||
|
|
@ -254,6 +256,8 @@ up_history_get_data (UpHistory *history, UpHistoryType type, guint timespan, gui
|
||||||
array_data = history->priv->data_time_full;
|
array_data = history->priv->data_time_full;
|
||||||
else if (type == UP_HISTORY_TYPE_TIME_EMPTY)
|
else if (type == UP_HISTORY_TYPE_TIME_EMPTY)
|
||||||
array_data = history->priv->data_time_empty;
|
array_data = history->priv->data_time_empty;
|
||||||
|
else if (type == UP_HISTORY_TYPE_VOLTAGE)
|
||||||
|
array_data = history->priv->data_voltage;
|
||||||
|
|
||||||
/* not recognized */
|
/* not recognized */
|
||||||
if (array_data == NULL)
|
if (array_data == NULL)
|
||||||
|
|
@ -549,6 +553,7 @@ up_history_save_data (UpHistory *history)
|
||||||
gchar *filename_charge = NULL;
|
gchar *filename_charge = NULL;
|
||||||
gchar *filename_time_full = NULL;
|
gchar *filename_time_full = NULL;
|
||||||
gchar *filename_time_empty = NULL;
|
gchar *filename_time_empty = NULL;
|
||||||
|
gchar *filename_voltage = NULL;
|
||||||
|
|
||||||
/* we have an ID? */
|
/* we have an ID? */
|
||||||
if (history->priv->id == NULL) {
|
if (history->priv->id == NULL) {
|
||||||
|
|
@ -561,6 +566,7 @@ up_history_save_data (UpHistory *history)
|
||||||
filename_charge = up_history_get_filename (history, "charge");
|
filename_charge = up_history_get_filename (history, "charge");
|
||||||
filename_time_full = up_history_get_filename (history, "time-full");
|
filename_time_full = up_history_get_filename (history, "time-full");
|
||||||
filename_time_empty = up_history_get_filename (history, "time-empty");
|
filename_time_empty = up_history_get_filename (history, "time-empty");
|
||||||
|
filename_voltage = up_history_get_filename (history, "voltage");
|
||||||
|
|
||||||
/* save to disk */
|
/* save to disk */
|
||||||
ret = up_history_array_to_file (history, history->priv->data_rate, filename_rate);
|
ret = up_history_array_to_file (history, history->priv->data_rate, filename_rate);
|
||||||
|
|
@ -575,11 +581,15 @@ up_history_save_data (UpHistory *history)
|
||||||
ret = up_history_array_to_file (history, history->priv->data_time_empty, filename_time_empty);
|
ret = up_history_array_to_file (history, history->priv->data_time_empty, filename_time_empty);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
ret = up_history_array_to_file (history, history->priv->data_voltage, filename_voltage);
|
||||||
|
if (!ret)
|
||||||
|
goto out;
|
||||||
out:
|
out:
|
||||||
g_free (filename_rate);
|
g_free (filename_rate);
|
||||||
g_free (filename_charge);
|
g_free (filename_charge);
|
||||||
g_free (filename_time_full);
|
g_free (filename_time_full);
|
||||||
g_free (filename_time_empty);
|
g_free (filename_time_empty);
|
||||||
|
g_free (filename_voltage);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,6 +703,11 @@ up_history_load_data (UpHistory *history)
|
||||||
up_history_array_from_file (history->priv->data_time_empty, filename);
|
up_history_array_from_file (history->priv->data_time_empty, filename);
|
||||||
g_free (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 */
|
/* save a marker so we don't use incomplete percentages */
|
||||||
item = up_history_item_new ();
|
item = up_history_item_new ();
|
||||||
up_history_item_set_time_to_present (item);
|
up_history_item_set_time_to_present (item);
|
||||||
|
|
@ -700,6 +715,7 @@ up_history_load_data (UpHistory *history)
|
||||||
g_ptr_array_add (history->priv->data_charge, g_object_ref (item));
|
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_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_time_empty, g_object_ref (item));
|
||||||
|
g_ptr_array_add (history->priv->data_voltage, g_object_ref (item));
|
||||||
g_object_unref (item);
|
g_object_unref (item);
|
||||||
up_history_schedule_save (history);
|
up_history_schedule_save (history);
|
||||||
|
|
||||||
|
|
@ -870,6 +886,37 @@ up_history_set_time_empty_data (UpHistory *history, gint64 time_s)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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:
|
* up_history_is_device_id_equal:
|
||||||
**/
|
**/
|
||||||
|
|
@ -907,6 +954,7 @@ up_history_init (UpHistory *history)
|
||||||
history->priv->data_charge = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
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_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_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;
|
history->priv->max_data_age = UP_HISTORY_DEFAULT_MAX_DATA_AGE;
|
||||||
|
|
||||||
if (g_getenv ("UPOWER_HISTORY_DIR"))
|
if (g_getenv ("UPOWER_HISTORY_DIR"))
|
||||||
|
|
@ -937,6 +985,7 @@ up_history_finalize (GObject *object)
|
||||||
g_ptr_array_unref (history->priv->data_charge);
|
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_full);
|
||||||
g_ptr_array_unref (history->priv->data_time_empty);
|
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->id);
|
||||||
g_free (history->priv->dir);
|
g_free (history->priv->dir);
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ typedef enum {
|
||||||
UP_HISTORY_TYPE_RATE,
|
UP_HISTORY_TYPE_RATE,
|
||||||
UP_HISTORY_TYPE_TIME_FULL,
|
UP_HISTORY_TYPE_TIME_FULL,
|
||||||
UP_HISTORY_TYPE_TIME_EMPTY,
|
UP_HISTORY_TYPE_TIME_EMPTY,
|
||||||
|
UP_HISTORY_TYPE_VOLTAGE,
|
||||||
UP_HISTORY_TYPE_UNKNOWN
|
UP_HISTORY_TYPE_UNKNOWN
|
||||||
} UpHistoryType;
|
} UpHistoryType;
|
||||||
|
|
||||||
|
|
@ -81,6 +82,8 @@ gboolean up_history_set_time_full_data (UpHistory *history,
|
||||||
gint64 time);
|
gint64 time);
|
||||||
gboolean up_history_set_time_empty_data (UpHistory *history,
|
gboolean up_history_set_time_empty_data (UpHistory *history,
|
||||||
gint64 time);
|
gint64 time);
|
||||||
|
gboolean up_history_set_voltage_data (UpHistory *history,
|
||||||
|
gdouble voltage);
|
||||||
void up_history_set_max_data_age (UpHistory *history,
|
void up_history_set_max_data_age (UpHistory *history,
|
||||||
guint max_data_age);
|
guint max_data_age);
|
||||||
gboolean up_history_save_data (UpHistory *history);
|
gboolean up_history_save_data (UpHistory *history);
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,9 @@ up_test_history_remove_temp_files (void)
|
||||||
filename = g_build_filename (history_dir, "history-rate-test.dat", NULL);
|
filename = g_build_filename (history_dir, "history-rate-test.dat", NULL);
|
||||||
g_unlink (filename);
|
g_unlink (filename);
|
||||||
g_free (filename);
|
g_free (filename);
|
||||||
|
filename = g_build_filename (history_dir, "history-voltage-test.dat", NULL);
|
||||||
|
g_unlink (filename);
|
||||||
|
g_free (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -178,18 +181,21 @@ up_test_history_func (void)
|
||||||
up_history_set_rate_data (history, 0.99f);
|
up_history_set_rate_data (history, 0.99f);
|
||||||
up_history_set_time_empty_data (history, 12346);
|
up_history_set_time_empty_data (history, 12346);
|
||||||
up_history_set_time_full_data (history, 54322);
|
up_history_set_time_full_data (history, 54322);
|
||||||
|
up_history_set_voltage_data (history, 3.7f);
|
||||||
|
|
||||||
g_usleep (2 * G_USEC_PER_SEC);
|
g_usleep (2 * G_USEC_PER_SEC);
|
||||||
up_history_set_charge_data (history, 90);
|
up_history_set_charge_data (history, 90);
|
||||||
up_history_set_rate_data (history, 1.00f);
|
up_history_set_rate_data (history, 1.00f);
|
||||||
up_history_set_time_empty_data (history, 12345);
|
up_history_set_time_empty_data (history, 12345);
|
||||||
up_history_set_time_full_data (history, 54321);
|
up_history_set_time_full_data (history, 54321);
|
||||||
|
up_history_set_voltage_data (history, 3.9f);
|
||||||
|
|
||||||
g_usleep (2 * G_USEC_PER_SEC);
|
g_usleep (2 * G_USEC_PER_SEC);
|
||||||
up_history_set_charge_data (history, 95);
|
up_history_set_charge_data (history, 95);
|
||||||
up_history_set_rate_data (history, 1.01f);
|
up_history_set_rate_data (history, 1.01f);
|
||||||
up_history_set_time_empty_data (history, 12344);
|
up_history_set_time_empty_data (history, 12344);
|
||||||
up_history_set_time_full_data (history, 54320);
|
up_history_set_time_full_data (history, 54320);
|
||||||
|
up_history_set_voltage_data (history, 4.1f);
|
||||||
|
|
||||||
/* get data for last 10 seconds */
|
/* get data for last 10 seconds */
|
||||||
array = up_history_get_data (history, UP_HISTORY_TYPE_CHARGE, 10, 100);
|
array = up_history_get_data (history, UP_HISTORY_TYPE_CHARGE, 10, 100);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue