/**
  * 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
  */
 public static void stopNonAccountMailboxSyncsForAccount(long acctId) {
   SyncManager exchangeService = INSTANCE;
   if (exchangeService != null) {
     exchangeService.stopAccountSyncs(acctId, false);
     kick("reload folder list");
   }
 }
 /**
  * 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() {
   SyncManager exchangeService = INSTANCE;
   if (exchangeService == null) return;
   if (sServiceThread == null) {
     log("!!! checkExchangeServiceServiceRunning; starting service...");
     exchangeService.startService(new Intent(exchangeService, ExchangeService.class));
   }
 }
 /**
  * This is the remote call from the Email app, currently unused. TODO: remove this when it's
  * been deleted from IEmailService.aidl.
  */
 @Deprecated
 @Override
 public void startSync(long mailboxId, boolean userRequest, int deltaMessageCount)
     throws RemoteException {
   SyncManager 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) {
       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)) {
     return;
   }
   startManualSync(
       mailboxId,
       userRequest
           ? ExchangeService.SYNC_UI_REQUEST
           : ExchangeService.SYNC_SERVICE_START_SYNC,
       null);
 }
 @Override
 public void hostChanged(long accountId) throws RemoteException {
   SyncManager 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");
 }
  public static void reloadFolderList(Context context, long accountId, boolean force) {
    SyncManager 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();
    }
  }