diff --git a/man/systemd-sleep.conf.xml b/man/systemd-sleep.conf.xml
index 623e614b6a..c02b44f3de 100644
--- a/man/systemd-sleep.conf.xml
+++ b/man/systemd-sleep.conf.xml
@@ -227,6 +227,23 @@
+
+ HibernateOnACPower=
+
+
+ Whether to allow hibernation when the system has AC power. Only used by
+ systemd-suspend-then-hibernate.service8
+ when HibernateDelaySec= is set.
+
+ If this option is disabled, the countdown of HibernateDelaySec= starts only
+ after AC power is disconnected, keeping the system in the suspend state otherwise.
+
+ This option is only effective on systems with a battery.
+
+
+
+
+
SuspendEstimationSec=
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index 3d4d331710..947ef582bd 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -124,7 +124,8 @@ int parse_sleep_config(SleepConfig **ret) {
return log_oom();
*sc = (SleepConfig) {
- .hibernate_delay_usec = USEC_INFINITY,
+ .hibernate_delay_usec = USEC_INFINITY,
+ .hibernate_on_ac_power = true,
};
const ConfigTableItem items[] = {
@@ -145,6 +146,7 @@ int parse_sleep_config(SleepConfig **ret) {
{ "Sleep", "MemorySleepMode", config_parse_sleep_mode, 0, &sc->mem_modes },
{ "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_usec },
+ { "Sleep", "HibernateOnACPower", config_parse_bool, 0, &sc->hibernate_on_ac_power },
{ "Sleep", "SuspendEstimationSec", config_parse_sec, 0, &sc->suspend_estimation_usec },
{}
};
diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h
index b59bce8fc4..b05efaea95 100644
--- a/src/shared/sleep-config.h
+++ b/src/shared/sleep-config.h
@@ -33,6 +33,7 @@ typedef struct SleepConfig {
char **mem_modes; /* /sys/power/mem_sleep */
usec_t hibernate_delay_usec;
+ bool hibernate_on_ac_power;
usec_t suspend_estimation_usec;
} SleepConfig;
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 15ef7ae913..3f113fff74 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -390,7 +390,15 @@ static int custom_timer_suspend(const SleepConfig *sleep_config) {
}
}
- /* Do not suspend more than HibernateDelaySec= */
+ /* Do not suspend more than HibernateDelaySec= unless HibernateOnACPower=no and currently on AC power */
+ if (!sleep_config->hibernate_on_ac_power) {
+ /* Do not allow "decay" to suspend if the system has no battery. */
+ if (hashmap_isempty(last_capacity))
+ log_once(LOG_WARNING, "HibernateOnACPower=no was ignored because the system does not have a battery.");
+ else if (on_ac_power() > 0)
+ hibernate_timestamp = usec_add(now(CLOCK_BOOTTIME), sleep_config->hibernate_delay_usec);
+ }
+
usec_t before_timestamp = now(CLOCK_BOOTTIME);
suspend_interval = MIN(suspend_interval, usec_sub_unsigned(hibernate_timestamp, before_timestamp));
if (suspend_interval <= 0)
diff --git a/src/sleep/sleep.conf b/src/sleep/sleep.conf
index 98430348a7..153f747342 100644
--- a/src/sleep/sleep.conf
+++ b/src/sleep/sleep.conf
@@ -25,4 +25,5 @@
#HibernateMode=platform shutdown
#MemorySleepMode=
#HibernateDelaySec=
+#HibernateOnACPower=yes
#SuspendEstimationSec=60min