FolderSyncParser.java revision ab4fe820cb8e1fa3781485ab2e44ec458ce0669e
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);
765586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(1,  Mailbox.TYPE_MAIL);       // User-created folder (generic)
775586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(2,  Mailbox.TYPE_INBOX);      // Default Inbox folder
785586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(3,  Mailbox.TYPE_DRAFTS);     // Default Drafts folder
795586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(4,  Mailbox.TYPE_TRASH);      // Default Deleted Items folder
805586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(5,  Mailbox.TYPE_SENT);       // Default Sent Items folder
815586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(6,  Mailbox.TYPE_OUTBOX);     // Default Outbox folder
825586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(7,  Mailbox.TYPE_TASKS);      // Default Tasks folder
835586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(8,  Mailbox.TYPE_CALENDAR);   // Default Calendar folder
845586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(9,  Mailbox.TYPE_CONTACTS);   // Default Contacts folder
855586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(10, Mailbox.TYPE_NONE);       // Default Notes folder
865586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(11, Mailbox.TYPE_NONE);       // Default Journal folder
875586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(12, Mailbox.TYPE_MAIL);       // User-created Mail folder
885586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(13, Mailbox.TYPE_CALENDAR);   // User-created Calendar folder
895586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        MAILBOX_TYPE_MAP.put(14, Mailbox.TYPE_CONTACTS);   // User-created Contacts folder
905586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(15, Mailbox.TYPE_TASKS);      // User-created Tasks folder
915586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(16, Mailbox.TYPE_NONE);       // User-created Journal folder
925586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(17, Mailbox.TYPE_NONE);       // User-created Notes folder
935586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(18, Mailbox.TYPE_NONE);       // Unknown folder type
945586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        //MAILBOX_TYPE_MAP.put(19, Mailbox.TYPE_NONE);       // Recipient information cache
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)) {
23377186bb1a174432ef272584374942d8b9228e39cMarc Blank                        throw new CommandStatusException(status);
23477186bb1a174432ef272584374942d8b9228e39cMarc Blank                    // Note that we need to catch both old-style (Eas.FOLDER_STATUS_INVALID_KEY)
23577186bb1a174432ef272584374942d8b9228e39cMarc Blank                    // and EAS 14 style command status
23677186bb1a174432ef272584374942d8b9228e39cMarc Blank                    } else if (status == Eas.FOLDER_STATUS_INVALID_KEY ||
23777186bb1a174432ef272584374942d8b9228e39cMarc Blank                            CommandStatus.isBadSyncKey(status)) {
23828f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                        wipe();
239c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu                        // Reconstruct _main
240ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        res = true;
2411b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank                        resetFolders = true;
242ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    } else {
243ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        // Other errors are at the server, so let's throw an error that will
244ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        // cause this sync to be retried at a later time
2451431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank                        throw new EasParserException("Folder status error");
246ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    }
247ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
2487c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_SYNC_KEY) {
2496c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                final String newKey = getValue();
2506c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                if (newKey != null && !resetFolders) {
2516c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    mSyncKeyChanged = !newKey.equals(mAccount.mSyncKey);
252e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                    mAccount.mSyncKey = newKey;
253e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
2547c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_CHANGES) {
25577186bb1a174432ef272584374942d8b9228e39cMarc Blank                if (mStatusOnly) return res;
2566c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                changesParser();
257ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            } else
258ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                skipTag();
259ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
260c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu        if (!mStatusOnly) {
261c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu            commit();
2621b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        }
263ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return res;
264ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
265ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
2666c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
2676c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Get a cursor with folder ids for a specific folder.
2686c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param serverId The server id for the folder we are interested in.
2696c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @return A cursor for the folder specified by serverId for this account.
2706c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
2716c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private Cursor getServerIdCursor(final String serverId) {
272ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mBindArguments[0] = serverId;
273ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mBindArguments[1] = mAccountIdAsString;
274e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank        return mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_ID_COLUMNS_PROJECTION,
275ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                WHERE_SERVER_ID_AND_ACCOUNT, mBindArguments, null);
276ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
277ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
2786c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
2796c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for a Delete
2806c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * change in the FolderSync response.
2816c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
2826c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
2836c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void deleteParser() throws IOException {
284135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        while (nextTag(Tags.FOLDER_DELETE) != END) {
285ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            switch (tag) {
2867c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_SERVER_ID:
287bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                    final String serverId = getValue();
288ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    // Find the mailbox in this account with the given serverId
289bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                    final Cursor c = getServerIdCursor(serverId);
290ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    try {
291ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        if (c.moveToFirst()) {
2926c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            LogUtils.i(TAG, "Deleting %s", serverId);
293bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                            final long mailboxId = c.getLong(MAILBOX_ID_COLUMNS_ID);
2946c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            mOperations.add(ContentProviderOperation.newDelete(
295ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                                    ContentUris.withAppendedId(Mailbox.CONTENT_URI,
296bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                                            mailboxId)).build());
297e951b589c5134a1154ec3743d79236dee54a6519Marc Blank                            AttachmentUtilities.deleteAllMailboxAttachmentFiles(mContext,
298bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu                                    mAccountId, mailboxId);
2996c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            final String parentId =
3006c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                    c.getString(MAILBOX_ID_COLUMNS_PARENT_SERVER_ID);
3016c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                            if (!TextUtils.isEmpty(parentId)) {
3026c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                mParentFixupsNeeded.add(parentId);
303e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                            }
304ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        }
305ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    } finally {
306ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                        c.close();
307ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    }
308ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
309ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                default:
310ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    skipTag();
311ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
312ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
313ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
314ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
315f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static class SyncOptions {
316f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        private final int mInterval;
317f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        private final int mLookback;
318f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
319f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        private SyncOptions(int interval, int lookback) {
320f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mInterval = interval;
321f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mLookback = lookback;
322f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
323f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    }
324f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
325f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final String MAILBOX_STATE_SELECTION =
326f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        MailboxColumns.ACCOUNT_KEY + "=? AND (" + MailboxColumns.SYNC_INTERVAL + "!=" +
327f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            Account.CHECK_INTERVAL_NEVER + " OR " + Mailbox.SYNC_LOOKBACK + "!=" +
32835b892c7570b06e72c97c0915d0e41abc83ed6b0Yu Ping Hu            SyncWindow.SYNC_WINDOW_ACCOUNT + ")";
329f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
330f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final String[] MAILBOX_STATE_PROJECTION = new String[] {
331f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        MailboxColumns.SERVER_ID, MailboxColumns.SYNC_INTERVAL, MailboxColumns.SYNC_LOOKBACK};
332f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final int MAILBOX_STATE_SERVER_ID = 0;
333f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final int MAILBOX_STATE_INTERVAL = 1;
334f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    private static final int MAILBOX_STATE_LOOKBACK = 2;
335f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
336f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    final HashMap<String, SyncOptions> mSyncOptionsMap = new HashMap<String, SyncOptions>();
337f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
338f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    /**
339f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     * For every mailbox in this account that has a non-default interval or lookback, save those
340f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     * values.
341f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     */
342f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
343f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    void saveMailboxSyncOptions() {
344f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        // Shouldn't be necessary, but...
345f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        mSyncOptionsMap.clear();
346f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_STATE_PROJECTION,
347f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                MAILBOX_STATE_SELECTION, new String[] {mAccountIdAsString}, null);
348f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        if (c != null) {
349f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            try {
350f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                while (c.moveToNext()) {
351f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                    mSyncOptionsMap.put(c.getString(MAILBOX_STATE_SERVER_ID),
352f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                            new SyncOptions(c.getInt(MAILBOX_STATE_INTERVAL),
353f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                                    c.getInt(MAILBOX_STATE_LOOKBACK)));
354f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                }
355f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            } finally {
356f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                c.close();
357f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            }
358f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
359f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    }
360f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
361f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    /**
362f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     * For every set of saved mailbox sync options, try to find and restore those values
363f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank     */
364f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    @VisibleForTesting
365f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    void restoreMailboxSyncOptions() {
366f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        try {
367f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            ContentValues cv = new ContentValues();
368f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mBindArguments[1] = mAccountIdAsString;
369f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            for (String serverId: mSyncOptionsMap.keySet()) {
370f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                SyncOptions options = mSyncOptionsMap.get(serverId);
371f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                cv.put(MailboxColumns.SYNC_INTERVAL, options.mInterval);
372f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                cv.put(MailboxColumns.SYNC_LOOKBACK, options.mLookback);
373f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                mBindArguments[0] = serverId;
374f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                // If we match account and server id, set the sync options
375f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                mContentResolver.update(Mailbox.CONTENT_URI, cv, WHERE_SERVER_ID_AND_ACCOUNT,
376f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank                        mBindArguments);
377f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            }
378f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        } finally {
379f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            mSyncOptionsMap.clear();
380f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
381f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank    }
382f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
3836c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
3846c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add a {@link ContentProviderOperation} to {@link #mOperations} to add a mailbox.
3856c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param name The new mailbox's name.
3866c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param serverId The new mailbox's server id.
3876c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @param parentServerId The server id of the new mailbox's parent ("0" if none).
3885586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * @param mailboxType The mailbox's type, which is one of the values defined in {@link Mailbox}.
3895586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu     * @param fromServer Whether this mailbox was synced from server (as opposed to local-only).
3906c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
3916c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
3926c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void addMailboxOp(final String name, final String serverId,
3935586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            final String parentServerId, final int mailboxType, final boolean fromServer)
3945586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            throws IOException {
3955586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        final ContentValues cv = new ContentValues(10);
3966c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.DISPLAY_NAME, name);
3975586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        if (fromServer) {
3985586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.SERVER_ID, serverId);
3995586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            final String parentId;
4005586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            if (parentServerId.equals("0")) {
4015586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                parentId = NO_MAILBOX_STRING;
4025586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                cv.put(MailboxColumns.PARENT_KEY, Mailbox.NO_MAILBOX);
4035586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            } else {
4045586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                parentId = parentServerId;
4055586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                mParentFixupsNeeded.add(parentId);
4065586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            }
4075586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.PARENT_SERVER_ID, parentId);
4086c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        } else {
4095586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.SERVER_ID, "");
4105586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.PARENT_KEY, Mailbox.NO_MAILBOX);
4115586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.PARENT_SERVER_ID, NO_MAILBOX_STRING);
4125586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            cv.put(MailboxColumns.TOTAL_COUNT, -1);
4136c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
4146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.ACCOUNT_KEY, mAccountId);
4156c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.TYPE, mailboxType);
4165586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu
4175586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        final boolean shouldSync = fromServer && Mailbox.getDefaultSyncStateForType(mailboxType);
418456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu        cv.put(MailboxColumns.SYNC_INTERVAL, shouldSync ? 1 : 0);
4196c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Set basic flags
4216c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        int flags = 0;
4226c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mailboxType <= Mailbox.TYPE_NOT_EMAIL) {
4236c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            flags |= Mailbox.FLAG_HOLDS_MAIL + Mailbox.FLAG_SUPPORTS_SETTINGS;
4246c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
4256c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Outbox, Drafts, and Sent don't allow mail to be moved to them
4266c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mailboxType == Mailbox.TYPE_MAIL || mailboxType == Mailbox.TYPE_TRASH ||
4276c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                mailboxType == Mailbox.TYPE_JUNK || mailboxType == Mailbox.TYPE_INBOX) {
4286c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            flags |= Mailbox.FLAG_ACCEPTS_MOVED_MAIL;
4296c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
4306c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.FLAGS, flags);
4316c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4326c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Make boxes like Contacts and Calendar invisible in the folder list
4336c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        cv.put(MailboxColumns.FLAG_VISIBLE, (mailboxType < Mailbox.TYPE_NOT_EMAIL));
4346c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4356c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        mOperations.add(
4366c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                ContentProviderOperation.newInsert(Mailbox.CONTENT_URI).withValues(cv).build());
4375586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu
4385586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        mCreatedFolderTypes.put(mailboxType, true);
4396c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    }
4406c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
4416c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
4426c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for an Add
4436c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * change in the FolderSync response.
4446c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
4456c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
4466c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void addParser() throws IOException {
447ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String name = null;
448ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String serverId = null;
449ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String parentId = null;
450ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        int type = 0;
451ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
4527c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        while (nextTag(Tags.FOLDER_ADD) != END) {
453ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            switch (tag) {
4547c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_DISPLAY_NAME: {
455ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    name = getValue();
456ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
457ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
4587c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_TYPE: {
459ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    type = getValueInt();
460ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
461ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
4627c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_PARENT_ID: {
463ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    parentId = getValue();
464ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
465ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
4667c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank                case Tags.FOLDER_SERVER_ID: {
467ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    serverId = getValue();
468ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
469ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
470ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                default:
471ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    skipTag();
472ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
473ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
4745586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        if (name != null && serverId != null && parentId != null) {
4755586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            final int mailboxType = MAILBOX_TYPE_MAP.get(type, Mailbox.TYPE_NONE);
4765586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            if (mailboxType != Mailbox.TYPE_NONE) {
4775586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                addMailboxOp(name, serverId, parentId, mailboxType, true);
4785586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            }
479ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
480d3eab5e6ffa39c931c2ca31e6670b7743723e034Marc Blank    }
481ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
4826c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
4836c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for an Update
4846c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * change in the FolderSync response.
4856c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
4866c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
4876c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void updateParser() throws IOException {
488135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        String serverId = null;
489135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        String displayName = null;
490135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        String parentId = null;
491135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        while (nextTag(Tags.FOLDER_UPDATE) != END) {
492135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            switch (tag) {
493135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                case Tags.FOLDER_SERVER_ID:
494135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    serverId = getValue();
495135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
496135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                case Tags.FOLDER_DISPLAY_NAME:
497135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    displayName = getValue();
498135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
499135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                case Tags.FOLDER_PARENT_ID:
500135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    parentId = getValue();
501135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
502135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                default:
503135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    skipTag();
504135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    break;
505135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            }
506135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        }
507135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        // We'll make a change if one of parentId or displayName are specified
508135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        // serverId is required, but let's be careful just the same
509135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        if (serverId != null && (displayName != null || parentId != null)) {
5106c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final Cursor c = getServerIdCursor(serverId);
511135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            try {
512135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                // If we find the mailbox (using serverId), make the change
513135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                if (c.moveToFirst()) {
5146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    LogUtils.i(TAG, "Updating %s", serverId);
5156c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    final ContentValues cv = new ContentValues();
5166c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // Store the new parent key.
5176c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    cv.put(Mailbox.PARENT_SERVER_ID, parentId);
518e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    // Fix up old and new parents, as needed
519e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    if (!TextUtils.isEmpty(parentId)) {
520e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                        mParentFixupsNeeded.add(parentId);
5216c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    } else {
5226c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        cv.put(Mailbox.PARENT_KEY, Mailbox.NO_MAILBOX);
523e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    }
5246c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    final String oldParentId = c.getString(MAILBOX_ID_COLUMNS_PARENT_SERVER_ID);
525e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    if (!TextUtils.isEmpty(oldParentId)) {
526e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                        mParentFixupsNeeded.add(oldParentId);
527e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    }
528e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                    // Set display name if we've got one
529135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    if (displayName != null) {
530135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                        cv.put(Mailbox.DISPLAY_NAME, displayName);
531135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                    }
5326c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    mOperations.add(ContentProviderOperation.newUpdate(
533135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                            ContentUris.withAppendedId(Mailbox.CONTENT_URI,
534e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                                    c.getLong(MAILBOX_ID_COLUMNS_ID))).withValues(cv).build());
535135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                }
536135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            } finally {
537135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank                c.close();
538135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            }
539135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank        }
540135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank    }
541135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank
5426c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
5436c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Handle the Changes element of the FolderSync response. This is the container for Add, Delete,
5446c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * and Update elements.
5456c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
5466c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
5476c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void changesParser() throws IOException {
5487c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        while (nextTag(Tags.FOLDER_CHANGES) != END) {
5497c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            if (tag == Tags.FOLDER_ADD) {
5506c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                addParser();
5517c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_DELETE) {
5526c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                deleteParser();
553135e3c2c6653131e57525a50e0a3bc6ccf6c7f45Marc Blank            } else if (tag == Tags.FOLDER_UPDATE) {
5546c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                updateParser();
5557c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank            } else if (tag == Tags.FOLDER_COUNT) {
5566c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                // TODO: Maybe we can make use of this count somehow.
557ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                getValueInt();
558ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            } else
559ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                skipTag();
560ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
5616c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    }
562ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
5636c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
5646c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Commit the contents of {@link #mOperations} to the content provider.
5656c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
5666c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
5676c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void flushOperations() throws IOException {
5686c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mOperations.isEmpty()) {
5696c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            return;
57092c9d37d883eaafdbe7d9428a5de017eee9f3d2bMarc Blank        }
571ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        int transactionSize = mOperations.size();
572ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        final ArrayList<ContentProviderOperation> subOps =
573ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                new ArrayList<ContentProviderOperation>(transactionSize);
574ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        while (!mOperations.isEmpty()) {
575ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            subOps.clear();
576ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            subOps.addAll(mOperations.subList(0, transactionSize));
577ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            // Try to apply the ops. If the transaction is too large, split it in half and try again
578ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            // If some other error happens then throw an IOException up the stack.
579ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            try {
580ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                mContentResolver.applyBatch(EmailContent.AUTHORITY, subOps);
581ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                mOperations.removeAll(subOps);
582ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            } catch (final TransactionTooLargeException e) {
583ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                // If the transaction is too large, try splitting it.
584ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                if (transactionSize == 1) {
585ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                    LogUtils.e(TAG, "Single operation transaction too large");
586ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                    throw new IOException("Single operation transaction too large");
587ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                }
588ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                LogUtils.d(TAG, "Transaction operation count %d too large, halving...",
589ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                        transactionSize);
590ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                transactionSize = transactionSize / 2;
591ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                if (transactionSize < 1) {
592ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                    transactionSize = 1;
593ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                }
594ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            } catch (final RemoteException e) {
595ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                LogUtils.e(TAG, "RemoteException in commit");
596ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                throw new IOException("RemoteException in commit");
597ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            } catch (final OperationApplicationException e) {
598ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                LogUtils.e(TAG, "OperationApplicationException in commit");
599ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler                throw new IOException("OperationApplicationException in commit");
600ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            }
6016c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
6026c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        mOperations.clear();
6036c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    }
6046c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6056c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    /**
6066c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Fix folder data for any folders whose parent or children changed during this sync.
6076c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * Unfortunately this cannot be done in the same pass as the actual sync: newly synced folders
6086c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * lack ids until they're committed to the content provider, so we can't set the parentKey
6096c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * for their children.
6106c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * During parsing, we only track the parents who have changed. We need to do a query for
6116c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * children anyway (to determine whether a parent still has any) so it's simpler to not bother
6126c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * tracking which folders have had their parents changed.
6136c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * TODO: Figure out if we can avoid the two-pass.
6146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     * @throws IOException
6156c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu     */
6166c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu    private void doParentFixups() throws IOException {
6176c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mParentFixupsNeeded.isEmpty()) {
6186c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            return;
6196c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
6206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6216c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // These objects will be used in every loop iteration, so create them here for efficiency
6226c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // and just reset the values inside the loop as necessary.
6236c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        final String[] bindArguments = new String[2];
6246c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        bindArguments[1] = mAccountIdAsString;
625ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler        final ContentValues cv = new ContentValues(1);
6266c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6276c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        for (final String parentServerId : mParentFixupsNeeded) {
6286c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            // Get info about this parent.
6296c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            bindArguments[0] = parentServerId;
6306c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final Cursor parentCursor = mContentResolver.query(Mailbox.CONTENT_URI,
6316c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    FIXUP_PARENT_PROJECTION, WHERE_SERVER_ID_AND_ACCOUNT, bindArguments, null);
6326c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (parentCursor == null) {
6336c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                // TODO: Error handling.
6346c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                continue;
6356c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            }
6366c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final long parentId;
6376c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final int parentFlags;
6386c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            try {
6396c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                if (parentCursor.moveToFirst()) {
6406c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    parentId = parentCursor.getLong(FIXUP_PARENT_ID_COLUMN);
6416c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    parentFlags = parentCursor.getInt(FIXUP_PARENT_FLAGS_COLUMN);
6426c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                } else {
6436c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // TODO: Error handling.
64492c9d37d883eaafdbe7d9428a5de017eee9f3d2bMarc Blank                    continue;
645e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
6466c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            } finally {
6476c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                parentCursor.close();
648e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank            }
64992c9d37d883eaafdbe7d9428a5de017eee9f3d2bMarc Blank
6506c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            // Fix any children for this parent.
6516c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final Cursor childCursor = mContentResolver.query(Mailbox.CONTENT_URI,
6526c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    FIXUP_CHILD_PROJECTION, WHERE_PARENT_SERVER_ID_AND_ACCOUNT, bindArguments,
6536c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    null);
6546c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            boolean hasChildren = false;
6556c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (childCursor != null) {
656e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                try {
6576c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // Clear the results of the last iteration.
6586c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    cv.clear();
6596c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    // All children in this loop share the same parentId.
6606c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    cv.put(MailboxColumns.PARENT_KEY, parentId);
6616c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    while (childCursor.moveToNext()) {
6626c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        final long childId = childCursor.getLong(FIXUP_CHILD_ID_COLUMN);
6636c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        mOperations.add(ContentProviderOperation.newUpdate(
6646c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                ContentUris.withAppendedId(Mailbox.CONTENT_URI, childId)).
6656c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                                withValues(cv).build());
6666c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        hasChildren = true;
667e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                    }
668e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                } finally {
6696c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    childCursor.close();
670e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank                }
671e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank            }
672e6c2456aa6c00ef78c6d1d1621511d7ef8507f83Marc Blank
6736c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            // Fix the parent's flags based on whether it now has children.
6746c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final int newFlags;
6756c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
6766c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (hasChildren) {
6776c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                newFlags = parentFlags | HAS_CHILDREN_FLAGS;
6786c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            } else {
6796c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                newFlags = parentFlags & ~HAS_CHILDREN_FLAGS;
6806c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            }
6816c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            if (newFlags != parentFlags) {
6826c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                cv.clear();
6836c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                cv.put(MailboxColumns.FLAGS, newFlags);
6846c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                mOperations.add(ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
6856c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                        Mailbox.CONTENT_URI, parentId)).withValues(cv).build());
6866c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            }
687ab4fe820cb8e1fa3781485ab2e44ec458ce0669eTony Mantler            flushOperations();
6889f551ed0c2794a4ebb775df0dc5f714cf07f29b7Marc Blank        }
689ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
690ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
6910a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    @Override
6920a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void commandsParser() throws IOException {
6930a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    }
6940a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank
69548af7392c82262d17700e3fbdccf3a582809d449Marc Blank    @Override
69648af7392c82262d17700e3fbdccf3a582809d449Marc Blank    public void commit() throws IOException {
6976c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Set the account sync key.
6986c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        if (mSyncKeyChanged) {
6996c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            final ContentValues cv = new ContentValues(1);
7006c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
7016c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu            mOperations.add(
7026c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu                    ContentProviderOperation.newUpdate(mAccount.getUri()).withValues(cv).build());
7036c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
7046c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
7055586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        // If this is the initial sync, make sure we have all the required folder types.
7065586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu        if (mInitialSync) {
7075586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            for (final int requiredType : Mailbox.REQUIRED_FOLDER_TYPES) {
7085586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                if (!mCreatedFolderTypes.get(requiredType)) {
7095586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                    addMailboxOp(Mailbox.getSystemMailboxName(mContext, requiredType),
7105586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                            null, null, requiredType, false);
7115586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu                }
7125586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu            }
7136c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        }
7146c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
7156c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Send all operations so far.
7166c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        flushOperations();
7176c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
7186c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        // Now that new mailboxes are committed, let's do parent fixups.
7196c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu        doParentFixups();
7206c4767d056fc1ad6bb3986d8e54bf7dfcbd61b06Yu Ping Hu
721f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        // Look for sync issues and its children and delete them
722f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        // I'm not aware of any other way to deal with this properly
723f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        mBindArguments[0] = "Sync Issues";
724f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        mBindArguments[1] = mAccountIdAsString;
725f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        Cursor c = mContentResolver.query(Mailbox.CONTENT_URI,
726f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                MAILBOX_ID_COLUMNS_PROJECTION, WHERE_DISPLAY_NAME_AND_ACCOUNT,
727f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                mBindArguments, null);
728f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        String parentServerId = null;
729f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        long id = 0;
730f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        try {
731f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            if (c.moveToFirst()) {
732e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                id = c.getLong(MAILBOX_ID_COLUMNS_ID);
733e1358075882e5abfb37f8f3ff2266e5a0fabbcfcMarc Blank                parentServerId = c.getString(MAILBOX_ID_COLUMNS_SERVER_ID);
734f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            }
735f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        } finally {
736f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            c.close();
737f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        }
738f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        if (parentServerId != null) {
739f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            mContentResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id),
740f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                    null, null);
741f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            mBindArguments[0] = parentServerId;
742f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank            mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
743f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank                    mBindArguments);
744f2465b983215c848d2082b1421af0d5b523d23d0Marc Blank        }
745f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank
746f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        // If we have saved options, restore them now
747f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        if (mInitialSync) {
748f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank            restoreMailboxSyncOptions();
749f80dd6855e64091ccac83f1bf37cd808ef2f3e71Marc Blank        }
75048af7392c82262d17700e3fbdccf3a582809d449Marc Blank    }
75148af7392c82262d17700e3fbdccf3a582809d449Marc Blank
7520a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    @Override
75348af7392c82262d17700e3fbdccf3a582809d449Marc Blank    public void responsesParser() throws IOException {
75448af7392c82262d17700e3fbdccf3a582809d449Marc Blank    }
75548af7392c82262d17700e3fbdccf3a582809d449Marc Blank
75628f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon    @Override
75728f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon    protected void wipe() {
75828f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        EasCalendarSyncHandler.wipeAccountFromContentProvider(mContext,
75928f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                mAccount.mEmailAddress);
76028f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        EasContactsSyncHandler.wipeAccountFromContentProvider(mContext,
76128f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                mAccount.mEmailAddress);
76228f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon
76328f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        // Save away any mailbox sync information that is NOT default
76428f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        saveMailboxSyncOptions();
76528f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        // And only then, delete mailboxes
76628f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_ACCOUNT_KEY,
76728f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                new String[] {mAccountIdAsString});
76828f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        // Reset the sync key and save.
76928f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        mAccount.mSyncKey = "0";
77028f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        ContentValues cv = new ContentValues();
77128f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
77228f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon        mContentResolver.update(ContentUris.withAppendedId(Account.CONTENT_URI,
77328f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon                mAccount.mId), cv, null, null);
77428f3556f92b20b2efb800c1d95c29b04a3bbbb4fMartin Hibdon    }
775ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank}
776