Save sync options if folders are deleted and restore when reloaded
Bug: 5176640
Change-Id: I7c709998b65080545f468997e2df5bc00162a89f
diff --git a/src/com/android/exchange/adapter/FolderSyncParser.java b/src/com/android/exchange/adapter/FolderSyncParser.java
index 9ba3697..c899cb2 100644
--- a/src/com/android/exchange/adapter/FolderSyncParser.java
+++ b/src/com/android/exchange/adapter/FolderSyncParser.java
@@ -30,6 +30,7 @@
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.Mailbox;
+import com.android.emailcommon.service.SyncWindow;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.emailcommon.utility.Utility;
@@ -38,6 +39,7 @@
import com.android.exchange.Eas;
import com.android.exchange.ExchangeService;
import com.android.exchange.provider.MailboxUtilities;
+import com.google.common.annotations.VisibleForTesting;
import java.io.IOException;
import java.io.InputStream;
@@ -96,8 +98,10 @@
private static final int MAILBOX_ID_COLUMNS_SERVER_ID = 1;
private static final int MAILBOX_ID_COLUMNS_PARENT_SERVER_ID = 2;
- private long mAccountId;
- private String mAccountIdAsString;
+ @VisibleForTesting
+ long mAccountId;
+ @VisibleForTesting
+ String mAccountIdAsString;
private String[] mBindArguments = new String[2];
private ArrayList<ContentProviderOperation> mOperations =
new ArrayList<ContentProviderOperation>();
@@ -165,6 +169,8 @@
mAccount.mId), cv, null, null);
// Delete PIM data
ExchangeService.deleteAccountPIMData(mAccountId);
+ // Save away any mailbox sync information that is NOT default
+ saveMailboxSyncOptions();
// And only then, delete mailboxes
mContentResolver.delete(Mailbox.CONTENT_URI, ALL_BUT_ACCOUNT_MAILBOX,
new String[] {Long.toString(mAccountId)});
@@ -237,6 +243,74 @@
}
}
+ private static class SyncOptions {
+ private final int mInterval;
+ private final int mLookback;
+
+ private SyncOptions(int interval, int lookback) {
+ mInterval = interval;
+ mLookback = lookback;
+ }
+ }
+
+ private static final String MAILBOX_STATE_SELECTION =
+ MailboxColumns.ACCOUNT_KEY + "=? AND (" + MailboxColumns.SYNC_INTERVAL + "!=" +
+ Account.CHECK_INTERVAL_NEVER + " OR " + Mailbox.SYNC_LOOKBACK + "!=" +
+ SyncWindow.SYNC_WINDOW_UNKNOWN + ")";
+
+ private static final String[] MAILBOX_STATE_PROJECTION = new String[] {
+ MailboxColumns.SERVER_ID, MailboxColumns.SYNC_INTERVAL, MailboxColumns.SYNC_LOOKBACK};
+ private static final int MAILBOX_STATE_SERVER_ID = 0;
+ private static final int MAILBOX_STATE_INTERVAL = 1;
+ private static final int MAILBOX_STATE_LOOKBACK = 2;
+ @VisibleForTesting
+ final HashMap<String, SyncOptions> mSyncOptionsMap = new HashMap<String, SyncOptions>();
+
+ /**
+ * For every mailbox in this account that has a non-default interval or lookback, save those
+ * values.
+ */
+ @VisibleForTesting
+ void saveMailboxSyncOptions() {
+ // Shouldn't be necessary, but...
+ mSyncOptionsMap.clear();
+ Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_STATE_PROJECTION,
+ MAILBOX_STATE_SELECTION, new String[] {mAccountIdAsString}, null);
+ if (c != null) {
+ try {
+ while (c.moveToNext()) {
+ mSyncOptionsMap.put(c.getString(MAILBOX_STATE_SERVER_ID),
+ new SyncOptions(c.getInt(MAILBOX_STATE_INTERVAL),
+ c.getInt(MAILBOX_STATE_LOOKBACK)));
+ }
+ } finally {
+ c.close();
+ }
+ }
+ }
+
+ /**
+ * For every set of saved mailbox sync options, try to find and restore those values
+ */
+ @VisibleForTesting
+ void restoreMailboxSyncOptions() {
+ try {
+ ContentValues cv = new ContentValues();
+ mBindArguments[1] = mAccountIdAsString;
+ for (String serverId: mSyncOptionsMap.keySet()) {
+ SyncOptions options = mSyncOptionsMap.get(serverId);
+ cv.put(MailboxColumns.SYNC_INTERVAL, options.mInterval);
+ cv.put(MailboxColumns.SYNC_LOOKBACK, options.mLookback);
+ mBindArguments[0] = serverId;
+ // If we match account and server id, set the sync options
+ mContentResolver.update(Mailbox.CONTENT_URI, cv, WHERE_SERVER_ID_AND_ACCOUNT,
+ mBindArguments);
+ }
+ } finally {
+ mSyncOptionsMap.clear();
+ }
+ }
+
public Mailbox addParser() throws IOException {
String name = null;
String serverId = null;
@@ -591,6 +665,11 @@
mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
mBindArguments);
}
+
+ // If we have saved options, restore them now
+ if (mInitialSync) {
+ restoreMailboxSyncOptions();
+ }
}
@Override
diff --git a/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java b/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java
index e0cabf5..1538f99 100644
--- a/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java
+++ b/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java
@@ -16,12 +16,15 @@
package com.android.exchange.adapter;
+import android.content.ContentResolver;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.Mailbox;
+import com.android.emailcommon.service.SyncWindow;
import com.android.exchange.EasSyncService;
import com.android.exchange.provider.EmailContentSetupUtils;
-import android.test.suitebuilder.annotation.MediumTest;
-
import java.io.IOException;
import java.util.HashMap;
@@ -32,6 +35,10 @@
@MediumTest
public class FolderSyncParserTests extends SyncAdapterTestCase<EmailSyncAdapter> {
+ // We increment this to generate unique server id's
+ private int mServerIdCount = 0;
+ private final long mCreationTime = System.currentTimeMillis();
+
public FolderSyncParserTests() {
super();
}
@@ -99,4 +106,102 @@
// parent's parent is a mail type
assertTrue(parser.isValidMailFolder(boxUnknownType, mailboxMap));
}
+
+ private Mailbox setupBoxSync(int interval, int lookback, String serverId) {
+ // Don't save the box; just create it, and give it a server id
+ Mailbox box = EmailContentSetupUtils.setupMailbox("box1", mAccount.mId, false,
+ mProviderContext, Mailbox.TYPE_MAIL);
+ box.mSyncInterval = interval;
+ box.mSyncLookback = lookback;
+ if (serverId != null) {
+ box.mServerId = serverId;
+ } else {
+ box.mServerId = "serverId-" + mCreationTime + '-' + mServerIdCount++;
+ }
+ box.save(mProviderContext);
+ return box;
+ }
+
+ private boolean syncOptionsSame(Mailbox a, Mailbox b) {
+ if (a.mSyncInterval != b.mSyncInterval) return false;
+ if (a.mSyncLookback != b.mSyncLookback) return false;
+ return true;
+ }
+
+ public void testSaveAndRestoreMailboxSyncOptions() throws IOException {
+ EasSyncService service = getTestService();
+ EmailSyncAdapter adapter = new EmailSyncAdapter(service);
+ FolderSyncParser parser = new FolderSyncParser(getTestInputStream(), adapter);
+ mAccount.save(mProviderContext);
+
+ parser.mAccount = mAccount;
+ parser.mAccountId = mAccount.mId;
+ parser.mAccountIdAsString = Long.toString(mAccount.mId);
+ parser.mContext = mProviderContext;
+ parser.mContentResolver = mProviderContext.getContentResolver();
+
+ // Don't save the box; just create it, and give it a server id
+ Mailbox box1 = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ null);
+ Mailbox box2 = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ null);
+ Mailbox boxa = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_1_MONTH,
+ null);
+ Mailbox boxb = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_2_WEEKS,
+ null);
+ Mailbox boxc = setupBoxSync(Account.CHECK_INTERVAL_PUSH, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ null);
+ Mailbox boxd = setupBoxSync(Account.CHECK_INTERVAL_PUSH, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ null);
+ Mailbox boxe = setupBoxSync(Account.CHECK_INTERVAL_PUSH, SyncWindow.SYNC_WINDOW_1_DAY,
+ null);
+
+ // Save the options (for a, b, c, d, e);
+ parser.saveMailboxSyncOptions();
+ // There should be 5 entries in the map, and they should be the correct ones
+ assertNotNull(parser.mSyncOptionsMap.get(boxa.mServerId));
+ assertNotNull(parser.mSyncOptionsMap.get(boxb.mServerId));
+ assertNotNull(parser.mSyncOptionsMap.get(boxc.mServerId));
+ assertNotNull(parser.mSyncOptionsMap.get(boxd.mServerId));
+ assertNotNull(parser.mSyncOptionsMap.get(boxe.mServerId));
+
+ // Delete all the mailboxes in the account
+ ContentResolver cr = mProviderContext.getContentResolver();
+ cr.delete(Mailbox.CONTENT_URI, Mailbox.ACCOUNT_KEY + "=?",
+ new String[] {parser.mAccountIdAsString});
+
+ // Create new boxes, all with default values for interval & window
+ Mailbox box1x = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ box1.mServerId);
+ Mailbox box2x = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ box2.mServerId);
+ Mailbox boxax = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ boxa.mServerId);
+ Mailbox boxbx = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ boxb.mServerId);
+ Mailbox boxcx = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ boxc.mServerId);
+ Mailbox boxdx = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ boxd.mServerId);
+ Mailbox boxex = setupBoxSync(Account.CHECK_INTERVAL_NEVER, SyncWindow.SYNC_WINDOW_UNKNOWN,
+ boxe.mServerId);
+
+ // Restore the sync options
+ parser.restoreMailboxSyncOptions();
+ box1x = Mailbox.restoreMailboxWithId(mProviderContext, box1x.mId);
+ box2x = Mailbox.restoreMailboxWithId(mProviderContext, box2x.mId);
+ boxax = Mailbox.restoreMailboxWithId(mProviderContext, boxax.mId);
+ boxbx = Mailbox.restoreMailboxWithId(mProviderContext, boxbx.mId);
+ boxcx = Mailbox.restoreMailboxWithId(mProviderContext, boxcx.mId);
+ boxdx = Mailbox.restoreMailboxWithId(mProviderContext, boxdx.mId);
+ boxex = Mailbox.restoreMailboxWithId(mProviderContext, boxex.mId);
+
+ assertTrue(syncOptionsSame(box1, box1x));
+ assertTrue(syncOptionsSame(box2, box2x));
+ assertTrue(syncOptionsSame(boxa, boxax));
+ assertTrue(syncOptionsSame(boxb, boxbx));
+ assertTrue(syncOptionsSame(boxc, boxcx));
+ assertTrue(syncOptionsSame(boxd, boxdx));
+ assertTrue(syncOptionsSame(boxe, boxex));
+ }
}