Allow multiple mailboxes to be synced in a single request

b/11103878

Change-Id: Ic6abf51457fe94e89fe51b461da4371f50e0fe86
This commit is contained in:
Martin Hibdon 2013-10-09 11:03:40 -07:00
parent 7c03217316
commit 56aba8d843
4 changed files with 121 additions and 25 deletions

View File

@ -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<Long> 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",

View File

@ -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());

View File

@ -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);
}

View File

@ -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) {