Fix remote wipe with mobile sync server

* It appears as if our running multiple sync threads can confuse the
  mobile sync server during a remote wipe (the server expects the next
  client response to be an acknowledgment, whereas it might well be
  a command or response from a different thread)
* To avoid this, we first put the account on security hold and then
  shut down all other sync threads for the account
* After this, we send the acknowledgment and the remote wipe proceeds
  normally.
* NOTE: It's possible that, due to the vagaries of multithreaded
  operation, one of the other syncing threads could still send a non-
  acknowledgment response to the server before our provisioning thread
  gets a chance to send its acknowledgment.  However, since the other
  syncing threads will terminate (and not restart, because of the hold),
  the provision/remote wipe/ack sequence will work on the subsequent
  attempt

Bug: 2844888
Change-Id: Ib4ffbbc67b681e69176b6c1d5515fa80c7d1e121
diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java
index fab45e9..51707e6 100644
--- a/src/com/android/exchange/EasSyncService.java
+++ b/src/com/android/exchange/EasSyncService.java
@@ -1391,17 +1391,29 @@
             sp.updatePolicies(mAccount.mId);
             if (pp.getRemoteWipe()) {
                 // We've gotten a remote wipe command
+                ExchangeService.alwaysLog("!!! Remote wipe request received");
+                // Start by setting the account to security hold
+                sp.setAccountHoldFlag(mAccount, true);
+                // Force a stop to any running syncs for this account (except this one)
+                ExchangeService.stopNonAccountMailboxSyncsForAccount(mAccount.mId);
+
                 // If we're not the admin, we can't do the wipe, so just return
-                if (!sp.isActiveAdmin()) return false;
+                if (!sp.isActiveAdmin()) {
+                    ExchangeService.alwaysLog("!!! Not device admin; can't wipe");
+                    return false;
+                }
+
                 // First, we've got to acknowledge it, but wrap the wipe in try/catch so that
                 // we wipe the device regardless of any errors in acknowledgment
                 try {
+                    ExchangeService.alwaysLog("!!! Acknowledging remote wipe to server");
                     acknowledgeRemoteWipe(pp.getPolicyKey());
                 } catch (Exception e) {
                     // Because remote wipe is such a high priority task, we don't want to
                     // circumvent it if there's an exception in acknowledgment
                 }
                 // Then, tell SecurityPolicy to wipe the device
+                ExchangeService.alwaysLog("!!! Executing remote wipe");
                 sp.remoteWipe();
                 return false;
             } else if (sp.isActive(ps)) {
diff --git a/src/com/android/exchange/ExchangeService.java b/src/com/android/exchange/ExchangeService.java
index bc3f4e8..7b87b75 100644
--- a/src/com/android/exchange/ExchangeService.java
+++ b/src/com/android/exchange/ExchangeService.java
@@ -1288,7 +1288,7 @@
      *
      * @param acctId
      */
-    static public void folderListReloaded(long acctId) {
+    static public void stopNonAccountMailboxSyncsForAccount(long acctId) {
         ExchangeService exchangeService = INSTANCE;
         if (exchangeService != null) {
             exchangeService.stopAccountSyncs(acctId, false);
diff --git a/src/com/android/exchange/adapter/FolderSyncParser.java b/src/com/android/exchange/adapter/FolderSyncParser.java
index 1e8f893..7e4863c 100644
--- a/src/com/android/exchange/adapter/FolderSyncParser.java
+++ b/src/com/android/exchange/adapter/FolderSyncParser.java
@@ -118,7 +118,7 @@
                         mContentResolver.delete(Mailbox.CONTENT_URI, ALL_BUT_ACCOUNT_MAILBOX,
                                 new String[] {Long.toString(mAccountId)});
                         // Stop existing syncs and reconstruct _main
-                        ExchangeService.folderListReloaded(mAccountId);
+                        ExchangeService.stopNonAccountMailboxSyncsForAccount(mAccountId);
                         res = true;
                         resetFolders = true;
                     } else {