Synchronize getSyncKey/setSyncKey in Calendar and Contacts sync
* When the sync state of Calendar/Contacts is changed, a number of observer calls are triggered. In addition, we might have a running sync. * The syncKey operations need to be synchronized, because we may otherwise inadvertently use stale data when syncing, which would cause symptoms as seen in the referenced bug Bug: 2561864 Change-Id: I03db58fe01c45778d271fad34d8d4940edefe8fe
This commit is contained in:
parent
78021cbbf8
commit
79976209d7
|
@ -683,7 +683,7 @@ public class SyncManager extends Service implements Runnable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
public synchronized void onChange(boolean selfChange) {
|
||||
// See if the user has changed syncing of our calendar
|
||||
if (!selfChange) {
|
||||
new Thread(new Runnable() {
|
||||
|
|
|
@ -105,6 +105,8 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
|
|||
private static final Uri sExtendedPropertiesUri = asSyncAdapter(ExtendedProperties.CONTENT_URI);
|
||||
private static final Uri sRemindersUri = asSyncAdapter(Reminders.CONTENT_URI);
|
||||
|
||||
private static final Object sSyncKeyLock = new Object();
|
||||
|
||||
private long mCalendarId = -1;
|
||||
|
||||
private ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
|
||||
|
@ -173,20 +175,24 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
|
|||
*/
|
||||
@Override
|
||||
public String getSyncKey() throws IOException {
|
||||
ContentProviderClient client =
|
||||
mService.mContentResolver.acquireContentProviderClient(Calendar.CONTENT_URI);
|
||||
try {
|
||||
byte[] data = SyncStateContract.Helpers.get(client,
|
||||
asSyncAdapter(Calendar.SyncState.CONTENT_URI), mAccountManagerAccount);
|
||||
if (data == null || data.length == 0) {
|
||||
// Initialize the SyncKey
|
||||
setSyncKey("0", false);
|
||||
return "0";
|
||||
} else {
|
||||
return new String(data);
|
||||
synchronized (sSyncKeyLock) {
|
||||
ContentProviderClient client = mService.mContentResolver
|
||||
.acquireContentProviderClient(Calendar.CONTENT_URI);
|
||||
try {
|
||||
byte[] data = SyncStateContract.Helpers.get(client,
|
||||
asSyncAdapter(Calendar.SyncState.CONTENT_URI), mAccountManagerAccount);
|
||||
if (data == null || data.length == 0) {
|
||||
// Initialize the SyncKey
|
||||
setSyncKey("0", false);
|
||||
return "0";
|
||||
} else {
|
||||
String syncKey = new String(data);
|
||||
userLog("SyncKey retrieved as ", syncKey, " from CalendarProvider");
|
||||
return syncKey;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't get SyncKey from CalendarProvider");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't get SyncKey from ContactsProvider");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,19 +202,21 @@ public class CalendarSyncAdapter extends AbstractSyncAdapter {
|
|||
*/
|
||||
@Override
|
||||
public void setSyncKey(String syncKey, boolean inCommands) throws IOException {
|
||||
if ("0".equals(syncKey) || !inCommands) {
|
||||
ContentProviderClient client =
|
||||
mService.mContentResolver
|
||||
.acquireContentProviderClient(Calendar.CONTENT_URI);
|
||||
try {
|
||||
SyncStateContract.Helpers.set(client, asSyncAdapter(Calendar.SyncState.CONTENT_URI),
|
||||
mAccountManagerAccount, syncKey.getBytes());
|
||||
userLog("SyncKey set to ", syncKey, " in CalendarProvider");
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't set SyncKey in CalendarProvider");
|
||||
synchronized (sSyncKeyLock) {
|
||||
if ("0".equals(syncKey) || !inCommands) {
|
||||
ContentProviderClient client = mService.mContentResolver
|
||||
.acquireContentProviderClient(Calendar.CONTENT_URI);
|
||||
try {
|
||||
SyncStateContract.Helpers.set(client,
|
||||
asSyncAdapter(Calendar.SyncState.CONTENT_URI), mAccountManagerAccount,
|
||||
syncKey.getBytes());
|
||||
userLog("SyncKey set to ", syncKey, " in CalendarProvider");
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't set SyncKey in CalendarProvider");
|
||||
}
|
||||
}
|
||||
mMailbox.mSyncKey = syncKey;
|
||||
}
|
||||
mMailbox.mSyncKey = syncKey;
|
||||
}
|
||||
|
||||
class EasCalendarSyncParser extends AbstractSyncParser {
|
||||
|
|
|
@ -118,6 +118,8 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
|
|||
private static final int[] HOME_PHONE_TAGS = new int[] {Tags.CONTACTS_HOME_TELEPHONE_NUMBER,
|
||||
Tags.CONTACTS_HOME2_TELEPHONE_NUMBER};
|
||||
|
||||
private static final Object sSyncKeyLock = new Object();
|
||||
|
||||
ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
|
||||
ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();
|
||||
|
||||
|
@ -156,26 +158,29 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
|
|||
*/
|
||||
@Override
|
||||
public String getSyncKey() throws IOException {
|
||||
ContentProviderClient client =
|
||||
mService.mContentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
|
||||
try {
|
||||
byte[] data = SyncStateContract.Helpers.get(client,
|
||||
ContactsContract.SyncState.CONTENT_URI, mAccountManagerAccount);
|
||||
if (data == null || data.length == 0) {
|
||||
// Initialize the SyncKey
|
||||
setSyncKey("0", false);
|
||||
// Make sure ungrouped contacts for Exchange are defaultly visible
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Groups.ACCOUNT_NAME, mAccount.mEmailAddress);
|
||||
cv.put(Groups.ACCOUNT_TYPE, com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
|
||||
cv.put(Settings.UNGROUPED_VISIBLE, true);
|
||||
client.insert(addCallerIsSyncAdapterParameter(Settings.CONTENT_URI), cv);
|
||||
return "0";
|
||||
} else {
|
||||
return new String(data);
|
||||
synchronized (sSyncKeyLock) {
|
||||
ContentProviderClient client = mService.mContentResolver
|
||||
.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
|
||||
try {
|
||||
byte[] data = SyncStateContract.Helpers.get(client,
|
||||
ContactsContract.SyncState.CONTENT_URI, mAccountManagerAccount);
|
||||
if (data == null || data.length == 0) {
|
||||
// Initialize the SyncKey
|
||||
setSyncKey("0", false);
|
||||
// Make sure ungrouped contacts for Exchange are defaultly visible
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Groups.ACCOUNT_NAME, mAccount.mEmailAddress);
|
||||
cv.put(Groups.ACCOUNT_TYPE,
|
||||
com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
|
||||
cv.put(Settings.UNGROUPED_VISIBLE, true);
|
||||
client.insert(addCallerIsSyncAdapterParameter(Settings.CONTENT_URI), cv);
|
||||
return "0";
|
||||
} else {
|
||||
return new String(data);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't get SyncKey from ContactsProvider");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't get SyncKey from ContactsProvider");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,19 +190,20 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
|
|||
*/
|
||||
@Override
|
||||
public void setSyncKey(String syncKey, boolean inCommands) throws IOException {
|
||||
if ("0".equals(syncKey) || !inCommands) {
|
||||
ContentProviderClient client =
|
||||
mService.mContentResolver
|
||||
.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
|
||||
try {
|
||||
SyncStateContract.Helpers.set(client, ContactsContract.SyncState.CONTENT_URI,
|
||||
mAccountManagerAccount, syncKey.getBytes());
|
||||
userLog("SyncKey set to ", syncKey, " in ContactsProvider");
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't set SyncKey in ContactsProvider");
|
||||
synchronized (sSyncKeyLock) {
|
||||
if ("0".equals(syncKey) || !inCommands) {
|
||||
ContentProviderClient client = mService.mContentResolver
|
||||
.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
|
||||
try {
|
||||
SyncStateContract.Helpers.set(client, ContactsContract.SyncState.CONTENT_URI,
|
||||
mAccountManagerAccount, syncKey.getBytes());
|
||||
userLog("SyncKey set to ", syncKey, " in ContactsProvider");
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException("Can't set SyncKey in ContactsProvider");
|
||||
}
|
||||
}
|
||||
mMailbox.mSyncKey = syncKey;
|
||||
}
|
||||
mMailbox.mSyncKey = syncKey;
|
||||
}
|
||||
|
||||
public static final class EasChildren {
|
||||
|
|
Loading…
Reference in New Issue