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