From e83a428107acde7d338f313e2e3bf724825a06bd Mon Sep 17 00:00:00 2001 From: Daniel Applebaum Date: Wed, 10 Feb 2010 06:18:35 +0000 Subject: [PATCH] Far more advanced poll scheduler. Now it remembers that finish time of the last successful periodic mail and computes the next start time as an offset from that successful finish. The ramifications of this new method is that changing polling interval on an account does not force delaying all accounts to poll next in the future by the new interval. Instead, K-9 Mail now adjusts the next poll time based on what the next poll time should be based on the last poll finish and the new interval. Example 1: In the old way, if the old polling interval was 1 hour, and the next poll was 50 minutes away (10 minutes have passed), and you changed the interval to 15 minutes, the poll would happen 15 minutes from now. In the new way, the next poll will happen only 5 minutes from now, which is 15 minutes since the last poll. Example 2: In the old way, if the old polling interval was 1 hour, and the next poll was 10 minutes away (50 minutes have passed), and you changed the interval to 30 minutes, the poll would happen 30 minutes from now. The next poll would then happen actually 80 minutes after the previous poll completed. In the new way, it'll actually happen immediately, because the time for the next poll, based on the new schedule, has already passed. Similar scenarios happen when a loss of network connectivity occurs. In the old way, polling would resume using the restoration of connectivity as the starting point. Each time network connectivity was lost and restored, the next poll would be further delayed. *If connectivity was lost and restored frequently, a poll might never happen!* In the new way, the next poll is rescheduled based on the time of the last successful poll, so will be rescheduled just like it was before the loss of connectivity. If the time has already been passed, the poll will happen immediately. --- src/com/fsck/k9/Account.java | 10 +---- src/com/fsck/k9/service/MailService.java | 49 +++++++++++++++++++----- src/com/fsck/k9/service/PollService.java | 3 ++ 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/com/fsck/k9/Account.java b/src/com/fsck/k9/Account.java index ab2174881..32f831acf 100644 --- a/src/com/fsck/k9/Account.java +++ b/src/com/fsck/k9/Account.java @@ -765,15 +765,7 @@ public class Account implements Serializable int newInterval = automaticCheckIntervalMinutes; this.mAutomaticCheckIntervalMinutes = automaticCheckIntervalMinutes; - if (oldInterval == -1 && newInterval != -1) - { - return true; - } - if (newInterval < oldInterval) - { - return true; - } - return false; + return (oldInterval != newInterval); } /** diff --git a/src/com/fsck/k9/service/MailService.java b/src/com/fsck/k9/service/MailService.java index e2ce83125..64673dd13 100644 --- a/src/com/fsck/k9/service/MailService.java +++ b/src/com/fsck/k9/service/MailService.java @@ -9,6 +9,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.NetworkInfo.State; @@ -147,8 +148,7 @@ public class MailService extends CoreService { PollService.startService(this); } - - reschedule(hasConnectivity, doBackground, startIdObj); + reschedulePoll(hasConnectivity, doBackground, startIdObj, false); startIdObj = null; } else if (ACTION_CANCEL.equals(intent.getAction())) @@ -179,7 +179,7 @@ public class MailService extends CoreService { if (K9.DEBUG) Log.v(K9.LOG_TAG, "***** MailService *****: rescheduling poll"); - reschedule(hasConnectivity, doBackground, startIdObj); + reschedulePoll(hasConnectivity, doBackground, startIdObj, true); startIdObj = null; } @@ -218,7 +218,7 @@ public class MailService extends CoreService private void rescheduleAll(final boolean hasConnectivity, final boolean doBackground, final Integer startId) { - reschedule(hasConnectivity, doBackground, null); + reschedulePoll(hasConnectivity, doBackground, null, true); reschedulePushers(hasConnectivity, doBackground, startId); } @@ -271,7 +271,23 @@ public class MailService extends CoreService BootReceiver.cancelIntent(this, i); } - private void reschedule(final boolean hasConnectivity, final boolean doBackground, Integer startId) + private final static String PREVIOUS_INTERVAL = "MailService.previousInterval"; + private final static String LAST_CHECK_END = "MailService.lastCheckEnd"; + + public static void saveLastCheckEnd(Context context) + { + + long lastCheckEnd = System.currentTimeMillis(); + if (K9.DEBUG) + Log.i(K9.LOG_TAG, "Saving lastCheckEnd = " + new Date(lastCheckEnd)); + Preferences prefs = Preferences.getPreferences(context); + SharedPreferences sPrefs = prefs.getPreferences(); + SharedPreferences.Editor editor = sPrefs.edit(); + editor.putLong(LAST_CHECK_END, lastCheckEnd); + editor.commit(); + } + + private void reschedulePoll(final boolean hasConnectivity, final boolean doBackground, Integer startId, final boolean considerLastCheckEnd) { if (hasConnectivity && doBackground) { @@ -280,8 +296,12 @@ public class MailService extends CoreService public void run() { int shortestInterval = -1; - - for (Account account : Preferences.getPreferences(MailService.this).getAccounts()) + + Preferences prefs = Preferences.getPreferences(MailService.this); + SharedPreferences sPrefs = prefs.getPreferences(); + int previousInterval = sPrefs.getInt(PREVIOUS_INTERVAL, -1); + long lastCheckEnd = sPrefs.getLong(LAST_CHECK_END, -1); + for (Account account : prefs.getAccounts()) { if (account.getAutomaticCheckIntervalMinutes() != -1 && account.getFolderSyncMode() != FolderMode.NONE @@ -290,7 +310,10 @@ public class MailService extends CoreService shortestInterval = account.getAutomaticCheckIntervalMinutes(); } } - + SharedPreferences.Editor editor = sPrefs.edit(); + editor.putInt(PREVIOUS_INTERVAL, shortestInterval); + editor.commit(); + if (shortestInterval == -1) { nextCheck = -1; @@ -301,8 +324,14 @@ public class MailService extends CoreService else { long delay = (shortestInterval * (60 * 1000)); - - long nextTime = System.currentTimeMillis() + delay; + long base = (previousInterval == -1 || lastCheckEnd == -1 || considerLastCheckEnd == false ? System.currentTimeMillis() : lastCheckEnd); + long nextTime = base + delay; + if (K9.DEBUG) + Log.i(K9.LOG_TAG, + "previousInterval = " + previousInterval + + ", shortestInterval = " + shortestInterval + + ", lastCheckEnd = " + new Date(lastCheckEnd) + + ", considerLastCheckEnd = " + considerLastCheckEnd); nextCheck = nextTime; try { diff --git a/src/com/fsck/k9/service/PollService.java b/src/com/fsck/k9/service/PollService.java index 98f5314b0..27cc61ff5 100644 --- a/src/com/fsck/k9/service/PollService.java +++ b/src/com/fsck/k9/service/PollService.java @@ -2,6 +2,7 @@ package com.fsck.k9.service; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.IBinder; import android.os.PowerManager; import android.os.PowerManager.WakeLock; @@ -140,6 +141,8 @@ public class PollService extends CoreService private void release() { + MailService.saveLastCheckEnd(getApplication()); + MessagingController controller = MessagingController.getInstance(getApplication()); controller.setCheckMailListener(null); MailService.actionReschedulePoll(PollService.this, null);