15c523858385176c33a7456bb84035de78552d22dMarc Blank/*
25c523858385176c33a7456bb84035de78552d22dMarc Blank * Copyright (C) 2010 The Android Open Source Project
35c523858385176c33a7456bb84035de78552d22dMarc Blank *
45c523858385176c33a7456bb84035de78552d22dMarc Blank * Licensed under the Apache License, Version 2.0 (the "License");
55c523858385176c33a7456bb84035de78552d22dMarc Blank * you may not use this file except in compliance with the License.
65c523858385176c33a7456bb84035de78552d22dMarc Blank * You may obtain a copy of the License at
75c523858385176c33a7456bb84035de78552d22dMarc Blank *
85c523858385176c33a7456bb84035de78552d22dMarc Blank *      http://www.apache.org/licenses/LICENSE-2.0
95c523858385176c33a7456bb84035de78552d22dMarc Blank *
105c523858385176c33a7456bb84035de78552d22dMarc Blank * Unless required by applicable law or agreed to in writing, software
115c523858385176c33a7456bb84035de78552d22dMarc Blank * distributed under the License is distributed on an "AS IS" BASIS,
125c523858385176c33a7456bb84035de78552d22dMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135c523858385176c33a7456bb84035de78552d22dMarc Blank * See the License for the specific language governing permissions and
145c523858385176c33a7456bb84035de78552d22dMarc Blank * limitations under the License.
155c523858385176c33a7456bb84035de78552d22dMarc Blank */
165c523858385176c33a7456bb84035de78552d22dMarc Blank
175c523858385176c33a7456bb84035de78552d22dMarc Blankpackage com.android.email.service;
185c523858385176c33a7456bb84035de78552d22dMarc Blank
195c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.app.Service;
205c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.AbstractThreadedSyncAdapter;
215c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.ContentProviderClient;
225c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.ContentResolver;
235c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.ContentUris;
245c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.ContentValues;
255c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.Context;
265c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.Intent;
275c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.content.SyncResult;
285c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.database.Cursor;
295c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.net.Uri;
305c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.os.Bundle;
315c523858385176c33a7456bb84035de78552d22dMarc Blankimport android.os.IBinder;
325c523858385176c33a7456bb84035de78552d22dMarc Blank
335c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.email.R;
345c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.TempDirectory;
355c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.mail.MessagingException;
365c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.provider.Account;
375c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.provider.EmailContent;
385c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.provider.EmailContent.AccountColumns;
395c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.provider.EmailContent.Message;
403dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantlerimport com.android.emailcommon.provider.EmailContent.MessageColumns;
415c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.provider.Mailbox;
425c523858385176c33a7456bb84035de78552d22dMarc Blankimport com.android.emailcommon.service.EmailServiceProxy;
432075c97f608a853923980865b72147a5c8ef71f0Yu Ping Huimport com.android.emailcommon.service.EmailServiceStatus;
448c989772dfba08438650575f1ac2bb952bd56158Alon Albertimport com.android.mail.providers.UIProvider;
45560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils;
465c523858385176c33a7456bb84035de78552d22dMarc Blank
475c523858385176c33a7456bb84035de78552d22dMarc Blankimport java.util.ArrayList;
485c523858385176c33a7456bb84035de78552d22dMarc Blank
495c523858385176c33a7456bb84035de78552d22dMarc Blankpublic class PopImapSyncAdapterService extends Service {
50d1a87bc02d65dde9e635848531e09aadc79ff538Paul Westbrook    private static final String TAG = "PopImapSyncService";
511484c6663db7b194eea9341ec8ecab6b44985c7cYu Ping Hu    private SyncAdapterImpl mSyncAdapter = null;
525c523858385176c33a7456bb84035de78552d22dMarc Blank
535c523858385176c33a7456bb84035de78552d22dMarc Blank    public PopImapSyncAdapterService() {
545c523858385176c33a7456bb84035de78552d22dMarc Blank        super();
555c523858385176c33a7456bb84035de78552d22dMarc Blank    }
565c523858385176c33a7456bb84035de78552d22dMarc Blank
575c523858385176c33a7456bb84035de78552d22dMarc Blank    private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
585c523858385176c33a7456bb84035de78552d22dMarc Blank        public SyncAdapterImpl(Context context) {
595c523858385176c33a7456bb84035de78552d22dMarc Blank            super(context, true /* autoInitialize */);
605c523858385176c33a7456bb84035de78552d22dMarc Blank        }
615c523858385176c33a7456bb84035de78552d22dMarc Blank
625c523858385176c33a7456bb84035de78552d22dMarc Blank        @Override
635c523858385176c33a7456bb84035de78552d22dMarc Blank        public void onPerformSync(android.accounts.Account account, Bundle extras,
645c523858385176c33a7456bb84035de78552d22dMarc Blank                String authority, ContentProviderClient provider, SyncResult syncResult) {
651b8e0fa23f6e9957f0b8753dd3f5b95d3f5d98eaScott Kennedy            PopImapSyncAdapterService.performSync(getContext(), account, extras, provider,
661b8e0fa23f6e9957f0b8753dd3f5b95d3f5d98eaScott Kennedy                    syncResult);
675c523858385176c33a7456bb84035de78552d22dMarc Blank        }
685c523858385176c33a7456bb84035de78552d22dMarc Blank    }
695c523858385176c33a7456bb84035de78552d22dMarc Blank
705c523858385176c33a7456bb84035de78552d22dMarc Blank    @Override
715c523858385176c33a7456bb84035de78552d22dMarc Blank    public void onCreate() {
725c523858385176c33a7456bb84035de78552d22dMarc Blank        super.onCreate();
731484c6663db7b194eea9341ec8ecab6b44985c7cYu Ping Hu        mSyncAdapter = new SyncAdapterImpl(getApplicationContext());
745c523858385176c33a7456bb84035de78552d22dMarc Blank    }
755c523858385176c33a7456bb84035de78552d22dMarc Blank
765c523858385176c33a7456bb84035de78552d22dMarc Blank    @Override
775c523858385176c33a7456bb84035de78552d22dMarc Blank    public IBinder onBind(Intent intent) {
781484c6663db7b194eea9341ec8ecab6b44985c7cYu Ping Hu        return mSyncAdapter.getSyncAdapterBinder();
795c523858385176c33a7456bb84035de78552d22dMarc Blank    }
805c523858385176c33a7456bb84035de78552d22dMarc Blank
815c523858385176c33a7456bb84035de78552d22dMarc Blank    /**
825c523858385176c33a7456bb84035de78552d22dMarc Blank     * @return whether or not this mailbox retrieves its data from the server (as opposed to just
835c523858385176c33a7456bb84035de78552d22dMarc Blank     *     a local mailbox that is never synced).
845c523858385176c33a7456bb84035de78552d22dMarc Blank     */
855c523858385176c33a7456bb84035de78552d22dMarc Blank    private static boolean loadsFromServer(Context context, Mailbox m, String protocol) {
865c523858385176c33a7456bb84035de78552d22dMarc Blank        String legacyImapProtocol = context.getString(R.string.protocol_legacy_imap);
8754347010fbbdd3ae1dea5b0e282514c640e16a5fMarc Blank        String pop3Protocol = context.getString(R.string.protocol_pop3);
885c523858385176c33a7456bb84035de78552d22dMarc Blank        if (legacyImapProtocol.equals(protocol)) {
895c523858385176c33a7456bb84035de78552d22dMarc Blank            // TODO: actually use a sync flag when creating the mailboxes. Right now we use an
905c523858385176c33a7456bb84035de78552d22dMarc Blank            // approximation for IMAP.
915c523858385176c33a7456bb84035de78552d22dMarc Blank            return m.mType != Mailbox.TYPE_DRAFTS
925c523858385176c33a7456bb84035de78552d22dMarc Blank                    && m.mType != Mailbox.TYPE_OUTBOX
935c523858385176c33a7456bb84035de78552d22dMarc Blank                    && m.mType != Mailbox.TYPE_SEARCH;
945c523858385176c33a7456bb84035de78552d22dMarc Blank
9554347010fbbdd3ae1dea5b0e282514c640e16a5fMarc Blank        } else if (pop3Protocol.equals(protocol)) {
965c523858385176c33a7456bb84035de78552d22dMarc Blank            return Mailbox.TYPE_INBOX == m.mType;
975c523858385176c33a7456bb84035de78552d22dMarc Blank        }
985c523858385176c33a7456bb84035de78552d22dMarc Blank
995c523858385176c33a7456bb84035de78552d22dMarc Blank        return false;
1005c523858385176c33a7456bb84035de78552d22dMarc Blank    }
1015c523858385176c33a7456bb84035de78552d22dMarc Blank
1022075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu    private static void sync(final Context context, final long mailboxId,
1032075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu            final Bundle extras, final SyncResult syncResult, final boolean uiRefresh,
1042075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu            final int deltaMessageCount) {
1055c523858385176c33a7456bb84035de78552d22dMarc Blank        TempDirectory.setTempDirectory(context);
1065c523858385176c33a7456bb84035de78552d22dMarc Blank        Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
1075c523858385176c33a7456bb84035de78552d22dMarc Blank        if (mailbox == null) return;
1085c523858385176c33a7456bb84035de78552d22dMarc Blank        Account account = Account.restoreAccountWithId(context, mailbox.mAccountKey);
1095c523858385176c33a7456bb84035de78552d22dMarc Blank        if (account == null) return;
1105c523858385176c33a7456bb84035de78552d22dMarc Blank        ContentResolver resolver = context.getContentResolver();
1115c523858385176c33a7456bb84035de78552d22dMarc Blank        String protocol = account.getProtocol(context);
1125c523858385176c33a7456bb84035de78552d22dMarc Blank        if ((mailbox.mType != Mailbox.TYPE_OUTBOX) &&
1135c523858385176c33a7456bb84035de78552d22dMarc Blank                !loadsFromServer(context, mailbox, protocol)) {
1145c523858385176c33a7456bb84035de78552d22dMarc Blank            // This is an update to a message in a non-syncing mailbox; delete this from the
1155c523858385176c33a7456bb84035de78552d22dMarc Blank            // updates table and return
1163dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler            resolver.delete(Message.UPDATED_CONTENT_URI, MessageColumns.MAILBOX_KEY + "=?",
1175c523858385176c33a7456bb84035de78552d22dMarc Blank                    new String[] {Long.toString(mailbox.mId)});
1185c523858385176c33a7456bb84035de78552d22dMarc Blank            return;
1195c523858385176c33a7456bb84035de78552d22dMarc Blank        }
12037b539063d30e6b59cbbbdda470de81d41025e51Martin Hibdon        LogUtils.d(TAG, "About to sync mailbox: " + mailbox.mDisplayName);
1215c523858385176c33a7456bb84035de78552d22dMarc Blank
1225c523858385176c33a7456bb84035de78552d22dMarc Blank        Uri mailboxUri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId);
1235c523858385176c33a7456bb84035de78552d22dMarc Blank        ContentValues values = new ContentValues();
1245c523858385176c33a7456bb84035de78552d22dMarc Blank        // Set mailbox sync state
12540236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux        final int syncStatus = uiRefresh ? EmailContent.SYNC_STATUS_USER :
12640236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                EmailContent.SYNC_STATUS_BACKGROUND;
12740236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux        values.put(Mailbox.UI_SYNC_STATUS, syncStatus);
1285c523858385176c33a7456bb84035de78552d22dMarc Blank        resolver.update(mailboxUri, values, null, null);
1295c523858385176c33a7456bb84035de78552d22dMarc Blank        try {
13040236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux            int lastSyncResult;
1315c523858385176c33a7456bb84035de78552d22dMarc Blank            try {
1325c523858385176c33a7456bb84035de78552d22dMarc Blank                String legacyImapProtocol = context.getString(R.string.protocol_legacy_imap);
1335c523858385176c33a7456bb84035de78552d22dMarc Blank                if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
1345c523858385176c33a7456bb84035de78552d22dMarc Blank                    EmailServiceStub.sendMailImpl(context, account.mId);
1355c523858385176c33a7456bb84035de78552d22dMarc Blank                } else {
13640236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                    lastSyncResult = UIProvider.createSyncValue(syncStatus,
13740236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                            EmailContent.LAST_SYNC_RESULT_SUCCESS);
1382075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                    EmailServiceStatus.syncMailboxStatus(resolver, extras, mailboxId,
13940236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                            EmailServiceStatus.IN_PROGRESS, 0, lastSyncResult);
1402075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                    final int status;
1412075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                    if (protocol.equals(legacyImapProtocol)) {
1422075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                        status = ImapService.synchronizeMailboxSynchronous(context, account,
143c75f5880ab70d9f4938727587696b864bb4ea02aMartin Hibdon                                mailbox, deltaMessageCount != 0, uiRefresh);
1442075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                    } else {
1452075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                        status = Pop3Service.synchronizeMailboxSynchronous(context, account,
1462075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                                mailbox, deltaMessageCount);
1472075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                    }
1488c989772dfba08438650575f1ac2bb952bd56158Alon Albert                    EmailServiceStatus.syncMailboxStatus(resolver, extras, mailboxId, status, 0,
14940236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                            lastSyncResult);
1505c523858385176c33a7456bb84035de78552d22dMarc Blank                }
1515c523858385176c33a7456bb84035de78552d22dMarc Blank            } catch (MessagingException e) {
1520dffe3afd7a2fdfb394573aa0d8d06dd90e9fe12James Lemieux                final int type = e.getExceptionType();
1530dffe3afd7a2fdfb394573aa0d8d06dd90e9fe12James Lemieux                // type must be translated into the domain of values used by EmailServiceStatus
15440236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                switch (type) {
1555c523858385176c33a7456bb84035de78552d22dMarc Blank                    case MessagingException.IOERROR:
15640236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        lastSyncResult = UIProvider.createSyncValue(syncStatus,
15740236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailContent.LAST_SYNC_RESULT_CONNECTION_ERROR);
15840236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        EmailServiceStatus.syncMailboxStatus(resolver, extras, mailboxId,
15940236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailServiceStatus.FAILURE, 0, lastSyncResult);
1605c523858385176c33a7456bb84035de78552d22dMarc Blank                        syncResult.stats.numIoExceptions++;
1615c523858385176c33a7456bb84035de78552d22dMarc Blank                        break;
1625c523858385176c33a7456bb84035de78552d22dMarc Blank                    case MessagingException.AUTHENTICATION_FAILED:
16340236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        lastSyncResult = UIProvider.createSyncValue(syncStatus,
16440236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailContent.LAST_SYNC_RESULT_AUTH_ERROR);
16540236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        EmailServiceStatus.syncMailboxStatus(resolver, extras, mailboxId,
16640236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailServiceStatus.FAILURE, 0, lastSyncResult);
1675c523858385176c33a7456bb84035de78552d22dMarc Blank                        syncResult.stats.numAuthExceptions++;
1685c523858385176c33a7456bb84035de78552d22dMarc Blank                        break;
1690dffe3afd7a2fdfb394573aa0d8d06dd90e9fe12James Lemieux                    case MessagingException.SERVER_ERROR:
17040236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        lastSyncResult = UIProvider.createSyncValue(syncStatus,
17140236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailContent.LAST_SYNC_RESULT_SERVER_ERROR);
17240236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        EmailServiceStatus.syncMailboxStatus(resolver, extras, mailboxId,
17340236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailServiceStatus.FAILURE, 0, lastSyncResult);
1740dffe3afd7a2fdfb394573aa0d8d06dd90e9fe12James Lemieux                        break;
1758c989772dfba08438650575f1ac2bb952bd56158Alon Albert
1768c989772dfba08438650575f1ac2bb952bd56158Alon Albert                    default:
17740236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        lastSyncResult = UIProvider.createSyncValue(syncStatus,
17840236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailContent.LAST_SYNC_RESULT_INTERNAL_ERROR);
17940236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                        EmailServiceStatus.syncMailboxStatus(resolver, extras, mailboxId,
18040236a89316ab2151a8c93de0e286c2f1a9a8d37James Lemieux                                EmailServiceStatus.FAILURE, 0, lastSyncResult);
1815c523858385176c33a7456bb84035de78552d22dMarc Blank                }
1825c523858385176c33a7456bb84035de78552d22dMarc Blank            }
1835c523858385176c33a7456bb84035de78552d22dMarc Blank        } finally {
18417d5bbf768c27ac7782b155e2ab25bcd480f5dcfYu Ping Hu            // Always clear our sync state and update sync time.
1855c523858385176c33a7456bb84035de78552d22dMarc Blank            values.put(Mailbox.UI_SYNC_STATUS, EmailContent.SYNC_STATUS_NONE);
18617d5bbf768c27ac7782b155e2ab25bcd480f5dcfYu Ping Hu            values.put(Mailbox.SYNC_TIME, System.currentTimeMillis());
1875c523858385176c33a7456bb84035de78552d22dMarc Blank            resolver.update(mailboxUri, values, null, null);
1885c523858385176c33a7456bb84035de78552d22dMarc Blank        }
1895c523858385176c33a7456bb84035de78552d22dMarc Blank    }
1905c523858385176c33a7456bb84035de78552d22dMarc Blank
1915c523858385176c33a7456bb84035de78552d22dMarc Blank    /**
1925c523858385176c33a7456bb84035de78552d22dMarc Blank     * Partial integration with system SyncManager; we initiate manual syncs upon request
1935c523858385176c33a7456bb84035de78552d22dMarc Blank     */
1945c523858385176c33a7456bb84035de78552d22dMarc Blank    private static void performSync(Context context, android.accounts.Account account,
1951b8e0fa23f6e9957f0b8753dd3f5b95d3f5d98eaScott Kennedy            Bundle extras, ContentProviderClient provider, SyncResult syncResult) {
1965c523858385176c33a7456bb84035de78552d22dMarc Blank        // Find an EmailProvider account with the Account's email address
1975c523858385176c33a7456bb84035de78552d22dMarc Blank        Cursor c = null;
1985c523858385176c33a7456bb84035de78552d22dMarc Blank        try {
1995c523858385176c33a7456bb84035de78552d22dMarc Blank            c = provider.query(com.android.emailcommon.provider.Account.CONTENT_URI,
2005c523858385176c33a7456bb84035de78552d22dMarc Blank                    Account.CONTENT_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?",
2015c523858385176c33a7456bb84035de78552d22dMarc Blank                    new String[] {account.name}, null);
2025c523858385176c33a7456bb84035de78552d22dMarc Blank            if (c != null && c.moveToNext()) {
2035c523858385176c33a7456bb84035de78552d22dMarc Blank                Account acct = new Account();
2045c523858385176c33a7456bb84035de78552d22dMarc Blank                acct.restore(c);
2055c523858385176c33a7456bb84035de78552d22dMarc Blank                if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD)) {
206560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.d(TAG, "Upload sync request for " + acct.mDisplayName);
2075c523858385176c33a7456bb84035de78552d22dMarc Blank                    // See if any boxes have mail...
2085c523858385176c33a7456bb84035de78552d22dMarc Blank                    ArrayList<Long> mailboxesToUpdate;
2095c523858385176c33a7456bb84035de78552d22dMarc Blank                    Cursor updatesCursor = provider.query(Message.UPDATED_CONTENT_URI,
2103dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler                            new String[] {MessageColumns.MAILBOX_KEY},
2113dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler                            MessageColumns.ACCOUNT_KEY + "=?",
2125c523858385176c33a7456bb84035de78552d22dMarc Blank                            new String[] {Long.toString(acct.mId)},
2135c523858385176c33a7456bb84035de78552d22dMarc Blank                            null);
2145c523858385176c33a7456bb84035de78552d22dMarc Blank                    try {
2155c523858385176c33a7456bb84035de78552d22dMarc Blank                        if ((updatesCursor == null) || (updatesCursor.getCount() == 0)) return;
2165c523858385176c33a7456bb84035de78552d22dMarc Blank                        mailboxesToUpdate = new ArrayList<Long>();
2175c523858385176c33a7456bb84035de78552d22dMarc Blank                        while (updatesCursor.moveToNext()) {
2185c523858385176c33a7456bb84035de78552d22dMarc Blank                            Long mailboxId = updatesCursor.getLong(0);
2195c523858385176c33a7456bb84035de78552d22dMarc Blank                            if (!mailboxesToUpdate.contains(mailboxId)) {
2205c523858385176c33a7456bb84035de78552d22dMarc Blank                                mailboxesToUpdate.add(mailboxId);
2215c523858385176c33a7456bb84035de78552d22dMarc Blank                            }
2225c523858385176c33a7456bb84035de78552d22dMarc Blank                        }
2235c523858385176c33a7456bb84035de78552d22dMarc Blank                    } finally {
2245c523858385176c33a7456bb84035de78552d22dMarc Blank                        if (updatesCursor != null) {
2255c523858385176c33a7456bb84035de78552d22dMarc Blank                            updatesCursor.close();
2265c523858385176c33a7456bb84035de78552d22dMarc Blank                        }
2275c523858385176c33a7456bb84035de78552d22dMarc Blank                    }
2285c523858385176c33a7456bb84035de78552d22dMarc Blank                    for (long mailboxId: mailboxesToUpdate) {
2292075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu                        sync(context, mailboxId, extras, syncResult, false, 0);
2305c523858385176c33a7456bb84035de78552d22dMarc Blank                    }
2315c523858385176c33a7456bb84035de78552d22dMarc Blank                } else {
232560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.d(TAG, "Sync request for " + acct.mDisplayName);
233560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.d(TAG, extras.toString());
2341a7838eed7558a8f5caa23128518cae09d8a034fMartin Hibdon
2351a7838eed7558a8f5caa23128518cae09d8a034fMartin Hibdon                    // We update our folder structure on every sync.
2361a7838eed7558a8f5caa23128518cae09d8a034fMartin Hibdon                    final EmailServiceProxy service =
2371a7838eed7558a8f5caa23128518cae09d8a034fMartin Hibdon                            EmailServiceUtils.getServiceForAccount(context, acct.mId);
2381a7838eed7558a8f5caa23128518cae09d8a034fMartin Hibdon                    service.updateFolderList(acct.mId);
2391a7838eed7558a8f5caa23128518cae09d8a034fMartin Hibdon
240c48670a5692144b293cea1c42b138e5228860da4Yu Ping Hu                    // Get the id for the mailbox we want to sync.
24156aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                    long [] mailboxIds = Mailbox.getMailboxIdsFromBundle(extras);
24256aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                    if (mailboxIds == null || mailboxIds.length == 0) {
24356aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        // No mailbox specified, just sync the inbox.
244c48670a5692144b293cea1c42b138e5228860da4Yu Ping Hu                        // TODO: IMAP may eventually want to allow multiple auto-sync mailboxes.
24556aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        final long inboxId = Mailbox.findMailboxOfType(context, acct.mId,
246c48670a5692144b293cea1c42b138e5228860da4Yu Ping Hu                                Mailbox.TYPE_INBOX);
24756aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        if (inboxId != Mailbox.NO_MAILBOX) {
24856aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                            mailboxIds = new long[1];
24956aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                            mailboxIds[0] = inboxId;
25056aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        }
251c48670a5692144b293cea1c42b138e5228860da4Yu Ping Hu                    }
25256aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon
25356aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                    if (mailboxIds != null) {
25456aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        boolean uiRefresh =
2555c523858385176c33a7456bb84035de78552d22dMarc Blank                            extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
25656aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        int deltaMessageCount =
25756aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                                extras.getInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, 0);
25856aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        for (long mailboxId : mailboxIds) {
2590c8696c2ebd52c7f2a92fa7b6b8d5d2005c19d1cTony Mantler                            sync(context, mailboxId, extras, syncResult, uiRefresh,
2600c8696c2ebd52c7f2a92fa7b6b8d5d2005c19d1cTony Mantler                                    deltaMessageCount);
26156aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                        }
26256aba8d8436b083bfc1169dd8b988161d537f7e5Martin Hibdon                    }
2635c523858385176c33a7456bb84035de78552d22dMarc Blank                }
2645c523858385176c33a7456bb84035de78552d22dMarc Blank            }
2655c523858385176c33a7456bb84035de78552d22dMarc Blank        } catch (Exception e) {
2665c523858385176c33a7456bb84035de78552d22dMarc Blank            e.printStackTrace();
2675c523858385176c33a7456bb84035de78552d22dMarc Blank        } finally {
2685c523858385176c33a7456bb84035de78552d22dMarc Blank            if (c != null) {
2695c523858385176c33a7456bb84035de78552d22dMarc Blank                c.close();
2705c523858385176c33a7456bb84035de78552d22dMarc Blank            }
2715c523858385176c33a7456bb84035de78552d22dMarc Blank        }
2725c523858385176c33a7456bb84035de78552d22dMarc Blank    }
2732075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu}
274