Fix account creation race condition
* Due to the order in which account creation occurs in the Provider
and in AccountManager, and the fact that there are data observers
on each that initiate account reconciliation, a race condition exists
that can cause either of these accounts to appear to be orphaned,
and thereby get deleted
* We add an "incomplete" flag to the Account in EmailProvider and
set/clear it during account creation. The various reconciliation
methods will ignore accounts marked as incomplete.
Bug: 2353755
Change-Id: I13fb144dd857f839eb3471b01f271f3a0d4d8159
diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java
index 9e1f0db..401d5cf 100644
--- a/src/com/android/exchange/SyncManager.java
+++ b/src/com/android/exchange/SyncManager.java
@@ -496,7 +496,11 @@
try {
collectEasAccounts(c, currentAccounts);
for (Account account : mAccounts) {
- if (!currentAccounts.contains(account.mId)) {
+ // Ignore accounts not fully created
+ if ((account.mFlags & Account.FLAGS_INCOMPLETE) != 0) {
+ log("Account observer noticed incomplete account; ignoring");
+ continue;
+ } else if (!currentAccounts.contains(account.mId)) {
// This is a deletion; shut down any account-related syncs
stopAccountSyncs(account.mId, true);
// Delete this from AccountManager...
@@ -518,8 +522,7 @@
WHERE_IN_ACCOUNT_AND_PUSHABLE,
new String[] {Long.toString(account.mId)});
// Stop all current syncs; the appropriate ones will restart
- INSTANCE.log("Account " + account.mDisplayName +
- " changed; stop running syncs...");
+ log("Account " + account.mDisplayName + " changed; stop syncs");
stopAccountSyncs(account.mId, true);
}
}
@@ -529,6 +532,7 @@
for (Account account: currentAccounts) {
if (!mAccounts.contains(account.mId)) {
// This is an addition; create our magic hidden mailbox...
+ log("Account observer found new account: " + account.mDisplayName);
addAccountMailbox(account.mId);
// Don't forget to cache the HostAuth
HostAuth ha =
@@ -1241,6 +1245,10 @@
}
}
if (!found) {
+ if ((providerAccount.mFlags & Account.FLAGS_INCOMPLETE) != 0) {
+ log("Account reconciler noticed incomplete account; ignoring");
+ continue;
+ }
// This account has been deleted in the AccountManager!
log("Account deleted in AccountManager; deleting from provider: " +
providerAccountName);