Update to support sync only restrictions in provider
Change-Id: I38d7dca8405ac8710dde8c08ee16e1f4c7689fcb
diff --git a/src/com/android/exchange/adapter/CalendarSyncAdapter.java b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
index 5a079af..ec2805c 100644
--- a/src/com/android/exchange/adapter/CalendarSyncAdapter.java
+++ b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
@@ -29,6 +29,7 @@
import com.android.exchange.utility.CalendarUtilities;
import com.android.exchange.utility.Duration;
+import android.accounts.Account;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -125,12 +126,6 @@
private static final ContentProviderOperation PLACEHOLDER_OPERATION =
ContentProviderOperation.newInsert(Uri.EMPTY).build();
- private static final Uri EVENTS_URI = asSyncAdapter(Events.CONTENT_URI);
- private static final Uri ATTENDEES_URI = asSyncAdapter(Attendees.CONTENT_URI);
- private static final Uri EXTENDED_PROPERTIES_URI =
- asSyncAdapter(ExtendedProperties.CONTENT_URI);
- private static final Uri REMINDERS_URI = asSyncAdapter(Reminders.CONTENT_URI);
-
private static final Object sSyncKeyLock = new Object();
private static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC");
@@ -196,10 +191,12 @@
public void wipe() {
// Delete the calendar associated with this account
// CalendarProvider2 does NOT handle selection arguments in deletions
- mContentResolver.delete(Calendars.CONTENT_URI, Calendars._SYNC_ACCOUNT +
- "=" + DatabaseUtils.sqlEscapeString(mEmailAddress) + " AND " +
- Calendars._SYNC_ACCOUNT_TYPE + "=" +
- DatabaseUtils.sqlEscapeString(AccountManagerTypes.TYPE_EXCHANGE), null);
+ mContentResolver.delete(
+ asSyncAdapter(Calendars.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
+ Calendars._SYNC_ACCOUNT + "=" + DatabaseUtils.sqlEscapeString(mEmailAddress)
+ + " AND " + Calendars._SYNC_ACCOUNT_TYPE + "="
+ + DatabaseUtils.sqlEscapeString(AccountManagerTypes.TYPE_EXCHANGE), null);
// Invalidate our calendar observers
ExchangeService.unregisterCalendarObservers();
}
@@ -220,8 +217,10 @@
return p.parse();
}
- static Uri asSyncAdapter(Uri uri) {
- return uri.buildUpon().appendQueryParameter(Calendar.CALLER_IS_SYNCADAPTER, "true").build();
+ static Uri asSyncAdapter(Uri uri, String account, String accountType) {
+ return uri.buildUpon().appendQueryParameter(Calendar.CALLER_IS_SYNCADAPTER, "true")
+ .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
+ .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
}
/**
@@ -245,8 +244,10 @@
ContentProviderClient client = mService.mContentResolver
.acquireContentProviderClient(Calendar.CONTENT_URI);
try {
- byte[] data = SyncStateContract.Helpers.get(client,
- asSyncAdapter(Calendar.SyncState.CONTENT_URI), mAccountManagerAccount);
+ byte[] data = SyncStateContract.Helpers.get(
+ client,
+ asSyncAdapter(Calendar.SyncState.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), mAccountManagerAccount);
if (data == null || data.length == 0) {
// Initialize the SyncKey
setSyncKey("0", false);
@@ -273,8 +274,10 @@
ContentProviderClient client = mService.mContentResolver
.acquireContentProviderClient(Calendar.CONTENT_URI);
try {
- SyncStateContract.Helpers.set(client,
- asSyncAdapter(Calendar.SyncState.CONTENT_URI), mAccountManagerAccount,
+ SyncStateContract.Helpers.set(
+ client,
+ asSyncAdapter(Calendar.SyncState.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), mAccountManagerAccount,
syncKey.getBytes());
userLog("SyncKey set to ", syncKey, " in CalendarProvider");
} catch (RemoteException e) {
@@ -433,9 +436,13 @@
dtStamp = getValue();
continue;
} else if (tag == Tags.CALENDAR_ATTENDEES) {
- // This is an attendees-only update; just delete/re-add attendees
+ // This is an attendees-only update; just
+ // delete/re-add attendees
mBindArgument[0] = Long.toString(id);
- ops.add(ContentProviderOperation.newDelete(ATTENDEES_URI)
+ ops.add(ContentProviderOperation
+ .newDelete(
+ asSyncAdapter(Attendees.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE))
.withSelection(ATTENDEES_EXCEPT_ORGANIZER, mBindArgument)
.build());
eventId = id;
@@ -659,8 +666,12 @@
}
if (isValidEventValues(cv)) {
- ops.set(eventOffset, ContentProviderOperation
- .newInsert(EVENTS_URI).withValues(cv).build());
+ ops.set(eventOffset,
+ ContentProviderOperation
+ .newInsert(
+ asSyncAdapter(Events.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE))
+ .withValues(cv).build());
} else {
// If we can't add this event (it's invalid), remove all of the inserts
// we've built for it
@@ -1186,16 +1197,22 @@
ContentValues cv = new ContentValues();
cv.put(Events._SYNC_DIRTY, 0);
cv.put(Events._SYNC_MARK, 0);
- for (long eventId: mUploadedIdList) {
- mContentResolver.update(ContentUris.withAppendedId(EVENTS_URI, eventId), cv,
+ for (long eventId : mUploadedIdList) {
+ mContentResolver.update(
+ asSyncAdapter(
+ ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), cv,
null, null);
}
}
// Delete events marked for deletion
if (!mDeletedIdList.isEmpty()) {
- for (long eventId: mDeletedIdList) {
- mContentResolver.delete(ContentUris.withAppendedId(EVENTS_URI, eventId),
- null, null);
+ for (long eventId : mDeletedIdList) {
+ mContentResolver.delete(
+ asSyncAdapter(
+ ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), null,
+ null);
}
}
// Send any queued up email (invitations replies, etc.)
@@ -1242,10 +1259,12 @@
cv.put(Events._SYNC_DATA, clientId);
long id = c.getLong(0);
// Write the serverId into the Event
- mOps.add(ContentProviderOperation.newUpdate(
- ContentUris.withAppendedId(EVENTS_URI, id))
- .withValues(cv)
- .build());
+ mOps.add(ContentProviderOperation
+ .newUpdate(
+ asSyncAdapter(
+ ContentUris.withAppendedId(Events.CONTENT_URI, id),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE))
+ .withValues(cv).build());
userLog("New event " + clientId + " was given serverId: " + serverId);
}
} finally {
@@ -1319,28 +1338,30 @@
public void newAttendee(ContentValues cv, int eventStart) {
add(ContentProviderOperation
- .newInsert(ATTENDEES_URI)
- .withValues(cv)
- .withValueBackReference(Attendees.EVENT_ID, eventStart)
- .build());
+ .newInsert(asSyncAdapter(Attendees.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE)).withValues(cv)
+ .withValueBackReference(Attendees.EVENT_ID, eventStart).build());
}
public void updatedAttendee(ContentValues cv, long id) {
cv.put(Attendees.EVENT_ID, id);
- add(ContentProviderOperation.newInsert(ATTENDEES_URI).withValues(cv).build());
+ add(ContentProviderOperation.newInsert(asSyncAdapter(Attendees.CONTENT_URI,
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE)).withValues(cv).build());
}
public void newException(ContentValues cv) {
- add(ContentProviderOperation.newInsert(EVENTS_URI).withValues(cv).build());
+ add(ContentProviderOperation.newInsert(
+ asSyncAdapter(Events.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE)).withValues(cv).build());
}
public void newExtendedProperty(String name, String value) {
add(ContentProviderOperation
- .newInsert(EXTENDED_PROPERTIES_URI)
+ .newInsert(asSyncAdapter(ExtendedProperties.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE))
.withValue(ExtendedProperties.NAME, name)
.withValue(ExtendedProperties.VALUE, value)
- .withValueBackReference(ExtendedProperties.EVENT_ID, mEventStart)
- .build());
+ .withValueBackReference(ExtendedProperties.EVENT_ID, mEventStart).build());
}
public void updatedExtendedProperty(String name, String value, long id) {
@@ -1359,13 +1380,16 @@
c.close();
}
}
- // Either do an update or an insert, depending on whether one already exists
+ // Either do an update or an insert, depending on whether one
+ // already exists
if (extendedPropertyId >= 0) {
add(ContentProviderOperation
- .newUpdate(ContentUris.withAppendedId(EXTENDED_PROPERTIES_URI,
- extendedPropertyId))
- .withValue(ExtendedProperties.VALUE, value)
- .build());
+ .newUpdate(
+ ContentUris.withAppendedId(
+ asSyncAdapter(ExtendedProperties.CONTENT_URI,
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
+ extendedPropertyId))
+ .withValue(ExtendedProperties.VALUE, value).build());
} else {
newExtendedProperty(name, value);
}
@@ -1373,11 +1397,11 @@
public void newReminder(int mins, int eventStart) {
add(ContentProviderOperation
- .newInsert(REMINDERS_URI)
+ .newInsert(asSyncAdapter(Reminders.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE))
.withValue(Reminders.MINUTES, mins)
.withValue(Reminders.METHOD, Reminders.METHOD_ALERT)
- .withValueBackReference(ExtendedProperties.EVENT_ID, eventStart)
- .build());
+ .withValueBackReference(ExtendedProperties.EVENT_ID, eventStart).build());
}
public void newReminder(int mins) {
@@ -1385,12 +1409,15 @@
}
public void delete(long id, String syncId) {
+ add(ContentProviderOperation.newDelete(
+ asSyncAdapter(ContentUris.withAppendedId(Events.CONTENT_URI, id),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE)).build());
+ // Delete the exceptions for this Event (CalendarProvider doesn't do
+ // this)
add(ContentProviderOperation
- .newDelete(ContentUris.withAppendedId(EVENTS_URI, id)).build());
- // Delete the exceptions for this Event (CalendarProvider doesn't do this)
- add(ContentProviderOperation
- .newDelete(EVENTS_URI).withSelection(Events.ORIGINAL_EVENT + "=?",
- new String[] {syncId}).build());
+ .newDelete(asSyncAdapter(Events.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE))
+ .withSelection(Events.ORIGINAL_EVENT + "=?", new String[] {syncId}).build());
}
public void execute() {
@@ -1472,7 +1499,9 @@
ContentValues cv = new ContentValues();
cv.put(Events.STATUS, Events.STATUS_CANCELED);
mService.mContentResolver.update(
- ContentUris.withAppendedId(EVENTS_URI, eventId), cv, null, null);
+ asSyncAdapter(ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), cv, null,
+ null);
}
} else {
s.data(Tags.CALENDAR_EXCEPTION_IS_DELETED, "0");
@@ -1676,7 +1705,9 @@
// Get busy status from Attendees table
long eventId = entityValues.getAsLong(Events._ID);
int busyStatus = CalendarUtilities.BUSY_STATUS_TENTATIVE;
- Cursor c = mService.mContentResolver.query(ATTENDEES_URI,
+ Cursor c = mService.mContentResolver.query(
+ asSyncAdapter(Attendees.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
ATTENDEE_STATUS_PROJECTION, EVENT_AND_EMAIL,
new String[] {Long.toString(eventId), mEmailAddress}, null);
if (c != null) {
@@ -1753,8 +1784,12 @@
while (c.moveToNext()) {
// Mark the parents of dirty exceptions
String serverId = c.getString(0);
- int cnt = cr.update(EVENTS_URI, cv, SERVER_ID_AND_CALENDAR_ID,
- new String[] {serverId, mCalendarIdString});
+ int cnt = cr.update(
+ asSyncAdapter(Events.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), cv,
+ SERVER_ID_AND_CALENDAR_ID, new String[] {
+ serverId, mCalendarIdString
+ });
// Keep track of any orphaned exceptions
if (cnt == 0) {
orphanedExceptions.add(c.getLong(1));
@@ -1764,17 +1799,21 @@
c.close();
}
- // Delete any orphaned exceptions
- for (long orphan: orphanedExceptions) {
+ // Delete any orphaned exceptions
+ for (long orphan : orphanedExceptions) {
userLog(TAG, "Deleted orphaned exception: " + orphan);
- cr.delete(ContentUris.withAppendedId(EVENTS_URI, orphan), null, null);
+ cr.delete(
+ asSyncAdapter(ContentUris.withAppendedId(Events.CONTENT_URI, orphan),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), null, null);
}
orphanedExceptions.clear();
- // Now we can go through dirty/marked top-level events and send them back to the server
- EntityIterator eventIterator = EventsEntity.newEntityIterator(
- cr.query(EVENTS_URI, null, DIRTY_OR_MARKED_TOP_LEVEL_IN_CALENDAR,
- mCalendarIdArgument, null), cr);
+ // Now we can go through dirty/marked top-level events and send them
+ // back to the server
+ EntityIterator eventIterator = EventsEntity.newEntityIterator(cr.query(
+ asSyncAdapter(Events.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), null,
+ DIRTY_OR_MARKED_TOP_LEVEL_IN_CALENDAR, mCalendarIdArgument, null), cr);
ContentValues cidValues = new ContentValues();
try {
@@ -1834,8 +1873,11 @@
// And save it in the Event as the local id
cidValues.put(Events._SYNC_DATA, clientId);
cidValues.put(Events._SYNC_VERSION, "0");
- cr.update(ContentUris.withAppendedId(EVENTS_URI, eventId), cidValues,
- null, null);
+ cr.update(
+ asSyncAdapter(
+ ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
+ cidValues, null, null);
} else {
if (entityValues.getAsInteger(Calendar.EventsColumns.DELETED) == 1) {
userLog("Deleting event with serverId: ", serverId);
@@ -1868,8 +1910,11 @@
cidValues.put(Events._SYNC_VERSION, version);
// Also save in entityValues so that we send it this time around
entityValues.put(Events._SYNC_VERSION, version);
- cr.update(ContentUris.withAppendedId(EVENTS_URI, eventId), cidValues,
- null, null);
+ cr.update(
+ asSyncAdapter(
+ ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
+ mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
+ cidValues, null, null);
s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, serverId);
}
s.start(Tags.SYNC_APPLICATION_DATA);
@@ -1878,9 +1923,12 @@
// Now, the hard part; find exceptions for this event
if (serverId != null) {
- EntityIterator exIterator = EventsEntity.newEntityIterator(
- cr.query(EVENTS_URI, null, ORIGINAL_EVENT_AND_CALENDAR,
- new String[] {serverId, mCalendarIdString}, null), cr);
+ EntityIterator exIterator = EventsEntity.newEntityIterator(cr.query(
+ asSyncAdapter(Events.CONTENT_URI, mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), null,
+ ORIGINAL_EVENT_AND_CALENDAR, new String[] {
+ serverId, mCalendarIdString
+ }, null), cr);
boolean exFirst = true;
while (exIterator.hasNext()) {
Entity exEntity = exIterator.next();
diff --git a/src/com/android/exchange/utility/CalendarUtilities.java b/src/com/android/exchange/utility/CalendarUtilities.java
index edf3b65..3b177fa 100644
--- a/src/com/android/exchange/utility/CalendarUtilities.java
+++ b/src/com/android/exchange/utility/CalendarUtilities.java
@@ -1240,7 +1240,9 @@
cv.put(Calendars.ACCESS_LEVEL, Calendars.OWNER_ACCESS);
cv.put(Calendars.OWNER_ACCOUNT, account.mEmailAddress);
- Uri uri = service.mContentResolver.insert(Calendars.CONTENT_URI, cv);
+ Uri uri = service.mContentResolver.insert(
+ asSyncAdapter(Calendars.CONTENT_URI, account.mEmailAddress,
+ Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), cv);
// We save the id of the calendar into mSyncStatus
if (uri != null) {
String stringId = uri.getPathSegments().get(1);
@@ -1250,6 +1252,13 @@
return -1;
}
+ static Uri asSyncAdapter(Uri uri, String account, String accountType) {
+ return uri.buildUpon()
+ .appendQueryParameter(android.provider.Calendar.CALLER_IS_SYNCADAPTER, "true")
+ .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
+ .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
+ }
+
/**
* Return the uid for an event based on its globalObjId
* @param globalObjId the base64 encoded String provided by EAS
@@ -1720,32 +1729,36 @@
}
/**
- * Create a Message for an Event that can be retrieved from CalendarProvider by its unique id
+ * Create a Message for an Event that can be retrieved from CalendarProvider
+ * by its unique id
+ *
* @param cr a content resolver that can be used to query for the Event
* @param eventId the unique id of the Event
- * @param messageFlag the Message.FLAG_XXX constant indicating the type of email to be sent
- * @param the unique id of this Event, or null if it can be retrieved from the Event
+ * @param messageFlag the Message.FLAG_XXX constant indicating the type of
+ * email to be sent
+ * @param the unique id of this Event, or null if it can be retrieved from
+ * the Event
* @param the user's account
- * @param requireAddressees if true (the default), no Message is returned if there aren't any
- * addressees; if false, return the Message regardless (addressees will be filled in later)
+ * @param requireAddressees if true (the default), no Message is returned if
+ * there aren't any addressees; if false, return the Message
+ * regardless (addressees will be filled in later)
* @return a Message with many fields pre-filled (more later)
- * @throws RemoteException if there is an issue retrieving the Event from CalendarProvider
+ * @throws RemoteException if there is an issue retrieving the Event from
+ * CalendarProvider
*/
static public EmailContent.Message createMessageForEventId(Context context, long eventId,
int messageFlag, String uid, Account account) throws RemoteException {
return createMessageForEventId(context, eventId, messageFlag, uid, account,
- null /*specifiedAttendee*/);
+ null /* specifiedAttendee */);
}
static public EmailContent.Message createMessageForEventId(Context context, long eventId,
int messageFlag, String uid, Account account, String specifiedAttendee)
throws RemoteException {
ContentResolver cr = context.getContentResolver();
- EntityIterator eventIterator =
- EventsEntity.newEntityIterator(
- cr.query(ContentUris.withAppendedId(Events.CONTENT_URI.buildUpon()
- .appendQueryParameter(android.provider.Calendar.CALLER_IS_SYNCADAPTER,
- "true").build(), eventId), null, null, null, null), cr);
+ EntityIterator eventIterator = EventsEntity.newEntityIterator(cr.query(
+ ContentUris.withAppendedId(Events.CONTENT_URI, eventId), null, null, null, null),
+ cr);
try {
while (eventIterator.hasNext()) {
Entity entity = eventIterator.next();