From 56aba8d8436b083bfc1169dd8b988161d537f7e5 Mon Sep 17 00:00:00 2001 From: Martin Hibdon Date: Wed, 9 Oct 2013 11:03:40 -0700 Subject: [PATCH] Allow multiple mailboxes to be synced in a single request b/11103878 Change-Id: Ic6abf51457fe94e89fe51b461da4371f50e0fe86 --- .../android/emailcommon/provider/Mailbox.java | 97 +++++++++++++++++-- .../android/email/provider/EmailProvider.java | 19 +++- .../email/service/EmailServiceStub.java | 3 +- .../service/PopImapSyncAdapterService.java | 27 ++++-- 4 files changed, 121 insertions(+), 25 deletions(-) diff --git a/emailcommon/src/com/android/emailcommon/provider/Mailbox.java b/emailcommon/src/com/android/emailcommon/provider/Mailbox.java index 48a95ddde..4d32c16fb 100644 --- a/emailcommon/src/com/android/emailcommon/provider/Mailbox.java +++ b/emailcommon/src/com/android/emailcommon/provider/Mailbox.java @@ -44,17 +44,25 @@ import java.util.ArrayList; public class Mailbox extends EmailContent implements MailboxColumns, Parcelable { /** - * Sync extras key when syncing a mailbox to specify which mailbox to sync. + * Sync extras key when syncing one or more mailboxes to specify how many + * mailboxes are included in the extra. */ - public static final String SYNC_EXTRA_MAILBOX_ID = "__mailboxId__"; + public static final String SYNC_EXTRA_MAILBOX_COUNT = "__mailboxCount__"; /** - * Value for {@link #SYNC_EXTRA_MAILBOX_ID} when requesting an account only sync. + * Sync extras key pattern when syncing one or more mailboxes to specify + * which mailbox to sync. Is intentionally private, we have helper functions + * to set up an appropriate bundle, or read its contents. */ - public static final long SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY = -2; + private static final String SYNC_EXTRA_MAILBOX_ID_PATTERN = "__mailboxId%d__"; /** - * Value for {@link #SYNC_EXTRA_MAILBOX_ID} when (re)starting push. + * Sync extra key indicating that we are doing a sync of the folder structure for an account. */ - public static final long SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY = -3; + public static final String SYNC_EXTRA_ACCOUNT_ONLY = "__account_only__"; + /** + * Sync extra key indicating that we are only starting a ping. + */ + public static final String SYNC_EXTRA_PUSH_ONLY = "__push_only__"; + /** * Sync extras key to specify that only a specific mailbox type should be synced. */ @@ -64,8 +72,11 @@ public class Mailbox extends EmailContent implements MailboxColumns, Parcelable */ public static final String SYNC_EXTRA_DELTA_MESSAGE_COUNT = "__deltaMessageCount__"; + public static final String SYNC_EXTRA_NOOP = "__noop__"; + public static final String TABLE_NAME = "Mailbox"; + public static Uri CONTENT_URI; public static Uri MESSAGE_COUNT_URI; @@ -74,6 +85,77 @@ public class Mailbox extends EmailContent implements MailboxColumns, Parcelable MESSAGE_COUNT_URI = Uri.parse(EmailContent.CONTENT_URI + "/mailboxCount"); } + private static String formatMailboxIdExtra(final int index) { + return String.format(SYNC_EXTRA_MAILBOX_ID_PATTERN, index); + } + + public static Bundle createSyncBundle(final ArrayList mailboxIds) { + Bundle bundle = new Bundle(); + bundle.putInt(SYNC_EXTRA_MAILBOX_COUNT, mailboxIds.size()); + for (int i = 0; i < mailboxIds.size(); i++) { + bundle.putLong(formatMailboxIdExtra(i), mailboxIds.get(i)); + } + return bundle; + } + + public static Bundle createSyncBundle(final long[] mailboxIds) { + Bundle bundle = new Bundle(); + bundle.putInt(SYNC_EXTRA_MAILBOX_COUNT, mailboxIds.length); + for (int i = 0; i < mailboxIds.length; i++) { + bundle.putLong(formatMailboxIdExtra(i), mailboxIds[i]); + } + return bundle; + } + + public static Bundle createSyncBundle(final long mailboxId) { + Bundle bundle = new Bundle(); + bundle.putInt(SYNC_EXTRA_MAILBOX_COUNT, 1); + bundle.putLong(formatMailboxIdExtra(0), mailboxId); + return bundle; + } + + public static long[] getMailboxIdsFromBundle(Bundle bundle) { + final int count = bundle.getInt(SYNC_EXTRA_MAILBOX_COUNT, 0); + if (count > 0) { + if (bundle.getBoolean(SYNC_EXTRA_PUSH_ONLY, false)) { + LogUtils.w(Logging.LOG_TAG, "Mailboxes specified in a push only sync"); + } + if (bundle.getBoolean(SYNC_EXTRA_ACCOUNT_ONLY, false)) { + LogUtils.w(Logging.LOG_TAG, "Mailboxes specified in an account only sync"); + } + long [] result = new long[count]; + for (int i = 0; i < count; i++) { + result[i] = bundle.getLong(formatMailboxIdExtra(i), 0); + } + + return result; + } else { + return null; + } + } + + public static boolean isAccountOnlyExtras(Bundle bundle) { + final boolean result = bundle.getBoolean(SYNC_EXTRA_ACCOUNT_ONLY, false); + if (result) { + final int count = bundle.getInt(SYNC_EXTRA_MAILBOX_COUNT, 0); + if (count != 0) { + LogUtils.w(Logging.LOG_TAG, "Mailboxes specified in an account only sync"); + } + } + return result; + } + + public static boolean isPushOnlyExtras(Bundle bundle) { + final boolean result = bundle.getBoolean(SYNC_EXTRA_PUSH_ONLY, false); + if (result) { + final int count = bundle.getInt(SYNC_EXTRA_MAILBOX_COUNT, 0); + if (count != 0) { + LogUtils.w(Logging.LOG_TAG, "Mailboxes specified in a push only sync"); + } + } + return result; + } + public String mDisplayName; public String mServerId; public String mParentServerId; @@ -909,8 +991,7 @@ public class Mailbox extends EmailContent implements MailboxColumns, Parcelable .withValue(Mailbox.SYNC_KEY, "0").build()); cr.applyBatch(AUTHORITY, ops); - final Bundle extras = new Bundle(); - extras.putLong(SYNC_EXTRA_MAILBOX_ID, mailboxId); + final Bundle extras = createSyncBundle(mailboxId); extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true); ContentResolver.requestSync(account, AUTHORITY, extras); LogUtils.i(Logging.LOG_TAG, "requestSync resyncMailbox %s, %s", diff --git a/src/com/android/email/provider/EmailProvider.java b/src/com/android/email/provider/EmailProvider.java index 8ca8a0653..f36578ff5 100644 --- a/src/com/android/email/provider/EmailProvider.java +++ b/src/com/android/email/provider/EmailProvider.java @@ -4944,11 +4944,10 @@ public class EmailProvider extends ContentProvider { */ private static void startSync(final android.accounts.Account account, final long mailboxId, final int deltaMessageCount) { - final Bundle extras = new Bundle(7); + final Bundle extras = Mailbox.createSyncBundle(mailboxId); extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true); extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); - extras.putLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, mailboxId); if (deltaMessageCount != 0) { extras.putInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, deltaMessageCount); } @@ -4977,7 +4976,18 @@ public class EmailProvider extends ContentProvider { * @param account The {@link android.accounts.Account} we're interested in. */ private static void restartPush(final android.accounts.Account account) { - startSync(account, Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY, 0); + final Bundle extras = new Bundle(); + extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); + extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true); + extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); + extras.putBoolean(Mailbox.SYNC_EXTRA_PUSH_ONLY, true); + extras.putString(EmailServiceStatus.SYNC_EXTRAS_CALLBACK_URI, + EmailContent.CONTENT_URI.toString()); + extras.putString(EmailServiceStatus.SYNC_EXTRAS_CALLBACK_METHOD, + SYNC_STATUS_CALLBACK_METHOD); + ContentResolver.requestSync(account, EmailContent.AUTHORITY, extras); + LogUtils.i(TAG, "requestSync EmailProvider startSync %s, %s", account.toString(), + extras.toString()); } private Cursor uiFolderRefresh(final Mailbox mailbox, final int deltaMessageCount) { @@ -5297,8 +5307,7 @@ public class EmailProvider extends ContentProvider { // TODO: It's possible that the account is deleted by the time we get here // It would be nice if we could validate it before trying to sync final android.accounts.Account account = request.mAccount; - final Bundle extras = new Bundle(); - extras.putLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, request.mMailboxId); + final Bundle extras = Mailbox.createSyncBundle(request.mMailboxId); ContentResolver.requestSync(account, request.mAuthority, extras); LogUtils.i(TAG, "requestSync getDelayedSyncHandler %s, %s", account.toString(), extras.toString()); diff --git a/src/com/android/email/service/EmailServiceStub.java b/src/com/android/email/service/EmailServiceStub.java index fa4cfd841..3a7383fc2 100644 --- a/src/com/android/email/service/EmailServiceStub.java +++ b/src/com/android/email/service/EmailServiceStub.java @@ -110,13 +110,12 @@ public abstract class EmailServiceStub extends IEmailService.Stub implements IEm EmailServiceUtils.getServiceInfoForAccount(mContext, account.mId); final android.accounts.Account acct = new android.accounts.Account(account.mEmailAddress, info.accountType); - final Bundle extras = new Bundle(5); + final Bundle extras = Mailbox.createSyncBundle(mailboxId); if (userRequest) { extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true); extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); } - extras.putLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, mailboxId); if (deltaMessageCount != 0) { extras.putInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, deltaMessageCount); } diff --git a/src/com/android/email/service/PopImapSyncAdapterService.java b/src/com/android/email/service/PopImapSyncAdapterService.java index 43f8e1211..672309439 100644 --- a/src/com/android/email/service/PopImapSyncAdapterService.java +++ b/src/com/android/email/service/PopImapSyncAdapterService.java @@ -213,20 +213,27 @@ public class PopImapSyncAdapterService extends Service { service.updateFolderList(acct.mId); // Get the id for the mailbox we want to sync. - long mailboxId = - extras.getLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, Mailbox.NO_MAILBOX); - if (mailboxId == Mailbox.NO_MAILBOX) { - // If the extras didn't specify a mailbox, assume we want the inbox. + long [] mailboxIds = Mailbox.getMailboxIdsFromBundle(extras); + if (mailboxIds == null || mailboxIds.length == 0) { + // No mailbox specified, just sync the inbox. // TODO: IMAP may eventually want to allow multiple auto-sync mailboxes. - mailboxId = Mailbox.findMailboxOfType(context, acct.mId, + final long inboxId = Mailbox.findMailboxOfType(context, acct.mId, Mailbox.TYPE_INBOX); + if (inboxId != Mailbox.NO_MAILBOX) { + mailboxIds = new long[1]; + mailboxIds[0] = inboxId; + } } - if (mailboxId == Mailbox.NO_MAILBOX) return; - boolean uiRefresh = + + if (mailboxIds != null) { + boolean uiRefresh = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false); - int deltaMessageCount = - extras.getInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, 0); - sync(context, mailboxId, extras, syncResult, uiRefresh, deltaMessageCount); + int deltaMessageCount = + extras.getInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, 0); + for (long mailboxId : mailboxIds) { + sync(context, mailboxId, extras, syncResult, uiRefresh, deltaMessageCount); + } + } } } } catch (Exception e) {