diff --git a/app/src/main/java/eu/faircode/email/ApplicationEx.java b/app/src/main/java/eu/faircode/email/ApplicationEx.java index 55ccd7e5f3..8f9d155a63 100644 --- a/app/src/main/java/eu/faircode/email/ApplicationEx.java +++ b/app/src/main/java/eu/faircode/email/ApplicationEx.java @@ -351,6 +351,7 @@ public class ApplicationEx extends Application EntityLog.log(context, "Upgrading from " + version + " to " + BuildConfig.VERSION_CODE); SharedPreferences.Editor editor = prefs.edit(); + editor.remove("max_backoff_power"); if (version < BuildConfig.VERSION_CODE) editor.remove("crash_report_count"); diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java index e8a12d7bf9..6b4122c980 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java @@ -213,6 +213,8 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc private SwitchCompat swEmptyPool; private SwitchCompat swIdleDone; private SwitchCompat swFastFetch; + private TextView tvMaxBackoff; + private SeekBar sbMaxBackOff; private SwitchCompat swLogarithmicBackoff; private SwitchCompat swExactAlarms; private SwitchCompat swInfra; @@ -271,7 +273,8 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc "show_recent", "use_modseq", "preamble", "uid_command", "perform_expunge", "uid_expunge", "auth_plain", "auth_login", "auth_ntlm", "auth_sasl", "auth_apop", "use_top", - "keep_alive_poll", "empty_pool", "idle_done", "fast_fetch", "logarithmic_backoff", + "keep_alive_poll", "empty_pool", "idle_done", "fast_fetch", + "max_backoff_power", "logarithmic_backoff", "exact_alarms", "infra", "dkim_verify", "dup_msgids", "global_keywords", "test_iab" }; @@ -433,6 +436,8 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc swEmptyPool = view.findViewById(R.id.swEmptyPool); swIdleDone = view.findViewById(R.id.swIdleDone); swFastFetch = view.findViewById(R.id.swFastFetch); + tvMaxBackoff = view.findViewById(R.id.tvMaxBackoff); + sbMaxBackOff = view.findViewById(R.id.sbMaxBackOff); swLogarithmicBackoff = view.findViewById(R.id.swLogarithmicBackoff); swExactAlarms = view.findViewById(R.id.swExactAlarms); swInfra = view.findViewById(R.id.swInfra); @@ -1549,6 +1554,23 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc } }); + sbMaxBackOff.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + prefs.edit().putInt("max_backoff_power", progress).apply(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // Do nothing + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // Do nothing + } + }); + swLogarithmicBackoff.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -2263,6 +2285,12 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc swEmptyPool.setChecked(prefs.getBoolean("empty_pool", true)); swIdleDone.setChecked(prefs.getBoolean("idle_done", true)); swFastFetch.setChecked(prefs.getBoolean("fast_fetch", false)); + + int max_backoff_power = prefs.getInt("max_backoff_power", ServiceSynchronize.DEFAULT_BACKOFF_POWER - 3); + int max_backoff = (int) Math.pow(2, max_backoff_power + 3); + tvMaxBackoff.setText(getString(R.string.title_advanced_max_backoff, max_backoff)); + sbMaxBackOff.setProgress(max_backoff_power); + swLogarithmicBackoff.setChecked(prefs.getBoolean("logarithmic_backoff", true)); swExactAlarms.setChecked(prefs.getBoolean("exact_alarms", true)); swInfra.setChecked(prefs.getBoolean("infra", false)); diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 58f682e14d..fc57a3b643 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -133,6 +133,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences private static final ExecutorService executorNotify = Helper.getBackgroundExecutor(1, "notify"); + static final int DEFAULT_BACKOFF_POWER = 3; // 2^3=8 seconds (totally 8+2x20=48 seconds) + private static final long BACKUP_DELAY = 30 * 1000L; // milliseconds private static final long PURGE_DELAY = 30 * 1000L; // milliseconds private static final int QUIT_DELAY = 10; // seconds @@ -141,7 +143,6 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences private static final int TUNE_KEEP_ALIVE_INTERVAL_STEP = 2; // minutes private static final int OPTIMIZE_POLL_INTERVAL = 15; // minutes private static final int CONNECT_BACKOFF_START = 8; // seconds - private static final int CONNECT_BACKOFF_MAX = 8; // seconds (totally 8+2x20=48 seconds) private static final int CONNECT_BACKOFF_INTERMEDIATE = 5; // minutes private static final int CONNECT_BACKOFF_ALARM_START = 15; // minutes private static final int CONNECT_BACKOFF_ALARM_MAX = 60; // minutes @@ -2647,6 +2648,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences if (state.isRunning()) { long now = new Date().getTime(); boolean logarithmic_backoff = prefs.getBoolean("logarithmic_backoff", true); + int max_backoff_power = prefs.getInt("max_backoff_power", DEFAULT_BACKOFF_POWER - 3); + int max_backoff = (int) Math.pow(2, max_backoff_power + 3); if (logarithmic_backoff) { // Check for fast successive server, connectivity, etc failures @@ -2679,7 +2682,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences " avg=" + (avg_fail / 1000L) + "/" + (fail_threshold / 1000L) + " missing=" + (missing / 1000L) + " compensate=" + compensate + - " backoff=" + backoff + + " backoff=" + backoff + "/" + max_backoff + " host=" + account.host + " ex=" + Log.formatThrowable(last_fail, false); if (compensate > 2) @@ -2700,14 +2703,14 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences int backoff = state.getBackoff(); int recently = (lastLost + LOST_RECENTLY < now ? 1 : 2); EntityLog.log(this, EntityLog.Type.Account, account, - account.name + " backoff=" + backoff + + account.name + " backoff=" + backoff + "/" + max_backoff + " recently=" + recently + "x" + " logarithmic=" + logarithmic_backoff); if (logarithmic_backoff) { - if (backoff < CONNECT_BACKOFF_MAX) + if (backoff < max_backoff) state.setBackoff(backoff * 2); - else if (backoff == CONNECT_BACKOFF_MAX) + else if (backoff == max_backoff) if (AlarmManagerCompatEx.hasExactAlarms(this)) state.setBackoff(CONNECT_BACKOFF_INTERMEDIATE * 60); else @@ -2731,11 +2734,12 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences Map crumb = new HashMap<>(); crumb.put("account", account.name); crumb.put("backoff", Integer.toString(backoff)); + crumb.put("max_backoff", Integer.toString(max_backoff)); crumb.put("recently", Integer.toString(recently)); crumb.put("logarithmic", Boolean.toString(logarithmic_backoff)); Log.breadcrumb("Backing off", crumb); - if (backoff <= CONNECT_BACKOFF_MAX) { + if (backoff <= max_backoff) { // Short back-off period, keep device awake try { long interval = backoff * 1000L * recently; diff --git a/app/src/main/res/layout/fragment_options_misc.xml b/app/src/main/res/layout/fragment_options_misc.xml index 1cb8d69349..0e5c0705dc 100644 --- a/app/src/main/res/layout/fragment_options_misc.xml +++ b/app/src/main/res/layout/fragment_options_misc.xml @@ -1580,6 +1580,28 @@ app:layout_constraintTop_toBottomOf="@id/swIdleDone" app:switchPadding="12dp" /> + + + + Use TOP IDLE/DONE Fast FETCH + Max. back-off: %1$d s Logarithmic back-off Turning this off can result in a significant increase in battery usage! Poll on keep-alive