]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
on-ac-power: rework logic
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 23 Aug 2022 14:30:05 +0000 (16:30 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 23 Aug 2022 15:04:31 +0000 (17:04 +0200)
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.

src/shared/udev-util.c

index db968a17c47744eb5b767cd68f92986974389554..8892d2bc9a9134d94d5fd5a17c12565ab118d276 100644 (file)
@@ -661,7 +661,7 @@ static int device_is_power_sink(sd_device *device) {
 
 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;
 
@@ -678,25 +678,18 @@ int on_ac_power(void) {
                 return r;
 
         FOREACH_DEVICE(e, d) {
-                const char *val;
-                unsigned v;
+                /* See
+                 * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
+                 * for defined power source types. Also see:
+                 * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-power */
 
+                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;
                 }
 
-                /* We assume every power source is AC, except for batteries. See
-                 * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
-                 * for defined power source types. Also see:
-                 * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-power */
-                if (streq(val, "Battery")) {
-                        found_battery = true;
-                        log_device_debug(d, "The power supply is battery, ignoring device.");
-                        continue;
-                }
-
                 /* Ignore USB-C power supply in source mode. See issue #21988. */
                 if (streq(val, "USB")) {
                         r = device_is_power_sink(d);
@@ -709,36 +702,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;
-                }
-
-                if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
-                        found_online = true;
-                else
-                        found_offline = true;
+                } else if (r > 0)  /* At least 1 and 2 are defined as different types of 'online' */
+                        found_ac_online = 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) {