From 6b2c004118219293b8fae874e0b474321a949915 Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Sun, 11 Jan 2026 15:35:47 -0500 Subject: [PATCH] Add support for respecting battery saver mode This is configurable, but enabled by default. Signed-off-by: Andrew Gunnerson --- .../com/chiller3/basicsync/Preferences.kt | 7 +++++- .../basicsync/syncthing/SyncthingService.kt | 24 ++++++++++++++++++- app/src/main/res/values/strings.xml | 4 +++- app/src/main/res/xml/preferences_root.xml | 9 ++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/chiller3/basicsync/Preferences.kt b/app/src/main/java/com/chiller3/basicsync/Preferences.kt index 99b63ed..7034f96 100644 --- a/app/src/main/java/com/chiller3/basicsync/Preferences.kt +++ b/app/src/main/java/com/chiller3/basicsync/Preferences.kt @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Andrew Gunnerson + * SPDX-FileCopyrightText: 2023-2026 Andrew Gunnerson * SPDX-License-Identifier: GPL-3.0-only */ @@ -19,6 +19,7 @@ class Preferences(context: Context) { // Main preferences. const val PREF_REQUIRE_UNMETERED_NETWORK = "require_unmetered_network" const val PREF_REQUIRE_SUFFICIENT_BATTERY = "require_sufficient_battery" + const val PREF_RESPECT_BATTERY_SAVER = "respect_battery_saver" const val PREF_KEEP_ALIVE = "keep_alive" // Main UI actions only. @@ -58,6 +59,10 @@ class Preferences(context: Context) { get() = prefs.getBoolean(PREF_REQUIRE_SUFFICIENT_BATTERY, true) set(enabled) = prefs.edit { putBoolean(PREF_REQUIRE_SUFFICIENT_BATTERY, enabled) } + var respectBatterySaver: Boolean + get() = prefs.getBoolean(PREF_RESPECT_BATTERY_SAVER, true) + set(enabled) = prefs.edit { putBoolean(PREF_RESPECT_BATTERY_SAVER, enabled) } + var keepAlive: Boolean get() = prefs.getBoolean(PREF_KEEP_ALIVE, true) set(enabled) = prefs.edit { putBoolean(PREF_KEEP_ALIVE, enabled) } diff --git a/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt b/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt index 6f0ee2d..378b58f 100644 --- a/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt +++ b/app/src/main/java/com/chiller3/basicsync/syncthing/SyncthingService.kt @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Andrew Gunnerson + * SPDX-FileCopyrightText: 2025-2026 Andrew Gunnerson * SPDX-License-Identifier: GPL-3.0-only */ @@ -22,6 +22,7 @@ import android.os.BatteryManager import android.os.Binder import android.os.Build import android.os.IBinder +import android.os.PowerManager import android.util.Log import androidx.annotation.GuardedBy import androidx.annotation.WorkerThread @@ -179,6 +180,7 @@ class SyncthingService : Service(), SyncthingStatusReceiver, private lateinit var prefs: Preferences private lateinit var notifications: Notifications private lateinit var connectivityManager: ConnectivityManager + private lateinit var powerManager: PowerManager private val runnerThread = Thread(::runner) private val stateLock = Object() @@ -194,6 +196,8 @@ class SyncthingService : Service(), SyncthingStatusReceiver, private var networkSufficient = false @GuardedBy("stateLock") private var batterySufficient = false + @GuardedBy("stateLock") + private var isBatterySaverMode = false @GuardedBy("stateLock") private var runningProxyInfo: ProxyInfo? = null @@ -205,6 +209,7 @@ class SyncthingService : Service(), SyncthingStatusReceiver, get() = networkConnected && (!prefs.requireUnmeteredNetwork || networkSufficient) && (!prefs.requireSufficientBattery || batterySufficient) + && (!prefs.respectBatterySaver || !isBatterySaverMode) private val shouldRun: Boolean @GuardedBy("stateLock") @@ -314,6 +319,18 @@ class SyncthingService : Service(), SyncthingStatusReceiver, } } + private val batterySaverReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + synchronized(stateLock) { + isBatterySaverMode = powerManager.isPowerSaveMode + + Log.d(TAG, "Battery saver mode changed: $isBatterySaverMode") + + stateChanged() + } + } + } + private val proxyChangeReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Log.d(TAG, "Proxy settings changed") @@ -344,7 +361,11 @@ class SyncthingService : Service(), SyncthingStatusReceiver, connectivityManager = getSystemService(ConnectivityManager::class.java) connectivityManager.registerDefaultNetworkCallback(networkCallback) + powerManager = getSystemService(PowerManager::class.java) + isBatterySaverMode = powerManager.isPowerSaveMode + registerReceiver(batteryStatusReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + registerReceiver(batterySaverReceiver, IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) registerReceiver(proxyChangeReceiver, IntentFilter(Proxy.PROXY_CHANGE_ACTION)) runnerThread.start() @@ -398,6 +419,7 @@ class SyncthingService : Service(), SyncthingStatusReceiver, Preferences.PREF_MANUAL_SHOULD_RUN, Preferences.PREF_REQUIRE_UNMETERED_NETWORK, Preferences.PREF_REQUIRE_SUFFICIENT_BATTERY, + Preferences.PREF_RESPECT_BATTERY_SAVER, Preferences.PREF_KEEP_ALIVE -> stateChanged() Preferences.PREF_DEBUG_MODE -> setLogLevel() } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 51f7262..6739cdc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ @@ -33,6 +33,8 @@ Only run if the device is connected to an unmetered network (eg. Wi-Fi). Require sufficient battery level Only run if the battery level is not low or if the device is charging. + Respect battery saver mode + Only run when Android\'s battery saver mode is disabled. Keep Syncthing alive When Syncthing should not run, pause it instead of shutting it down. The avoids a potential performance hit when scanning large folders on startup. Version diff --git a/app/src/main/res/xml/preferences_root.xml b/app/src/main/res/xml/preferences_root.xml index 491e86d..0009ba7 100644 --- a/app/src/main/res/xml/preferences_root.xml +++ b/app/src/main/res/xml/preferences_root.xml @@ -1,6 +1,6 @@ @@ -96,6 +96,13 @@ app:summary="@string/pref_require_sufficient_battery_desc" app:iconSpaceReserved="false" /> + +