From 214c6c6c8173cf90a3e45615a6896a48dc643e68 Mon Sep 17 00:00:00 2001 From: Andy Stadler Date: Wed, 13 Oct 2010 15:39:27 -0700 Subject: [PATCH] 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 Backport From: Ib4ffbbc67b681e69176b6c1d5515fa80c7d1e121 Change-Id: Ie9e944bd39f331c2ddc0f0ba303a3d5684f6f033 --- src/com/android/exchange/EasSyncService.java | 13 ++++++++++++- src/com/android/exchange/SyncManager.java | 2 +- .../android/exchange/adapter/FolderSyncParser.java | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java index 304f65ff0..20e1ea87b 100644 --- a/src/com/android/exchange/EasSyncService.java +++ b/src/com/android/exchange/EasSyncService.java @@ -1282,17 +1282,28 @@ public class EasSyncService extends AbstractSyncService { } 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"); 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 + SyncManager.alwaysLog("!!! Executing remote wipe"); sp.remoteWipe(); return false; } else if (sp.isActive(ps)) { diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java index bf8b8b0ba..3defdc5e3 100644 --- a/src/com/android/exchange/SyncManager.java +++ b/src/com/android/exchange/SyncManager.java @@ -1232,7 +1232,7 @@ public class SyncManager extends Service implements Runnable { * * @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/FolderSyncParser.java b/src/com/android/exchange/adapter/FolderSyncParser.java index ed97d315e..3706b18a2 100644 --- a/src/com/android/exchange/adapter/FolderSyncParser.java +++ b/src/com/android/exchange/adapter/FolderSyncParser.java @@ -114,7 +114,7 @@ public class FolderSyncParser extends AbstractSyncParser { 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 {