From e669f28b0866e66c629103698ad14b22a204442f Mon Sep 17 00:00:00 2001 From: Yu Ping Hu Date: Fri, 19 Apr 2013 16:32:57 -0700 Subject: [PATCH] Fix periodic sync (for POP/IMAP). Periodic sync management was wrong in at least two ways: 1) Periodic syncs were scheduled as a side effect of performing a sync, so changing the sync interval setting would not do what you expect. 2) Performing a manual mailbox sync would schedule a periodic sync on that mailbox. This change removes the side effect from sync, and instead actually responds to updates to the sync interval by removing the extra syncs and updating just the account sync. Bug: 8666490 Change-Id: I3f4a3fb7044c408578f0dc75ccb6c5bb176bfc0b --- .../android/email/provider/EmailProvider.java | 69 +++++++++++++++++++ .../service/PopImapSyncAdapterService.java | 18 ----- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/src/com/android/email/provider/EmailProvider.java b/src/com/android/email/provider/EmailProvider.java index 48d159ec2..2f231b1a9 100644 --- a/src/com/android/email/provider/EmailProvider.java +++ b/src/com/android/email/provider/EmailProvider.java @@ -27,6 +27,7 @@ import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.OperationApplicationException; +import android.content.PeriodicSync; import android.content.UriMatcher; import android.content.res.Resources; import android.database.ContentObserver; @@ -771,6 +772,7 @@ public class EmailProvider extends ContentProvider { } break; case ACCOUNT: + updateAccountSyncInterval(longId, values); if (!uri.getBooleanQueryParameter(IS_UIPROVIDER, false)) { notifyUIAccount(longId); } @@ -1514,6 +1516,7 @@ public class EmailProvider extends ContentProvider { // TODO: should this notify on keys other than sync status? notifyUIFolder(id, null); } else if (match == ACCOUNT_ID) { + updateAccountSyncInterval(Long.parseLong(id), values); // Notify individual account and "all accounts" notifyUI(UIPROVIDER_ACCOUNT_NOTIFIER, id); resolver.notifyChange(UIPROVIDER_ALL_ACCOUNTS_NOTIFIER, null); @@ -4109,6 +4112,70 @@ public class EmailProvider extends ContentProvider { return Mailbox.restoreMailboxWithId(getContext(), id); } + /** + * Create an android.accounts.Account object for this account. + * @param accountId id of account to load. + * @return an android.accounts.Account for this account, or null if we can't load it. + */ + private android.accounts.Account getAccountManagerAccount(final long accountId) { + final Context context = getContext(); + final Account account = Account.restoreAccountWithId(context, accountId); + if (account == null) return null; + final String protocol = account.getProtocol(context); + loadProtocolTypeMap(context); + final String type = sProtocolTypeMap.get(protocol); + if (type == null) return null; + return new android.accounts.Account(account.mEmailAddress, type); + } + + /** + * The old sync code used to add periodic syncs for a mailbox when it was manually synced. + * This function removes all such non-default periodic syncs. + * @param account The account for which to remove unnecessary periodic syncs. + */ + private void removeExtraPeriodicSyncs(final android.accounts.Account account) { + final List syncs = + ContentResolver.getPeriodicSyncs(account, EmailContent.AUTHORITY); + for (PeriodicSync sync : syncs) { + if (!sync.extras.isEmpty()) { + ContentResolver.removePeriodicSync(account, EmailContent.AUTHORITY, sync.extras); + } + } + } + + /** + * Update an account's periodic sync if the sync interval has changed. + * @param accountId id for the account to update. + * @param values the ContentValues for this update to the account. + */ + private void updateAccountSyncInterval(final long accountId, final ContentValues values) { + final Integer syncInterval = values.getAsInteger(AccountColumns.SYNC_INTERVAL); + if (syncInterval == null) { + // No change to the sync interval. + return; + } + final android.accounts.Account account = getAccountManagerAccount(accountId); + if (account == null) { + // Unable to load the account, or unknown protocol. + return; + } + + Log.d(TAG, "Setting sync interval for account " + accountId + " to " + syncInterval + + " minutes"); + + // TODO: Ideally we don't need to do this every time we change the sync interval. + // Either do this on upgrade, or perhaps on startup. + removeExtraPeriodicSyncs(account); + + final Bundle extras = new Bundle(); + if (syncInterval > 0) { + ContentResolver.addPeriodicSync(account, EmailContent.AUTHORITY, extras, + syncInterval * 60); + } else { + ContentResolver.removePeriodicSync(account, EmailContent.AUTHORITY, extras); + } + } + private Cursor uiFolderRefresh(final Mailbox mailbox, final int deltaMessageCount) { if (mailbox == null) return null; EmailServiceProxy service = EmailServiceUtils.getServiceForAccount(getContext(), @@ -4413,6 +4480,8 @@ public class EmailProvider extends ContentProvider { context.getString(R.string.account_manager_type_exchange)); builder.put(context.getString(R.string.protocol_imap), context.getString(R.string.account_manager_type_imap)); + builder.put(context.getString(R.string.protocol_legacy_imap), + context.getString(R.string.account_manager_type_legacy_imap)); builder.put(context.getString(R.string.protocol_pop3), context.getString(R.string.account_manager_type_pop3)); diff --git a/src/com/android/email/service/PopImapSyncAdapterService.java b/src/com/android/email/service/PopImapSyncAdapterService.java index 99182b31b..9a80d5151 100644 --- a/src/com/android/email/service/PopImapSyncAdapterService.java +++ b/src/com/android/email/service/PopImapSyncAdapterService.java @@ -226,24 +226,6 @@ public class PopImapSyncAdapterService extends Service { int deltaMessageCount = extras.getInt(EmailServiceStub.SYNC_EXTRA_DELTA_MESSAGE_COUNT, 0); sync(context, mailboxId, syncResult, uiRefresh, deltaMessageCount); - - // Outbox is a special case here - Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId); - if (mailbox.mType == Mailbox.TYPE_OUTBOX) { - return; - } - - // Convert from minutes to seconds - int syncFrequency = acct.mSyncInterval * 60; - // Values < 0 are for "never" or "push"; 0 is undefined - if (syncFrequency <= 0) return; - Bundle ex = new Bundle(); - if (!isInbox) { - ex.putLong(EmailServiceStub.SYNC_EXTRA_MAILBOX_ID, mailboxId); - } - Log.d(TAG, "Setting periodic sync for " + acct.mDisplayName + ": " + - syncFrequency + " seconds"); - ContentResolver.addPeriodicSync(account, authority, ex, syncFrequency); } } } catch (Exception e) {