diff --git a/src/com/android/exchange/adapter/ContactsSyncAdapter.java b/src/com/android/exchange/adapter/ContactsSyncAdapter.java index a75477453..b08724f04 100644 --- a/src/com/android/exchange/adapter/ContactsSyncAdapter.java +++ b/src/com/android/exchange/adapter/ContactsSyncAdapter.java @@ -97,7 +97,9 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { private static final int MAX_IM_ROWS = 3; private static final int MAX_EMAIL_ROWS = 3; + private static final int MAX_PHONE_ROWS = 2; private static final String COMMON_DATA_ROW = Im.DATA; // Could have been Email.DATA, etc. + private static final String COMMON_TYPE_ROW = Phone.TYPE; // Could have been any typed row private static final int[] IM_TAGS = new int[] {Tags.CONTACTS2_IM_ADDRESS, Tags.CONTACTS2_IM_ADDRESS_2, Tags.CONTACTS2_IM_ADDRESS_3}; @@ -105,9 +107,11 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { private static final int[] EMAIL_TAGS = new int[] {Tags.CONTACTS_EMAIL1_ADDRESS, Tags.CONTACTS_EMAIL2_ADDRESS, Tags.CONTACTS_EMAIL3_ADDRESS}; - private static final int TYPE_WORK2 = 26; - private static final int TYPE_HOME2 = 27; - private static final int TYPE_MMS = 30; + private static final int[] WORK_PHONE_TAGS = new int[] {Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER, + Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER}; + + private static final int[] HOME_PHONE_TAGS = new int[] {Tags.CONTACTS_HOME_TELEPHONE_NUMBER, + Tags.CONTACTS_HOME2_TELEPHONE_NUMBER}; ArrayList mDeletedIdList = new ArrayList(); ArrayList mUpdatedIdList = new ArrayList(); @@ -128,7 +132,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { interface UntypedRow { public void addValues(RowBuilder builder); - public boolean isSameAs(String value); + public boolean isSameAs(int type, String value); } /** @@ -147,7 +151,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { 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_NAME, mService.mHostLogin); cv.put(Groups.ACCOUNT_TYPE, Eas.ACCOUNT_MANAGER_TYPE); cv.put(Settings.UNGROUPED_VISIBLE, true); client.insert(Settings.CONTENT_URI, cv); @@ -186,7 +190,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { public android.accounts.Account getAccountManagerAccount() { if (mAccountManagerAccount == null) { mAccountManagerAccount = - new android.accounts.Account(mAccount.mEmailAddress, Eas.ACCOUNT_MANAGER_TYPE); + new android.accounts.Account(mService.mHostLogin, Eas.ACCOUNT_MANAGER_TYPE); } return mAccountManagerAccount; } @@ -271,7 +275,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { builder.withValue(Email.DISPLAY_NAME, displayName); } - public boolean isSameAs(String value) { + public boolean isSameAs(int type, String value) { return email.equalsIgnoreCase(value); } } @@ -287,11 +291,30 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { builder.withValue(Im.DATA, im); } - public boolean isSameAs(String value) { + public boolean isSameAs(int type, String value) { return im.equalsIgnoreCase(value); } } + class PhoneRow implements UntypedRow { + String phone; + int type; + + public PhoneRow(String _phone, int _type) { + phone = _phone; + type = _type; + } + + public void addValues(RowBuilder builder) { + builder.withValue(Im.DATA, phone); + builder.withValue(Phone.TYPE, type); + } + + public boolean isSameAs(int _type, String value) { + return type == _type && phone.equalsIgnoreCase(value); + } + } + class EasContactsSyncParser extends AbstractSyncParser { String[] mBindArgument = new String[1]; @@ -299,7 +322,8 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { Uri mAccountUri; ContactOperations ops = new ContactOperations(); - public EasContactsSyncParser(InputStream in, ContactsSyncAdapter adapter) throws IOException { + public EasContactsSyncParser(InputStream in, ContactsSyncAdapter adapter) + throws IOException { super(in, adapter); mAccountUri = uriWithAccountAndIsSyncAdapter(RawContacts.CONTENT_URI); } @@ -331,6 +355,8 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { ArrayList children = new ArrayList(); ArrayList emails = new ArrayList(); ArrayList ims = new ArrayList(); + ArrayList homePhones = new ArrayList(); + ArrayList workPhones = new ArrayList(); if (entity == null) { ops.newContact(serverId); } @@ -364,13 +390,11 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { emails.add(new EmailRow(getValue())); break; case Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER: - ops.addPhone(entity, TYPE_WORK2, getValue()); - break; case Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER: - ops.addPhone(entity, Phone.TYPE_WORK, getValue()); + workPhones.add(new PhoneRow(getValue(), Phone.TYPE_WORK)); break; case Tags.CONTACTS2_MMS: - ops.addPhone(entity, TYPE_MMS, getValue()); + ops.addPhone(entity, Phone.TYPE_MMS, getValue()); break; case Tags.CONTACTS_BUSINESS_FAX_NUMBER: ops.addPhone(entity, Phone.TYPE_FAX_WORK, getValue()); @@ -382,10 +406,8 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { ops.addPhone(entity, Phone.TYPE_FAX_HOME, getValue()); break; case Tags.CONTACTS_HOME_TELEPHONE_NUMBER: - ops.addPhone(entity, Phone.TYPE_HOME, getValue()); - break; case Tags.CONTACTS_HOME2_TELEPHONE_NUMBER: - ops.addPhone(entity, TYPE_HOME2, getValue()); + homePhones.add(new PhoneRow(getValue(), Phone.TYPE_HOME)); break; case Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER: ops.addPhone(entity, Phone.TYPE_MOBILE, getValue()); @@ -557,8 +579,12 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { ops.addBusiness(entity, business); ops.addPersonal(entity, personal); - ops.addUntyped(entity, emails, Email.CONTENT_ITEM_TYPE, MAX_EMAIL_ROWS); - ops.addUntyped(entity, ims, Im.CONTENT_ITEM_TYPE, MAX_IM_ROWS); + ops.addUntyped(entity, emails, Email.CONTENT_ITEM_TYPE, -1, MAX_EMAIL_ROWS); + ops.addUntyped(entity, ims, Im.CONTENT_ITEM_TYPE, -1, MAX_IM_ROWS); + ops.addUntyped(entity, homePhones, Phone.CONTENT_ITEM_TYPE, Phone.TYPE_HOME, + MAX_PHONE_ROWS); + ops.addUntyped(entity, workPhones, Phone.CONTENT_ITEM_TYPE, Phone.TYPE_WORK, + MAX_PHONE_ROWS); if (!children.isEmpty()) { ops.addChildren(entity, children); @@ -815,6 +841,28 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { c.close(); } } + + public void changeResponsesParser() throws IOException { + String serverId = null; + String status = null; + while (nextTag(Tags.SYNC_CHANGE) != END) { + switch (tag) { + case Tags.SYNC_SERVER_ID: + serverId = getValue(); + break; + case Tags.SYNC_STATUS: + status = getValue(); + break; + default: + skipTag(); + } + } + if (serverId != null && status != null) { + userLog("Changed contact " + serverId + " failed with status: " + status); + } + } + + @Override public void responsesParser() throws IOException { // Handle server responses here (for Add and Change) @@ -822,7 +870,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { if (tag == Tags.SYNC_ADD) { addResponsesParser(); } else if (tag == Tags.SYNC_CHANGE) { - //changeResponsesParser(); + changeResponsesParser(); } else skipTag(); } @@ -832,7 +880,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { private Uri uriWithAccountAndIsSyncAdapter(Uri uri) { return uri.buildUpon() - .appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccount.mEmailAddress) + .appendQueryParameter(RawContacts.ACCOUNT_NAME, mService.mHostLogin) .appendQueryParameter(RawContacts.ACCOUNT_TYPE, Eas.ACCOUNT_MANAGER_TYPE) .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") .build(); @@ -984,7 +1032,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { * @return the matching NCVs */ private ArrayList findUntypedData(ArrayList list, - String contentItemType) { + int type, String contentItemType) { ArrayList result = new ArrayList(); // Loop through the ncv's, looking for an existing row @@ -994,6 +1042,12 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { if (Data.CONTENT_URI.equals(uri)) { String mimeType = cv.getAsString(Data.MIMETYPE); if (mimeType.equals(contentItemType)) { + if (type != -1) { + int subtype = cv.getAsInteger(Phone.TYPE); + if (type != subtype) { + continue; + } + } result.add(namedContentValues); } } @@ -1257,11 +1311,11 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { * that no longer matches. This is similar to the way Emails are handled. */ public void addUntyped(Entity entity, ArrayList rows, String mimeType, - int maxRows) { + int type, int maxRows) { // Make a list of all same type rows in the existing entity ArrayList oldAccounts = new ArrayList(); if (entity != null) { - oldAccounts = findUntypedData(entity.getSubValues(), mimeType); + oldAccounts = findUntypedData(entity.getSubValues(), type, mimeType); } // These will be rows needing replacement with new values @@ -1275,7 +1329,11 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { for (NamedContentValues ncv: oldAccounts) { ContentValues cv = ncv.values; String data = cv.getAsString(COMMON_DATA_ROW); - if (row.isSameAs(data)) { + int rowType = -1; + if (cv.containsKey(COMMON_TYPE_ROW)) { + rowType = cv.getAsInteger(COMMON_TYPE_ROW); + } + if (row.isSameAs(rowType, data)) { cv.put(FOUND_DATA_ROW, true); found = true; break; @@ -1599,17 +1657,17 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { } } - private void sendPhone(Serializer s, ContentValues cv) throws IOException { + private void sendPhone(Serializer s, ContentValues cv, int workCount, int homeCount) + throws IOException { String value = cv.getAsString(Phone.NUMBER); if (value == null) return; switch (cv.getAsInteger(Phone.TYPE)) { - case TYPE_WORK2: - s.data(Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER, value); - break; case Phone.TYPE_WORK: - s.data(Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER, value); + if (workCount < MAX_PHONE_ROWS) { + s.data(WORK_PHONE_TAGS[workCount], value); + } break; - case TYPE_MMS: + case Phone.TYPE_MMS: s.data(Tags.CONTACTS2_MMS, value); break; case Phone.TYPE_FAX_WORK: @@ -1619,10 +1677,9 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { s.data(Tags.CONTACTS2_COMPANY_MAIN_PHONE, value); break; case Phone.TYPE_HOME: - s.data(Tags.CONTACTS_HOME_TELEPHONE_NUMBER, value); - break; - case TYPE_HOME2: - s.data(Tags.CONTACTS_HOME2_TELEPHONE_NUMBER, value); + if (homeCount < MAX_PHONE_ROWS) { + s.data(HOME_PHONE_TAGS[homeCount], value); + } break; case Phone.TYPE_MOBILE: s.data(Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER, value); @@ -1667,7 +1724,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { // First, let's find Contacts that have changed. ContentResolver cr = mService.mContentResolver; Uri uri = RawContacts.CONTENT_URI.buildUpon() - .appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccount.mEmailAddress) + .appendQueryParameter(RawContacts.ACCOUNT_NAME, mService.mHostLogin) .appendQueryParameter(RawContacts.ACCOUNT_TYPE, Eas.ACCOUNT_MANAGER_TYPE) .build(); @@ -1717,6 +1774,8 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { // Write out the data here int imCount = 0; int emailCount = 0; + int homePhoneCount = 0; + int workPhoneCount = 0; String displayName = null; ArrayList emailValues = new ArrayList(); for (NamedContentValues ncv: entity.getSubValues()) { @@ -1735,7 +1794,10 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { } else if (mimeType.equals(EasPersonal.CONTENT_ITEM_TYPE)) { sendPersonal(s, cv); } else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) { - sendPhone(s, cv); + sendPhone(s, cv, workPhoneCount, homePhoneCount); + int type = cv.getAsInteger(Phone.TYPE); + if (type == Phone.TYPE_HOME) homePhoneCount++; + if (type == Phone.TYPE_WORK) workPhoneCount++; } else if (mimeType.equals(Relation.CONTENT_ITEM_TYPE)) { sendRelation(s, cv); } else if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE)) { @@ -1760,11 +1822,11 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter { } // We do the email rows last, because we need to make sure we've found the - // displayName (if one exists); this would be in a StructuredName row + // displayName (if one exists); this would be in a StructuredName rnow for (ContentValues cv: emailValues) { sendEmail(s, cv, emailCount++, displayName); } - + // Now, we'll send up groups, if any if (!groupIds.isEmpty()) { boolean groupFirst = true;