1ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/*
2ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Copyright (C) 2008-2009 Marc Blank
3ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Licensed to The Android Open Source Project.
4ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *
5ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Licensed under the Apache License, Version 2.0 (the "License");
6ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * you may not use this file except in compliance with the License.
7ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * You may obtain a copy of the License at
8ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *
9ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *      http://www.apache.org/licenses/LICENSE-2.0
10ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *
11ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Unless required by applicable law or agreed to in writing, software
12ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * distributed under the License is distributed on an "AS IS" BASIS,
13ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * See the License for the specific language governing permissions and
15ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * limitations under the License.
16ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank */
17ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
18ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankpackage com.android.exchange.adapter;
19ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
206aa35f65d70f476367b3ee951b4470662a296fa1Marc Blankimport android.content.ContentProviderOperation;
21c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Huimport android.content.ContentResolver;
226aa35f65d70f476367b3ee951b4470662a296fa1Marc Blankimport android.content.ContentUris;
236aa35f65d70f476367b3ee951b4470662a296fa1Marc Blankimport android.content.ContentValues;
24c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Huimport android.content.Context;
256aa35f65d70f476367b3ee951b4470662a296fa1Marc Blankimport android.content.OperationApplicationException;
266aa35f65d70f476367b3ee951b4470662a296fa1Marc Blankimport android.database.Cursor;
276aa35f65d70f476367b3ee951b4470662a296fa1Marc Blankimport android.os.RemoteException;
28ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantlerimport android.os.TransactionTooLargeException;
296aa35f65d70f476367b3ee951b4470662a296fa1Marc Blankimport android.text.TextUtils;
305586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Huimport android.util.SparseBooleanArray;
315586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Huimport android.util.SparseIntArray;
326aa35f65d70f476367b3ee951b4470662a296fa1Marc Blank
337372782488977df778a33d990401ce9e397f646bMarc Blankimport com.android.emailcommon.provider.Account;
34c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent;
35c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent.AccountColumns;
36c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent.MailboxColumns;
374d8774462ace9a45154b2df418b9f2fe7a9c685dBen Komaloimport com.android.emailcommon.provider.Mailbox;
38f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blankimport com.android.emailcommon.service.SyncWindow;
39e951b589c5134a1154ec3743d79236dee54a6519Marc Blankimport com.android.emailcommon.utility.AttachmentUtilities;
4077186bb1a174432ef272584374942d8b9228e39cMarc Blankimport com.android.exchange.CommandStatusException;
4177186bb1a174432ef272584374942d8b9228e39cMarc Blankimport com.android.exchange.CommandStatusException.CommandStatus;
42ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.exchange.Eas;
437b6a75def9f415a75b4ff4b640216c95a7e799a5Martin Hibdonimport com.android.exchange.service.EasCalendarSyncHandler;
447b6a75def9f415a75b4ff4b640216c95a7e799a5Martin Hibdonimport com.android.exchange.service.EasContactsSyncHandler;
45942b7d73f2f5b3d6c651e39463e615fe6902a910Scott Kennedyimport com.android.mail.utils.LogUtils;
46f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blankimport com.google.common.annotations.VisibleForTesting;
47ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
4800d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.io.IOException;
4900d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.io.InputStream;
5000d91b2e12d65df06916afdc4bebca67fd27214cMarc Blankimport java.util.ArrayList;
51d3eab5e6ffa39c931c2ca31e6670b7743723e034Marc Blankimport java.util.HashMap;
52ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantlerimport java.util.LinkedHashSet;
53ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantlerimport java.util.Set;
5400d91b2e12d65df06916afdc4bebca67fd27214cMarc Blank
55ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/**
56ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Parse the result of a FolderSync command
57ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *
58ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Handles the addition, deletion, and changes to folders in the user's Exchange account.
59ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank **/
60ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
610a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blankpublic class FolderSyncParser extends AbstractSyncParser {
6222bc4e0e4f4a5e43e4eea8d59e1961860c507594Marc Blank
63ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String TAG = "FolderSyncParser";
64ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
655586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu    /**
665586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * Mapping from EAS type values to {@link Mailbox} types.
675586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * See http://msdn.microsoft.com/en-us/library/gg650877(v=exchg.80).aspx for the list of EAS
685586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * type values.
695586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * If an EAS type is not in the map, or is inserted with a value of {@link Mailbox#TYPE_NONE},
705586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * then we don't support that type and we should ignore it.
715586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * TODO: Maybe we should store the mailbox anyway, otherwise it'll be annoying to upgrade.
725586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     */
735586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu    private static final SparseIntArray MAILBOX_TYPE_MAP;
745586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu    static {
755586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP = new SparseIntArray(11);
76774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_GENERIC,  Mailbox.TYPE_MAIL);
77774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_INBOX,  Mailbox.TYPE_INBOX);
78774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_DRAFTS,  Mailbox.TYPE_DRAFTS);
79774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_DELETED,  Mailbox.TYPE_TRASH);
80774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_SENT,  Mailbox.TYPE_SENT);
81774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_OUTBOX,  Mailbox.TYPE_OUTBOX);
82774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_TASKS,  Mailbox.TYPE_TASKS);
83774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_CALENDAR,  Mailbox.TYPE_CALENDAR);
84774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_CONTACTS,  Mailbox.TYPE_CONTACTS);
85774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_NOTES, Mailbox.TYPE_NONE);
86774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_JOURNAL, Mailbox.TYPE_NONE);
87774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_MAIL, Mailbox.TYPE_MAIL);
88774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_CALENDAR, Mailbox.TYPE_CALENDAR);
89774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_CONTACTS, Mailbox.TYPE_CONTACTS);
90774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_TASKS, Mailbox.TYPE_TASKS);
91774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_JOURNAL, Mailbox.TYPE_NONE);
92774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_NOTES, Mailbox.TYPE_NONE);
93774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_UNKNOWN, Mailbox.TYPE_NONE);
94774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert        //MAILBOX_TYPE_MAP.put(MAILBOX_TYPE_RECIPIENT_INFORMATION_CACHE, Mailbox.TYPE_NONE);
955586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu    }
96ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
976c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Content selection for all mailboxes belonging to an account. */
986c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private static final String WHERE_ACCOUNT_KEY = MailboxColumns.ACCOUNT_KEY + "=?";
999d4ac93efbba01afe668f9406feec69b3a2374ebMarc Blank
1006c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
1016c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Content selection to find a specific mailbox by server id. Since server ids aren't unique
1026c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * across all accounts, this must also check account id.
1036c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
104d3eab5e6ffa39c931c2ca31e6670b7743723e034Marc Blank    private static final String WHERE_SERVER_ID_AND_ACCOUNT = MailboxColumns.SERVER_ID + "=? and " +
105ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        MailboxColumns.ACCOUNT_KEY + "=?";
106ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1076c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
1086c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Content selection to find a specific mailbox by display name and account.
1096c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
110ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    private static final String WHERE_DISPLAY_NAME_AND_ACCOUNT = MailboxColumns.DISPLAY_NAME +
111ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        "=? and " + MailboxColumns.ACCOUNT_KEY + "=?";
112ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1136c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
1146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Content selection to find children by parent's server id. Since server ids aren't unique
1156c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * across accounts, this must also use account id.
1166c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
117ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    private static final String WHERE_PARENT_SERVER_ID_AND_ACCOUNT =
118ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        MailboxColumns.PARENT_SERVER_ID +"=? and " + MailboxColumns.ACCOUNT_KEY + "=?";
119ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Projection used when fetching a Mailbox's ids. */
121ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    private static final String[] MAILBOX_ID_COLUMNS_PROJECTION =
122e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank        new String[] {MailboxColumns.ID, MailboxColumns.SERVER_ID, MailboxColumns.PARENT_SERVER_ID};
123e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank    private static final int MAILBOX_ID_COLUMNS_ID = 0;
124e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank    private static final int MAILBOX_ID_COLUMNS_SERVER_ID = 1;
125e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank    private static final int MAILBOX_ID_COLUMNS_PARENT_SERVER_ID = 2;
126ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1276c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Projection used for changed parents during parent/child fixup. */
1286c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private static final String[] FIXUP_PARENT_PROJECTION =
129ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            { MailboxColumns.ID, MailboxColumns.FLAGS };
1306c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private static final int FIXUP_PARENT_ID_COLUMN = 0;
131ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler    private static final int FIXUP_PARENT_FLAGS_COLUMN = 1;
1326c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
1336c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Projection used for changed children during parent/child fixup. */
1346c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private static final String[] FIXUP_CHILD_PROJECTION =
135ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            { MailboxColumns.ID };
1366c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private static final int FIXUP_CHILD_ID_COLUMN = 0;
1376c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
1386c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Flags that are set or cleared when a mailbox's child status changes. */
1396c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private static final int HAS_CHILDREN_FLAGS =
1406c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            Mailbox.FLAG_HAS_CHILDREN | Mailbox.FLAG_CHILDREN_VISIBLE;
1416c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
1426c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Mailbox.NO_MAILBOX, as a string (convenience since this is used in several places). */
1436c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private static final String NO_MAILBOX_STRING = Long.toString(Mailbox.NO_MAILBOX);
1446c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
145f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
146f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    long mAccountId;
147f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
148f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    String mAccountIdAsString;
1499f551ed0c2794a4ebb775df0dc5f714cf07f29b7Marc Blank
1507b6a75def9f415a75b4ff4b640216c95a7e799a5Martin Hibdon    private final String[] mBindArguments = new String[2];
1516c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
1526c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** List of pending operations to send as a batch to the content provider. */
1537b6a75def9f415a75b4ff4b640216c95a7e799a5Martin Hibdon    private final ArrayList<ContentProviderOperation> mOperations =
1546c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            new ArrayList<ContentProviderOperation>();
1556c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Indicates whether this sync is an initial FolderSync. */
156e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank    private boolean mInitialSync;
1576c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** List of folder server ids whose children changed with this sync. */
158ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler    private final Set<String> mParentFixupsNeeded = new LinkedHashSet<String>();
1596c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /** Indicates whether the sync response provided a different sync key than we had. */
1606c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private boolean mSyncKeyChanged = false;
1616c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
16277186bb1a174432ef272584374942d8b9228e39cMarc Blank    // If true, we only care about status (this is true when validating an account) and ignore
16377186bb1a174432ef272584374942d8b9228e39cMarc Blank    // other data
16477186bb1a174432ef272584374942d8b9228e39cMarc Blank    private final boolean mStatusOnly;
165e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank
1665586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu    /** Map of folder types that have been created during this sync. */
1675586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu    private final SparseBooleanArray mCreatedFolderTypes =
1685586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            new SparseBooleanArray(Mailbox.REQUIRED_FOLDER_TYPES.length);
169fc8809b47ba408d74ca49c08d9b3299d377ef1a0Yu Ping Hu
170e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank    private static final ContentValues UNINITIALIZED_PARENT_KEY = new ContentValues();
171e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank
172ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler    static {
173e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank        UNINITIALIZED_PARENT_KEY.put(MailboxColumns.PARENT_KEY, Mailbox.PARENT_KEY_UNINITIALIZED);
174e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank    }
175ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
176c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu    public FolderSyncParser(final Context context, final ContentResolver resolver,
177bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu            final InputStream in, final Account account, final boolean statusOnly)
178bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                    throws IOException {
179bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu        super(context, resolver, in, null, account);
180c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu        mAccountId = mAccount.mId;
181c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu        mAccountIdAsString = Long.toString(mAccountId);
182bc278f1e81ef1d44c28093e830ebe84faa960843Yu Ping Hu        mStatusOnly = statusOnly;
183c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu    }
184c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu
18548af7392c82262d17700e3fbdccf3a582809d449Marc Blank    public FolderSyncParser(InputStream in, AbstractSyncAdapter adapter) throws IOException {
18677186bb1a174432ef272584374942d8b9228e39cMarc Blank        this(in, adapter, false);
18777186bb1a174432ef272584374942d8b9228e39cMarc Blank    }
18877186bb1a174432ef272584374942d8b9228e39cMarc Blank
18977186bb1a174432ef272584374942d8b9228e39cMarc Blank    public FolderSyncParser(InputStream in, AbstractSyncAdapter adapter, boolean statusOnly)
19077186bb1a174432ef272584374942d8b9228e39cMarc Blank            throws IOException {
19148af7392c82262d17700e3fbdccf3a582809d449Marc Blank        super(in, adapter);
192ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mAccountId = mAccount.mId;
193ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mAccountIdAsString = Long.toString(mAccountId);
19477186bb1a174432ef272584374942d8b9228e39cMarc Blank        mStatusOnly = statusOnly;
195ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
196ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1977c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank    @Override
19877186bb1a174432ef272584374942d8b9228e39cMarc Blank    public boolean parse() throws IOException, CommandStatusException {
199ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        int status;
200ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        boolean res = false;
2011b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        boolean resetFolders = false;
2026c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        mInitialSync = (mAccount.mSyncKey == null) || "0".equals(mAccount.mSyncKey);
203e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank        if (mInitialSync) {
2046c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            // We're resyncing all folders for this account, so nuke any existing ones.
2056c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_ACCOUNT_KEY,
2066c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    new String[] {mAccountIdAsString});
207f1284e663702435fda3bb96bee5a75fbdc858e8aMarc Blank        }
2087c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        if (nextTag(START_DOCUMENT) != Tags.FOLDER_FOLDER_SYNC)
2091431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank            throw new EasParserException();
210ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
2117c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            if (tag == Tags.FOLDER_STATUS) {
212ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                status = getValueInt();
213e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                // Do a sanity check on the account here; if we have any duplicated folders, we'll
214e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                // act as though we have a bad folder sync key (wipe/reload mailboxes)
215e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                // Note: The ContentValues isn't used, but no point creating a new one
216e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                int dupes = 0;
217e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                if (mAccountId > 0) {
218e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                    dupes = mContentResolver.update(
219e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                            ContentUris.withAppendedId(EmailContent.ACCOUNT_CHECK_URI, mAccountId),
220e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                            UNINITIALIZED_PARENT_KEY, null, null);
221e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
222e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                if (dupes > 0) {
2236c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    LogUtils.w(TAG, "Duplicate mailboxes found for account %d: %d", mAccountId,
2246c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            dupes);
225e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                    status = Eas.FOLDER_STATUS_INVALID_KEY;
226e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
227ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                if (status != Eas.FOLDER_STATUS_OK) {
2286aa35f65d70f476367b3ee951b4470662a296fa1Marc Blank                    // If the account hasn't been saved, this is a validation attempt, so we don't
2296aa35f65d70f476367b3ee951b4470662a296fa1Marc Blank                    // try reloading the folder list...
23077186bb1a174432ef272584374942d8b9228e39cMarc Blank                    if (CommandStatus.isDeniedAccess(status) ||
2316aa35f65d70f476367b3ee951b4470662a296fa1Marc Blank                            CommandStatus.isNeedsProvisioning(status) ||
2326aa35f65d70f476367b3ee951b4470662a296fa1Marc Blank                            (mAccount.mId == Account.NOT_SAVED)) {
2339cdb8c8219349c654101ee5fc71e2986a6cebc3bAlon Albert                        LogUtils.e(LogUtils.TAG, "FolderSync: Unknown status: " + status);
23477186bb1a174432ef272584374942d8b9228e39cMarc Blank                        throw new CommandStatusException(status);
23577186bb1a174432ef272584374942d8b9228e39cMarc Blank                    // Note that we need to catch both old-style (Eas.FOLDER_STATUS_INVALID_KEY)
23677186bb1a174432ef272584374942d8b9228e39cMarc Blank                    // and EAS 14 style command status
23777186bb1a174432ef272584374942d8b9228e39cMarc Blank                    } else if (status == Eas.FOLDER_STATUS_INVALID_KEY ||
23877186bb1a174432ef272584374942d8b9228e39cMarc Blank                            CommandStatus.isBadSyncKey(status)) {
23928f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                        wipe();
240c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu                        // Reconstruct _main
241ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        res = true;
2421b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank                        resetFolders = true;
243ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    } else {
244ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        // Other errors are at the server, so let's throw an error that will
245ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        // cause this sync to be retried at a later time
2461431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank                        throw new EasParserException("Folder status error");
247ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    }
248ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
2497c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_SYNC_KEY) {
2506c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                final String newKey = getValue();
2516c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                if (newKey != null && !resetFolders) {
2526c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    mSyncKeyChanged = !newKey.equals(mAccount.mSyncKey);
253e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                    mAccount.mSyncKey = newKey;
254e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
2557c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_CHANGES) {
25677186bb1a174432ef272584374942d8b9228e39cMarc Blank                if (mStatusOnly) return res;
2576c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                changesParser();
258ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            } else
259ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                skipTag();
260ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
261c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu        if (!mStatusOnly) {
262c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu            commit();
2631b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        }
264ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return res;
265ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
266ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
2676c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
2686c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Get a cursor with folder ids for a specific folder.
2696c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param serverId The server id for the folder we are interested in.
2706c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @return A cursor for the folder specified by serverId for this account.
2716c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
2726c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private Cursor getServerIdCursor(final String serverId) {
273ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mBindArguments[0] = serverId;
274ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mBindArguments[1] = mAccountIdAsString;
275e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank        return mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_ID_COLUMNS_PROJECTION,
276ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                WHERE_SERVER_ID_AND_ACCOUNT, mBindArguments, null);
277ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
278ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
2796c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
2806c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for a Delete
2816c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * change in the FolderSync response.
2826c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
2836c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
2846c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void deleteParser() throws IOException {
285135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        while (nextTag(Tags.FOLDER_DELETE) != END) {
286ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            switch (tag) {
2877c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_SERVER_ID:
288bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                    final String serverId = getValue();
289ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    // Find the mailbox in this account with the given serverId
290bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                    final Cursor c = getServerIdCursor(serverId);
291ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    try {
292ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        if (c.moveToFirst()) {
2933eef378426c7c88608f53f5a268baed40259ccf6Alon Albert                            LogUtils.d(TAG, "Deleting %s", serverId);
294bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                            final long mailboxId = c.getLong(MAILBOX_ID_COLUMNS_ID);
2956c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            mOperations.add(ContentProviderOperation.newDelete(
296ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                                    ContentUris.withAppendedId(Mailbox.CONTENT_URI,
297bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                                            mailboxId)).build());
298e951b589c5134a1154ec3743d79236dee54a6519Marc Blank                            AttachmentUtilities.deleteAllMailboxAttachmentFiles(mContext,
299bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                                    mAccountId, mailboxId);
3006c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            final String parentId =
3016c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                    c.getString(MAILBOX_ID_COLUMNS_PARENT_SERVER_ID);
3026c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            if (!TextUtils.isEmpty(parentId)) {
3036c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                mParentFixupsNeeded.add(parentId);
304e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                            }
305ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        }
306ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    } finally {
307ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        c.close();
308ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    }
309ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
310ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                default:
311ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    skipTag();
312ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
313ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
314ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
315ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
316f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static class SyncOptions {
317f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        private final int mInterval;
318f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        private final int mLookback;
319f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
320f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        private SyncOptions(int interval, int lookback) {
321f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mInterval = interval;
322f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mLookback = lookback;
323f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
324f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    }
325f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
326f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final String MAILBOX_STATE_SELECTION =
327f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        MailboxColumns.ACCOUNT_KEY + "=? AND (" + MailboxColumns.SYNC_INTERVAL + "!=" +
328f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            Account.CHECK_INTERVAL_NEVER + " OR " + Mailbox.SYNC_LOOKBACK + "!=" +
32935b892c7570b06e72c97c0915d0e41abc83ed6b0Yu Ping Hu            SyncWindow.SYNC_WINDOW_ACCOUNT + ")";
330f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
331f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final String[] MAILBOX_STATE_PROJECTION = new String[] {
332f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        MailboxColumns.SERVER_ID, MailboxColumns.SYNC_INTERVAL, MailboxColumns.SYNC_LOOKBACK};
333f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final int MAILBOX_STATE_SERVER_ID = 0;
334f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final int MAILBOX_STATE_INTERVAL = 1;
335f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final int MAILBOX_STATE_LOOKBACK = 2;
336f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
337f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    final HashMap<String, SyncOptions> mSyncOptionsMap = new HashMap<String, SyncOptions>();
338f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
339f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    /**
340f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     * For every mailbox in this account that has a non-default interval or lookback, save those
341f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     * values.
342f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     */
343f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
344f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    void saveMailboxSyncOptions() {
345f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        // Shouldn't be necessary, but...
346f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        mSyncOptionsMap.clear();
347f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_STATE_PROJECTION,
348f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                MAILBOX_STATE_SELECTION, new String[] {mAccountIdAsString}, null);
349f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        if (c != null) {
350f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            try {
351f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                while (c.moveToNext()) {
352f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                    mSyncOptionsMap.put(c.getString(MAILBOX_STATE_SERVER_ID),
353f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                            new SyncOptions(c.getInt(MAILBOX_STATE_INTERVAL),
354f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                                    c.getInt(MAILBOX_STATE_LOOKBACK)));
355f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                }
356f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            } finally {
357f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                c.close();
358f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            }
359f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
360f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    }
361f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
362f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    /**
363f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     * For every set of saved mailbox sync options, try to find and restore those values
364f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     */
365f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
366f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    void restoreMailboxSyncOptions() {
367f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        try {
368f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            ContentValues cv = new ContentValues();
369f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mBindArguments[1] = mAccountIdAsString;
370f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            for (String serverId: mSyncOptionsMap.keySet()) {
371f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                SyncOptions options = mSyncOptionsMap.get(serverId);
372f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                cv.put(MailboxColumns.SYNC_INTERVAL, options.mInterval);
373f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                cv.put(MailboxColumns.SYNC_LOOKBACK, options.mLookback);
374f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                mBindArguments[0] = serverId;
375f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                // If we match account and server id, set the sync options
376f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                mContentResolver.update(Mailbox.CONTENT_URI, cv, WHERE_SERVER_ID_AND_ACCOUNT,
377f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                        mBindArguments);
378f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            }
379f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        } finally {
380f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mSyncOptionsMap.clear();
381f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
382f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    }
383f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
3846c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
3856c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add a {@link ContentProviderOperation} to {@link #mOperations} to add a mailbox.
3866c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param name The new mailbox's name.
3876c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param serverId The new mailbox's server id.
3886c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param parentServerId The server id of the new mailbox's parent ("0" if none).
3895586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * @param mailboxType The mailbox's type, which is one of the values defined in {@link Mailbox}.
3905586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * @param fromServer Whether this mailbox was synced from server (as opposed to local-only).
3916c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
3926c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
3936c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void addMailboxOp(final String name, final String serverId,
3945586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            final String parentServerId, final int mailboxType, final boolean fromServer)
3955586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            throws IOException {
3965586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        final ContentValues cv = new ContentValues(10);
3976c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.DISPLAY_NAME, name);
3985586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        if (fromServer) {
3995586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.SERVER_ID, serverId);
4005586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            final String parentId;
4015586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            if (parentServerId.equals("0")) {
4025586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                parentId = NO_MAILBOX_STRING;
4035586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                cv.put(MailboxColumns.PARENT_KEY, Mailbox.NO_MAILBOX);
4045586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            } else {
4055586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                parentId = parentServerId;
4065586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                mParentFixupsNeeded.add(parentId);
4075586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            }
4085586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.PARENT_SERVER_ID, parentId);
4096c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        } else {
4105586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.SERVER_ID, "");
4115586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.PARENT_KEY, Mailbox.NO_MAILBOX);
4125586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.PARENT_SERVER_ID, NO_MAILBOX_STRING);
4135586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.TOTAL_COUNT, -1);
4146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
4156c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.ACCOUNT_KEY, mAccountId);
4166c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.TYPE, mailboxType);
4175586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu
4185586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        final boolean shouldSync = fromServer && Mailbox.getDefaultSyncStateForType(mailboxType);
419456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu        cv.put(MailboxColumns.SYNC_INTERVAL, shouldSync ? 1 : 0);
4206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4216c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Set basic flags
4226c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        int flags = 0;
4236c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mailboxType <= Mailbox.TYPE_NOT_EMAIL) {
4246c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            flags |= Mailbox.FLAG_HOLDS_MAIL + Mailbox.FLAG_SUPPORTS_SETTINGS;
4256c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
4266c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Outbox, Drafts, and Sent don't allow mail to be moved to them
4276c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mailboxType == Mailbox.TYPE_MAIL || mailboxType == Mailbox.TYPE_TRASH ||
4286c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                mailboxType == Mailbox.TYPE_JUNK || mailboxType == Mailbox.TYPE_INBOX) {
4296c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            flags |= Mailbox.FLAG_ACCEPTS_MOVED_MAIL;
4306c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
4316c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.FLAGS, flags);
4326c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4336c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Make boxes like Contacts and Calendar invisible in the folder list
4346c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.FLAG_VISIBLE, (mailboxType < Mailbox.TYPE_NOT_EMAIL));
4356c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4366c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        mOperations.add(
4376c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                ContentProviderOperation.newInsert(Mailbox.CONTENT_URI).withValues(cv).build());
4385586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu
4395586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        mCreatedFolderTypes.put(mailboxType, true);
4406c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    }
4416c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4426c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
4436c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for an Add
4446c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * change in the FolderSync response.
4456c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
4466c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
4476c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void addParser() throws IOException {
448ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String name = null;
449ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String serverId = null;
450ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String parentId = null;
451ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        int type = 0;
452ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
4537c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        while (nextTag(Tags.FOLDER_ADD) != END) {
454ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            switch (tag) {
4557c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_DISPLAY_NAME: {
456ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    name = getValue();
457ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
458ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
4597c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_TYPE: {
460ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    type = getValueInt();
461ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
462ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
4637c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_PARENT_ID: {
464ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    parentId = getValue();
465ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
466ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
4677c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_SERVER_ID: {
468ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    serverId = getValue();
469ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
470ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
471ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                default:
472ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    skipTag();
473ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
474ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
4755586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        if (name != null && serverId != null && parentId != null) {
4765586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            final int mailboxType = MAILBOX_TYPE_MAP.get(type, Mailbox.TYPE_NONE);
4775586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            if (mailboxType != Mailbox.TYPE_NONE) {
478774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert                if (type == Eas.MAILBOX_TYPE_CALENDAR && !name.contains(mAccount.mEmailAddress)) {
479774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert                    name = mAccount.mEmailAddress;
480774b28589925b8610e436d1fb52b2086b2d3ac7dAlon Albert                }
4815586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                addMailboxOp(name, serverId, parentId, mailboxType, true);
4825586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            }
483ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
484d3eab5e6ffa39c931c2ca31e6670b7743723e034Marc Blank    }
485ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
4866c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
4876c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for an Update
4886c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * change in the FolderSync response.
4896c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
4906c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
4916c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void updateParser() throws IOException {
492135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        String serverId = null;
493135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        String displayName = null;
494135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        String parentId = null;
495135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        while (nextTag(Tags.FOLDER_UPDATE) != END) {
496135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            switch (tag) {
497135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                case Tags.FOLDER_SERVER_ID:
498135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    serverId = getValue();
499135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
500135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                case Tags.FOLDER_DISPLAY_NAME:
501135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    displayName = getValue();
502135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
503135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                case Tags.FOLDER_PARENT_ID:
504135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    parentId = getValue();
505135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
506135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                default:
507135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    skipTag();
508135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
509135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            }
510135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        }
511135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        // We'll make a change if one of parentId or displayName are specified
512135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        // serverId is required, but let's be careful just the same
513135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        if (serverId != null && (displayName != null || parentId != null)) {
5146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final Cursor c = getServerIdCursor(serverId);
515135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            try {
516135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                // If we find the mailbox (using serverId), make the change
517135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                if (c.moveToFirst()) {
5183eef378426c7c88608f53f5a268baed40259ccf6Alon Albert                    LogUtils.d(TAG, "Updating %s", serverId);
5196c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    final ContentValues cv = new ContentValues();
5206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // Store the new parent key.
5216c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    cv.put(Mailbox.PARENT_SERVER_ID, parentId);
522e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    // Fix up old and new parents, as needed
523e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    if (!TextUtils.isEmpty(parentId)) {
524e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                        mParentFixupsNeeded.add(parentId);
5256c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    } else {
5266c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        cv.put(Mailbox.PARENT_KEY, Mailbox.NO_MAILBOX);
527e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    }
5286c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    final String oldParentId = c.getString(MAILBOX_ID_COLUMNS_PARENT_SERVER_ID);
529e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    if (!TextUtils.isEmpty(oldParentId)) {
530e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                        mParentFixupsNeeded.add(oldParentId);
531e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    }
532e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    // Set display name if we've got one
533135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    if (displayName != null) {
534135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                        cv.put(Mailbox.DISPLAY_NAME, displayName);
535135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    }
5366c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    mOperations.add(ContentProviderOperation.newUpdate(
537135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                            ContentUris.withAppendedId(Mailbox.CONTENT_URI,
538e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                                    c.getLong(MAILBOX_ID_COLUMNS_ID))).withValues(cv).build());
539135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                }
540135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            } finally {
541135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                c.close();
542135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            }
543135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        }
544135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank    }
545135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank
5466c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
5476c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Handle the Changes element of the FolderSync response. This is the container for Add, Delete,
5486c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * and Update elements.
5496c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
5506c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
5516c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void changesParser() throws IOException {
5527c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        while (nextTag(Tags.FOLDER_CHANGES) != END) {
5537c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            if (tag == Tags.FOLDER_ADD) {
5546c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                addParser();
5557c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_DELETE) {
5566c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                deleteParser();
557135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            } else if (tag == Tags.FOLDER_UPDATE) {
5586c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                updateParser();
5597c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_COUNT) {
5606c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                // TODO: Maybe we can make use of this count somehow.
561ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                getValueInt();
562ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            } else
563ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                skipTag();
564ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
5656c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    }
566ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
5676c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
5686c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Commit the contents of {@link #mOperations} to the content provider.
5696c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
5706c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
5716c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void flushOperations() throws IOException {
5726c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mOperations.isEmpty()) {
5736c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            return;
57492c9d37d883eaafdbe7d9428a5de017eee9f3d2bMarc Blank        }
575ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        int transactionSize = mOperations.size();
576ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        final ArrayList<ContentProviderOperation> subOps =
577ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                new ArrayList<ContentProviderOperation>(transactionSize);
578ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        while (!mOperations.isEmpty()) {
579ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            subOps.clear();
580ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            subOps.addAll(mOperations.subList(0, transactionSize));
581ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            // Try to apply the ops. If the transaction is too large, split it in half and try again
582ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            // If some other error happens then throw an IOException up the stack.
583ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            try {
584ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                mContentResolver.applyBatch(EmailContent.AUTHORITY, subOps);
585ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                mOperations.removeAll(subOps);
586ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            } catch (final TransactionTooLargeException e) {
587ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                // If the transaction is too large, try splitting it.
588ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                if (transactionSize == 1) {
589ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                    LogUtils.e(TAG, "Single operation transaction too large");
590ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                    throw new IOException("Single operation transaction too large");
591ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                }
592ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                LogUtils.d(TAG, "Transaction operation count %d too large, halving...",
593ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                        transactionSize);
594ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                transactionSize = transactionSize / 2;
595ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                if (transactionSize < 1) {
596ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                    transactionSize = 1;
597ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                }
598ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            } catch (final RemoteException e) {
599ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                LogUtils.e(TAG, "RemoteException in commit");
600ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                throw new IOException("RemoteException in commit");
601ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            } catch (final OperationApplicationException e) {
602ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                LogUtils.e(TAG, "OperationApplicationException in commit");
603ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                throw new IOException("OperationApplicationException in commit");
604ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            }
6056c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
6066c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        mOperations.clear();
6076c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    }
6086c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6096c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
6106c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Fix folder data for any folders whose parent or children changed during this sync.
6116c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Unfortunately this cannot be done in the same pass as the actual sync: newly synced folders
6126c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * lack ids until they're committed to the content provider, so we can't set the parentKey
6136c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * for their children.
6146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * During parsing, we only track the parents who have changed. We need to do a query for
6156c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * children anyway (to determine whether a parent still has any) so it's simpler to not bother
6166c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * tracking which folders have had their parents changed.
6176c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * TODO: Figure out if we can avoid the two-pass.
6186c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
6196c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
6206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void doParentFixups() throws IOException {
6216c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mParentFixupsNeeded.isEmpty()) {
6226c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            return;
6236c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
6246c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6256c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // These objects will be used in every loop iteration, so create them here for efficiency
6266c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // and just reset the values inside the loop as necessary.
6276c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        final String[] bindArguments = new String[2];
6286c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        bindArguments[1] = mAccountIdAsString;
629ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        final ContentValues cv = new ContentValues(1);
6306c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6316c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        for (final String parentServerId : mParentFixupsNeeded) {
6326c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            // Get info about this parent.
6336c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            bindArguments[0] = parentServerId;
6346c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final Cursor parentCursor = mContentResolver.query(Mailbox.CONTENT_URI,
6356c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    FIXUP_PARENT_PROJECTION, WHERE_SERVER_ID_AND_ACCOUNT, bindArguments, null);
6366c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (parentCursor == null) {
6376c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                // TODO: Error handling.
6386c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                continue;
6396c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            }
6406c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final long parentId;
6416c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final int parentFlags;
6426c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            try {
6436c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                if (parentCursor.moveToFirst()) {
6446c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    parentId = parentCursor.getLong(FIXUP_PARENT_ID_COLUMN);
6456c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    parentFlags = parentCursor.getInt(FIXUP_PARENT_FLAGS_COLUMN);
6466c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                } else {
6476c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // TODO: Error handling.
64892c9d37d883eaafdbe7d9428a5de017eee9f3d2bMarc Blank                    continue;
649e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
6506c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            } finally {
6516c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                parentCursor.close();
652e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank            }
65392c9d37d883eaafdbe7d9428a5de017eee9f3d2bMarc Blank
6546c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            // Fix any children for this parent.
6556c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final Cursor childCursor = mContentResolver.query(Mailbox.CONTENT_URI,
6566c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    FIXUP_CHILD_PROJECTION, WHERE_PARENT_SERVER_ID_AND_ACCOUNT, bindArguments,
6576c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    null);
6586c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            boolean hasChildren = false;
6596c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (childCursor != null) {
660e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                try {
6616c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // Clear the results of the last iteration.
6626c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    cv.clear();
6636c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // All children in this loop share the same parentId.
6646c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    cv.put(MailboxColumns.PARENT_KEY, parentId);
6656c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    while (childCursor.moveToNext()) {
6666c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        final long childId = childCursor.getLong(FIXUP_CHILD_ID_COLUMN);
6676c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        mOperations.add(ContentProviderOperation.newUpdate(
6686c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                ContentUris.withAppendedId(Mailbox.CONTENT_URI, childId)).
6696c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                withValues(cv).build());
6706c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        hasChildren = true;
671e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                    }
672e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                } finally {
6736c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    childCursor.close();
674e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
675e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank            }
676e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank
6776c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            // Fix the parent's flags based on whether it now has children.
6786c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final int newFlags;
6796c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6806c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (hasChildren) {
6816c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                newFlags = parentFlags | HAS_CHILDREN_FLAGS;
6826c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            } else {
6836c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                newFlags = parentFlags & ~HAS_CHILDREN_FLAGS;
6846c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            }
6856c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (newFlags != parentFlags) {
6866c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                cv.clear();
6876c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                cv.put(MailboxColumns.FLAGS, newFlags);
6886c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                mOperations.add(ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
6896c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        Mailbox.CONTENT_URI, parentId)).withValues(cv).build());
6906c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            }
691ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            flushOperations();
6929f551ed0c2794a4ebb775df0dc5f714cf07f29b7Marc Blank        }
693ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
694ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
6950a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    @Override
6960a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void commandsParser() throws IOException {
6970a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    }
6980a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank
69948af7392c82262d17700e3fbdccf3a582809d449Marc Blank    @Override
70048af7392c82262d17700e3fbdccf3a582809d449Marc Blank    public void commit() throws IOException {
7016c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Set the account sync key.
7026c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mSyncKeyChanged) {
7036c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final ContentValues cv = new ContentValues(1);
7046c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
7056c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            mOperations.add(
7066c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    ContentProviderOperation.newUpdate(mAccount.getUri()).withValues(cv).build());
7076c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
7086c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
7095586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        // If this is the initial sync, make sure we have all the required folder types.
7105586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        if (mInitialSync) {
7115586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            for (final int requiredType : Mailbox.REQUIRED_FOLDER_TYPES) {
7125586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                if (!mCreatedFolderTypes.get(requiredType)) {
7135586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                    addMailboxOp(Mailbox.getSystemMailboxName(mContext, requiredType),
7145586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                            null, null, requiredType, false);
7155586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                }
7165586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            }
7176c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
7186c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
7196c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Send all operations so far.
7206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        flushOperations();
7216c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
7226c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Now that new mailboxes are committed, let's do parent fixups.
7236c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        doParentFixups();
7246c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
725f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        // Look for sync issues and its children and delete them
726f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        // I'm not aware of any other way to deal with this properly
727f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        mBindArguments[0] = "Sync Issues";
728f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        mBindArguments[1] = mAccountIdAsString;
729f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        Cursor c = mContentResolver.query(Mailbox.CONTENT_URI,
730f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                MAILBOX_ID_COLUMNS_PROJECTION, WHERE_DISPLAY_NAME_AND_ACCOUNT,
731f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                mBindArguments, null);
732f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        String parentServerId = null;
733f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        long id = 0;
734f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        try {
735f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            if (c.moveToFirst()) {
736e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                id = c.getLong(MAILBOX_ID_COLUMNS_ID);
737e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                parentServerId = c.getString(MAILBOX_ID_COLUMNS_SERVER_ID);
738f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            }
739f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        } finally {
740f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            c.close();
741f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        }
742f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        if (parentServerId != null) {
743f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            mContentResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id),
744f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                    null, null);
745f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            mBindArguments[0] = parentServerId;
746f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
747f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                    mBindArguments);
748f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        }
749f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
750f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        // If we have saved options, restore them now
751f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        if (mInitialSync) {
752f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            restoreMailboxSyncOptions();
753f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
75448af7392c82262d17700e3fbdccf3a582809d449Marc Blank    }
75548af7392c82262d17700e3fbdccf3a582809d449Marc Blank
7560a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    @Override
75748af7392c82262d17700e3fbdccf3a582809d449Marc Blank    public void responsesParser() throws IOException {
75848af7392c82262d17700e3fbdccf3a582809d449Marc Blank    }
75948af7392c82262d17700e3fbdccf3a582809d449Marc Blank
76028f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon    @Override
76128f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon    protected void wipe() {
76228f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        EasCalendarSyncHandler.wipeAccountFromContentProvider(mContext,
76328f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                mAccount.mEmailAddress);
76428f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        EasContactsSyncHandler.wipeAccountFromContentProvider(mContext,
76528f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                mAccount.mEmailAddress);
76628f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon
76728f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        // Save away any mailbox sync information that is NOT default
76828f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        saveMailboxSyncOptions();
76928f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        // And only then, delete mailboxes
77028f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_ACCOUNT_KEY,
77128f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                new String[] {mAccountIdAsString});
77228f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        // Reset the sync key and save.
77328f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        mAccount.mSyncKey = "0";
77428f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        ContentValues cv = new ContentValues();
77528f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
77628f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        mContentResolver.update(ContentUris.withAppendedId(Account.CONTENT_URI,
77728f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                mAccount.mId), cv, null, null);
77828f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon    }
779ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank}
780