/*
 * 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 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.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.provider.ContactsContract;
import android.util.Log;

import com.android.emailcommon.Api;
import com.android.emailcommon.TempDirectory;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Attachment;
import com.android.emailcommon.provider.EmailContent.Body;
import com.android.emailcommon.provider.EmailContent.BodyColumns;
import com.android.emailcommon.provider.EmailContent.HostAuthColumns;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.SyncColumns;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.provider.Policy;
import com.android.emailcommon.provider.ProviderUnavailableException;
import com.android.emailcommon.service.AccountServiceProxy;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.emailcommon.service.EmailServiceStatus;
import com.android.emailcommon.service.IEmailService;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.emailcommon.service.PolicyServiceProxy;
import com.android.emailcommon.service.SearchParams;
import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.emailcommon.utility.EmailClientConnectionManager;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.adapter.CalendarSyncAdapter;
import com.android.exchange.adapter.ContactsSyncAdapter;
import com.android.exchange.adapter.Search;
import com.android.exchange.provider.MailboxUtilities;
import com.android.exchange.utility.FileLogger;

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.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * The ExchangeService 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 ExchangeService's binder interface,
 * which exposes UI-related functionality to the application (see the definitions below)
 *
 * ExchangeService 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 ExchangeService extends Service implements Runnable {

    private static final String TAG = "ExchangeService";

    // The ExchangeService's mailbox "id"
    public static final int EXTRA_MAILBOX_ID = -1;
    public static final int EXCHANGE_SERVICE_MAILBOX_ID = 0;

    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 EXCHANGE_SERVICE_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 ExchangeService.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;
    // Misc.
    public static final int SYNC_KICK = 4;
    // A part request (attachment load, for now) was sent to ExchangeService
    public static final int SYNC_SERVICE_PART_REQUEST = 5;

    // Requests >= SYNC_CALLBACK_START generate callbacks to the UI
    public static final int SYNC_CALLBACK_START = 6;
    // startSync was requested of ExchangeService (other than due to user request)
    public static final int SYNC_SERVICE_START_SYNC = SYNC_CALLBACK_START + 0;
    // startSync was requested of ExchangeService (due to user request)
    public static final int SYNC_UI_REQUEST = SYNC_CALLBACK_START + 1;

    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 + ')';
    protected static final String WHERE_IN_ACCOUNT_AND_TYPE_INBOX =
        MailboxColumns.ACCOUNT_KEY + "=? and type = " + Mailbox.TYPE_INBOX ;
    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 (";
    private static final String WHERE_CALENDAR_ID = Events.CALENDAR_ID + "=?";

    // 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;
    // Service is disabled by user (checkbox)
    public static final int PING_STATUS_DISABLED = 4;

    private static final int MAX_CLIENT_CONNECTION_MANAGER_SHUTDOWNS = 1;

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

    // Keeps track of running services (by mailbox id)
    private final HashMap<Long, AbstractSyncService> mServiceMap =
        new HashMap<Long, AbstractSyncService>();
    // Keeps track of services whose last sync ended with an error (by mailbox id)
    /*package*/ ConcurrentHashMap<Long, SyncError> mSyncErrorMap =
        new ConcurrentHashMap<Long, SyncError>();
    // Keeps track of which services require a wake lock (by mailbox id)
    private final HashMap<Long, Boolean> mWakeLocks = new HashMap<Long, Boolean>();
    // Keeps track of PendingIntents for mailbox alarms (by mailbox id)
    private final HashMap<Long, PendingIntent> mPendingIntents = new HashMap<Long, PendingIntent>();
    // The actual WakeLock obtained by ExchangeService
    private WakeLock mWakeLock = null;
    // Keep our cached list of active Accounts here
    public final AccountList mAccountList = new AccountList();

    // Observers that we use to look for changed mail-related data
    private final Handler mHandler = new Handler();
    private AccountObserver mAccountObserver;
    private MailboxObserver mMailboxObserver;
    private SyncedMessageObserver mSyncedMessageObserver;

    // Concurrent because CalendarSyncAdapter can modify the map during a wipe
    private final ConcurrentHashMap<Long, CalendarObserver> mCalendarObservers =
        new ConcurrentHashMap<Long, CalendarObserver>();

    private ContentResolver mResolver;

    // The singleton ExchangeService object, with its thread and stop flag
    protected static ExchangeService INSTANCE;
    private static Thread sServiceThread = null;
    // Cached unique device id
    private static String sDeviceId = null;
    // HashMap of ConnectionManagers that all EAS threads can use (by ssl/port pair)
    private static HashMap<Integer, EmailClientConnectionManager> sClientConnectionManagers =
            new HashMap<Integer, EmailClientConnectionManager>();
    // Count of ClientConnectionManager shutdowns
    private static volatile int sClientConnectionManagerShutdownCount = 0;

    private static volatile boolean sStartingUp = false;
    private static volatile boolean sStop = false;

    // The reason for ExchangeService'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;
    private ConnectivityReceiver mBackgroundDataSettingReceiver = null;
    private volatile boolean mBackgroundData = true;
    // The most current NetworkInfo (from ConnectivityManager)
    private NetworkInfo mNetworkInfo;

    // Callbacks as set up via setCallback
    private final RemoteCallbackList<IEmailServiceCallback> mCallbackList =
        new RemoteCallbackList<IEmailServiceCallback>();

    private interface ServiceCallbackWrapper {
        public void call(IEmailServiceCallback cb) throws RemoteException;
    }

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

        /**
         * Broadcast a callback to the everyone that's registered
         *
         * @param wrapper the ServiceCallbackWrapper used in the broadcast
         */
        private synchronized void broadcastCallback(ServiceCallbackWrapper wrapper) {
            RemoteCallbackList<IEmailServiceCallback> callbackList =
                (INSTANCE == null) ? null: INSTANCE.mCallbackList;
            if (callbackList != null) {
                // Call everyone on our callback list
                int count = callbackList.beginBroadcast();
                try {
                    for (int i = 0; i < count; i++) {
                        try {
                            wrapper.call(callbackList.getBroadcastItem(i));
                        } catch (RemoteException e) {
                            // Safe to ignore
                        } catch (RuntimeException e) {
                            // We don't want an exception in one call to prevent other calls, so
                            // we'll just log this and continue
                            Log.e(TAG, "Caught RuntimeException in broadcast", e);
                        }
                    }
                } finally {
                    // No matter what, we need to finish the broadcast
                    callbackList.finishBroadcast();
                }
            }
        }

        @Override
        public void loadAttachmentStatus(final long messageId, final long attachmentId,
                final int status, final int progress) {
            broadcastCallback(new ServiceCallbackWrapper() {
                @Override
                public void call(IEmailServiceCallback cb) throws RemoteException {
                    cb.loadAttachmentStatus(messageId, attachmentId, status, progress);
                }
            });
        }

        @Override
        public void sendMessageStatus(final long messageId, final String subject, final int status,
                final int progress) {
            broadcastCallback(new ServiceCallbackWrapper() {
                @Override
                public void call(IEmailServiceCallback cb) throws RemoteException {
                    cb.sendMessageStatus(messageId, subject, status, progress);
                }
            });
        }

        @Override
        public void syncMailboxListStatus(final long accountId, final int status,
                final int progress) {
            broadcastCallback(new ServiceCallbackWrapper() {
                @Override
                public void call(IEmailServiceCallback cb) throws RemoteException {
                    cb.syncMailboxListStatus(accountId, status, progress);
                }
            });
        }

        @Override
        public void syncMailboxStatus(final long mailboxId, final int status,
                final int progress) {
            broadcastCallback(new ServiceCallbackWrapper() {
                @Override
                public void call(IEmailServiceCallback cb) throws RemoteException {
                    cb.syncMailboxStatus(mailboxId, status, progress);
                }
            });
        }

        @Override
        public void loadMessageStatus(long messageId, int statusCode, int progress)
                throws RemoteException {
        }
    };

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

        @Override
        public int getApiLevel() {
            return Api.LEVEL;
        }

        @Override
        public Bundle validate(HostAuth hostAuth) throws RemoteException {
            return AbstractSyncService.validate(EasSyncService.class,
                    hostAuth, ExchangeService.this);
        }

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

        @Override
        public void startSync(long mailboxId, boolean userRequest) throws RemoteException {
            ExchangeService exchangeService = INSTANCE;
            if (exchangeService == null) return;
            checkExchangeServiceServiceRunning();
            Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
            if (m == null) return;
            Account acct = Account.restoreAccountWithId(exchangeService, m.mAccountKey);
            if (acct == null) return;
            // If this is a user request and we're being held, release the hold; this allows us to
            // try again (the hold might have been specific to this account and released already)
            if (userRequest) {
                if (onSyncDisabledHold(acct)) {
                    releaseSyncHolds(exchangeService, AbstractSyncService.EXIT_ACCESS_DENIED, acct);
                    log("User requested sync of account in sync disabled hold; releasing");
                } else if (onSecurityHold(acct)) {
                    releaseSyncHolds(exchangeService, AbstractSyncService.EXIT_SECURITY_FAILURE,
                            acct);
                    log("User requested sync of account in security hold; releasing");
                }
                if (sConnectivityHold) {
                    try {
                        // UI is expecting the callbacks....
                        sCallbackProxy.syncMailboxStatus(mailboxId, EmailServiceStatus.IN_PROGRESS,
                                0);
                        sCallbackProxy.syncMailboxStatus(mailboxId,
                                EmailServiceStatus.CONNECTION_ERROR, 0);
                    } catch (RemoteException ignore) {
                    }
                    return;
                }
            }
            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);
                exchangeService.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
                exchangeService.mSyncErrorMap.remove(mailboxId);
                kick("start outbox");
                // Outbox can't be synced in EAS
                return;
            } else if (!isSyncable(m)) {
                try {
                    // UI may be expecting the callbacks, so send them
                    sCallbackProxy.syncMailboxStatus(mailboxId, EmailServiceStatus.IN_PROGRESS, 0);
                    sCallbackProxy.syncMailboxStatus(mailboxId, EmailServiceStatus.SUCCESS, 0);
                } catch (RemoteException ignore) {
                    // We tried
                }
                return;
            }
            startManualSync(mailboxId, userRequest ? ExchangeService.SYNC_UI_REQUEST :
                ExchangeService.SYNC_SERVICE_START_SYNC, null);
        }

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

        @Override
        public void loadAttachment(long attachmentId, boolean background) throws RemoteException {
            Attachment att = Attachment.restoreAttachmentWithId(ExchangeService.this, attachmentId);
            log("loadAttachment " + attachmentId + ": " + att.mFileName);
            sendMessageRequest(new PartRequest(att, null, null));
        }

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

        @Override
        public void hostChanged(long accountId) throws RemoteException {
            ExchangeService exchangeService = INSTANCE;
            if (exchangeService == null) return;
            ConcurrentHashMap<Long, SyncError> syncErrorMap = exchangeService.mSyncErrorMap;
            // 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(exchangeService, 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) {
                    syncErrorMap.remove(mailboxId);
                } else if (error != null && m.mAccountKey == accountId) {
                    error.fatal = false;
                    error.holdEndTime = 0;
                }
            }
            // Stop any running syncs
            exchangeService.stopAccountSyncs(accountId, true);
            // Kick ExchangeService
            kick("host changed");
        }

        @Override
        public void setLogging(int flags) throws RemoteException {
            Eas.setUserDebug(flags);
        }

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

        @Override
        public void loadMore(long messageId) throws RemoteException {
        }

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

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

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

        @Override
        public void setCallback(IEmailServiceCallback cb) throws RemoteException {
            mCallbackList.register(cb);
        }

        /**
         * Delete PIM (calendar, contacts) data for the specified account
         *
         * @param accountId the account whose data should be deleted
         * @throws RemoteException
         */
        @Override
        public void deleteAccountPIMData(long accountId) throws RemoteException {
            ExchangeService exchangeService = INSTANCE;
            if (exchangeService == null) return;
            // Stop any running syncs
            ExchangeService.stopAccountSyncs(accountId);
            // Delete the data
            ExchangeService.deleteAccountPIMData(accountId);
            long accountMailboxId = Mailbox.findMailboxOfType(exchangeService, accountId,
                    Mailbox.TYPE_EAS_ACCOUNT_MAILBOX);
            if (accountMailboxId != Mailbox.NO_MAILBOX) {
                // Make sure the account mailbox is held due to security
                synchronized(sSyncLock) {
                    mSyncErrorMap.put(accountMailboxId, exchangeService.new SyncError(
                            AbstractSyncService.EXIT_SECURITY_FAILURE, false));

                }
            }
            // Make sure the reconciler runs
            runAccountReconcilerSync(ExchangeService.this);
        }

        @Override
        public int searchMessages(long accountId, SearchParams searchParams, long destMailboxId) {
            ExchangeService exchangeService = INSTANCE;
            if (exchangeService == null) return 0;
            return Search.searchMessages(exchangeService, accountId, searchParams,
                    destMailboxId);
        }

        @Override
        public void sendMail(long accountId) throws RemoteException {
        }
    };

    /**
     * Return a list of all Accounts in EmailProvider.  Because the result of this call may be used
     * in account reconciliation, an exception is thrown if the result cannot be guaranteed accurate
     * @param context the caller's context
     * @param accounts a list that Accounts will be added into
     * @return the list of Accounts
     * @throws ProviderUnavailableException if the list of Accounts cannot be guaranteed valid
     */
    private static AccountList collectEasAccounts(Context context, AccountList accounts) {
        ContentResolver resolver = context.getContentResolver();
        Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION, null, null,
                null);
        // We must throw here; callers might use the information we provide for reconciliation, etc.
        if (c == null) throw new ProviderUnavailableException();
        try {
            ContentValues cv = new ContentValues();
            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();
                        account.restore(c);
                        // Cache the HostAuth
                        account.mHostAuthRecv = ha;
                        accounts.add(account);
                        // Fixup flags for inbox (should accept moved mail)
                        Mailbox inbox = Mailbox.restoreMailboxOfType(context, account.mId,
                                Mailbox.TYPE_INBOX);
                        if (inbox != null &&
                                ((inbox.mFlags & Mailbox.FLAG_ACCEPTS_MOVED_MAIL) == 0)) {
                            cv.put(MailboxColumns.FLAGS,
                                    inbox.mFlags | Mailbox.FLAG_ACCEPTS_MOVED_MAIL);
                            resolver.update(
                                    ContentUris.withAppendedId(Mailbox.CONTENT_URI, inbox.mId), cv,
                                    null, null);
                        }
                    }
                }
            }
        } finally {
            c.close();
        }
        return accounts;
    }

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

        @Override
        public boolean add(Account account) {
            // Cache the account manager account
            account.mAmAccount = new android.accounts.Account(account.mEmailAddress,
                    Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
            super.add(account);
            return true;
        }

        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;
        }

        public Account getByName(String accountName) {
            for (Account account : this) {
                if (account.mEmailAddress.equalsIgnoreCase(accountName)) {
                    return account;
                }
            }
            return null;
        }
    }

    public static void deleteAccountPIMData(long accountId) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return;
        Mailbox mailbox =
            Mailbox.restoreMailboxOfType(exchangeService, accountId, Mailbox.TYPE_CONTACTS);
        if (mailbox != null) {
            EasSyncService service = EasSyncService.getServiceForMailbox(exchangeService, mailbox);
            ContactsSyncAdapter adapter = new ContactsSyncAdapter(service);
            adapter.wipe();
        }
        mailbox =
            Mailbox.restoreMailboxOfType(exchangeService, accountId, Mailbox.TYPE_CALENDAR);
        if (mailbox != null) {
            EasSyncService service = EasSyncService.getServiceForMailbox(exchangeService, mailbox);
            CalendarSyncAdapter adapter = new CalendarSyncAdapter(service);
            adapter.wipe();
        }
    }

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

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

    class AccountObserver extends ContentObserver {
        String mSyncableEasMailboxSelector = null;
        String mEasAccountSelector = null;

        // Runs when ExchangeService first starts
        public AccountObserver(Handler handler) {
            super(handler);
            // At startup, we want to see what EAS accounts exist and cache them
            // TODO: Move database work out of UI thread
            Context context = getContext();
            synchronized (mAccountList) {
                try {
                    collectEasAccounts(context, mAccountList);
                } catch (ProviderUnavailableException e) {
                    // Just leave if EmailProvider is unavailable
                    return;
                }
                // Create an account mailbox for any account without one
                for (Account account : mAccountList) {
                    int cnt = Mailbox.count(context, Mailbox.CONTENT_URI, "accountKey="
                            + account.mId, null);
                    if (cnt == 0) {
                        // This case handles a newly created account
                        addAccountMailbox(account.mId);
                    }
                }
            }
            // Run through accounts and update account hold information
            Utility.runAsync(new Runnable() {
                @Override
                public void run() {
                    synchronized (mAccountList) {
                        for (Account account : mAccountList) {
                            if (onSecurityHold(account)) {
                                // If we're in a security hold, and our policies are active, release
                                // the hold
                                if (PolicyServiceProxy.isActive(ExchangeService.this, null)) {
                                    PolicyServiceProxy.setAccountHoldFlag(ExchangeService.this,
                                            account, false);
                                    log("isActive true; release hold for " + account.mDisplayName);
                                }
                            }
                        }
                    }
                }});
        }

        /**
         * 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;
                synchronized (mAccountList) {
                    for (Account account : mAccountList) {
                        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;
                synchronized (mAccountList) {
                    for (Account account : mAccountList) {
                        if (!first) {
                            sb.append(',');
                        } else {
                            first = false;
                        }
                        sb.append(account.mId);
                    }
                }
                sb.append(')');
                mEasAccountSelector = sb.toString();
            }
            return mEasAccountSelector;
        }

        private void onAccountChanged() {
            try {
                maybeStartExchangeServiceThread();
                Context context = getContext();

                // A change to the list requires us to scan for deletions (stop running syncs)
                // At startup, we want to see what accounts exist and cache them
                AccountList currentAccounts = new AccountList();
                try {
                    collectEasAccounts(context, currentAccounts);
                } catch (ProviderUnavailableException e) {
                    // Just leave if EmailProvider is unavailable
                    return;
                }
                synchronized (mAccountList) {
                    for (Account account : mAccountList) {
                        boolean accountIncomplete =
                            (account.mFlags & Account.FLAGS_INCOMPLETE) != 0;
                        // If the current list doesn't include this account and the account wasn't
                        // incomplete, then this is a deletion
                        if (!currentAccounts.contains(account.mId) && !accountIncomplete) {
                            // The implication is that the account has been deleted; let's find out
                            alwaysLog("Observer found deleted account: " + account.mDisplayName);
                            // Run the reconciler (the reconciliation itself runs in the Email app)
                            runAccountReconcilerSync(ExchangeService.this);
                            // See if the account is still around
                            Account deletedAccount =
                                Account.restoreAccountWithId(context, account.mId);
                            if (deletedAccount != null) {
                                // It is; add it to our account list
                                alwaysLog("Account still in provider: " + account.mDisplayName);
                                currentAccounts.add(account);
                            } else {
                                // It isn't; stop syncs and clear our selectors
                                alwaysLog("Account deletion confirmed: " + account.mDisplayName);
                                stopAccountSyncs(account.mId, true);
                                mSyncableEasMailboxSelector = null;
                                mEasAccountSelector = null;
                            }
                        } else {
                            // Get the newest version of this account
                            Account updatedAccount =
                                Account.restoreAccountWithId(context, account.mId);
                            if (updatedAccount == null) continue;
                            if (account.mSyncInterval != updatedAccount.mSyncInterval
                                    || account.mSyncLookback != updatedAccount.mSyncLookback) {
                                // Set the inbox interval to the interval of the Account
                                // This setting should NOT affect other boxes
                                ContentValues cv = new ContentValues();
                                cv.put(MailboxColumns.SYNC_INTERVAL, updatedAccount.mSyncInterval);
                                getContentResolver().update(Mailbox.CONTENT_URI, cv,
                                        WHERE_IN_ACCOUNT_AND_TYPE_INBOX, 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(ExchangeService.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 (!mAccountList.contains(account.mId)) {
                            // Don't forget to cache the HostAuth
                            HostAuth ha = HostAuth.restoreHostAuthWithId(getContext(),
                                    account.mHostAuthKeyRecv);
                            if (ha == null) continue;
                            account.mHostAuthRecv = ha;
                            // This is an addition; create our magic hidden mailbox...
                            log("Account observer found new account: " + account.mDisplayName);
                            addAccountMailbox(account.mId);
                            mAccountList.add(account);
                            mSyncableEasMailboxSelector = null;
                            mEasAccountSelector = null;
                        }
                    }
                    // Finally, make sure our account list is up to date
                    mAccountList.clear();
                    mAccountList.addAll(currentAccounts);
                }

                // See if there's anything to do...
                kick("account changed");
            } catch (ProviderUnavailableException e) {
                alwaysLog("Observer failed; provider unavailable");
            }
        }

        @Override
        public void onChange(boolean selfChange) {
            new Thread(new Runnable() {
               @Override
            public void run() {
                   onAccountChanged();
                }}, "Account Observer").start();
        }

        private void addAccountMailbox(long acctId) {
            Account acct = Account.restoreAccountWithId(getContext(), acctId);
            Mailbox main = new Mailbox();
            main.mDisplayName = Eas.ACCOUNT_MAILBOX_PREFIX;
            main.mServerId = Eas.ACCOUNT_MAILBOX_PREFIX + 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());
            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
     */
    static public void unregisterCalendarObservers() {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return;
        ContentResolver resolver = exchangeService.mResolver;
        for (CalendarObserver observer: exchangeService.mCalendarObservers.values()) {
            resolver.unregisterContentObserver(observer);
        }
        exchangeService.mCalendarObservers.clear();
    }

    /**
     * Return the syncable state of an account's calendar, as determined by the sync_events column
     * of our Calendar (from CalendarProvider2)
     * Note that the current state of sync_events is cached in our CalendarObserver
     * @param accountId the id of the account whose calendar we are checking
     * @return whether or not syncing of events is enabled
     */
    private boolean isCalendarEnabled(long accountId) {
        CalendarObserver observer = mCalendarObservers.get(accountId);
        if (observer != null) {
            return (observer.mSyncEvents == 1);
        }
        // If there's no observer, there's no Calendar in CalendarProvider2, so we return true
        // to allow Calendar creation
        return true;
    }

    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, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE},
                    null);
            if (c != 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 synchronized void onChange(boolean selfChange) {
            // See if the user has changed syncing of our calendar
            if (!selfChange) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Cursor c = mResolver.query(Calendars.CONTENT_URI,
                                    new String[] {Calendars.SYNC_EVENTS}, Calendars._ID + "=?",
                                    new String[] {Long.toString(mCalendarId)}, null);
                            if (c == null) return;
                            // 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) {
                                        log("_sync_events changed for calendar in " + mAccountName);
                                        Mailbox mailbox = Mailbox.restoreMailboxOfType(INSTANCE,
                                                mAccountId, Mailbox.TYPE_CALENDAR);
                                        // Sanity check for mailbox deletion
                                        if (mailbox == null) return;
                                        ContentValues cv = new ContentValues();
                                        if (newSyncEvents == 0) {
                                            // When sync is disabled, we're supposed to delete
                                            // all events in the calendar
                                            log("Deleting events and setting syncKey to 0 for " +
                                                    mAccountName);
                                            // First, stop any sync that's ongoing
                                            stopManualSync(mailbox.mId);
                                            // Set the syncKey to 0 (reset)
                                            EasSyncService service =
                                                EasSyncService.getServiceForMailbox(
                                                        INSTANCE, mailbox);
                                            CalendarSyncAdapter adapter =
                                                new CalendarSyncAdapter(service);
                                            try {
                                                adapter.setSyncKey("0", false);
                                            } catch (IOException e) {
                                                // The provider can't be reached; nothing to be done
                                            }
                                            // Reset the sync key locally and stop syncing
                                            cv.put(Mailbox.SYNC_KEY, "0");
                                            cv.put(Mailbox.SYNC_INTERVAL,
                                                    Mailbox.CHECK_INTERVAL_NEVER);
                                            mResolver.update(ContentUris.withAppendedId(
                                                    Mailbox.CONTENT_URI, mailbox.mId), cv, null,
                                                    null);
                                            // Delete all events using the sync adapter
                                            // parameter so that the deletion is only local
                                            Uri eventsAsSyncAdapter =
                                                CalendarSyncAdapter.asSyncAdapter(
                                                    Events.CONTENT_URI,
                                                    mAccountName,
                                                    Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                                            mResolver.delete(eventsAsSyncAdapter, WHERE_CALENDAR_ID,
                                                    new String[] {Long.toString(mCalendarId)});
                                        } else {
                                            // Make this a push mailbox and kick; this will start
                                            // a resync of the Calendar; the account mailbox will
                                            // ping on this during the next cycle of the ping loop
                                            cv.put(Mailbox.SYNC_INTERVAL,
                                                    Mailbox.CHECK_INTERVAL_PUSH);
                                            mResolver.update(ContentUris.withAppendedId(
                                                    Mailbox.CONTENT_URI, mailbox.mId), cv, null,
                                                    null);
                                            kick("calendar sync changed");
                                        }

                                        // Save away the new value
                                        mSyncEvents = newSyncEvents;
                                    }
                                }
                            } finally {
                                c.close();
                            }
                        } catch (ProviderUnavailableException e) {
                            Log.w(TAG, "Observer failed; provider unavailable");
                        }
                    }}, "Calendar Observer").start();
            }
        }
    }

    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) {
            alarmManager.set(AlarmManager.RTC_WAKEUP,
                    System.currentTimeMillis() + 10*SECONDS, syncAlarmPendingIntent);
        }
    }

    static public IEmailServiceCallback callback() {
        return sCallbackProxy;
    }

    static public Account getAccountById(long accountId) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            AccountList accountList = exchangeService.mAccountList;
            synchronized (accountList) {
                return accountList.getById(accountId);
            }
        }
        return null;
    }

    static public Account getAccountByName(String accountName) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            AccountList accountList = exchangeService.mAccountList;
            synchronized (accountList) {
                return accountList.getByName(accountName);
            }
        }
        return null;
    }

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

    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;
        }
    }

    private void logSyncHolds() {
        if (Eas.USER_LOG) {
            log("Sync holds:");
            long time = System.currentTimeMillis();
            for (long mailboxId : mSyncErrorMap.keySet()) {
                Mailbox m = Mailbox.restoreMailboxWithId(this, mailboxId);
                if (m == null) {
                    log("Mailbox " + mailboxId + " no longer exists");
                } else {
                    SyncError error = mSyncErrorMap.get(mailboxId);
                    if (error != null) {
                        log("Mailbox " + m.mDisplayName + ", error = " + error.reason
                                + ", fatal = " + error.fatal);
                        if (error.holdEndTime > 0) {
                            log("Hold ends in " + ((error.holdEndTime - time) / 1000) + "s");
                        }
                    }
                }
            }
        }
    }

    /**
     * Release security holds for the specified account
     * @param account the account whose Mailboxes should be released from security hold
     */
    static public void releaseSecurityHold(Account account) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            exchangeService.releaseSyncHolds(INSTANCE, AbstractSyncService.EXIT_SECURITY_FAILURE,
                    account);
        }
    }

    /**
     * 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)
     * @return whether or not any mailboxes were released
     */
    /*package*/ boolean releaseSyncHolds(Context context, int reason, Account account) {
        boolean holdWasReleased = releaseSyncHoldsImpl(context, reason, account);
        kick("security release");
        return holdWasReleased;
    }

    private boolean releaseSyncHoldsImpl(Context context, int reason, Account account) {
        boolean holdWasReleased = false;
        for (long mailboxId: mSyncErrorMap.keySet()) {
            if (account != null) {
                Mailbox m = Mailbox.restoreMailboxWithId(context, mailboxId);
                if (m == null) {
                    mSyncErrorMap.remove(mailboxId);
                } else if (m.mAccountKey != account.mId) {
                    continue;
                }
            }
            SyncError error = mSyncErrorMap.get(mailboxId);
            if (error != null && error.reason == reason) {
                mSyncErrorMap.remove(mailboxId);
                holdWasReleased = true;
            }
        }
        return holdWasReleased;
    }

    /**
     * Reconcile Exchange accounts with AccountManager (asynchronous)
     * @param context the caller's Context
     */
    public static void reconcileAccounts(final Context context) {
        Utility.runAsync(new Runnable() {
            @Override
            public void run() {
                ExchangeService exchangeService = INSTANCE;
                if (exchangeService != null) {
                    exchangeService.runAccountReconcilerSync(context);
                }
            }});
    }

    /**
     * Blocking call to the account reconciler
     */
    public static void runAccountReconcilerSync(Context context) {
        alwaysLog("Reconciling accounts...");
        new AccountServiceProxy(context).reconcileAccounts(
                HostAuth.SCHEME_EAS, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
    }

    public static void log(String str) {
        log(TAG, str);
    }

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

    public 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 "device".
     * 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(Context context) throws IOException {
        if (sDeviceId == null) {
            sDeviceId = new AccountServiceProxy(context).getDeviceId();
            alwaysLog("Received deviceId from Email app: " + sDeviceId);
        }
        return sDeviceId;
    }

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

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

    static public synchronized EmailClientConnectionManager getClientConnectionManager(boolean ssl,
            int port) {
        // We'll use a different connection manager for each ssl/port pair
        int key = (ssl ? 0x10000 : 0) + port;
        EmailClientConnectionManager mgr = sClientConnectionManagers.get(key);
        if (mgr == null) {
            // After two tries, kill the process.  Most likely, this will happen in the background
            // The service will restart itself after about 5 seconds
            if (sClientConnectionManagerShutdownCount > MAX_CLIENT_CONNECTION_MANAGER_SHUTDOWNS) {
                alwaysLog("Shutting down process to unblock threads");
                Process.killProcess(Process.myPid());
            }
            HttpParams params = new BasicHttpParams();
            params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 25);
            params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, sConnPerRoute);
            mgr = EmailClientConnectionManager.newInstance(params, ssl, port);
            log("Creating connection manager for port " + port + ", ssl: " + ssl);
            sClientConnectionManagers.put(key, mgr);
        }
        // Null is a valid return result if we get an exception
        return mgr;
    }

    static private synchronized void shutdownConnectionManager() {
        log("Shutting down ClientConnectionManagers");
        for (EmailClientConnectionManager mgr: sClientConnectionManagers.values()) {
            mgr.shutdown();
        }
        sClientConnectionManagers.clear();
    }

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

    private void stopAccountSyncs(long acctId, boolean includeAccountMailbox) {
        synchronized (sSyncLock) {
            List<Long> deletedBoxes = new ArrayList<Long>();
            for (Long mid : mServiceMap.keySet()) {
                Mailbox box = Mailbox.restoreMailboxWithId(this, mid);
                if (box != null) {
                    if (box.mAccountKey == acctId) {
                        if (!includeAccountMailbox &&
                                box.mType == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
                            AbstractSyncService svc = mServiceMap.get(mid);
                            if (svc != null) {
                                svc.stop();
                            }
                            continue;
                        }
                        AbstractSyncService svc = 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 private void reloadFolderListFailed(long accountId) {
        try {
            callback().syncMailboxListStatus(accountId,
                    EmailServiceStatus.ACCOUNT_UNINITIALIZED, 0);
        } catch (RemoteException e1) {
            // Don't care if this fails
        }
    }

    static public void reloadFolderList(Context context, long accountId, boolean force) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == 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(sSyncLock) {
                    Mailbox mailbox = new Mailbox();
                    mailbox.restore(c);
                    Account acct = Account.restoreAccountWithId(context, accountId);
                    if (acct == null) {
                        reloadFolderListFailed(accountId);
                        return;
                    }
                    String syncKey = acct.mSyncKey;
                    // No need to reload the list if we don't have one
                    if (!force && (syncKey == null || syncKey.equals("0"))) {
                        reloadFolderListFailed(accountId);
                        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)});
                    log("Set push/ping boxes to push/hold");

                    long id = mailbox.mId;
                    AbstractSyncService svc = exchangeService.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;
                            if (thread != null) {
                                thread.setName(thread.getName() + " (Stopped)");
                                thread.interrupt();
                            }
                        }
                        // Abandon the service
                        exchangeService.releaseMailbox(id);
                        // And have it start naturally
                        kick("reload folder list");
                    }
                }
            }
        } finally {
            c.close();
        }
    }

    /**
     * Informs ExchangeService 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 stopNonAccountMailboxSyncsForAccount(long acctId) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            exchangeService.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 == EXTRA_MAILBOX_ID) {
            return "ExchangeService";
        } 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) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            exchangeService.acquireWakeLock(id);
            exchangeService.clearAlarm(id);
        }
    }

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

    static public void clearWatchdogAlarm(long id) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            exchangeService.clearAlarm(id);
        }
    }

    static public void setWatchdogAlarm(long id, long millis) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            exchangeService.setAlarm(id, millis);
        }
    }

    static public void alert(Context context, final long id) {
        final ExchangeService exchangeService = INSTANCE;
        checkExchangeServiceServiceRunning();
        if (id < 0) {
            log("ExchangeService alert");
            kick("ping ExchangeService");
        } else if (exchangeService == null) {
            context.startService(new Intent(context, ExchangeService.class));
        } else {
            final AbstractSyncService service = exchangeService.mServiceMap.get(id);
            if (service != null) {
                // Handle alerts in a background thread, as we are typically called from a
                // broadcast receiver, and are therefore running in the UI thread
                String threadName = "ExchangeService Alert: ";
                if (service.mMailbox != null) {
                    threadName += service.mMailbox.mDisplayName;
                }
                new Thread(new Runnable() {
                   @Override
                public void run() {
                       Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, 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 (Eas.USER_LOG) {
                               Log.d(TAG, "Alert for mailbox " + id + " (" + m.mDisplayName + ")");
                           }
                           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;
                           // Send the alarm to the sync service
                           if (!service.alarm()) {
                               // A false return means that we were forced to interrupt the thread
                               // In this case, we release the mailbox so that we can start another
                               // thread to do the work
                               log("Alarm failed; releasing mailbox");
                               synchronized(sSyncLock) {
                                   exchangeService.releaseMailbox(id);
                               }
                               // Shutdown the connection manager; this should close all of our
                               // sockets and generate IOExceptions all around.
                               ExchangeService.shutdownConnectionManager();
                           }
                       }
                    }}, threadName).start();
            }
        }
    }

    public class ConnectivityReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                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);
                        synchronized (sConnectivityLock) {
                            sConnectivityLock.notifyAll();
                        }
                        kick("connected");
                    } else if (state == State.DISCONNECTED) {
                        info += " DISCONNECTED";
                        log(info);
                        kick("disconnected");
                    }
                }
            } else if (intent.getAction().equals(
                    ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED)) {
                ConnectivityManager cm =
                        (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
                mBackgroundData = cm.getBackgroundDataSetting();
                // If background data is now on, we want to kick ExchangeService
                if (mBackgroundData) {
                    kick("background data on");
                    log("Background data on; restart syncs");
                // Otherwise, stop all syncs
                } else {
                    log("Background data off: stop all syncs");
                    EmailAsyncTask.runAsyncParallel(new Runnable() {
                        @Override
                        public void run() {
                            synchronized (mAccountList) {
                                for (Account account : mAccountList)
                                    ExchangeService.stopAccountSyncs(account.mId);
                            }
                        }});
                }
            }
        }
    }

    /**
     * Starts a service thread and enters it into the service map
     * This is the point of instantiation of all sync threads
     * @param service the service to start
     * @param m the Mailbox on which the service will operate
     */
    private void startServiceThread(AbstractSyncService service) {
        synchronized (sSyncLock) {
            Mailbox mailbox = service.mMailbox;
            String mailboxName = mailbox.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(mailbox.mId, service);
            runAwake(mailbox.mId);
            if (mailbox.mServerId != null && mailbox.mType != Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
                stopPing(mailbox.mAccountKey);
            }
        }
    }

    /**
     * Stop any ping in progress for the given account
     * @param accountId
     */
    private void stopPing(long accountId) {
        // Go through our active mailboxes looking for the right one
        synchronized (sSyncLock) {
            for (long mailboxId: mServiceMap.keySet()) {
                Mailbox m = Mailbox.restoreMailboxWithId(this, mailboxId);
                if (m != null) {
                    String serverId = m.mServerId;
                    if (m.mAccountKey == accountId && serverId != null &&
                          m.mType == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
                        // Here's our account mailbox; reset him (stopping pings)
                        AbstractSyncService svc = mServiceMap.get(mailboxId);
                        svc.reset();
                    }
                }
            }
        }
    }

    private void requestSync(Mailbox m, int reason, Request req) {
        int syncStatus = EmailContent.SYNC_STATUS_BACKGROUND;
        // Don't sync if there's no connectivity
        if (sConnectivityHold || (m == null) || sStop) {
            if (reason >= SYNC_CALLBACK_START) {
                try {
                    sCallbackProxy.syncMailboxStatus(m.mId, EmailServiceStatus.CONNECTION_ERROR, 0);
                } catch (RemoteException e) {
                    // We tried...
                }
            }
            return;
        }
        synchronized (sSyncLock) {
            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 = EasSyncService.getServiceForMailbox(this, m);
                    if (!((EasSyncService)service).mIsValid) return;
                    service.mSyncReason = reason;
                    if (req != null) {
                        service.addRequest(req);
                    }
                    startServiceThread(service);
                    if (reason >= SYNC_CALLBACK_START) {
                        syncStatus = EmailContent.SYNC_STATUS_USER;
                    }
                    setMailboxSyncStatus(m.mId, syncStatus);
                }
            }
        }
    }

    private void setMailboxSyncStatus(long id, int status) {
        ContentValues values = new ContentValues();
        values.put(Mailbox.UI_SYNC_STATUS, status);
        mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id), values, null, null);
    }

    private void setMailboxLastSyncResult(long id, int result) {
        ContentValues values = new ContentValues();
        values.put(Mailbox.UI_LAST_SYNC_RESULT, result);
        mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id), values, null, null);
    }

    private void stopServiceThreads() {
        synchronized (sSyncLock) {
            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() {
        boolean waiting = false;
        ConnectivityManager cm =
            (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        while (!sStop) {
            NetworkInfo info = cm.getActiveNetworkInfo();
            if (info != null) {
                mNetworkInfo = info;
                // We're done if there's an active network
                if (waiting) {
                    // If we've been waiting, release any I/O error holds
                    releaseSyncHolds(this, AbstractSyncService.EXIT_IO_ERROR, null);
                    // And log what's still being held
                    logSyncHolds();
                }
                return;
            } else {
                // If this is our first time through the loop, shut down running service threads
                if (!waiting) {
                    waiting = true;
                    stopServiceThreads();
                }
                // Wait until a network is connected (or 10 mins), but let the device sleep
                // We'll set an alarm just in case we don't get notified (bugs happen)
                synchronized (sConnectivityLock) {
                    runAsleep(EXTRA_MAILBOX_ID, CONNECTIVITY_WAIT_TIME+5*SECONDS);
                    try {
                        log("Connectivity lock...");
                        sConnectivityHold = true;
                        sConnectivityLock.wait(CONNECTIVITY_WAIT_TIME);
                        log("Connectivity lock released...");
                    } catch (InterruptedException e) {
                        // This is fine; we just go around the loop again
                    } finally {
                        sConnectivityHold = false;
                    }
                    runAwake(EXTRA_MAILBOX_ID);
                }
            }
        }
    }

    /**
     * Note that there are two ways the EAS ExchangeService 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() {
        Utility.runAsync(new Runnable() {
            @Override
            public void run() {
                // Quick checks first, before getting the lock
                if (sStartingUp) return;
                synchronized (sSyncLock) {
                    alwaysLog("!!! EAS ExchangeService, onCreate");
                    // Try to start up properly; we might be coming back from a crash that the Email
                    // application isn't aware of.
                    startService(new Intent(EmailServiceProxy.EXCHANGE_INTENT));
                    if (sStop) {
                        return;
                    }
                }
            }});
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        alwaysLog("!!! EAS ExchangeService, onStartCommand, startingUp = " + sStartingUp +
                ", running = " + (INSTANCE != null));
        if (!sStartingUp && INSTANCE == null) {
            sStartingUp = true;
            Utility.runAsync(new Runnable() {
                @Override
                public void run() {
                    try {
                        synchronized (sSyncLock) {
                            // ExchangeService cannot start unless we can connect to AccountService
                            if (!new AccountServiceProxy(ExchangeService.this).test()) {
                                alwaysLog("!!! Email application not found; stopping self");
                                stopSelf();
                            }
                            if (sDeviceId == null) {
                                try {
                                    String deviceId = getDeviceId(ExchangeService.this);
                                    if (deviceId != null) {
                                        sDeviceId = deviceId;
                                    }
                                } catch (IOException e) {
                                }
                                if (sDeviceId == null) {
                                    alwaysLog("!!! deviceId unknown; stopping self and retrying");
                                    stopSelf();
                                    // Try to restart ourselves in a few seconds
                                    Utility.runAsync(new Runnable() {
                                        @Override
                                        public void run() {
                                            try {
                                                Thread.sleep(5000);
                                            } catch (InterruptedException e) {
                                            }
                                            startService(new Intent(
                                                    EmailServiceProxy.EXCHANGE_INTENT));
                                        }});
                                    return;
                                }
                            }
                            // Run the reconciler and clean up mismatched accounts - if we weren't
                            // running when accounts were deleted, it won't have been called.
                            runAccountReconcilerSync(ExchangeService.this);
                            // Update other services depending on final account configuration
                            maybeStartExchangeServiceThread();
                            if (sServiceThread == null) {
                                log("!!! EAS ExchangeService, stopping self");
                                stopSelf();
                            } else if (sStop) {
                                // If we were trying to stop, attempt a restart in 5 secs
                                setAlarm(EXCHANGE_SERVICE_MAILBOX_ID, 5*SECONDS);
                            }
                        }
                    } finally {
                        sStartingUp = false;
                    }
                }});
        }
        return Service.START_STICKY;
    }

    @Override
    public void onDestroy() {
        log("!!! EAS ExchangeService, onDestroy");
        // Handle shutting down off the UI thread
        Utility.runAsync(new Runnable() {
            @Override
            public void run() {
                // Quick checks first, before getting the lock
                if (INSTANCE == null || sServiceThread == null) return;
                synchronized(sSyncLock) {
                    // Stop the sync manager thread and return
                    if (sServiceThread != null) {
                        sStop = true;
                        sServiceThread.interrupt();
                    }
                }
            }});
    }

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

    /**
     * Start up the ExchangeService service if it's not already running
     * This is a stopgap for cases in which ExchangeService died (due to a crash somewhere in
     * com.android.email) and hasn't been restarted. See the comment for onCreate for details
     */
    static void checkExchangeServiceServiceRunning() {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return;
        if (sServiceThread == null) {
            log("!!! checkExchangeServiceServiceRunning; starting service...");
            exchangeService.startService(new Intent(exchangeService, ExchangeService.class));
        }
    }

    @Override
    public void run() {
        sStop = false;
        alwaysLog("ExchangeService thread running");
        // If we're really debugging, turn on all logging
        if (Eas.DEBUG) {
            Eas.USER_LOG = true;
            Eas.PARSER_LOG = true;
            Eas.FILE_LOG = true;
        }

        TempDirectory.setTempDirectory(this);

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

        // Synchronize here to prevent a shutdown from happening while we initialize our observers
        // and receivers
        synchronized (sSyncLock) {
            if (INSTANCE != null) {
                mResolver = getContentResolver();

                // 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
                mAccountObserver = new AccountObserver(mHandler);
                mResolver.registerContentObserver(Account.NOTIFIER_URI, true, mAccountObserver);
                mMailboxObserver = new MailboxObserver(mHandler);
                mResolver.registerContentObserver(Mailbox.CONTENT_URI, false, mMailboxObserver);
                mSyncedMessageObserver = new SyncedMessageObserver(mHandler);
                mResolver.registerContentObserver(Message.SYNCED_CONTENT_URI, true,
                        mSyncedMessageObserver);

                // Set up receivers for connectivity and background data setting
                mConnectivityReceiver = new ConnectivityReceiver();
                registerReceiver(mConnectivityReceiver, new IntentFilter(
                        ConnectivityManager.CONNECTIVITY_ACTION));

                mBackgroundDataSettingReceiver = new ConnectivityReceiver();
                registerReceiver(mBackgroundDataSettingReceiver, new IntentFilter(
                        ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED));
                // Save away the current background data setting; we'll keep track of it with the
                // receiver we just registered
                ConnectivityManager cm = (ConnectivityManager)getSystemService(
                        Context.CONNECTIVITY_SERVICE);
                mBackgroundData = cm.getBackgroundDataSetting();

                // Do any required work to clean up our Mailboxes (this serves to upgrade
                // mailboxes that existed prior to EmailProvider database version 17)
                MailboxUtilities.fixupUninitializedParentKeys(this, getEasAccountSelector());
            }
        }

        try {
            // Loop indefinitely until we're shut down
            while (!sStop) {
                runAwake(EXTRA_MAILBOX_ID);
                waitForConnectivity();
                mNextWaitReason = null;
                long nextWait = checkMailboxes();
                try {
                    synchronized (this) {
                        if (!mKicked) {
                            if (nextWait < 0) {
                                log("Negative wait? Setting to 1s");
                                nextWait = 1*SECONDS;
                            }
                            if (nextWait > 10*SECONDS) {
                                if (mNextWaitReason != null) {
                                    log("Next awake " + nextWait / 1000 + "s: " + mNextWaitReason);
                                }
                                runAsleep(EXTRA_MAILBOX_ID, nextWait + (3*SECONDS));
                            }
                            wait(nextWait);
                        }
                    }
                } catch (InterruptedException e) {
                    // Needs to be caught, but causes no problem
                    log("ExchangeService interrupted");
                } finally {
                    synchronized (this) {
                        if (mKicked) {
                            //log("Wait deferred due to kick");
                            mKicked = false;
                        }
                    }
                }
            }
            log("Shutdown requested");
        } catch (ProviderUnavailableException pue) {
            // Shutdown cleanly in this case
            // NOTE: Sync adapters will also crash with this error, but that is already handled
            // in the adapters themselves, i.e. they return cleanly via done().  When the Email
            // process starts running again, the Exchange process will be started again in due
            // course, assuming there is at least one existing EAS account.
            Log.e(TAG, "EmailProvider unavailable; shutting down");
            // Ask for our service to be restarted; this should kick-start the Email process as well
            startService(new Intent(this, ExchangeService.class));
        } catch (RuntimeException e) {
            // Crash; this is a completely unexpected runtime error
            Log.e(TAG, "RuntimeException in ExchangeService", e);
            throw e;
        } finally {
            shutdown();
        }
    }

    private void shutdown() {
        synchronized (sSyncLock) {
            // If INSTANCE is null, we've already been shut down
            if (INSTANCE != null) {
                log("ExchangeService shutting down...");

                // Stop our running syncs
                stopServiceThreads();

                // Stop receivers
                if (mConnectivityReceiver != null) {
                    unregisterReceiver(mConnectivityReceiver);
                }
                if (mBackgroundDataSettingReceiver != null) {
                    unregisterReceiver(mBackgroundDataSettingReceiver);
                }

                // Unregister observers
                ContentResolver resolver = getContentResolver();
                if (mSyncedMessageObserver != null) {
                    resolver.unregisterContentObserver(mSyncedMessageObserver);
                    mSyncedMessageObserver = null;
                }
                if (mAccountObserver != null) {
                    resolver.unregisterContentObserver(mAccountObserver);
                    mAccountObserver = null;
                }
                if (mMailboxObserver != null) {
                    resolver.unregisterContentObserver(mMailboxObserver);
                    mMailboxObserver = null;
                }
                unregisterCalendarObservers();

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

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

                INSTANCE = null;
                sServiceThread = null;
                sStop = false;
                log("Goodbye");
            }
        }
    }

    /**
     * Release a mailbox from the service map and release its wake lock.
     * NOTE: This method MUST be called while holding sSyncLock!
     *
     * @param mailboxId the id of the mailbox to be released
     */
    private void releaseMailbox(long mailboxId) {
        mServiceMap.remove(mailboxId);
        releaseWakeLock(mailboxId);
    }

    /**
     * Check whether an Outbox (referenced by a Cursor) has any messages that can be sent
     * @param c the cursor to an Outbox
     * @return true if there is mail to be sent
     */
    private boolean hasSendableMessages(Cursor outboxCursor) {
        Cursor c = mResolver.query(Message.CONTENT_URI, Message.ID_COLUMN_PROJECTION,
                EasOutboxService.MAILBOX_KEY_AND_NOT_SEND_FAILED,
                new String[] {Long.toString(outboxCursor.getLong(Mailbox.CONTENT_ID_COLUMN))},
                null);
        try {
            while (c.moveToNext()) {
                if (!Utility.hasUnloadedAttachments(this, c.getLong(Message.CONTENT_ID_COLUMN))) {
                    return true;
                }
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return false;
    }

    /**
     * Taken from ConnectivityManager using public constants
     */
    public static boolean isNetworkTypeMobile(int networkType) {
        switch (networkType) {
            case ConnectivityManager.TYPE_MOBILE:
            case ConnectivityManager.TYPE_MOBILE_MMS:
            case ConnectivityManager.TYPE_MOBILE_SUPL:
            case ConnectivityManager.TYPE_MOBILE_DUN:
            case ConnectivityManager.TYPE_MOBILE_HIPRI:
                return true;
            default:
                return false;
        }
    }

    /**
     * Determine whether the account is allowed to sync automatically, as opposed to manually, based
     * on whether the "require manual sync when roaming" policy is in force and applicable
     * @param account the account
     * @return whether or not the account can sync automatically
     */
    /*package*/ static boolean canAutoSync(Account account) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) {
            return false;
        }
        NetworkInfo networkInfo = exchangeService.mNetworkInfo;

        // Enforce manual sync only while roaming here
        long policyKey = account.mPolicyKey;
        // Quick exit from this check
        if ((policyKey != 0) && (networkInfo != null) &&
                isNetworkTypeMobile(networkInfo.getType())) {
            // We'll cache the Policy data here
            Policy policy = account.mPolicy;
            if (policy == null) {
                policy = Policy.restorePolicyWithId(INSTANCE, policyKey);
                account.mPolicy = policy;
                if (!PolicyServiceProxy.isActive(exchangeService, policy)) return false;
            }
            if (policy != null && policy.mRequireManualSyncWhenRoaming && networkInfo.isRoaming()) {
                return false;
            }
        }
        return true;
    }

    /**
     * Convenience method to determine whether Email sync is enabled for a given account
     * @param account the Account in question
     * @return whether Email sync is enabled
     */
    private boolean canSyncEmail(android.accounts.Account account) {
        return ContentResolver.getSyncAutomatically(account, EmailContent.AUTHORITY);
    }

    /**
     * Determine whether a mailbox of a given type in a given account can be synced automatically
     * by ExchangeService.  This is an increasingly complex determination, taking into account
     * security policies and user settings (both within the Email application and in the Settings
     * application)
     *
     * @param account the Account that the mailbox is in
     * @param type the type of the Mailbox
     * @return whether or not to start a sync
     */
    private boolean isMailboxSyncable(Account account, int type) {
        // This 'if' statement performs checks to see whether or not a mailbox is a
        // candidate for syncing based on policies, user settings, & other restrictions
        if (type == Mailbox.TYPE_OUTBOX) {
            // Outbox is always syncable
            return true;
        } else if (type == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
            // Always sync EAS mailbox unless master sync is off
            return ContentResolver.getMasterSyncAutomatically();
        } else if (type == Mailbox.TYPE_CONTACTS || type == Mailbox.TYPE_CALENDAR) {
            // Contacts/Calendar obey this setting from ContentResolver
            if (!ContentResolver.getMasterSyncAutomatically()) {
                return false;
            }
            // Get the right authority for the mailbox
            String authority;
            if (type == Mailbox.TYPE_CONTACTS) {
                authority = ContactsContract.AUTHORITY;
            } else {
                authority = CalendarContract.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);
                }
            }
            // See if "sync automatically" is set; if not, punt
            if (!ContentResolver.getSyncAutomatically(account.mAmAccount, authority)) {
                return false;
            // See if the calendar is enabled from the Calendar app UI; if not, punt
            } else if ((type == Mailbox.TYPE_CALENDAR) && !isCalendarEnabled(account.mId)) {
                return false;
            }
        // Never automatically sync trash
        } else if (type == Mailbox.TYPE_TRASH) {
            return false;
        // For non-outbox, non-account mail, we do three checks:
        // 1) are we restricted by policy (i.e. manual sync only),
        // 2) has the user checked the "Sync Email" box in Account Settings, and
        // 3) does the user have the master "background data" box checked in Settings
        } else if (!canAutoSync(account) || !canSyncEmail(account.mAmAccount) || !mBackgroundData) {
            return false;
        }
        return true;
    }

    private long checkMailboxes () {
        // First, see if any running mailboxes have been deleted
        ArrayList<Long> deletedMailboxes = new ArrayList<Long>();
        synchronized (sSyncLock) {
            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 = EXCHANGE_SERVICE_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) {
            log("mAccountObserver null; service died??");
            return nextWait;
        }

        Cursor c = getContentResolver().query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION,
                mAccountObserver.getSyncableEasMailboxWhere(), null, null);
        if (c == null) throw new ProviderUnavailableException();
        try {
            while (c.moveToNext()) {
                long mailboxId = c.getLong(Mailbox.CONTENT_ID_COLUMN);
                AbstractSyncService service = null;
                synchronized (sSyncLock) {
                    service = mServiceMap.get(mailboxId);
                }
                if (service == null) {
                    // Get the cached account
                    Account account = getAccountById(c.getInt(Mailbox.CONTENT_ACCOUNT_KEY_COLUMN));
                    if (account == null) continue;

                    // We handle a few types of mailboxes specially
                    int mailboxType = c.getInt(Mailbox.CONTENT_TYPE_COLUMN);
                    if (!isMailboxSyncable(account, mailboxType)) {
                        continue;
                    }

                    // Check whether we're in a hold (temporary or permanent)
                    SyncError syncError = mSyncErrorMap.get(mailboxId);
                    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;
                        }
                    }

                    // Otherwise, we use the sync interval
                    long syncInterval = c.getInt(Mailbox.CONTENT_SYNC_INTERVAL_COLUMN);
                    if (syncInterval == Mailbox.CHECK_INTERVAL_PUSH) {
                        Mailbox m = EmailContent.getContent(c, Mailbox.class);
                        requestSync(m, SYNC_PUSH, null);
                    } else if (mailboxType == Mailbox.TYPE_OUTBOX) {
                        if (hasSendableMessages(c)) {
                            Mailbox m = EmailContent.getContent(c, Mailbox.class);
                            startServiceThread(EasSyncService.getServiceForMailbox(this, m));
                        }
                    } else if (syncInterval > 0 && syncInterval <= ONE_DAY_MINUTES) {
                        long lastSync = c.getLong(Mailbox.CONTENT_SYNC_TIME_COLUMN);
                        long sinceLastSync = now - lastSync;
                        long toNextSync = syncInterval*MINUTES - sinceLastSync;
                        String name = c.getString(Mailbox.CONTENT_DISPLAY_NAME_COLUMN);
                        if (toNextSync <= 0) {
                            Mailbox m = EmailContent.getContent(c, Mailbox.class);
                            requestSync(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 and remove them from the map
                    if (thread != null && !thread.isAlive()) {
                        if (Eas.USER_LOG) {
                            log("Dead thread, mailbox released: " +
                                    c.getString(Mailbox.CONTENT_DISPLAY_NAME_COLUMN));
                        }
                        releaseMailbox(mailboxId);
                        // 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 (timeToRequest <= 0) {
                                service.mRequestTime = 0;
                                service.alarm();
                            } 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);
    }

    /**
     * Return a boolean indicating whether the mailbox can be synced
     * @param m the mailbox
     * @return whether or not the mailbox can be synced
     */
    public static boolean isSyncable(Mailbox m) {
        return m.loadsFromServer(HostAuth.SCHEME_EAS);
    }

    static public void serviceRequest(long mailboxId, long ms, int reason) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return;
        Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
        if (m == null || !isSyncable(m)) return;
        try {
            AbstractSyncService service = exchangeService.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) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return;
        AbstractSyncService service = exchangeService.mServiceMap.get(mailboxId);
        if (service != null) {
            service.mRequestTime = System.currentTimeMillis();
            Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
            if (m != null) {
                service.mAccount = Account.restoreAccountWithId(exchangeService, m.mAccountKey);
                service.mMailbox = m;
                kick("service request immediate");
            }
        }
    }

    static public void sendMessageRequest(Request req) {
        ExchangeService exchangeService = INSTANCE;
        Message msg = Message.restoreMessageWithId(exchangeService, req.mMessageId);
        if (msg == null) return;
        long mailboxId = msg.mMailboxKey;
        Mailbox mailbox = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
        if (mailbox == null) return;

        // If we're loading an attachment for Outbox, we want to look at the source message
        // to find the loading mailbox
        if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
            long sourceId = Utility.getFirstRowLong(exchangeService, Body.CONTENT_URI,
                    new String[] {BodyColumns.SOURCE_MESSAGE_KEY},
                    BodyColumns.MESSAGE_KEY + "=?",
                    new String[] {Long.toString(msg.mId)}, null, 0, -1L);
            if (sourceId != -1L) {
                EmailContent.Message sourceMsg =
                        EmailContent.Message.restoreMessageWithId(exchangeService, sourceId);
                if (sourceMsg != null) {
                    mailboxId = sourceMsg.mMailboxKey;
                }
            }
        }

        AbstractSyncService service = exchangeService.mServiceMap.get(mailboxId);
        if (service == null) {
            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) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return PING_STATUS_OK;
        // Already syncing...
        if (exchangeService.mServiceMap.get(mailboxId) != null) {
            return PING_STATUS_RUNNING;
        }
        // No errors or a transient error, don't ping...
        SyncError error = exchangeService.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 void startManualSync(long mailboxId, int reason, Request req) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return;
        synchronized (sSyncLock) {
            AbstractSyncService svc = exchangeService.mServiceMap.get(mailboxId);
            if (svc == null) {
                exchangeService.mSyncErrorMap.remove(mailboxId);
                Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
                if (m != null) {
                    log("Starting sync for " + m.mDisplayName);
                    exchangeService.requestSync(m, reason, req);
                }
            } else {
                // If this is a ui request, set the sync reason for the service
                if (reason >= SYNC_CALLBACK_START) {
                    svc.mSyncReason = reason;
                }
            }
        }
    }

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

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

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

    /**
     * Tell ExchangeService to remove the mailbox from the map of mailboxes with sync errors
     * @param mailboxId the id of the mailbox
     */
    static public void removeFromSyncErrorMap(long mailboxId) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService != null) {
            exchangeService.mSyncErrorMap.remove(mailboxId);
        }
    }

    private boolean isRunningInServiceThread(long mailboxId) {
        AbstractSyncService syncService = mServiceMap.get(mailboxId);
        Thread thisThread = Thread.currentThread();
        return syncService != null && syncService.mThread != null &&
            thisThread == syncService.mThread;
    }

    /**
     * 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) {
        ExchangeService exchangeService = INSTANCE;
        if (exchangeService == null) return;
        synchronized(sSyncLock) {
            long mailboxId = svc.mMailboxId;
            // If we're no longer the syncing thread for the mailbox, just return
            if (!exchangeService.isRunningInServiceThread(mailboxId)) {
                return;
            }
            exchangeService.releaseMailbox(mailboxId);
            exchangeService.setMailboxSyncStatus(mailboxId, EmailContent.SYNC_STATUS_NONE);

            ConcurrentHashMap<Long, SyncError> errorMap = exchangeService.mSyncErrorMap;
            SyncError syncError = errorMap.get(mailboxId);

            int exitStatus = svc.mExitStatus;
            Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
            if (m == null) return;

            if (exitStatus != AbstractSyncService.EXIT_LOGIN_FAILURE) {
                long accountId = m.mAccountKey;
                Account account = Account.restoreAccountWithId(exchangeService, accountId);
                if (account == null) return;
                if (exchangeService.releaseSyncHolds(exchangeService,
                        AbstractSyncService.EXIT_LOGIN_FAILURE, account)) {
                    new AccountServiceProxy(exchangeService).notifyLoginSucceeded(accountId);
                }
            }

            int lastResult = EmailContent.LAST_SYNC_RESULT_SUCCESS;
            // For error states, whether the error is fatal (won't automatically be retried)
            boolean errorIsFatal = true;
            try {
                switch (exitStatus) {
                    case AbstractSyncService.EXIT_DONE:
                        if (svc.hasPendingRequests()) {
                            // TODO Handle this case
                        }
                        errorMap.remove(mailboxId);
                        // If we've had a successful sync, clear the shutdown count
                        synchronized (ExchangeService.class) {
                            sClientConnectionManagerShutdownCount = 0;
                        }
                        // Leave now; other statuses are errors
                        return;
                    // I/O errors get retried at increasing intervals
                    case AbstractSyncService.EXIT_IO_ERROR:
                        if (syncError != null) {
                            syncError.escalate();
                            log(m.mDisplayName + " held for " + syncError.holdDelay + "ms");
                        } else {
                            log(m.mDisplayName + " added to syncErrorMap, hold for 15s");
                        }
                        lastResult = EmailContent.LAST_SYNC_RESULT_CONNECTION_ERROR;
                        errorIsFatal = false;
                        break;
                    // These errors are not retried automatically
                    case AbstractSyncService.EXIT_LOGIN_FAILURE:
                        new AccountServiceProxy(exchangeService).notifyLoginFailed(m.mAccountKey);
                        lastResult = EmailContent.LAST_SYNC_RESULT_AUTH_ERROR;
                        break;
                    case AbstractSyncService.EXIT_SECURITY_FAILURE:
                    case AbstractSyncService.EXIT_ACCESS_DENIED:
                        lastResult = EmailContent.LAST_SYNC_RESULT_SECURITY_ERROR;
                        break;
                    case AbstractSyncService.EXIT_EXCEPTION:
                        lastResult = EmailContent.LAST_SYNC_RESULT_INTERNAL_ERROR;
                        break;
                }
                // Add this box to the error map
                errorMap.put(mailboxId, exchangeService.new SyncError(exitStatus, errorIsFatal));
            } finally {
                // Always set the last result
                exchangeService.setMailboxLastSyncResult(mailboxId, lastResult);
                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;
    }
}
