1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-02-12 21:57:27 +03:00

on-ac-power: rework logic

History of the function:
96788d2aa4f4b0b49874b4a240ce47d9e8485d1b assume system is running on AC power when no battery found
795e86b4f1e8a1fd440f8c817621779c6aedbdb5 ignore USB-C ports in power source mode when detecting system is running on AC power
c19a51bec40ae5e5073464e72411e7920d05d683 invert ac_power() source type check
6d89003462484c8656b698e07b9cf0a337e3818e assume ac when /sys/class/power_supply is missing
240dbaa44f8e5ad51775c776fc3ce9cd2f19f037 add ConditionACPower=

Interestingly, the return condition 'on_ac_power == found_online || !found_offline'
was there from the very beginning, and even Yu's latest change doesn't change this,
but only extends it to 'on_ac_power == found_online || !found_offline || !found_battery'.
This means that any system with no AC power supply will be unconditionally classified
as on_ac_power.

Let's change the logic: if we have an online AC supply, answer is "yes". If no
supplies, but we have a battery, answer is "no". Otherwise, assume "yes", based
on the assumption that presense of a battery would at least be always reported,
even if an AC power supply might not be.

Fixes #24407. It also shouldn't impact previous fixes: assume ac when
/sys/class/power_supply is missing, ignore USB-C ports in power source mode,
assume system is running on AC power when no battery found.

(cherry picked from commit 4a52514b371bf8013e89c421dfc2405a443feef8)
(cherry picked from commit 9886011356f9cd3737263b5bf9070181c7859f26)
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2022-08-23 16:30:05 +02:00
parent 3ce09d9127
commit 9e62e7facb

View File

@ -641,9 +641,28 @@ static int device_is_power_sink(sd_device *device) {
return found_sink || !found_source;
}
static int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value) {
const char *value;
int r;
r = sd_device_get_sysattr_value(device, sysattr, &value);
if (r < 0)
return r;
unsigned v;
r = safe_atou(value, &v);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
if (ret_value)
*ret_value = v;
/* We return "true" if the value is positive. */
return v > 0;
}
int on_ac_power(void) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
bool found_offline = false, found_online = false, found_battery = false;
bool found_ac_online = false, found_battery = false;
sd_device *d;
int r;
@ -660,22 +679,15 @@ int on_ac_power(void) {
return r;
FOREACH_DEVICE(e, d) {
const char *val;
unsigned v;
r = sd_device_get_sysattr_value(d, "type", &val);
if (r < 0) {
log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring device: %m");
continue;
}
/* We assume every power source is AC, except for batteries. See
/* See
* https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
* for defined power source types. Also see:
* https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power */
if (streq(val, "Battery")) {
found_battery = true;
log_device_debug(d, "The power supply is battery, ignoring device.");
const char *val;
r = sd_device_get_sysattr_value(d, "type", &val);
if (r < 0) {
log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring device: %m");
continue;
}
@ -691,36 +703,33 @@ int on_ac_power(void) {
}
}
r = sd_device_get_sysattr_value(d, "online", &val);
if (r < 0) {
log_device_debug_errno(d, r, "Failed to read 'online' sysfs attribute, ignoring device: %m");
bool is_battery = streq(val, "Battery");
if (is_battery) {
found_battery = true;
log_device_debug(d, "The power supply is battery.");
continue;
}
r = safe_atou(val, &v);
r = device_get_sysattr_unsigned(d, "online", NULL);
if (r < 0) {
log_device_debug_errno(d, r, "Failed to parse 'online' attribute, ignoring device: %m");
log_device_debug_errno(d, r, "Failed to query 'online' sysfs attribute: %m");
continue;
}
} else if (r > 0) /* At least 1 and 2 are defined as different types of 'online' */
found_ac_online = true;
if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
found_online = true;
else
found_offline = true;
log_device_debug(d, "The power supply is currently %s.", v > 0 ? "online" : "offline");
log_device_debug(d, "The power supply is currently %s.", r > 0 ? "online" : "offline");
}
if (found_online)
log_debug("Found at least one online non-battery power supply, system is running on AC power.");
else if (!found_offline)
log_debug("Found no offline non-battery power supply, assuming system is running on AC power.");
else if (!found_battery)
log_debug("Found no battery, assuming system is running on AC power.");
else
log_debug("All non-battery power supplies are offline, assuming system is running with battery.");
return found_online || !found_offline || !found_battery;
if (found_ac_online) {
log_debug("Found at least one online non-battery power supply, system is running on AC.");
return true;
} else if (found_battery) {
log_debug("Found battery and no online power sources, assuming system is running from battery.");
return false;
} else {
log_debug("No power supply reported online and no battery, assuming system is running on AC.");
return true;
}
}
bool udev_available(void) {