Handle upsync of EAS contact "group" (category) rename/delete
Bug: 3211907 Change-Id: I7bec90dae7c223b4bd0d0f366d18cac37e53fbcc
This commit is contained in:
parent
46e60b51e2
commit
fb3c389a14
@ -17,7 +17,6 @@
|
||||
package com.android.exchange;
|
||||
|
||||
import com.android.email.Email;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.AccountColumns;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.email.provider.EmailContent.MailboxColumns;
|
||||
@ -35,6 +34,7 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.provider.ContactsContract.Groups;
|
||||
import android.provider.ContactsContract.RawContacts;
|
||||
import android.util.Log;
|
||||
|
||||
@ -43,7 +43,7 @@ public class ContactsSyncAdapterService extends Service {
|
||||
private static SyncAdapterImpl sSyncAdapter = null;
|
||||
private static final Object sSyncAdapterLock = new Object();
|
||||
|
||||
private static final String[] ID_PROJECTION = new String[] {EmailContent.RECORD_ID};
|
||||
private static final String[] ID_PROJECTION = new String[] {"_id"};
|
||||
private static final String ACCOUNT_AND_TYPE_CONTACTS =
|
||||
MailboxColumns.ACCOUNT_KEY + "=? AND " + MailboxColumns.TYPE + '=' + Mailbox.TYPE_CONTACTS;
|
||||
|
||||
@ -85,6 +85,15 @@ public class ContactsSyncAdapterService extends Service {
|
||||
return sSyncAdapter.getSyncAdapterBinder();
|
||||
}
|
||||
|
||||
private static boolean hasDirtyRows(ContentResolver resolver, Uri uri, String dirtyColumn) {
|
||||
Cursor c = resolver.query(uri, ID_PROJECTION, dirtyColumn + "=1", null, null);
|
||||
try {
|
||||
return c.getCount() > 0;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial integration with system SyncManager; we tell our EAS ExchangeService to start a
|
||||
* contacts sync when we get the signal from SyncManager.
|
||||
@ -95,21 +104,29 @@ public class ContactsSyncAdapterService extends Service {
|
||||
String authority, ContentProviderClient provider, SyncResult syncResult)
|
||||
throws OperationCanceledException {
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
Log.i(TAG, "performSync");
|
||||
if (Email.DEBUG) {
|
||||
Log.d(TAG, "performSync");
|
||||
}
|
||||
|
||||
// If we've been asked to do an upload, make sure we've got work to do
|
||||
if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD)) {
|
||||
Uri uri = RawContacts.CONTENT_URI.buildUpon()
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, Email.EXCHANGE_ACCOUNT_MANAGER_TYPE)
|
||||
.build();
|
||||
Cursor c = cr.query(uri,
|
||||
new String[] {RawContacts._ID}, RawContacts.DIRTY + "=1", null, null);
|
||||
try {
|
||||
if (!c.moveToFirst()) {
|
||||
Log.i(TAG, "Upload sync; no changes");
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
// See if we've got dirty contacts or dirty groups containing our contacts
|
||||
boolean changed = hasDirtyRows(cr, uri, RawContacts.DIRTY);
|
||||
if (!changed) {
|
||||
uri = Groups.CONTENT_URI.buildUpon()
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_TYPE,
|
||||
Email.EXCHANGE_ACCOUNT_MANAGER_TYPE)
|
||||
.build();
|
||||
changed = hasDirtyRows(cr, uri, Groups.DIRTY);
|
||||
}
|
||||
if (!changed) {
|
||||
Log.i(TAG, "Upload sync; no changes");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,10 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
|
||||
private static final String SERVER_ID_SELECTION = RawContacts.SOURCE_ID + "=?";
|
||||
private static final String CLIENT_ID_SELECTION = RawContacts.SYNC1 + "=?";
|
||||
private static final String[] ID_PROJECTION = new String[] {RawContacts._ID};
|
||||
private static final String[] GROUP_PROJECTION = new String[] {Groups.SOURCE_ID};
|
||||
private static final String[] GROUP_TITLE_PROJECTION = new String[] {Groups.TITLE};
|
||||
private static final String MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS = Data.MIMETYPE + "='" +
|
||||
GroupMembership.CONTENT_ITEM_TYPE + "' AND " + GroupMembership.GROUP_ROW_ID + "=?";
|
||||
private static final String[] GROUPS_ID_PROJECTION = new String[] {Groups._ID};
|
||||
|
||||
private static final ArrayList<NamedContentValues> EMPTY_ARRAY_NAMEDCONTENTVALUES
|
||||
= new ArrayList<NamedContentValues>();
|
||||
@ -1742,17 +1745,47 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private void dirtyContactsWithinDirtyGroups() {
|
||||
ContentResolver cr = mService.mContentResolver;
|
||||
Cursor c = cr.query(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI),
|
||||
GROUPS_ID_PROJECTION, Groups.DIRTY + "=1", null, null);
|
||||
try {
|
||||
if (c.getCount() > 0) {
|
||||
String[] updateArgs = new String[1];
|
||||
ContentValues updateValues = new ContentValues();
|
||||
while (c.moveToNext()) {
|
||||
// For each, "touch" all data rows with this group id; this will mark contacts
|
||||
// in this group as dirty (per ContactsContract). We will then know to upload
|
||||
// them to the server with the modified group information
|
||||
long id = c.getLong(0);
|
||||
updateValues.put(GroupMembership.GROUP_ROW_ID, id);
|
||||
updateArgs[0] = Long.toString(id);
|
||||
cr.update(Data.CONTENT_URI, updateValues,
|
||||
MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS, updateArgs);
|
||||
}
|
||||
// Really delete groups that are marked deleted
|
||||
cr.delete(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI), Groups.DELETED + "=1",
|
||||
null);
|
||||
// Clear the dirty flag for all of our groups
|
||||
updateValues.clear();
|
||||
updateValues.put(Groups.DIRTY, 0);
|
||||
cr.update(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI), updateValues, null,
|
||||
null);
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendLocalChanges(Serializer s) throws IOException {
|
||||
// First, let's find Contacts that have changed.
|
||||
ContentResolver cr = mService.mContentResolver;
|
||||
Uri uri = RawContactsEntity.CONTENT_URI.buildUpon()
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccount.mEmailAddress)
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_TYPE,
|
||||
com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE)
|
||||
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||
.build();
|
||||
|
||||
// Find any groups of ours that are dirty and dirty those groups' members
|
||||
dirtyContactsWithinDirtyGroups();
|
||||
|
||||
// First, let's find Contacts that have changed.
|
||||
Uri uri = uriWithAccountAndIsSyncAdapter(RawContactsEntity.CONTENT_URI);
|
||||
if (getSyncKey().equals("0")) {
|
||||
return false;
|
||||
}
|
||||
@ -1863,7 +1896,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
|
||||
for (int id: groupIds) {
|
||||
// Since we get id's from the provider, we need to find their names
|
||||
Cursor c = cr.query(ContentUris.withAppendedId(Groups.CONTENT_URI, id),
|
||||
GROUP_PROJECTION, null, null, null);
|
||||
GROUP_TITLE_PROJECTION, null, null, null);
|
||||
try {
|
||||
// Presumably, this should always succeed, but ...
|
||||
if (c.moveToFirst()) {
|
||||
|
Loading…
Reference in New Issue
Block a user