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
* 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

Bug: 2844888
Backport From: Ib4ffbbc67b681e69176b6c1d5515fa80c7d1e121

Change-Id: Ie9e944bd39f331c2ddc0f0ba303a3d5684f6f033
diff --git a/src/com/android/exchange/ b/src/com/android/exchange/
index 304f65f..20e1ea8 100644
--- a/src/com/android/exchange/
+++ b/src/com/android/exchange/
@@ -1282,17 +1282,28 @@
             if (pp.getRemoteWipe()) {
                 // We've gotten a remote wipe command
+                SyncManager.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)
+                SyncManager.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()) {
+                    SyncManager.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 {
+                    SyncManager.alwaysLog("!!! Acknowledging remote wipe to server");
                 } 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
+                SyncManager.alwaysLog("!!! Executing remote wipe");
                 return false;
             } else if (sp.isActive(ps)) {
diff --git a/src/com/android/exchange/ b/src/com/android/exchange/
index bf8b8b0..3defdc5 100644
--- a/src/com/android/exchange/
+++ b/src/com/android/exchange/
@@ -1232,7 +1232,7 @@
      * @param acctId
-    static public void folderListReloaded(long acctId) {
+    static public void stopNonAccountMailboxSyncsForAccount(long acctId) {
         SyncManager syncManager = INSTANCE;
         if (syncManager != null) {
             syncManager.stopAccountSyncs(acctId, false);
diff --git a/src/com/android/exchange/adapter/ b/src/com/android/exchange/adapter/
index ed97d31..3706b18 100644
--- a/src/com/android/exchange/adapter/
+++ b/src/com/android/exchange/adapter/
@@ -114,7 +114,7 @@
                         mContentResolver.delete(Mailbox.CONTENT_URI, ALL_BUT_ACCOUNT_MAILBOX,
                                 new String[] {Long.toString(mAccountId)});
                         // Stop existing syncs and reconstruct _main
-                        SyncManager.folderListReloaded(mAccountId);
+                        SyncManager.stopNonAccountMailboxSyncsForAccount(mAccountId);
                         res = true;
                         resetFolders = true;
                     } else {