mirror of
https://gitlab.freedesktop.org/upower/upower.git
synced 2026-04-08 07:00:36 +02:00
Merge branch 'wip/mafm/property-time-to-action' into 'master'
New property for time estimate to CriticalPowerAction (time-to-action) See merge request upower/upower!291
This commit is contained in:
commit
4eca33db21
5 changed files with 221 additions and 2 deletions
|
|
@ -97,6 +97,10 @@ method return sender=:1.386 -> dest=:1.477 reply_serial=2
|
|||
string "time-to-empty"
|
||||
variant int64 0
|
||||
)
|
||||
dict entry(
|
||||
string "time-to-action"
|
||||
variant int64 0
|
||||
)
|
||||
dict entry(
|
||||
string "time-to-full"
|
||||
variant int64 0
|
||||
|
|
@ -603,6 +607,21 @@ method return sender=:1.386 -> dest=:1.477 reply_serial=2
|
|||
</doc:doc>
|
||||
</property>
|
||||
|
||||
<property name="TimeToAction" type="x" access="read">
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
Number of seconds until the CriticalPowerAction is triggered.
|
||||
Is set to 0 if unknown.
|
||||
</doc:para><doc:para>
|
||||
This property is only valid if the property
|
||||
<doc:ref type="property" to="Source:Type">type</doc:ref>
|
||||
has the value "battery" and the device is "/org/freedesktop/UPower/devices/DisplayDevice".
|
||||
</doc:para>
|
||||
</doc:description>
|
||||
</doc:doc>
|
||||
</property>
|
||||
|
||||
<property name="TimeToFull" type="x" access="read">
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ enum {
|
|||
PROP_VOLTAGE,
|
||||
PROP_LUMINOSITY,
|
||||
PROP_TIME_TO_EMPTY,
|
||||
PROP_TIME_TO_ACTION,
|
||||
PROP_TIME_TO_FULL,
|
||||
PROP_PERCENTAGE,
|
||||
PROP_TEMPERATURE,
|
||||
|
|
@ -390,6 +391,11 @@ up_device_to_text (UpDevice *device)
|
|||
g_string_append_printf (string, " time to full: %s\n", time_str);
|
||||
g_free (time_str);
|
||||
}
|
||||
if (up_exported_device_get_time_to_action (priv->proxy_device) > 0) {
|
||||
time_str = up_device_to_text_time_to_string (up_exported_device_get_time_to_action (priv->proxy_device));
|
||||
g_string_append_printf (string, " time to action: %s\n", time_str);
|
||||
g_free (time_str);
|
||||
}
|
||||
if (up_exported_device_get_time_to_empty (priv->proxy_device) > 0) {
|
||||
time_str = up_device_to_text_time_to_string (up_exported_device_get_time_to_empty (priv->proxy_device));
|
||||
g_string_append_printf (string, " time to empty: %s\n", time_str);
|
||||
|
|
@ -624,6 +630,7 @@ static void
|
|||
up_device_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
UpDevice *device = UP_DEVICE (object);
|
||||
gboolean is_display = FALSE;
|
||||
|
||||
if (device->priv->proxy_device == NULL) {
|
||||
GValue *v;
|
||||
|
|
@ -707,6 +714,12 @@ up_device_set_property (GObject *object, guint prop_id, const GValue *value, GPa
|
|||
case PROP_TIME_TO_EMPTY:
|
||||
up_exported_device_set_time_to_empty (device->priv->proxy_device, g_value_get_int64 (value));
|
||||
break;
|
||||
case PROP_TIME_TO_ACTION:
|
||||
/* set this property only for DisplayDevice */
|
||||
is_display = (g_strcmp0 ("/org/freedesktop/UPower/devices/DisplayDevice", up_device_get_object_path (device)) == 0);
|
||||
if (is_display)
|
||||
up_exported_device_set_time_to_action (device->priv->proxy_device, g_value_get_int64 (value));
|
||||
break;
|
||||
case PROP_TIME_TO_FULL:
|
||||
up_exported_device_set_time_to_full (device->priv->proxy_device, g_value_get_int64 (value));
|
||||
break;
|
||||
|
|
@ -857,6 +870,9 @@ up_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpe
|
|||
case PROP_TIME_TO_EMPTY:
|
||||
g_value_set_int64 (value, up_exported_device_get_time_to_empty (device->priv->proxy_device));
|
||||
break;
|
||||
case PROP_TIME_TO_ACTION:
|
||||
g_value_set_int64 (value, up_exported_device_get_time_to_action (device->priv->proxy_device));
|
||||
break;
|
||||
case PROP_TIME_TO_FULL:
|
||||
g_value_set_int64 (value, up_exported_device_get_time_to_full (device->priv->proxy_device));
|
||||
break;
|
||||
|
|
@ -1225,6 +1241,18 @@ up_device_class_init (UpDeviceClass *klass)
|
|||
g_param_spec_int64 ("time-to-empty", NULL, NULL,
|
||||
0, G_MAXINT64, 0,
|
||||
G_PARAM_READWRITE));
|
||||
/**
|
||||
* UpDevice:time-to-action:
|
||||
*
|
||||
* The amount of time until the CriticalPowerAction is triggered.
|
||||
*
|
||||
* Since: 1.90.11
|
||||
**/
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_TIME_TO_ACTION,
|
||||
g_param_spec_int64 ("time-to-action", NULL, NULL,
|
||||
0, G_MAXINT64, 0,
|
||||
G_PARAM_READWRITE));
|
||||
/**
|
||||
* UpDevice:time-to-full:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6178,6 +6178,168 @@ class Tests(dbusmock.DBusTestCase):
|
|||
os.rmdir(conf_d_dir_path)
|
||||
os.rmdir(base_dir.name)
|
||||
|
||||
def test_time_to_action(self):
|
||||
"""Test time-to-action property with different configurations to ensure calculations work as expected"""
|
||||
|
||||
def inner_helper_check_general_and_energy():
|
||||
# get devices
|
||||
devs = self.proxy.EnumerateDevices()
|
||||
self.assertEqual(len(devs), 1)
|
||||
bat0_up = devs[0]
|
||||
|
||||
# check general state
|
||||
self.assertDevs({"battery_BAT0": {"State": UP_DEVICE_STATE_DISCHARGING}})
|
||||
self.assertEqual(
|
||||
self.get_dbus_display_property("State"), UP_DEVICE_STATE_DISCHARGING
|
||||
)
|
||||
self.assertEqual(
|
||||
self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE
|
||||
)
|
||||
self.assertEqual(self.get_dbus_display_property("IsPresent"), True)
|
||||
|
||||
# energy is in uWh, charge_* is in uAh, energy=charge*voltage
|
||||
self.assertAlmostEqual(self.get_dbus_dev_property(bat0_up, "Voltage"), 12.0)
|
||||
self.assertAlmostEqual(
|
||||
self.get_dbus_dev_property(bat0_up, "EnergyFullDesign"), 132.0
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
self.get_dbus_display_property("EnergyFullDesign"), 0.0
|
||||
)
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("EnergyFull"), 120.0)
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("Energy"), 96.0)
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("Percentage"), 80.0)
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("EnergyRate"), 24.0)
|
||||
|
||||
# (96/24)*3600, 4h in seconds
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("TimeToEmpty"), 14400)
|
||||
|
||||
def inner_helper_check_log_line(check_string):
|
||||
self.daemon_log.check_line(
|
||||
check_string, timeout=UP_DAEMON_ACTION_DELAY + 0.5
|
||||
)
|
||||
|
||||
self.testbed.add_device(
|
||||
"power_supply",
|
||||
"BAT0",
|
||||
None,
|
||||
[
|
||||
"type",
|
||||
"Battery",
|
||||
"present",
|
||||
"1",
|
||||
"status",
|
||||
"Discharging",
|
||||
"charge_now",
|
||||
"8000000",
|
||||
"charge_full",
|
||||
"10000000",
|
||||
"charge_full_design",
|
||||
"11000000",
|
||||
"percentage",
|
||||
"80",
|
||||
"voltage_now",
|
||||
"12000000",
|
||||
"current_now",
|
||||
"2000000",
|
||||
],
|
||||
[],
|
||||
)
|
||||
|
||||
base_dir = tempfile.TemporaryDirectory(delete=False, prefix="UPower-")
|
||||
# UPower.conf.d dir is mandaory
|
||||
conf_d_dir_path = os.path.join(base_dir.name, "UPower.conf.d")
|
||||
conf_d_dir = os.mkdir(path=conf_d_dir_path)
|
||||
|
||||
# Combination of {Percentage,Time}{Low,Critical,Action} are all needed
|
||||
# in the "main config file" to avoid falling back to defaults, and for
|
||||
# the config fragments to be able to override and work as expected (they
|
||||
# keys in config fragments are assumed valid if, and only if, they have
|
||||
# been seen previously in the main config file)
|
||||
config = tempfile.NamedTemporaryFile(
|
||||
delete=False, mode="w", dir=base_dir.name, suffix=".conf"
|
||||
)
|
||||
config.write("[UPower]\n")
|
||||
config.write("AllowRiskyCriticalPowerAction=true\n")
|
||||
config.write("CriticalPowerAction=Ignore\n")
|
||||
config.write("UsePercentageForPolicy=true\n")
|
||||
config.write("PercentageLow=15.0\n")
|
||||
config.write("PercentageCritical=10.0\n")
|
||||
config.write("PercentageAction=5.0\n")
|
||||
config.write("TimeLow=300\n")
|
||||
config.write("TimeCritical=200\n")
|
||||
config.write("TimeAction=100\n")
|
||||
config.close()
|
||||
|
||||
###############################
|
||||
# Test #1, PercentageAction=5.0
|
||||
###############################
|
||||
self.start_daemon(cfgfile=config.name, warns=True)
|
||||
# check warning message to ensure that we're using the expected config:
|
||||
# AllowRiskyCriticalPowerAction=true and CriticalPowerAction=Ignore
|
||||
inner_helper_check_log_line(
|
||||
'The "Ignore" CriticalPowerAction setting is considered risky:'
|
||||
)
|
||||
inner_helper_check_general_and_energy()
|
||||
# specific time-to-action test: 4h-5%, in seconds
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("TimeToAction"), 13680)
|
||||
self.stop_daemon()
|
||||
|
||||
# Time-based instead of percentage-based, overriding main config
|
||||
config2 = tempfile.NamedTemporaryFile(
|
||||
delete=False, mode="w", dir=conf_d_dir_path, prefix="30-", suffix=".conf"
|
||||
)
|
||||
config2.write("[UPower]\n")
|
||||
config2.write("AllowRiskyCriticalPowerAction=true\n")
|
||||
config2.write("CriticalPowerAction=Suspend\n")
|
||||
config2.write("UsePercentageForPolicy=false\n")
|
||||
config2.write("TimeAction=60\n")
|
||||
config2.close()
|
||||
|
||||
###############################
|
||||
# Test #2, TimeAction=60
|
||||
###############################
|
||||
self.start_daemon(cfgfile=config.name, warns=True)
|
||||
# check warning message to ensure that we're using the expected config:
|
||||
# AllowRiskyCriticalPowerAction=true and CriticalPowerAction=Suspend
|
||||
inner_helper_check_log_line(
|
||||
'The "Suspend" CriticalPowerAction setting is considered risky:'
|
||||
)
|
||||
inner_helper_check_general_and_energy()
|
||||
# specific time-to-action test: 4h-1min, in seconds
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("TimeToAction"), 14340)
|
||||
self.stop_daemon()
|
||||
|
||||
# Percentage-based again, overriding both main config and lower-prio
|
||||
# config fragments
|
||||
config3 = tempfile.NamedTemporaryFile(
|
||||
delete=False, mode="w", dir=conf_d_dir_path, prefix="60-", suffix=".conf"
|
||||
)
|
||||
config3.write("[UPower]\n")
|
||||
config3.write("AllowRiskyCriticalPowerAction=false\n")
|
||||
config3.write("CriticalPowerAction=Ignore\n")
|
||||
config3.write("UsePercentageForPolicy=true\n")
|
||||
config3.write("PercentageAction=1.0\n")
|
||||
config3.close()
|
||||
|
||||
###############################
|
||||
# Test #3, PercentageAction=1.0
|
||||
###############################
|
||||
self.start_daemon(cfgfile=config.name, warns=True)
|
||||
# check warning message to ensure that we're using the expected config:
|
||||
# AllowRiskyCriticalPowerAction=false and CriticalPowerAction=Ignore
|
||||
inner_helper_check_log_line('The system will perform "HybridSleep" instead.')
|
||||
inner_helper_check_general_and_energy()
|
||||
# specific time-to-action test: 4h-1%, in seconds
|
||||
self.assertAlmostEqual(self.get_dbus_display_property("TimeToAction"), 14256)
|
||||
self.stop_daemon()
|
||||
|
||||
# final cleanup
|
||||
os.unlink(config.name)
|
||||
os.unlink(config2.name)
|
||||
os.unlink(config3.name)
|
||||
os.rmdir(conf_d_dir_path)
|
||||
os.rmdir(base_dir.name)
|
||||
|
||||
#
|
||||
# Helper methods
|
||||
#
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ up_device_supply_reset_values (UpDeviceSupply *supply)
|
|||
"energy-rate", (gdouble) 0.0,
|
||||
"voltage", (gdouble) 0.0,
|
||||
"time-to-empty", (gint64) 0,
|
||||
"time-to-action", (gint64) 0,
|
||||
"time-to-full", (gint64) 0,
|
||||
"percentage", (gdouble) 0.0,
|
||||
"temperature", (gdouble) 0.0,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ struct UpDaemonPrivate
|
|||
gdouble energy_full;
|
||||
gdouble energy_rate;
|
||||
gint64 time_to_empty;
|
||||
gint64 time_to_action;
|
||||
gint64 time_to_full;
|
||||
|
||||
gboolean charge_threshold_enabled;
|
||||
|
|
@ -150,6 +151,7 @@ up_daemon_update_display_battery (UpDaemon *daemon)
|
|||
gdouble energy_full_total = 0.0;
|
||||
gdouble energy_rate_total = 0.0;
|
||||
gint64 time_to_empty_total = 0;
|
||||
gint64 time_to_action_total = 0;
|
||||
gint64 time_to_full_total = 0;
|
||||
gboolean is_present_total = FALSE;
|
||||
gboolean charge_threshold_enabled_total = FALSE;
|
||||
|
|
@ -309,9 +311,13 @@ out:
|
|||
/* calculate a quick and dirty time remaining value
|
||||
* NOTE: Keep in sync with per-battery estimation code! */
|
||||
if (energy_rate_total > 0) {
|
||||
if (state_total == UP_DEVICE_STATE_DISCHARGING)
|
||||
if (state_total == UP_DEVICE_STATE_DISCHARGING) {
|
||||
time_to_empty_total = SECONDS_PER_HOUR * (energy_total / energy_rate_total);
|
||||
else if (state_total == UP_DEVICE_STATE_CHARGING)
|
||||
if (daemon->priv->use_percentage_for_policy)
|
||||
time_to_action_total = time_to_empty_total * (1.0 - (daemon->priv->action_percentage / 100.0));
|
||||
else
|
||||
time_to_action_total = time_to_empty_total - daemon->priv->action_time;
|
||||
} else if (state_total == UP_DEVICE_STATE_CHARGING)
|
||||
time_to_full_total = SECONDS_PER_HOUR * ((energy_full_total - energy_total) / energy_rate_total);
|
||||
}
|
||||
|
||||
|
|
@ -325,6 +331,7 @@ out:
|
|||
daemon->priv->energy_full == energy_full_total &&
|
||||
daemon->priv->energy_rate == energy_rate_total &&
|
||||
daemon->priv->time_to_empty == time_to_empty_total &&
|
||||
daemon->priv->time_to_action == time_to_action_total &&
|
||||
daemon->priv->time_to_full == time_to_full_total &&
|
||||
daemon->priv->percentage == percentage_total &&
|
||||
daemon->priv->charge_threshold_enabled == charge_threshold_enabled_total &&
|
||||
|
|
@ -337,6 +344,7 @@ out:
|
|||
daemon->priv->energy_full = energy_full_total;
|
||||
daemon->priv->energy_rate = energy_rate_total;
|
||||
daemon->priv->time_to_empty = time_to_empty_total;
|
||||
daemon->priv->time_to_action = time_to_action_total;
|
||||
daemon->priv->time_to_full = time_to_full_total;
|
||||
|
||||
daemon->priv->percentage = percentage_total;
|
||||
|
|
@ -351,6 +359,7 @@ out:
|
|||
"energy-full", energy_full_total,
|
||||
"energy-rate", energy_rate_total,
|
||||
"time-to-empty", time_to_empty_total,
|
||||
"time-to-action", time_to_action_total,
|
||||
"time-to-full", time_to_full_total,
|
||||
"percentage", percentage_total,
|
||||
"is-present", is_present_total,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue