/*
 * Copyright (C) 2008-2009 Marc Blank
 * Licensed to The Android Open Source Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.exchange;

import com.android.email.AccountBackupRestore;
import com.android.email.Email;
import com.android.email.SecurityPolicy;
import com.android.email.mail.MessagingException;
import com.android.email.mail.transport.SSLUtils;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Attachment;
import com.android.email.provider.EmailContent.HostAuth;
import com.android.email.provider.EmailContent.HostAuthColumns;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.SyncColumns;
import com.android.email.service.IEmailService;
import com.android.email.service.IEmailServiceCallback;
import com.android.exchange.adapter.CalendarSyncAdapter;
import com.android.exchange.utility.FileLogger;

import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerPNames;
import org.apache.http.conn.params.ConnPerRoute;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OnAccountsUpdateListener;
import android.accounts.OperationCanceledException;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SyncStatusObserver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.PowerManager.WakeLock;
import android.provider.Calendar;
import android.provider.ContactsContract;
import android.provider.Calendar.Calendars;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * The SyncManager handles all aspects of starting, maintaining, and stopping the various sync
 * adapters used by Exchange.  However, it is capable of handing any kind of email sync, and it
 * would be appropriate to use for IMAP push, when that functionality is added to the Email
 * application.
 *
 * The Email application communicates with EAS sync adapters via SyncManager's binder interface,
 * which exposes UI-related functionality to the application (see the definitions below)
 *
 * SyncManager uses ContentObservers to detect changes to accounts, mailboxes, and messages in
 * order to maintain proper 2-way syncing of data.  (More documentation to follow)
 *
 */
public class SyncManager extends Service implements Runnable {

    private static final String TAG = "EAS SyncManager";

    // The SyncManager's mailbox "id"
    private static final int SYNC_MANAGER_ID = -1;

    private static final int SECONDS = 1000;
    private static final int MINUTES = 60*SECONDS;
    private static final int ONE_DAY_MINUTES = 1440;

    private static final int SYNC_MANAGER_HEARTBEAT_TIME = 15*MINUTES;
    private static final int CONNECTIVITY_WAIT_TIME = 10*MINUTES;

    // Sync hold constants for services with transient errors
    private static final int HOLD_DELAY_MAXIMUM = 4*MINUTES;

    // Reason codes when SyncManager.kick is called (mainly for debugging)
    // UI has changed data, requiring an upsync of changes
    public static final int SYNC_UPSYNC = 0;
    // A scheduled sync (when not using push)
    public static final int SYNC_SCHEDULED = 1;
    // Mailbox was marked push
    public static final int SYNC_PUSH = 2;
    // A ping (EAS push signal) was received
    public static final int SYNC_PING = 3;
    // startSync was requested of SyncManager
    public static final int SYNC_SERVICE_START_SYNC = 4;
    // A part request (attachment load, for now) was sent to SyncManager
    public static final int SYNC_SERVICE_PART_REQUEST = 5;
    // Misc.
    public static final int SYNC_KICK = 6;

    private static final String WHERE_PUSH_OR_PING_NOT_ACCOUNT_MAILBOX =
        MailboxColumns.ACCOUNT_KEY + "=? and " + MailboxColumns.TYPE + "!=" +
        Mailbox.TYPE_EAS_ACCOUNT_MAILBOX + " and " + MailboxColumns.SYNC_INTERVAL +
        " IN (" + Mailbox.CHECK_INTERVAL_PING + ',' + Mailbox.CHECK_INTERVAL_PUSH + ')';
    protected static final String WHERE_IN_ACCOUNT_AND_PUSHABLE =
        MailboxColumns.ACCOUNT_KEY + "=? and type in (" + Mailbox.TYPE_INBOX + ','
        + Mailbox.TYPE_EAS_ACCOUNT_MAILBOX + ',' + Mailbox.TYPE_CONTACTS + ','
        + Mailbox.TYPE_CALENDAR + ')';
    private static final String WHERE_MAILBOX_KEY = Message.MAILBOX_KEY + "=?";
    private static final String WHERE_PROTOCOL_EAS = HostAuthColumns.PROTOCOL + "=\"" +
        AbstractSyncService.EAS_PROTOCOL + "\"";
    private static final String WHERE_NOT_INTERVAL_NEVER_AND_ACCOUNT_KEY_IN =
        "(" + MailboxColumns.TYPE + '=' + Mailbox.TYPE_OUTBOX
        + " or " + MailboxColumns.SYNC_INTERVAL + "!=" + Mailbox.CHECK_INTERVAL_NEVER + ')'
        + " and " + MailboxColumns.ACCOUNT_KEY + " in (";
    private static final String ACCOUNT_KEY_IN = MailboxColumns.ACCOUNT_KEY + " in (";

    // Offsets into the syncStatus data for EAS that indicate type, exit status, and change count
    // The format is S<type_char>:<exit_char>:<change_count>
    public static final int STATUS_TYPE_CHAR = 1;
    public static final int STATUS_EXIT_CHAR = 3;
    public static final int STATUS_CHANGE_COUNT_OFFSET = 5;

    // Ready for ping
    public static final int PING_STATUS_OK = 0;
    // Service already running (can't ping)
    public static final int PING_STATUS_RUNNING = 1;
    // Service waiting after I/O error (can't ping)
    public static final int PING_STATUS_WAITING = 2;
    // Service had a fatal error; can't run
    public static final int PING_STATUS_UNABLE = 3;

    // We synchronize on this for all actions affecting the service and error maps
    private static Object sSyncToken = new Object();
    // All threads can use this lock to wait for connectivity
    public static Object sConnectivityLock = new Object();
    public static boolean sConnectivityHold = false;

    // Keeps track of running services (by mailbox id)
    private HashMap<Long, AbstractSyncService> mServiceMap =
        new HashMap<Long, AbstractSyncService>();
    // Keeps track of services whose last sync ended with an error (by mailbox id)
    /*package*/ HashMap<Long, SyncError> mSyncErrorMap = new HashMap<Long, SyncError>();
    // Keeps track of which services require a wake lock (by mailbox id)
    private HashMap<Long, Boolean> mWakeLocks = new HashMap<Long, Boolean>();
    // Keeps track of PendingIntents for mailbox alarms (by mailbox id)
    private HashMap<Long, PendingIntent> mPendingIntents = new HashMap<Long, PendingIntent>();
    // The actual WakeLock obtained by SyncManager
    private WakeLock mWakeLock = null;
    private static final AccountList EMPTY_ACCOUNT_LIST = new AccountList();

    // Observers that we use to look for changed mail-related data
    private Handler mHandler = new Handler();
    private AccountObserver mAccountObserver;
    private MailboxObserver mMailboxObserver;
    private SyncedMessageObserver mSyncedMessageObserver;
    private MessageObserver mMessageObserver;
    private EasSyncStatusObserver mSyncStatusObserver;
    private EasAccountsUpdatedListener mAccountsUpdatedListener;

    private HashMap<Long, CalendarObserver> mCalendarObservers =
        new HashMap<Long, CalendarObserver>();

    private ContentResolver mResolver;

    // The singleton SyncManager object, with its thread and stop flag
    protected static SyncManager INSTANCE;
    private static Thread sServiceThread = null;
    // Cached unique device id
    private static String sDeviceId = null;
    // ConnectionManager that all EAS threads can use
    private static ClientConnectionManager sClientConnectionManager = null;

    private boolean mStop = false;

    // The reason for SyncManager's next wakeup call
    private String mNextWaitReason;
    // Whether we have an unsatisfied "kick" pending
    private boolean mKicked = false;

    // Receiver of connectivity broadcasts
    private ConnectivityReceiver mConnectivityReceiver = null;

    // The callback sent in from the UI using setCallback
    private IEmailServiceCallback mCallback;
    private RemoteCallbackList<IEmailServiceCallback> mCallbackList =
        new RemoteCallbackList<IEmailServiceCallback>();

    /**
     * Proxy that can be used by various sync adapters to tie into SyncManager's callback system.
     * Used this way:  SyncManager.callback().callbackMethod(args...);
     * The proxy wraps checking for existence of a SyncManager instance and an active callback.
     * Failures of these callbacks can be safely ignored.
     */
    static private final IEmailServiceCallback.Stub sCallbackProxy =
        new IEmailServiceCallback.Stub() {

        public void loadAttachmentStatus(long messageId, long attachmentId, int statusCode,
                int progress) throws RemoteException {
            IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
            if (cb != null) {
                cb.loadAttachmentStatus(messageId, attachmentId, statusCode, progress);
            }
        }

        public void sendMessageStatus(long messageId, String subject, int statusCode, int progress)
                throws RemoteException {
            IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
            if (cb != null) {
                cb.sendMessageStatus(messageId, subject, statusCode, progress);
            }
        }

        public void syncMailboxListStatus(long accountId, int statusCode, int progress)
                throws RemoteException {
            IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
            if (cb != null) {
                cb.syncMailboxListStatus(accountId, statusCode, progress);
            }
        }

        public void syncMailboxStatus(long mailboxId, int statusCode, int progress)
                throws RemoteException {
            IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
            if (cb != null) {
                cb.syncMailboxStatus(mailboxId, statusCode, progress);
            } else if (INSTANCE != null) {
                INSTANCE.log("orphan syncMailboxStatus, id=" + mailboxId + " status=" + statusCode);
            }
        }
    };

    /**
     * Create our EmailService implementation here.
     */
    private final IEmailService.Stub mBinder = new IEmailService.Stub() {

        public int validate(String protocol, String host, String userName, String password,
                int port, boolean ssl, boolean trustCertificates) throws RemoteException {
            try {
                AbstractSyncService.validate(EasSyncService.class, host, userName, password, port,
                        ssl, trustCertificates, SyncManager.this);
                return MessagingException.NO_ERROR;
            } catch (MessagingException e) {
                return e.getExceptionType();
            }
        }

        public Bundle autoDiscover(String userName, String password) throws RemoteException {
            return new EasSyncService().tryAutodiscover(userName, password);
        }

        public void startSync(long mailboxId) throws RemoteException {
            checkSyncManagerServiceRunning();
            Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
            if (m.mType == Mailbox.TYPE_OUTBOX) {
                // We're using SERVER_ID to indicate an error condition (it has no other use for
                // sent mail)  Upon request to sync the Outbox, we clear this so that all messages
                // are candidates for sending.
                ContentValues cv = new ContentValues();
                cv.put(SyncColumns.SERVER_ID, 0);
                INSTANCE.getContentResolver().update(Message.CONTENT_URI,
                    cv, WHERE_MAILBOX_KEY, new String[] {Long.toString(mailboxId)});
                // Clear the error state; the Outbox sync will be started from checkMailboxes
                INSTANCE.mSyncErrorMap.remove(mailboxId);
                kick("start outbox");
                // Outbox can't be synced in EAS
                return;
            } else if (m.mType == Mailbox.TYPE_DRAFTS || m.mType == Mailbox.TYPE_TRASH) {
                // Drafts & Trash can't be synced in EAS
                return;
            }
            startManualSync(mailboxId, SyncManager.SYNC_SERVICE_START_SYNC, null);
        }

        public void stopSync(long mailboxId) throws RemoteException {
            stopManualSync(mailboxId);
        }

        public void loadAttachment(long attachmentId, String destinationFile,
                String contentUriString) throws RemoteException {
            Attachment att = Attachment.restoreAttachmentWithId(SyncManager.this, attachmentId);
            sendMessageRequest(new PartRequest(att, destinationFile, contentUriString));
        }

        public void updateFolderList(long accountId) throws RemoteException {
            reloadFolderList(SyncManager.this, accountId, false);
        }

        public void hostChanged(long accountId) throws RemoteException {
            if (INSTANCE != null) {
                synchronized (sSyncToken) {
                    HashMap<Long, SyncError> syncErrorMap = INSTANCE.mSyncErrorMap;
                    ArrayList<Long> deletedMailboxes = new ArrayList<Long>();
                    // Go through the various error mailboxes
                    for (long mailboxId: syncErrorMap.keySet()) {
                        SyncError error = syncErrorMap.get(mailboxId);
                        // If it's a login failure, look a little harder
                        Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
                        // If it's for the account whose host has changed, clear the error
                        // If the mailbox is no longer around, remove the entry in the map
                        if (m == null) {
                            deletedMailboxes.add(mailboxId);
                        } else if (m.mAccountKey == accountId) {
                            error.fatal = false;
                            error.holdEndTime = 0;
                        }
                    }
                    for (long mailboxId: deletedMailboxes) {
                        syncErrorMap.remove(mailboxId);
                    }
                }
                // Stop any running syncs
                INSTANCE.stopAccountSyncs(accountId, true);
                // Kick SyncManager
                kick("host changed");
            }
        }

        public void setLogging(int on) throws RemoteException {
            Eas.setUserDebug(on);
        }

        public void sendMeetingResponse(long messageId, int response) throws RemoteException {
            sendMessageRequest(new MeetingResponseRequest(messageId, response));
        }

        public void loadMore(long messageId) throws RemoteException {
        }

        // The following three methods are not implemented in this version
        public boolean createFolder(long accountId, String name) throws RemoteException {
            return false;
        }

        public boolean deleteFolder(long accountId, String name) throws RemoteException {
            return false;
        }

        public boolean renameFolder(long accountId, String oldName, String newName)
                throws RemoteException {
            return false;
        }

        public void setCallback(IEmailServiceCallback cb) throws RemoteException {
            if (mCallback != null) {
                mCallbackList.unregister(mCallback);
            }
            mCallback = cb;
            mCallbackList.register(cb);
        }
    };

    static class AccountList extends ArrayList<Account> {
        private static final long serialVersionUID = 1L;

        public boolean contains(long id) {
            for (Account account: this) {
                if (account.mId == id) {
                    return true;
                }
            }
            return false;
        }

        public Account getById(long id) {
            for (Account account: this) {
                if (account.mId == id) {
                    return account;
                }
            }
            return null;
        }
    }

    class AccountObserver extends ContentObserver {
        // mAccounts keeps track of Accounts that we care about (EAS for now)
        AccountList mAccounts = new AccountList();
        String mSyncableEasMailboxSelector = null;
        String mEasAccountSelector = null;

        public AccountObserver(Handler handler) {
            super(handler);
            // At startup, we want to see what EAS accounts exist and cache them
            Cursor c = getContentResolver().query(Account.CONTENT_URI, Account.CONTENT_PROJECTION,
                    null, null, null);
            try {
                collectEasAccounts(c, mAccounts);
            } finally {
                c.close();
            }

            // Create the account mailbox for any account that doesn't have one
            Context context = getContext();
            for (Account account: mAccounts) {
                int cnt = Mailbox.count(context, Mailbox.CONTENT_URI, "accountKey=" + account.mId,
                        null);
                if (cnt == 0) {
                    addAccountMailbox(account.mId);
                }
            }
        }

        /**
         * Returns a String suitable for appending to a where clause that selects for all syncable
         * mailboxes in all eas accounts
         * @return a complex selection string that is not to be cached
         */
        public String getSyncableEasMailboxWhere() {
            if (mSyncableEasMailboxSelector == null) {
                StringBuilder sb = new StringBuilder(WHERE_NOT_INTERVAL_NEVER_AND_ACCOUNT_KEY_IN);
                boolean first = true;
                for (Account account: mAccounts) {
                    if (!first) {
                        sb.append(',');
                    } else {
                        first = false;
                    }
                    sb.append(account.mId);
                }
                sb.append(')');
                mSyncableEasMailboxSelector = sb.toString();
            }
            return mSyncableEasMailboxSelector;
        }

        /**
         * Returns a String suitable for appending to a where clause that selects for all eas
         * accounts.
         * @return a String in the form "accountKey in (a, b, c...)" that is not to be cached
         */
        public String getAccountKeyWhere() {
            if (mEasAccountSelector == null) {
                StringBuilder sb = new StringBuilder(ACCOUNT_KEY_IN);
                boolean first = true;
                for (Account account: mAccounts) {
                    if (!first) {
                        sb.append(',');
                    } else {
                        first = false;
                    }
                    sb.append(account.mId);
                }
                sb.append(')');
                mEasAccountSelector = sb.toString();
            }
            return mEasAccountSelector;
        }

        private boolean onSecurityHold(Account account) {
            return (account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0;
        }

        @Override
        public void onChange(boolean selfChange) {
            maybeStartSyncManagerThread();
            Context context = getContext();

            // A change to the list requires us to scan for deletions (to stop running syncs)
            // At startup, we want to see what accounts exist and cache them
            AccountList currentAccounts = new AccountList();
            Cursor c = getContentResolver().query(Account.CONTENT_URI, Account.CONTENT_PROJECTION,
                    null, null, null);
            try {
                collectEasAccounts(c, currentAccounts);
                for (Account account : mAccounts) {
                    // Ignore accounts not fully created
                    if ((account.mFlags & Account.FLAGS_INCOMPLETE) != 0) {
                        log("Account observer noticed incomplete account; ignoring");
                        continue;
                    } else if (!currentAccounts.contains(account.mId)) {
                        // This is a deletion; shut down any account-related syncs
                        stopAccountSyncs(account.mId, true);
                        // Delete this from AccountManager...
                        android.accounts.Account acct =
                            new android.accounts.Account(account.mEmailAddress,
                                    Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                        AccountManager.get(SyncManager.this).removeAccount(acct, null, null);
                        mSyncableEasMailboxSelector = null;
                        mEasAccountSelector = null;
                    } else {
                        // An account has changed
                        Account updatedAccount = Account.restoreAccountWithId(context, account.mId);
                        if (account.mSyncInterval != updatedAccount.mSyncInterval ||
                                account.mSyncLookback != updatedAccount.mSyncLookback) {
                            // Set pushable boxes' sync interval to the sync interval of the Account
                            ContentValues cv = new ContentValues();
                            cv.put(MailboxColumns.SYNC_INTERVAL, updatedAccount.mSyncInterval);
                            getContentResolver().update(Mailbox.CONTENT_URI, cv,
                                    WHERE_IN_ACCOUNT_AND_PUSHABLE,
                                    new String[] {Long.toString(account.mId)});
                            // Stop all current syncs; the appropriate ones will restart
                            log("Account " + account.mDisplayName + " changed; stop syncs");
                            stopAccountSyncs(account.mId, true);
                        }

                        // See if this account is no longer on security hold
                        if (onSecurityHold(account) && !onSecurityHold(updatedAccount)) {
                            releaseSyncHolds(SyncManager.this,
                                    AbstractSyncService.EXIT_SECURITY_FAILURE, account);
                        }

                        // Put current values into our cached account
                        account.mSyncInterval = updatedAccount.mSyncInterval;
                        account.mSyncLookback = updatedAccount.mSyncLookback;
                        account.mFlags = updatedAccount.mFlags;
                    }
                }

                // Look for new accounts
                for (Account account: currentAccounts) {
                    if (!mAccounts.contains(account.mId)) {
                        // This is an addition; create our magic hidden mailbox...
                        log("Account observer found new account: " + account.mDisplayName);
                        addAccountMailbox(account.mId);
                        // Don't forget to cache the HostAuth
                        HostAuth ha =
                            HostAuth.restoreHostAuthWithId(getContext(), account.mHostAuthKeyRecv);
                        account.mHostAuthRecv = ha;
                        mAccounts.add(account);
                        mSyncableEasMailboxSelector = null;
                        mEasAccountSelector = null;
                    }
                }

                // Finally, make sure mAccounts is up to date
                mAccounts = currentAccounts;
            } finally {
                c.close();
            }

            // See if there's anything to do...
            kick("account changed");
        }

        private void collectEasAccounts(Cursor c, ArrayList<Account> accounts) {
            Context context = getContext();
            if (context == null) return;
            while (c.moveToNext()) {
                long hostAuthId = c.getLong(Account.CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
                if (hostAuthId > 0) {
                    HostAuth ha = HostAuth.restoreHostAuthWithId(context, hostAuthId);
                    if (ha != null && ha.mProtocol.equals("eas")) {
                        Account account = new Account().restore(c);
                        // Cache the HostAuth
                        account.mHostAuthRecv = ha;
                        accounts.add(account);
                    }
                }
            }
        }

        private void addAccountMailbox(long acctId) {
            Account acct = Account.restoreAccountWithId(getContext(), acctId);
            Mailbox main = new Mailbox();
            main.mDisplayName = Eas.ACCOUNT_MAILBOX;
            main.mServerId = Eas.ACCOUNT_MAILBOX + System.nanoTime();
            main.mAccountKey = acct.mId;
            main.mType = Mailbox.TYPE_EAS_ACCOUNT_MAILBOX;
            main.mSyncInterval = Mailbox.CHECK_INTERVAL_PUSH;
            main.mFlagVisible = false;
            main.save(getContext());
            INSTANCE.log("Initializing account: " + acct.mDisplayName);
        }

    }

    /**
     * Register a specific Calendar's data observer; we need to recognize when the SYNC_EVENTS
     * column has changed (when sync has turned off or on)
     * @param account the Account whose Calendar we're observing
     */
    private void registerCalendarObserver(Account account) {
        // Get a new observer
        CalendarObserver observer = new CalendarObserver(mHandler, account);
        if (observer.mCalendarId != 0) {
            // If we find the Calendar (and we'd better) register it and store it in the map
            mCalendarObservers.put(account.mId, observer);
            mResolver.registerContentObserver(
                    ContentUris.withAppendedId(Calendars.CONTENT_URI, observer.mCalendarId), false,
                    observer);
        }
    }

    /**
     * Unregister all CalendarObserver's
     */
    private void unregisterCalendarObservers() {
        for (CalendarObserver observer: mCalendarObservers.values()) {
            mResolver.unregisterContentObserver(observer);
        }
        mCalendarObservers.clear();
    }

    private class CalendarObserver extends ContentObserver {
        long mAccountId;
        long mCalendarId;
        long mSyncEvents;
        String mAccountName;

        public CalendarObserver(Handler handler, Account account) {
            super(handler);
            mAccountId = account.mId;
            mAccountName = account.mEmailAddress;

            // Find the Calendar for this account
            Cursor c = mResolver.query(Calendars.CONTENT_URI,
                    new String[] {Calendars._ID, Calendars.SYNC_EVENTS},
                    CalendarSyncAdapter.CALENDAR_SELECTION,
                    new String[] {account.mEmailAddress, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE},
                    null);
            // Save its id and its sync events status
            try {
                if (c.moveToFirst()) {
                    mCalendarId = c.getLong(0);
                    mSyncEvents = c.getLong(1);
                }
            } finally {
                c.close();
            }
            
        }

        @Override
        public void onChange(boolean selfChange) {
            // See if the user has changed syncing of our calendar
            if (!selfChange) {
                Cursor c = mResolver.query(Calendars.CONTENT_URI,
                        new String[] {Calendars.SYNC_EVENTS}, Calendars._ID + "=?",
                        new String[] {Long.toString(mCalendarId)}, null);
                // Get its sync events; if it's changed, we've got work to do
                try {
                    if (c.moveToFirst()) {
                        long newSyncEvents = c.getLong(0);
                        if (newSyncEvents != mSyncEvents) {
                            // The user has changed sync state; let SyncManager know
                            android.accounts.Account account =
                                new android.accounts.Account(mAccountName,
                                        Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                            ContentResolver.setSyncAutomatically(account, Calendar.AUTHORITY,
                                    newSyncEvents != 0);
                            if (newSyncEvents == 0) {
                                // For some reason, CalendarProvider deletes all Events in this
                                // case; this means that we have to reset our sync key
                                Mailbox mailbox = Mailbox.restoreMailboxOfType(INSTANCE, mAccountId,
                                        Mailbox.TYPE_CALENDAR);
                                EasSyncService service = new EasSyncService(INSTANCE, mailbox);
                                CalendarSyncAdapter adapter =
                                    new CalendarSyncAdapter(mailbox, service);
                                try {
                                    adapter.setSyncKey("0", false);
                                } catch (IOException e) {
                                    // The provider can't be reached; nothing to be done
                                }
                                ContentValues cv = new ContentValues();
                                cv.put(Mailbox.SYNC_KEY, "0");
                                mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI,
                                        mailbox.mId), cv, null, null);

                                // TODO Stop sync in progress??
                            }

                            // Save away the new value
                            mSyncEvents = newSyncEvents;
                        }
                    }
                } finally {
                    c.close();
                }
            }
        }
    }

    private class MailboxObserver extends ContentObserver {
        public MailboxObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            // See if there's anything to do...
            if (!selfChange) {
                kick("mailbox changed");
            }
        }
    }

    private class SyncedMessageObserver extends ContentObserver {
        Intent syncAlarmIntent = new Intent(INSTANCE, EmailSyncAlarmReceiver.class);
        PendingIntent syncAlarmPendingIntent =
            PendingIntent.getBroadcast(INSTANCE, 0, syncAlarmIntent, 0);
        AlarmManager alarmManager = (AlarmManager)INSTANCE.getSystemService(Context.ALARM_SERVICE);

        public SyncedMessageObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            INSTANCE.log("SyncedMessage changed: (re)setting alarm for 10s");
            alarmManager.set(AlarmManager.RTC_WAKEUP,
                    System.currentTimeMillis() + 10*SECONDS, syncAlarmPendingIntent);
        }
    }

    private class MessageObserver extends ContentObserver {

        public MessageObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            // A rather blunt instrument here.  But we don't have information about the URI that
            // triggered this, though it must have been an insert
            if (!selfChange) {
                kick(null);
            }
        }
    }

    static public IEmailServiceCallback callback() {
        return sCallbackProxy;
    }

    static public AccountList getAccountList() {
        if (INSTANCE != null) {
            return INSTANCE.mAccountObserver.mAccounts;
        } else {
            return EMPTY_ACCOUNT_LIST;
        }
    }

    static public String getEasAccountSelector() {
        if (INSTANCE != null) {
            return INSTANCE.mAccountObserver.getAccountKeyWhere();
        } else {
            return null;
        }
    }

    private Account getAccountById(long accountId) {
        return mAccountObserver.mAccounts.getById(accountId);
    }

    public class SyncStatus {
        static public final int NOT_RUNNING = 0;
        static public final int DIED = 1;
        static public final int SYNC = 2;
        static public final int IDLE = 3;
    }

    /*package*/ class SyncError {
        int reason;
        boolean fatal = false;
        long holdDelay = 15*SECONDS;
        long holdEndTime = System.currentTimeMillis() + holdDelay;

        SyncError(int _reason, boolean _fatal) {
            reason = _reason;
            fatal = _fatal;
        }

        /**
         * We double the holdDelay from 15 seconds through 4 mins
         */
        void escalate() {
            if (holdDelay < HOLD_DELAY_MAXIMUM) {
                holdDelay *= 2;
            }
            holdEndTime = System.currentTimeMillis() + holdDelay;
        }
    }

    /**
     * Release a specific type of hold (the reason) for the specified Account; if the account
     * is null, mailboxes from all accounts with the specified hold will be released
     * @param reason the reason for the SyncError (AbstractSyncService.EXIT_XXX)
     * @param account an Account whose mailboxes should be released (or all if null)
     */
    /*package*/ void releaseSyncHolds(Context context, int reason, Account account) {
        releaseSyncHoldsImpl(context, reason, account);
        kick("security release");
    }

    private void releaseSyncHoldsImpl(Context context, int reason, Account account) {
        synchronized(sSyncToken) {
            ArrayList<Long> releaseList = new ArrayList<Long>();
            for (long mailboxId: mSyncErrorMap.keySet()) {
                if (account != null) {
                    Mailbox m = Mailbox.restoreMailboxWithId(context, mailboxId);
                    if (m == null) {
                        releaseList.add(mailboxId);
                    } else if (m.mAccountKey != account.mId) {
                        continue;
                    }
                }
                SyncError error = mSyncErrorMap.get(mailboxId);
                if (error.reason == reason) {
                    releaseList.add(mailboxId);
                }
            }
            for (long mailboxId: releaseList) {
                mSyncErrorMap.remove(mailboxId);
            }
        }
    }

    public class EasSyncStatusObserver implements SyncStatusObserver {
        public void onStatusChanged(int which) {
            // We ignore the argument (we can only get called in one case - when settings change)
            if (INSTANCE != null) {
                checkPIMSyncSettings();
            }
        }
    }

    /**
     * The reconciler (which is called from this listener) can make blocking calls back into
     * the account manager.  So, in this callback we spin up a worker thread to call the
     * reconciler.
     */
    public class EasAccountsUpdatedListener implements OnAccountsUpdateListener {
        public void onAccountsUpdated(android.accounts.Account[] accounts) {
            new Thread() {
                @Override
                public void run() {
                    android.accounts.Account[] accountMgrList = AccountManager.get(INSTANCE)
                            .getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                    AccountList providerList = getAccountList();
                    reconcileAccountsWithAccountManager(INSTANCE,
                            providerList, accountMgrList, false, mResolver);
                }
            }.start();
        }
    }

    static public void smLog(String str) {
        if (INSTANCE != null) {
            INSTANCE.log(str);
        }
    }

    protected static void log(String str) {
        if (Eas.USER_LOG) {
            Log.d(TAG, str);
            if (Eas.FILE_LOG) {
                FileLogger.log(TAG, str);
            }
        }
    }

    protected static void alwaysLog(String str) {
        if (!Eas.USER_LOG) {
            Log.d(TAG, str);
        } else {
            log(str);
        }
    }

    /**
     * EAS requires a unique device id, so that sync is possible from a variety of different
     * devices (e.g. the syncKey is specific to a device)  If we're on an emulator or some other
     * device that doesn't provide one, we can create it as droid<n> where <n> is system time.
     * This would work on a real device as well, but it would be better to use the "real" id if
     * it's available
     */
    static public String getDeviceId() throws IOException {
        return getDeviceId(null);
    }

    static public synchronized String getDeviceId(Context context) throws IOException {
        if (sDeviceId != null) {
            return sDeviceId;
        } else if (INSTANCE == null && context == null) {
            throw new IOException("No context for getDeviceId");
        } else if (context == null) {
            context = INSTANCE;
        }

        // Otherwise, we'll read the id file or create one if it's not found
        try {
            File f = context.getFileStreamPath("deviceName");
            BufferedReader rdr = null;
            String id;
            if (f.exists() && f.canRead()) {
                rdr = new BufferedReader(new FileReader(f), 128);
                id = rdr.readLine();
                rdr.close();
                return id;
            } else if (f.createNewFile()) {
                BufferedWriter w = new BufferedWriter(new FileWriter(f), 128);
                id = "android" + System.currentTimeMillis();
                w.write(id);
                w.close();
                sDeviceId = id;
                return id;
            }
        } catch (IOException e) {
        }
        throw new IOException("Can't get device name");
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

    /**
     * Note that there are two ways the EAS SyncManager service can be created:
     *
     * 1) as a background service instantiated via startService (which happens on boot, when the
     * first EAS account is created, etc), in which case the service thread is spun up, mailboxes
     * sync, etc. and
     * 2) to execute an RPC call from the UI, in which case the background service will already be
     * running most of the time (unless we're creating a first EAS account)
     *
     * If the running background service detects that there are no EAS accounts (on boot, if none
     * were created, or afterward if the last remaining EAS account is deleted), it will call
     * stopSelf() to terminate operation.
     *
     * The goal is to ensure that the background service is running at all times when there is at
     * least one EAS account in existence
     *
     * Because there are edge cases in which our process can crash (typically, this has been seen
     * in UI crashes, ANR's, etc.), it's possible for the UI to start up again without the
     * background service having been started.  We explicitly try to start the service in Welcome
     * (to handle the case of the app having been reloaded).  We also start the service on any
     * startSync call (if it isn't already running)
     */
    @Override
    public void onCreate() {
        alwaysLog("!!! EAS SyncManager, onCreate");
        if (INSTANCE == null) {
            INSTANCE = this;
            mResolver = getContentResolver();
            mAccountObserver = new AccountObserver(mHandler);
            mResolver.registerContentObserver(Account.CONTENT_URI, true, mAccountObserver);
            mMailboxObserver = new MailboxObserver(mHandler);
            mSyncedMessageObserver = new SyncedMessageObserver(mHandler);
            mMessageObserver = new MessageObserver(mHandler);
            mSyncStatusObserver = new EasSyncStatusObserver();
        } else {
            alwaysLog("!!! EAS SyncManager onCreated, but INSTANCE not null??");
        }
        if (sDeviceId == null) {
            try {
                getDeviceId(this);
            } catch (IOException e) {
                // We can't run in this situation
                throw new RuntimeException();
            }
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        alwaysLog("!!! EAS SyncManager, onStartCommand");

        // Restore accounts, if it has not happened already
        AccountBackupRestore.restoreAccountsIfNeeded(this);

        maybeStartSyncManagerThread();
        if (sServiceThread == null) {
            alwaysLog("!!! EAS SyncManager, stopping self");
            stopSelf();
        }
        return Service.START_STICKY;
    }

    @Override
    public void onDestroy() {
        alwaysLog("!!! EAS SyncManager, onDestroy");
        if (INSTANCE != null) {
            INSTANCE = null;
            mResolver.unregisterContentObserver(mAccountObserver);
            unregisterCalendarObservers();
            mResolver = null;
            mAccountObserver = null;
            mMailboxObserver = null;
            mSyncedMessageObserver = null;
            mMessageObserver = null;
            mSyncStatusObserver = null;
            mAccountsUpdatedListener = null;
        }
    }

    void maybeStartSyncManagerThread() {
        // Start our thread...
        // See if there are any EAS accounts; otherwise, just go away
        if (EmailContent.count(this, HostAuth.CONTENT_URI, WHERE_PROTOCOL_EAS, null) > 0) {
            if (sServiceThread == null || !sServiceThread.isAlive()) {
                log(sServiceThread == null ? "Starting thread..." : "Restarting thread...");
                sServiceThread = new Thread(this, "SyncManager");
                sServiceThread.start();
            }
        }
    }

    static void checkSyncManagerServiceRunning() {
        // Get the service thread running if it isn't
        // This is a stopgap for cases in which SyncManager died (due to a crash somewhere in
        // com.android.email) and hasn't been restarted
        // See the comment for onCreate for details
        if (INSTANCE == null) return;
        if (sServiceThread == null) {
            INSTANCE.alwaysLog("!!! checkSyncManagerServiceRunning; starting service...");
            INSTANCE.startService(new Intent(INSTANCE, SyncManager.class));
        }
    }

    static public ConnPerRoute sConnPerRoute = new ConnPerRoute() {
        public int getMaxForRoute(HttpRoute route) {
            return 8;
        }
    };

    static public synchronized ClientConnectionManager getClientConnectionManager() {
        if (sClientConnectionManager == null) {
            // Create a registry for our three schemes; http and https will use built-in factories
            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http",
                    PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

            // Use "insecure" socket factory.
            SSLSocketFactory sf = new SSLSocketFactory(SSLUtils.getSSLSocketFactory(true));
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            // Register the httpts scheme with our factory
            registry.register(new Scheme("httpts", sf, 443));
            // And create a ccm with our registry
            HttpParams params = new BasicHttpParams();
            params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 25);
            params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, sConnPerRoute);
            sClientConnectionManager = new ThreadSafeClientConnManager(params, registry);
        }
        // Null is a valid return result if we get an exception
        return sClientConnectionManager;
    }

    public static void stopAccountSyncs(long acctId) {
        if (INSTANCE != null) {
            INSTANCE.stopAccountSyncs(acctId, true);
        }
    }

    private void stopAccountSyncs(long acctId, boolean includeAccountMailbox) {
        synchronized (sSyncToken) {
            List<Long> deletedBoxes = new ArrayList<Long>();
            for (Long mid : INSTANCE.mServiceMap.keySet()) {
                Mailbox box = Mailbox.restoreMailboxWithId(INSTANCE, mid);
                if (box != null) {
                    if (box.mAccountKey == acctId) {
                        if (!includeAccountMailbox &&
                                box.mType == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
                            AbstractSyncService svc = INSTANCE.mServiceMap.get(mid);
                            if (svc != null) {
                                svc.stop();
                            }
                            continue;
                        }
                        AbstractSyncService svc = INSTANCE.mServiceMap.get(mid);
                        if (svc != null) {
                            svc.stop();
                            Thread t = svc.mThread;
                            if (t != null) {
                                t.interrupt();
                            }
                        }
                        deletedBoxes.add(mid);
                    }
                }
            }
            for (Long mid : deletedBoxes) {
                releaseMailbox(mid);
            }
        }
    }

    static public void reloadFolderList(Context context, long accountId, boolean force) {
        if (INSTANCE == null) return;
        Cursor c = context.getContentResolver().query(Mailbox.CONTENT_URI,
                Mailbox.CONTENT_PROJECTION, MailboxColumns.ACCOUNT_KEY + "=? AND " +
                MailboxColumns.TYPE + "=?",
                new String[] {Long.toString(accountId),
                    Long.toString(Mailbox.TYPE_EAS_ACCOUNT_MAILBOX)}, null);
        try {
            if (c.moveToFirst()) {
                synchronized(sSyncToken) {
                    Mailbox m = new Mailbox().restore(c);
                    Account acct = Account.restoreAccountWithId(context, accountId);
                    if (acct == null) {
                        return;
                    }
                    String syncKey = acct.mSyncKey;
                    // No need to reload the list if we don't have one
                    if (!force && (syncKey == null || syncKey.equals("0"))) {
                        return;
                    }

                    // Change all ping/push boxes to push/hold
                    ContentValues cv = new ContentValues();
                    cv.put(Mailbox.SYNC_INTERVAL, Mailbox.CHECK_INTERVAL_PUSH_HOLD);
                    context.getContentResolver().update(Mailbox.CONTENT_URI, cv,
                            WHERE_PUSH_OR_PING_NOT_ACCOUNT_MAILBOX,
                            new String[] {Long.toString(accountId)});
                    INSTANCE.log("Set push/ping boxes to push/hold");

                    long id = m.mId;
                    AbstractSyncService svc = INSTANCE.mServiceMap.get(id);
                    // Tell the service we're done
                    if (svc != null) {
                        synchronized (svc.getSynchronizer()) {
                            svc.stop();
                        }
                        // Interrupt the thread so that it can stop
                        Thread thread = svc.mThread;
                        thread.setName(thread.getName() + " (Stopped)");
                        thread.interrupt();
                        // Abandon the service
                        INSTANCE.releaseMailbox(id);
                        // And have it start naturally
                        kick("reload folder list");
                    }
                }
            }
        } finally {
            c.close();
        }
    }

    /**
     * Informs SyncManager that an account has a new folder list; as a result, any existing folder
     * might have become invalid.  Therefore, we act as if the account has been deleted, and then
     * we reinitialize it.
     *
     * @param acctId
     */
    static public void folderListReloaded(long acctId) {
        if (INSTANCE != null) {
            INSTANCE.stopAccountSyncs(acctId, false);
            kick("reload folder list");
        }
    }

    private void acquireWakeLock(long id) {
        synchronized (mWakeLocks) {
            Boolean lock = mWakeLocks.get(id);
            if (lock == null) {
                if (mWakeLock == null) {
                    PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
                    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MAIL_SERVICE");
                    mWakeLock.acquire();
                    log("+WAKE LOCK ACQUIRED");
                }
                mWakeLocks.put(id, true);
             }
        }
    }

    private void releaseWakeLock(long id) {
        synchronized (mWakeLocks) {
            Boolean lock = mWakeLocks.get(id);
            if (lock != null) {
                mWakeLocks.remove(id);
                if (mWakeLocks.isEmpty()) {
                    if (mWakeLock != null) {
                        mWakeLock.release();
                    }
                    mWakeLock = null;
                    log("+WAKE LOCK RELEASED");
                } else {
                }
            }
        }
    }

    static public String alarmOwner(long id) {
        if (id == SYNC_MANAGER_ID) {
            return "SyncManager";
        } else {
            String name = Long.toString(id);
            if (Eas.USER_LOG && INSTANCE != null) {
                Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, id);
                if (m != null) {
                    name = m.mDisplayName + '(' + m.mAccountKey + ')';
                }
            }
            return "Mailbox " + name;
        }
    }

    private void clearAlarm(long id) {
        synchronized (mPendingIntents) {
            PendingIntent pi = mPendingIntents.get(id);
            if (pi != null) {
                AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
                alarmManager.cancel(pi);
                log("+Alarm cleared for " + alarmOwner(id));
                mPendingIntents.remove(id);
            }
        }
    }

    private void setAlarm(long id, long millis) {
        synchronized (mPendingIntents) {
            PendingIntent pi = mPendingIntents.get(id);
            if (pi == null) {
                Intent i = new Intent(this, MailboxAlarmReceiver.class);
                i.putExtra("mailbox", id);
                i.setData(Uri.parse("Box" + id));
                pi = PendingIntent.getBroadcast(this, 0, i, 0);
                mPendingIntents.put(id, pi);

                AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
                alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + millis, pi);
                log("+Alarm set for " + alarmOwner(id) + ", " + millis/1000 + "s");
            }
        }
    }

    private void clearAlarms() {
        AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
        synchronized (mPendingIntents) {
            for (PendingIntent pi : mPendingIntents.values()) {
                alarmManager.cancel(pi);
            }
            mPendingIntents.clear();
        }
    }

    static public void runAwake(long id) {
        if (INSTANCE == null) return;
        INSTANCE.acquireWakeLock(id);
        INSTANCE.clearAlarm(id);
    }

    static public void runAsleep(long id, long millis) {
        if (INSTANCE == null) return;
        INSTANCE.setAlarm(id, millis);
        INSTANCE.releaseWakeLock(id);
    }

    static public void ping(Context context, long id) {
        checkSyncManagerServiceRunning();
        if (id < 0) {
            kick("ping SyncManager");
        } else if (INSTANCE == null) {
            context.startService(new Intent(context, SyncManager.class));
        } else {
            AbstractSyncService service = INSTANCE.mServiceMap.get(id);
            if (service != null) {
                Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, id);
                if (m != null) {
                    // We ignore drafts completely (doesn't sync).  Changes in Outbox are handled
                    // in the checkMailboxes loop, so we can ignore these pings.
                    if (m.mType == Mailbox.TYPE_DRAFTS || m.mType == Mailbox.TYPE_OUTBOX) {
                        String[] args = new String[] {Long.toString(m.mId)};
                        ContentResolver resolver = INSTANCE.mResolver;
                        resolver.delete(Message.DELETED_CONTENT_URI, WHERE_MAILBOX_KEY, args);
                        resolver.delete(Message.UPDATED_CONTENT_URI, WHERE_MAILBOX_KEY, args);
                        return;
                    }
                    service.mAccount = Account.restoreAccountWithId(INSTANCE, m.mAccountKey);
                    service.mMailbox = m;
                    service.ping();
                }
            }
        }
    }

    /**
     * See if we need to change the syncInterval for any of our PIM mailboxes based on changes
     * to settings in the AccountManager (sync settings).
     * This code is called 1) when SyncManager starts, and 2) when SyncManager is running and there
     * are changes made (this is detected via a SyncStatusObserver)
     */
    private void updatePIMSyncSettings(Account providerAccount, int mailboxType, String authority) {
        ContentValues cv = new ContentValues();
        long mailboxId =
            Mailbox.findMailboxOfType(this, providerAccount.mId, mailboxType);
        // Presumably there is one, but if not, it's ok.  Just move on...
        if (mailboxId != Mailbox.NO_MAILBOX) {
            // Create an AccountManager style Account
            android.accounts.Account acct =
                new android.accounts.Account(providerAccount.mEmailAddress,
                        Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
            // Get the mailbox; this happens rarely so it's ok to get it all
            Mailbox mailbox = Mailbox.restoreMailboxWithId(this, mailboxId);
            int syncInterval = mailbox.mSyncInterval;
            // If we're syncable, look further...
            if (ContentResolver.getIsSyncable(acct, authority) > 0) {
                // If we're supposed to sync automatically (push), set to push if it's not
                if (ContentResolver.getSyncAutomatically(acct, authority)) {
                    if (syncInterval == Mailbox.CHECK_INTERVAL_NEVER || syncInterval > 0) {
                        log("Sync for " + mailbox.mDisplayName + " in " + acct.name + ": push");
                        cv.put(MailboxColumns.SYNC_INTERVAL, Mailbox.CHECK_INTERVAL_PUSH);
                    }
                    // If we're NOT supposed to push, and we're not set up that way, change it
                } else if (syncInterval != Mailbox.CHECK_INTERVAL_NEVER) {
                    log("Sync for " + mailbox.mDisplayName + " in " + acct.name + ": manual");
                    cv.put(MailboxColumns.SYNC_INTERVAL, Mailbox.CHECK_INTERVAL_NEVER);
                }
                // If not, set it to never check
            } else if (syncInterval != Mailbox.CHECK_INTERVAL_NEVER) {
                log("Sync for " + mailbox.mDisplayName + " in " + acct.name + ": manual");
                cv.put(MailboxColumns.SYNC_INTERVAL, Mailbox.CHECK_INTERVAL_NEVER);
            }

            // If we've made a change, update the Mailbox, and kick
            if (cv.containsKey(MailboxColumns.SYNC_INTERVAL)) {
                mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
                        cv,null, null);
                kick("sync settings change");
            }
        }
    }

    /**
     * Make our sync settings match those of AccountManager
     */
    private void checkPIMSyncSettings() {
        List<Account> easAccounts = getAccountList();
        for (Account easAccount: easAccounts) {
            updatePIMSyncSettings(easAccount, Mailbox.TYPE_CONTACTS, ContactsContract.AUTHORITY);
            updatePIMSyncSettings(easAccount, Mailbox.TYPE_CALENDAR, Calendar.AUTHORITY);
        }
    }

    /**
     * Compare our account list (obtained from EmailProvider) with the account list owned by
     * AccountManager.  If there are any orphans (an account in one list without a corresponding
     * account in the other list), delete the orphan, as these must remain in sync.
     *
     * Note that the duplication of account information is caused by the Email application's
     * incomplete integration with AccountManager.
     *
     * This function may not be called from the main/UI thread, because it makes blocking calls
     * into the account manager.
     *
     * @param context The context in which to operate
     * @param cachedEasAccounts the exchange provider accounts to work from
     * @param accountManagerAccounts The account manager accounts to work from
     * @param blockExternalChanges FOR TESTING ONLY - block backups, security changes, etc.
     * @param resolver the content resolver for making provider updates (injected for testability)
     */
    /* package */ static void reconcileAccountsWithAccountManager(Context context,
            List<Account> cachedEasAccounts, android.accounts.Account[] accountManagerAccounts,
            boolean blockExternalChanges, ContentResolver resolver) {
        // First, look through our cached EAS Accounts (from EmailProvider) to make sure there's a
        // corresponding AccountManager account
        boolean accountsDeleted = false;
        for (Account providerAccount: cachedEasAccounts) {
            String providerAccountName = providerAccount.mEmailAddress;
            boolean found = false;
            for (android.accounts.Account accountManagerAccount: accountManagerAccounts) {
                if (accountManagerAccount.name.equalsIgnoreCase(providerAccountName)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                if ((providerAccount.mFlags & Account.FLAGS_INCOMPLETE) != 0) {
                    log("Account reconciler noticed incomplete account; ignoring");
                    continue;
                }
                // This account has been deleted in the AccountManager!
                alwaysLog("Account deleted in AccountManager; deleting from provider: " +
                        providerAccountName);
                // TODO This will orphan downloaded attachments; need to handle this
                resolver.delete(ContentUris.withAppendedId(Account.CONTENT_URI,
                        providerAccount.mId), null, null);
                accountsDeleted = true;
            }
        }
        // Now, look through AccountManager accounts to make sure we have a corresponding cached EAS
        // account from EmailProvider
        for (android.accounts.Account accountManagerAccount: accountManagerAccounts) {
            String accountManagerAccountName = accountManagerAccount.name;
            boolean found = false;
            for (Account cachedEasAccount: cachedEasAccounts) {
                if (cachedEasAccount.mEmailAddress.equalsIgnoreCase(accountManagerAccountName)) {
                    found = true;
                }
            }
            if (!found) {
                // This account has been deleted from the EmailProvider database
                alwaysLog("Account deleted from provider; deleting from AccountManager: " +
                        accountManagerAccountName);
                // Delete the account
                AccountManagerFuture<Boolean> blockingResult = AccountManager.get(context)
                        .removeAccount(accountManagerAccount, null, null);
                try {
                    // Note: All of the potential errors from removeAccount() are simply logged
                    // here, as there is nothing to actually do about them.
                    blockingResult.getResult();
                } catch (OperationCanceledException e) {
                    Log.w(Email.LOG_TAG, e.toString());
                } catch (AuthenticatorException e) {
                    Log.w(Email.LOG_TAG, e.toString());
                } catch (IOException e) {
                    Log.w(Email.LOG_TAG, e.toString());
                }
                accountsDeleted = true;
            }
        }
        // If we changed the list of accounts, refresh the backup & security settings
        if (!blockExternalChanges && accountsDeleted) {
            AccountBackupRestore.backupAccounts(context);
            SecurityPolicy.getInstance(context).reducePolicies();
        }
    }

    private void releaseConnectivityLock(String reason) {
        // Clear i/o error holds for all accounts
        releaseSyncHolds(this, AbstractSyncService.EXIT_IO_ERROR, null);
        synchronized (sConnectivityLock) {
            sConnectivityLock.notifyAll();
        }
        kick(reason);
    }

    public class ConnectivityReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle b = intent.getExtras();
            if (b != null) {
                NetworkInfo a = (NetworkInfo)b.get(ConnectivityManager.EXTRA_NETWORK_INFO);
                String info = "Connectivity alert for " + a.getTypeName();
                State state = a.getState();
                if (state == State.CONNECTED) {
                    info += " CONNECTED";
                    log(info);
                    releaseConnectivityLock("connected");
                } else if (state == State.DISCONNECTED) {
                    info += " DISCONNECTED";
                    a = (NetworkInfo)b.get(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
                    if (a != null && a.getState() == State.CONNECTED) {
                        info += " (OTHER CONNECTED)";
                        releaseConnectivityLock("disconnect/other");
                        ConnectivityManager cm =
                            (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
                        if (cm != null) {
                            NetworkInfo i = cm.getActiveNetworkInfo();
                            if (i == null || i.getState() != State.CONNECTED) {
                                log("CM says we're connected, but no active info?");
                            }
                        }
                    } else {
                        log(info);
                        kick("disconnected");
                    }
                }
            }
        }
    }

    private void startService(AbstractSyncService service, Mailbox m) {
        synchronized (sSyncToken) {
            String mailboxName = m.mDisplayName;
            String accountName = service.mAccount.mDisplayName;
            Thread thread = new Thread(service, mailboxName + "(" + accountName + ")");
            log("Starting thread for " + mailboxName + " in account " + accountName);
            thread.start();
            mServiceMap.put(m.mId, service);
            runAwake(m.mId);
        }
    }

    private void startService(Mailbox m, int reason, Request req) {
        // Don't sync if there's no connectivity
        if (sConnectivityHold) return;
        synchronized (sSyncToken) {
            Account acct = Account.restoreAccountWithId(this, m.mAccountKey);
            if (acct != null) {
                // Always make sure there's not a running instance of this service
                AbstractSyncService service = mServiceMap.get(m.mId);
                if (service == null) {
                    service = new EasSyncService(this, m);
                    if (!((EasSyncService)service).mIsValid) return;
                    service.mSyncReason = reason;
                    if (req != null) {
                        service.addRequest(req);
                    }
                    startService(service, m);
                }
            }
        }
    }

    private void stopServices() {
        synchronized (sSyncToken) {
            ArrayList<Long> toStop = new ArrayList<Long>();

            // Keep track of which services to stop
            for (Long mailboxId : mServiceMap.keySet()) {
                toStop.add(mailboxId);
            }

            // Shut down all of those running services
            for (Long mailboxId : toStop) {
                AbstractSyncService svc = mServiceMap.get(mailboxId);
                if (svc != null) {
                    log("Stopping " + svc.mAccount.mDisplayName + '/' + svc.mMailbox.mDisplayName);
                    svc.stop();
                    if (svc.mThread != null) {
                        svc.mThread.interrupt();
                    }
                }
                releaseWakeLock(mailboxId);
            }
        }
    }

    private void waitForConnectivity() {
        int cnt = 0;
        while (!mStop) {
            ConnectivityManager cm =
                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo info = cm.getActiveNetworkInfo();
            if (info != null) {
                //log("NetworkInfo: " + info.getTypeName() + ", " + info.getState().name());
                return;
            } else {

                // If we're waiting for the long haul, shut down running service threads
                if (++cnt > 1) {
                    stopServices();
                }

                // Wait until a network is connected, but let the device sleep
                // We'll set an alarm just in case we don't get notified (bugs happen)
                synchronized (sConnectivityLock) {
                    runAsleep(SYNC_MANAGER_ID, CONNECTIVITY_WAIT_TIME+5*SECONDS);
                    try {
                        log("Connectivity lock...");
                        sConnectivityHold = true;
                        sConnectivityLock.wait(CONNECTIVITY_WAIT_TIME);
                        log("Connectivity lock released...");
                    } catch (InterruptedException e) {
                    } finally {
                        sConnectivityHold = false;
                    }
                    runAwake(SYNC_MANAGER_ID);
                }
            }
        }
    }

    public void run() {
        mStop = false;

        // If we're really debugging, turn on all logging
        if (Eas.DEBUG) {
            Eas.USER_LOG = true;
            Eas.PARSER_LOG = true;
            Eas.FILE_LOG = true;
        }

        // If we need to wait for the debugger, do so
        if (Eas.WAIT_DEBUG) {
            Debug.waitForDebugger();
        }

        // Set up our observers; we need them to know when to start/stop various syncs based
        // on the insert/delete/update of mailboxes and accounts
        // We also observe synced messages to trigger upsyncs at the appropriate time
        mResolver.registerContentObserver(Mailbox.CONTENT_URI, false, mMailboxObserver);
        mResolver.registerContentObserver(Message.SYNCED_CONTENT_URI, true, mSyncedMessageObserver);
        mResolver.registerContentObserver(Message.CONTENT_URI, true, mMessageObserver);
        ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS,
                mSyncStatusObserver);
        mAccountsUpdatedListener = new EasAccountsUpdatedListener();
        AccountManager.get(getApplication())
            .addOnAccountsUpdatedListener(mAccountsUpdatedListener, mHandler, true);

        mConnectivityReceiver = new ConnectivityReceiver();
        registerReceiver(mConnectivityReceiver,
                new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

        // See if any settings have changed while we weren't running...
        checkPIMSyncSettings();

        try {
            while (!mStop) {
                runAwake(SYNC_MANAGER_ID);
                waitForConnectivity();
                mNextWaitReason = "Heartbeat";
                long nextWait = checkMailboxes();
                try {
                    synchronized (this) {
                        if (!mKicked) {
                            if (nextWait < 0) {
                                log("Negative wait? Setting to 1s");
                                nextWait = 1*SECONDS;
                            }
                            if (nextWait > 10*SECONDS) {
                                log("Next awake in " + nextWait / 1000 + "s: " + mNextWaitReason);
                                runAsleep(SYNC_MANAGER_ID, nextWait + (3*SECONDS));
                            }
                            wait(nextWait);
                        }
                    }
                } catch (InterruptedException e) {
                    // Needs to be caught, but causes no problem
                } finally {
                    synchronized (this) {
                        if (mKicked) {
                            //log("Wait deferred due to kick");
                            mKicked = false;
                        }
                    }
                }
            }
            stopServices();
            log("Shutdown requested");
        } finally {
            // Lots of cleanup here
            // Stop our running syncs
            stopServices();

            // Stop receivers and content observers
            if (mConnectivityReceiver != null) {
                unregisterReceiver(mConnectivityReceiver);
            }

            if (INSTANCE != null) {
                ContentResolver resolver = getContentResolver();
                resolver.unregisterContentObserver(mAccountObserver);
                resolver.unregisterContentObserver(mMailboxObserver);
                resolver.unregisterContentObserver(mSyncedMessageObserver);
                resolver.unregisterContentObserver(mMessageObserver);
                unregisterCalendarObservers();
            }
            // Don't leak the Intent associated with this listener
            if (mAccountsUpdatedListener != null) {
                AccountManager.get(this).removeOnAccountsUpdatedListener(mAccountsUpdatedListener);
                mAccountsUpdatedListener = null;
            }

            // Clear pending alarms and associated Intents
            clearAlarms();

            // Release our wake lock, if we have one
            synchronized (mWakeLocks) {
                if (mWakeLock != null) {
                    mWakeLock.release();
                    mWakeLock = null;
                }
            }

            log("Goodbye");
        }

        if (!mStop) {
            // If this wasn't intentional, try to restart the service
            throw new RuntimeException("EAS SyncManager crash; please restart me...");
       }
    }

    private void releaseMailbox(long mailboxId) {
        mServiceMap.remove(mailboxId);
        releaseWakeLock(mailboxId);
    }

    private long checkMailboxes () {
        // First, see if any running mailboxes have been deleted
        ArrayList<Long> deletedMailboxes = new ArrayList<Long>();
        synchronized (sSyncToken) {
            for (long mailboxId: mServiceMap.keySet()) {
                Mailbox m = Mailbox.restoreMailboxWithId(this, mailboxId);
                if (m == null) {
                    deletedMailboxes.add(mailboxId);
                }
            }
            // If so, stop them or remove them from the map
            for (Long mailboxId: deletedMailboxes) {
                AbstractSyncService svc = mServiceMap.get(mailboxId);
                if (svc == null || svc.mThread == null) {
                    releaseMailbox(mailboxId);
                    continue;
                } else {
                    boolean alive = svc.mThread.isAlive();
                    log("Deleted mailbox: " + svc.mMailboxName);
                    if (alive) {
                        stopManualSync(mailboxId);
                    } else {
                        log("Removing from serviceMap");
                        releaseMailbox(mailboxId);
                    }
                }
            }
        }

        long nextWait = SYNC_MANAGER_HEARTBEAT_TIME;
        long now = System.currentTimeMillis();

        // Start up threads that need it; use a query which finds eas mailboxes where the
        // the sync interval is not "never".  This is the set of mailboxes that we control
        if (mAccountObserver == null) return nextWait;
        Cursor c = getContentResolver().query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION,
                mAccountObserver.getSyncableEasMailboxWhere(), null, null);

        try {
            while (c.moveToNext()) {
                long mid = c.getLong(Mailbox.CONTENT_ID_COLUMN);
                AbstractSyncService service = null;
                synchronized (sSyncToken) {
                    service = mServiceMap.get(mid);
                }
                if (service == null) {
                    // Check whether we're in a hold (temporary or permanent)
                    SyncError syncError = mSyncErrorMap.get(mid);
                    if (syncError != null) {
                        // Nothing we can do about fatal errors
                        if (syncError.fatal) continue;
                        if (now < syncError.holdEndTime) {
                            // If release time is earlier than next wait time,
                            // move next wait time up to the release time
                            if (syncError.holdEndTime < now + nextWait) {
                                nextWait = syncError.holdEndTime - now;
                                mNextWaitReason = "Release hold";
                            }
                            continue;
                        } else {
                            // Keep the error around, but clear the end time
                            syncError.holdEndTime = 0;
                        }
                    }

                    // We handle a few types of mailboxes specially
                    int type = c.getInt(Mailbox.CONTENT_TYPE_COLUMN);
                    if (type == Mailbox.TYPE_CONTACTS || type == Mailbox.TYPE_CALENDAR) {
                        // Get the right authority for the mailbox
                        String authority;
                        Account account =
                            getAccountById(c.getInt(Mailbox.CONTENT_ACCOUNT_KEY_COLUMN));
                        if (account != null) {
                            if (type == Mailbox.TYPE_CONTACTS) {
                                authority = ContactsContract.AUTHORITY;
                            } else {
                                authority = Calendar.AUTHORITY;
                                if (!mCalendarObservers.containsKey(account.mId)){
                                    // Make sure we have an observer for this Calendar, as
                                    // we need to be able to detect sync state changes, sigh
                                    registerCalendarObserver(account);
                                }
                            }
                            android.accounts.Account a =
                                new android.accounts.Account(account.mEmailAddress,
                                        Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                            // See if "sync automatically" is set; if not, punt
                            if (!ContentResolver.getSyncAutomatically(a, authority)) {
                                continue;
                            }
                        }
                    } else if (type == Mailbox.TYPE_TRASH) {
                        continue;
                    }

                    // Otherwise, we use the sync interval
                    long interval = c.getInt(Mailbox.CONTENT_SYNC_INTERVAL_COLUMN);
                    if (interval == Mailbox.CHECK_INTERVAL_PUSH) {
                        Mailbox m = EmailContent.getContent(c, Mailbox.class);
                        startService(m, SYNC_PUSH, null);
                    } else if (type == Mailbox.TYPE_OUTBOX) {
                        int cnt = EmailContent.count(this, Message.CONTENT_URI,
                                EasOutboxService.MAILBOX_KEY_AND_NOT_SEND_FAILED,
                                new String[] {Long.toString(mid)});
                        if (cnt > 0) {
                            Mailbox m = EmailContent.getContent(c, Mailbox.class);
                            startService(new EasOutboxService(this, m), m);
                        }
                    } else if (interval > 0 && interval <= ONE_DAY_MINUTES) {
                        long lastSync = c.getLong(Mailbox.CONTENT_SYNC_TIME_COLUMN);
                        long sinceLastSync = now - lastSync;
                        if (sinceLastSync < 0) {
                            log("WHOA! lastSync in the future for mailbox: " + mid);
                            sinceLastSync = interval*MINUTES;
                        }
                        long toNextSync = interval*MINUTES - sinceLastSync;
                        String name = c.getString(Mailbox.CONTENT_DISPLAY_NAME_COLUMN);
                        if (toNextSync <= 0) {
                            Mailbox m = EmailContent.getContent(c, Mailbox.class);
                            startService(m, SYNC_SCHEDULED, null);
                        } else if (toNextSync < nextWait) {
                            nextWait = toNextSync;
                            if (Eas.USER_LOG) {
                                log("Next sync for " + name + " in " + nextWait/1000 + "s");
                            }
                            mNextWaitReason = "Scheduled sync, " + name;
                        } else if (Eas.USER_LOG) {
                            log("Next sync for " + name + " in " + toNextSync/1000 + "s");
                        }
                    }
                } else {
                    Thread thread = service.mThread;
                    // Look for threads that have died but aren't in an error state
                    if (thread != null && !thread.isAlive() && !mSyncErrorMap.containsKey(mid)) {
                        releaseMailbox(mid);
                        // Restart this if necessary
                        if (nextWait > 3*SECONDS) {
                            nextWait = 3*SECONDS;
                            mNextWaitReason = "Clean up dead thread(s)";
                        }
                    } else {
                        long requestTime = service.mRequestTime;
                        if (requestTime > 0) {
                            long timeToRequest = requestTime - now;
                            if (service instanceof AbstractSyncService && timeToRequest <= 0) {
                                service.mRequestTime = 0;
                                service.ping();
                            } else if (requestTime > 0 && timeToRequest < nextWait) {
                                if (timeToRequest < 11*MINUTES) {
                                    nextWait = timeToRequest < 250 ? 250 : timeToRequest;
                                    mNextWaitReason = "Sync data change";
                                } else {
                                    log("Illegal timeToRequest: " + timeToRequest);
                                }
                            }
                        }
                    }
                }
            }
        } finally {
            c.close();
        }
        return nextWait;
    }

    static public void serviceRequest(long mailboxId, int reason) {
        serviceRequest(mailboxId, 5*SECONDS, reason);
    }

    static public void serviceRequest(long mailboxId, long ms, int reason) {
        if (INSTANCE == null) return;
        Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
        // Never allow manual start of Drafts or Outbox via serviceRequest
        if (m == null || m.mType == Mailbox.TYPE_DRAFTS || m.mType == Mailbox.TYPE_OUTBOX) {
            INSTANCE.log("Ignoring serviceRequest for drafts/outbox");
            return;
        }
        try {
            AbstractSyncService service = INSTANCE.mServiceMap.get(mailboxId);
            if (service != null) {
                service.mRequestTime = System.currentTimeMillis() + ms;
                kick("service request");
            } else {
                startManualSync(mailboxId, reason, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static public void serviceRequestImmediate(long mailboxId) {
        if (INSTANCE == null) return;
        AbstractSyncService service = INSTANCE.mServiceMap.get(mailboxId);
        if (service != null) {
            service.mRequestTime = System.currentTimeMillis();
            Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
            if (m != null) {
                service.mAccount = Account.restoreAccountWithId(INSTANCE, m.mAccountKey);
                service.mMailbox = m;
                kick("service request immediate");
            }
        }
    }

    static public void sendMessageRequest(Request req) {
        if (INSTANCE == null) return;
        Message msg = Message.restoreMessageWithId(INSTANCE, req.mMessageId);
        if (msg == null) {
            return;
        }
        long mailboxId = msg.mMailboxKey;
        AbstractSyncService service = INSTANCE.mServiceMap.get(mailboxId);

        if (service == null) {
            service = startManualSync(mailboxId, SYNC_SERVICE_PART_REQUEST, req);
            kick("part request");
        } else {
            service.addRequest(req);
        }
    }

    /**
     * Determine whether a given Mailbox can be synced, i.e. is not already syncing and is not in
     * an error state
     *
     * @param mailboxId
     * @return whether or not the Mailbox is available for syncing (i.e. is a valid push target)
     */
    static public int pingStatus(long mailboxId) {
        // Already syncing...
        if (INSTANCE.mServiceMap.get(mailboxId) != null) {
            return PING_STATUS_RUNNING;
        }
        // No errors or a transient error, don't ping...
        SyncError error = INSTANCE.mSyncErrorMap.get(mailboxId);
        if (error != null) {
            if (error.fatal) {
                return PING_STATUS_UNABLE;
            } else if (error.holdEndTime > 0) {
                return PING_STATUS_WAITING;
            }
        }
        return PING_STATUS_OK;
    }

    static public AbstractSyncService startManualSync(long mailboxId, int reason, Request req) {
        if (INSTANCE == null || INSTANCE.mServiceMap == null) return null;
        synchronized (sSyncToken) {
            if (INSTANCE.mServiceMap.get(mailboxId) == null) {
                INSTANCE.mSyncErrorMap.remove(mailboxId);
                Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
                if (m != null) {
                    INSTANCE.log("Starting sync for " + m.mDisplayName);
                    INSTANCE.startService(m, reason, req);
                }
            }
        }
        return INSTANCE.mServiceMap.get(mailboxId);
    }

    // DO NOT CALL THIS IN A LOOP ON THE SERVICEMAP
    static private void stopManualSync(long mailboxId) {
        if (INSTANCE == null || INSTANCE.mServiceMap == null) return;
        synchronized (sSyncToken) {
            AbstractSyncService svc = INSTANCE.mServiceMap.get(mailboxId);
            if (svc != null) {
                INSTANCE.log("Stopping sync for " + svc.mMailboxName);
                svc.stop();
                svc.mThread.interrupt();
                INSTANCE.releaseWakeLock(mailboxId);
            }
        }
    }

    /**
     * Wake up SyncManager to check for mailboxes needing service
     */
    static public void kick(String reason) {
       if (INSTANCE != null) {
            synchronized (INSTANCE) {
                INSTANCE.log("Kick: " + reason);
                INSTANCE.mKicked = true;
                INSTANCE.notify();
            }
        }
        if (sConnectivityLock != null) {
            synchronized (sConnectivityLock) {
                sConnectivityLock.notify();
            }
        }
    }

    static public void accountUpdated(long acctId) {
        if (INSTANCE == null) return;
        synchronized (sSyncToken) {
            for (AbstractSyncService svc : INSTANCE.mServiceMap.values()) {
                if (svc.mAccount.mId == acctId) {
                    svc.mAccount = Account.restoreAccountWithId(INSTANCE, acctId);
                }
            }
        }
    }

    /**
     * Sent by services indicating that their thread is finished; action depends on the exitStatus
     * of the service.
     *
     * @param svc the service that is finished
     */
    static public void done(AbstractSyncService svc) {
        if (INSTANCE == null) return;
        synchronized(sSyncToken) {
            long mailboxId = svc.mMailboxId;
            HashMap<Long, SyncError> errorMap = INSTANCE.mSyncErrorMap;
            SyncError syncError = errorMap.get(mailboxId);
            INSTANCE.releaseMailbox(mailboxId);
            int exitStatus = svc.mExitStatus;
            switch (exitStatus) {
                case AbstractSyncService.EXIT_DONE:
                    if (!svc.mRequests.isEmpty()) {
                        // TODO Handle this case
                    }
                    errorMap.remove(mailboxId);
                    break;
                // I/O errors get retried at increasing intervals
                case AbstractSyncService.EXIT_IO_ERROR:
                    Mailbox m = Mailbox.restoreMailboxWithId(INSTANCE, mailboxId);
                    if (m == null) return;
                    if (syncError != null) {
                        syncError.escalate();
                        INSTANCE.log(m.mDisplayName + " held for " + syncError.holdDelay + "ms");
                    } else {
                        errorMap.put(mailboxId, INSTANCE.new SyncError(exitStatus, false));
                        INSTANCE.log(m.mDisplayName + " added to syncErrorMap, hold for 15s");
                    }
                    break;
                // These errors are not retried automatically
                case AbstractSyncService.EXIT_SECURITY_FAILURE:
                case AbstractSyncService.EXIT_LOGIN_FAILURE:
                case AbstractSyncService.EXIT_EXCEPTION:
                    errorMap.put(mailboxId, INSTANCE.new SyncError(exitStatus, true));
                    break;
            }
            kick("sync completed");
        }
    }

    /**
     * Given the status string from a Mailbox, return the type code for the last sync
     * @param status the syncStatus column of a Mailbox
     * @return
     */
    static public int getStatusType(String status) {
        if (status == null) {
            return -1;
        } else {
            return status.charAt(STATUS_TYPE_CHAR) - '0';
        }
    }

    /**
     * Given the status string from a Mailbox, return the change count for the last sync
     * The change count is the number of adds + deletes + changes in the last sync
     * @param status the syncStatus column of a Mailbox
     * @return
     */
    static public int getStatusChangeCount(String status) {
        try {
            String s = status.substring(STATUS_CHANGE_COUNT_OFFSET);
            return Integer.parseInt(s);
        } catch (RuntimeException e) {
            return -1;
        }
    }

    static public Context getContext() {
        return INSTANCE;
    }
}
