summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Ping Hu <yph@google.com>2013-10-07 16:01:30 -0700
committerYu Ping Hu <yph@google.com>2013-10-08 12:20:19 -0700
commit77b653fa1b5baabddb76802f0333c78f80c29ace (patch)
tree4619dd39eeda985041b3624fb00266aad6fb3244
parent2b11758e54bcefb9fb25aef2fd2024cab574c16c (diff)
downloadExchange-77b653fa1b5baabddb76802f0333c78f80c29ace.tar.gz
Improve sync logic.
- Always request FolderSync when the account hasn't synced yet. - Change the account broadcast receiver to only initiate FolderSync for accounts with all syncs disabled. - Add a mailbox type filter to ONLY sync calendar/contacts. Type filtered sync does not trigger FolderSync. - Do not sync non-enabled types when syncing multiple folders (i.e. for account sync, or for type sync). Bug: 11081520 Change-Id: Ic98e43a9fa3ed46d0597c348a5823d1accab7045
-rw-r--r--src/com/android/exchange/ExchangeBroadcastReceiver.java26
-rw-r--r--src/com/android/exchange/service/CalendarSyncAdapterService.java64
-rw-r--r--src/com/android/exchange/service/ContactsSyncAdapterService.java63
-rw-r--r--src/com/android/exchange/service/EmailSyncAdapterService.java128
4 files changed, 124 insertions, 157 deletions
diff --git a/src/com/android/exchange/ExchangeBroadcastReceiver.java b/src/com/android/exchange/ExchangeBroadcastReceiver.java
index f1918489..fbc424d1 100644
--- a/src/com/android/exchange/ExchangeBroadcastReceiver.java
+++ b/src/com/android/exchange/ExchangeBroadcastReceiver.java
@@ -9,6 +9,8 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.provider.CalendarContract;
+import android.provider.ContactsContract;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.Mailbox;
@@ -18,17 +20,23 @@ import com.android.mail.utils.LogUtils;
public class ExchangeBroadcastReceiver extends BroadcastReceiver {
@Override
- public void onReceive(Context context, Intent intent) {
+ public void onReceive(final Context context, final Intent intent) {
final Account[] accounts = AccountManager.get(context)
.getAccountsByType(context.getString(string.account_manager_type_exchange));
- LogUtils.i(Eas.LOG_TAG, "Accounts changed - requesting account sync for all accounts");
- for (Account account : accounts) {
- final Bundle bundle = new Bundle();
- bundle.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
- bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
- bundle.putLong(
- Mailbox.SYNC_EXTRA_MAILBOX_ID, Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY);
- ContentResolver.requestSync(account, EmailContent.AUTHORITY, bundle);
+ LogUtils.i(Eas.LOG_TAG, "Accounts changed - requesting FolderSync for unsynced accounts");
+ for (final Account account : accounts) {
+ // Only do a sync for accounts that are not configured to sync any types, since the
+ // initial sync will do the right thing if at least one of those is enabled.
+ if (!ContentResolver.getSyncAutomatically(account, EmailContent.AUTHORITY) &&
+ !ContentResolver.getSyncAutomatically(account, CalendarContract.AUTHORITY) &&
+ !ContentResolver.getSyncAutomatically(account, ContactsContract.AUTHORITY)) {
+ final Bundle bundle = new Bundle(3);
+ bundle.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
+ bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+ bundle.putLong(
+ Mailbox.SYNC_EXTRA_MAILBOX_ID, Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY);
+ ContentResolver.requestSync(account, EmailContent.AUTHORITY, bundle);
+ }
}
}
}
diff --git a/src/com/android/exchange/service/CalendarSyncAdapterService.java b/src/com/android/exchange/service/CalendarSyncAdapterService.java
index c8f00cf1..c3683c7f 100644
--- a/src/com/android/exchange/service/CalendarSyncAdapterService.java
+++ b/src/com/android/exchange/service/CalendarSyncAdapterService.java
@@ -27,7 +27,6 @@ import android.os.Bundle;
import android.provider.CalendarContract.Events;
import com.android.emailcommon.provider.EmailContent;
-import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.exchange.Eas;
@@ -101,58 +100,23 @@ public class CalendarSyncAdapterService extends AbstractSyncAdapterService {
}
}
+ // Forward the sync request to the EmailSyncAdapterService.
+ final Bundle mailExtras = new Bundle(4);
+ mailExtras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+ mailExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
+ if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
+ mailExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+ }
final long extrasMailboxId = extras.getLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, 0);
- final boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
if (extrasMailboxId != 0) {
- // If we've been given a mailbox, just sync that one and be done. Don't
- // do a query for the rest of the calendar mailboxes.
- syncMailbox(account, expedited, extrasMailboxId);
- return;
- }
-
- // Find the (EmailProvider) account associated with this email address
- final Cursor accountCursor =
- cr.query(com.android.emailcommon.provider.Account.CONTENT_URI,
- EmailContent.ID_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?",
- new String[] {account.name}, null);
- if (accountCursor == null) {
- LogUtils.e(TAG, "Null account cursor in CalendarSyncAdapterService");
- return;
- }
-
- try {
- if (accountCursor.moveToFirst()) {
- final long accountId = accountCursor.getLong(0);
- // Now, find the calendar mailbox associated with the account
- final Cursor mailboxCursor = cr.query(Mailbox.CONTENT_URI, Mailbox.ID_PROJECTION,
- ACCOUNT_AND_TYPE_CALENDAR, new String[] {Long.toString(accountId)}, null);
- try {
- while (mailboxCursor.moveToNext()) {
- // TODO: Currently just bouncing this to Email sync; eventually streamline.
- final long mailboxId = mailboxCursor.getLong(Mailbox.ID_PROJECTION_COLUMN);
- syncMailbox(account, expedited, mailboxId);
- }
- } finally {
- mailboxCursor.close();
- }
- }
- } finally {
- accountCursor.close();
- }
- }
-
- private static void syncMailbox(Account account, boolean expedited, long mailboxId) {
- // TODO: Should we be using the existing extras and just adding our bits?
- final Bundle mailboxExtras = new Bundle(4);
- mailboxExtras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
- mailboxExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
- if (expedited) {
- mailboxExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+ // If we've been given a mailbox, specify a sync for just that mailbox.
+ mailExtras.putLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, extrasMailboxId);
+ } else {
+ // Otherwise, specify a sync for all calendars.
+ mailExtras.putInt(Mailbox.SYNC_EXTRA_MAILBOX_TYPE, Mailbox.TYPE_CALENDAR);
}
- mailboxExtras.putLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, mailboxId);
- ContentResolver.requestSync(account, EmailContent.AUTHORITY, mailboxExtras);
+ ContentResolver.requestSync(account, EmailContent.AUTHORITY, mailExtras);
LogUtils.i(TAG, "requestSync CalendarSyncAdapter %s, %s",
- account.toString(), mailboxExtras.toString());
-
+ account.toString(), mailExtras.toString());
}
}
diff --git a/src/com/android/exchange/service/ContactsSyncAdapterService.java b/src/com/android/exchange/service/ContactsSyncAdapterService.java
index 19986fb6..8fae508a 100644
--- a/src/com/android/exchange/service/ContactsSyncAdapterService.java
+++ b/src/com/android/exchange/service/ContactsSyncAdapterService.java
@@ -29,7 +29,6 @@ import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import com.android.emailcommon.provider.EmailContent;
-import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.exchange.Eas;
@@ -112,59 +111,23 @@ public class ContactsSyncAdapterService extends AbstractSyncAdapterService {
}
}
- // Find the (EmailProvider) account associated with this email address
- final Cursor accountCursor =
- cr.query(com.android.emailcommon.provider.Account.CONTENT_URI,
- com.android.emailcommon.provider.Account.ID_PROJECTION,
- AccountColumns.EMAIL_ADDRESS + "=?",
- new String[] {account.name}, null);
- if (accountCursor == null) {
- LogUtils.e(TAG, "null account cursor in ContactsSyncAdapterService");
- return;
+ // Forward the sync request to the EmailSyncAdapterService.
+ final Bundle mailExtras = new Bundle(4);
+ mailExtras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+ mailExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
+ if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
+ mailExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
}
-
final long extrasMailboxId = extras.getLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, 0);
- final boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
if (extrasMailboxId != 0) {
- // If we've been given a mailbox, just sync that one and be done. Don't
- // do a query for the rest of the calendar mailboxes.
- syncMailbox(account, expedited, extrasMailboxId);
- return;
- }
-
- try {
- if (accountCursor.moveToFirst()) {
- final long accountId = accountCursor.getLong(
- com.android.emailcommon.provider.Account.ID_PROJECTION_COLUMN);
- // Now, find the contacts mailbox associated with the account
- final Cursor mailboxCursor = cr.query(Mailbox.CONTENT_URI, Mailbox.ID_PROJECTION,
- ACCOUNT_AND_TYPE_CONTACTS, new String[] {Long.toString(accountId)}, null);
- try {
- while (mailboxCursor.moveToNext()) {
- // TODO: Currently just bouncing this to Email sync; eventually streamline.
- final long mailboxId = mailboxCursor.getLong(Mailbox.ID_PROJECTION_COLUMN);
- syncMailbox(account, expedited, mailboxId);
- }
- } finally {
- mailboxCursor.close();
- }
- }
- } finally {
- accountCursor.close();
- }
- }
-
- private static void syncMailbox(Account account, boolean expedited, long mailboxId) {
- // TODO: Should we be using the existing extras and just adding our bits?
- final Bundle mailboxExtras = new Bundle(4);
- mailboxExtras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
- mailboxExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
- if (expedited) {
- mailboxExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+ // If we've been given a mailbox, specify a sync for just that mailbox.
+ mailExtras.putLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, extrasMailboxId);
+ } else {
+ // Otherwise, specify a sync for all calendars.
+ mailExtras.putInt(Mailbox.SYNC_EXTRA_MAILBOX_TYPE, Mailbox.TYPE_CONTACTS);
}
- mailboxExtras.putLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, mailboxId);
- ContentResolver.requestSync(account, EmailContent.AUTHORITY, mailboxExtras);
+ ContentResolver.requestSync(account, EmailContent.AUTHORITY, mailExtras);
LogUtils.i(TAG, "requestSync ContactsSyncAdapter %s, %s",
- account.toString(), mailboxExtras.toString());
+ account.toString(), mailExtras.toString());
}
}
diff --git a/src/com/android/exchange/service/EmailSyncAdapterService.java b/src/com/android/exchange/service/EmailSyncAdapterService.java
index ba5633a0..2261c0fb 100644
--- a/src/com/android/exchange/service/EmailSyncAdapterService.java
+++ b/src/com/android/exchange/service/EmailSyncAdapterService.java
@@ -208,17 +208,7 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
account.mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
boolean pushNeeded = false;
if (account.mSyncInterval == Account.CHECK_INTERVAL_PUSH) {
- // Determine which content types want sync.
- final HashSet<String> authsToSync = new HashSet();
- if (ContentResolver.getSyncAutomatically(amAccount, EmailContent.AUTHORITY)) {
- authsToSync.add(EmailContent.AUTHORITY);
- }
- if (ContentResolver.getSyncAutomatically(amAccount, CalendarContract.AUTHORITY)) {
- authsToSync.add(CalendarContract.AUTHORITY);
- }
- if (ContentResolver.getSyncAutomatically(amAccount, ContactsContract.AUTHORITY)) {
- authsToSync.add(ContactsContract.AUTHORITY);
- }
+ final HashSet<String> authsToSync = getAuthsToSync(amAccount);
// If we have at least one sync-enabled content type, check for syncing mailboxes.
if (!authsToSync.isEmpty()) {
final Cursor c = Mailbox.getMailboxesForPush(service.getContentResolver(),
@@ -632,16 +622,23 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
} finally {
accountCursor.close();
}
- // Get the mailbox that we want to sync.
- // There are four possibilities for Mailbox.SYNC_EXTRA_MAILBOX_ID:
- // 1) Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY: Restart push if appropriate.
- // 2) Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY: Sync only the account data.
- // 3) Not present: Perform a full account sync.
- // 4) Non-negative value: It's an actual mailbox id, sync that mailbox only.
- final long mailboxId = extras.getLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, FULL_ACCOUNT_SYNC);
-
- // If we're just twiddling the push, we do the lightweight thing and just bail.
- if (mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY) {
+
+ // Figure out what we want to sync, based on the extras and our account sync status.
+ final boolean isInitialSync = EmailContent.isInitialSyncKey(account.mSyncKey);
+ final long mailboxId = extras.getLong(Mailbox.SYNC_EXTRA_MAILBOX_ID,
+ Mailbox.NO_MAILBOX);
+ final int mailboxType = extras.getInt(Mailbox.SYNC_EXTRA_MAILBOX_TYPE,
+ Mailbox.TYPE_NONE);
+
+ // A "full sync" means no specific mailbox or type filter was requested.
+ final boolean isFullSync = (mailboxId == Mailbox.NO_MAILBOX &&
+ mailboxType == Mailbox.TYPE_NONE);
+ // A FolderSync is necessary for full sync, initial sync, and account only sync.
+ final boolean isFolderSync = (isFullSync || isInitialSync ||
+ mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY);
+
+ // If we're just twiddling the push, we do the lightweight thing and bail early.
+ if (mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY && !isFolderSync) {
mSyncHandlerMap.modifyPing(account);
LogUtils.i(TAG, "onPerformSync: mailbox push only %s, %s",
acct.toString(), extras.toString());
@@ -651,40 +648,50 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
// Do the bookkeeping for starting a sync, including stopping a ping if necessary.
mSyncHandlerMap.startSync(account.mId);
+ // Perform a FolderSync if necessary.
+ if (isFolderSync) {
+ final EasFolderSync folderSync = new EasFolderSync(context, account);
+ folderSync.doFolderSync(syncResult);
+ }
+
// Perform email upsync for this account. Moves first, then state changes.
- EasMoveItems move = new EasMoveItems(context, account);
- move.upsyncMovedMessages(syncResult);
- // TODO: EasSync should eventually handle both up and down; for now, it's used purely
- // for upsync.
- EasSync upsync = new EasSync(context, account);
- upsync.upsync(syncResult);
-
- // TODO: Should we refresh the account here? It may have changed while waiting for any
+ if (!isInitialSync) {
+ EasMoveItems move = new EasMoveItems(context, account);
+ move.upsyncMovedMessages(syncResult);
+ // TODO: EasSync should eventually handle both up and down; for now, it's used
+ // purely for upsync.
+ EasSync upsync = new EasSync(context, account);
+ upsync.upsync(syncResult);
+ }
+
+ // TODO: Should we refresh account here? It may have changed while waiting for any
// pings to stop. It may not matter since the things that may have been twiddled might
// not affect syncing.
- if (mailboxId == FULL_ACCOUNT_SYNC ||
- mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY) {
- final EasFolderSync folderSync = new EasFolderSync(context, account);
- folderSync.doFolderSync(syncResult);
-
- if (mailboxId == FULL_ACCOUNT_SYNC) {
+ if (mailboxId != Mailbox.NO_MAILBOX) {
+ // Sync the mailbox that was explicitly requested.
+ syncMailbox(context, cr, acct, account, mailboxId, extras, syncResult, null, true);
+ } else if (mailboxId != Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY) {
+ // We have to sync multiple folders.
+ final Cursor c;
+ if (isFullSync) {
// Full account sync includes all mailboxes that participate in system sync.
- final Cursor c = Mailbox.getMailboxIdsForSync(cr, account.mId);
- if (c != null) {
- try {
- while (c.moveToNext()) {
- syncMailbox(context, cr, acct, account, c.getLong(0), extras,
- syncResult, false);
- }
- } finally {
- c.close();
+ c = Mailbox.getMailboxIdsForSync(cr, account.mId);
+ } else {
+ // Type-filtered sync should only get the mailboxes of a specific type.
+ c = Mailbox.getMailboxIdsForSyncByType(cr, account.mId, mailboxType);
+ }
+ if (c != null) {
+ try {
+ final HashSet<String> authsToSync = getAuthsToSync(acct);
+ while (c.moveToNext()) {
+ syncMailbox(context, cr, acct, account, c.getLong(0), extras,
+ syncResult, authsToSync, false);
}
+ } finally {
+ c.close();
}
}
- } else {
- // Sync the mailbox that was explicitly requested.
- syncMailbox(context, cr, acct, account, mailboxId, extras, syncResult, true);
}
// Clean up the bookkeeping, including restarting ping if necessary.
@@ -715,7 +722,8 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
private boolean syncMailbox(final Context context, final ContentResolver cr,
final android.accounts.Account acct, final Account account, final long mailboxId,
- final Bundle extras, final SyncResult syncResult, final boolean isMailboxSync) {
+ final Bundle extras, final SyncResult syncResult, final HashSet<String> authsToSync,
+ final boolean isMailboxSync) {
final Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
if (mailbox == null) {
return false;
@@ -726,6 +734,11 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
extras.toString());
return false;
}
+ if (authsToSync != null && !authsToSync.contains(Mailbox.getAuthority(mailbox.mType))) {
+ // We are asking for an account sync, but this mailbox type is not configured for
+ // sync.
+ return false;
+ }
final boolean success;
// Non-mailbox syncs are whole account syncs initiated by the AccountManager and are
@@ -791,4 +804,23 @@ public class EmailSyncAdapterService extends AbstractSyncAdapterService {
IntentUtilities.setAccountName(builder, accountName);
return new Intent(Intent.ACTION_EDIT, builder.build());
}
+
+ /**
+ * Determine which content types are set to sync for an account.
+ * @param account The account whose sync settings we're looking for.
+ * @return The authorities for the content types we want to sync for account.
+ */
+ private static HashSet<String> getAuthsToSync(final android.accounts.Account account) {
+ final HashSet<String> authsToSync = new HashSet();
+ if (ContentResolver.getSyncAutomatically(account, EmailContent.AUTHORITY)) {
+ authsToSync.add(EmailContent.AUTHORITY);
+ }
+ if (ContentResolver.getSyncAutomatically(account, CalendarContract.AUTHORITY)) {
+ authsToSync.add(CalendarContract.AUTHORITY);
+ }
+ if (ContentResolver.getSyncAutomatically(account, ContactsContract.AUTHORITY)) {
+ authsToSync.add(ContactsContract.AUTHORITY);
+ }
+ return authsToSync;
+ }
}