Merge change 25691 into eclair

* changes:
  UI Refulesh of account folder list
diff --git a/src/com/android/exchange/EasOutboxService.java b/src/com/android/exchange/EasOutboxService.java
index ab5fa9f..de5cf49 100644
--- a/src/com/android/exchange/EasOutboxService.java
+++ b/src/com/android/exchange/EasOutboxService.java
@@ -41,7 +41,6 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.net.URLEncoder;
 
 public class EasOutboxService extends EasSyncService {
 
@@ -126,9 +125,9 @@
             String cmd = "SendMail&SaveInSent=T";
             if (smartSend) {
                 cmd = reply ? "SmartReply" : "SmartForward";
-                cmd += "&ItemId=" + URLEncoder.encode(itemId, "UTF-8") + "&CollectionId="
-                    + URLEncoder.encode(collectionId, "UTF-8") + "&SaveInSent=T";
+                cmd += "&ItemId=" + itemId + "&CollectionId=" + collectionId + "&SaveInSent=T";
             }
+            userLog("Send cmd: " + cmd);
             HttpResponse resp = sendHttpClientPost(cmd, inputEntity);
 
             inputStream.close();
@@ -140,6 +139,7 @@
                 result = EmailServiceStatus.SUCCESS;
                 sendCallback(-1, subject, EmailServiceStatus.SUCCESS);
             } else {
+                userLog("Message sending failed, code: " + code);
                 ContentValues cv = new ContentValues();
                 cv.put(SyncColumns.SERVER_ID, SEND_FAILED);
                 Message.update(mContext, Message.CONTENT_URI, msgId, cv);
@@ -196,6 +196,7 @@
         } catch (IOException e) {
             mExitStatus = EXIT_IO_ERROR;
         } catch (Exception e) {
+            userLog("Exception caught in EasOutboxService", e);
             mExitStatus = EXIT_EXCEPTION;
         } finally {
             userLog(mMailbox.mDisplayName, ": sync finished");
diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java
index 667eeae..ea56118 100644
--- a/src/com/android/exchange/EasSyncService.java
+++ b/src/com/android/exchange/EasSyncService.java
@@ -133,6 +133,7 @@
     private boolean mSsl = true;
     private boolean mTrustSsl = false;
     public ContentResolver mContentResolver;
+    public String mHostLogin;
     private String[] mBindArguments = new String[2];
     private ArrayList<String> mPingChangeList;
     private HttpPost mPendingPost = null;
@@ -147,6 +148,7 @@
         super(_context, _mailbox);
         mContentResolver = _context.getContentResolver();
         HostAuth ha = HostAuth.restoreHostAuthWithId(_context, mAccount.mHostAuthKeyRecv);
+        mHostLogin = ha.mLogin;
         mSsl = (ha.mFlags & HostAuth.FLAG_SSL) != 0;
         mTrustSsl = (ha.mFlags & HostAuth.FLAG_TRUST_ALL_CERTIFICATES) != 0;
     }
@@ -516,7 +518,9 @@
                 int code = resp.getStatusLine().getStatusCode();
                 userLog("OPTIONS response: ", code);
                 if (code == HttpStatus.SC_OK) {
-                    Header header = resp.getFirstHeader("ms-asprotocolversions");
+                    Header header = resp.getFirstHeader("MS-ASProtocolCommands");
+                    userLog(header.getValue());
+                    header = resp.getFirstHeader("ms-asprotocolversions");
                     String versions = header.getValue();
                     if (versions != null) {
                         if (versions.contains("12.0")) {
@@ -1039,7 +1043,6 @@
                 runAccountMailbox();
             } else {
                 AbstractSyncAdapter target;
-                mAccount = Account.restoreAccountWithId(mContext, mAccount.mId);
                 mProtocolVersion = mAccount.mProtocolVersion;
                 mProtocolVersionDouble = Double.parseDouble(mProtocolVersion);
                 if (mMailbox.mType == Mailbox.TYPE_CONTACTS) {
diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java
index 2da2a1f..8b35679 100644
--- a/src/com/android/exchange/SyncManager.java
+++ b/src/com/android/exchange/SyncManager.java
@@ -443,7 +443,7 @@
                         stopAccountSyncs(account.mId, true);
                         // Delete this from AccountManager...
                         android.accounts.Account acct =
-                            new android.accounts.Account(account.mEmailAddress,
+                            new android.accounts.Account(account.mHostAuthRecv.mLogin,
                                     Eas.ACCOUNT_MANAGER_TYPE);
                         AccountManager.get(SyncManager.this).removeAccount(acct, null, null);
                         mAccountKeyList = null;
@@ -471,6 +471,10 @@
                     if (!mAccounts.contains(account.mId)) {
                         // This is an addition; create our magic hidden mailbox...
                         addAccountMailbox(account.mId);
+                        // Don't forget to cache the HostAuth
+                        HostAuth ha =
+                            HostAuth.restoreHostAuthWithId(getContext(), account.mHostAuthKeyRecv);
+                        account.mHostAuthRecv = ha;
                         mAccounts.add(account);
                         mAccountKeyList = null;
                     }
@@ -493,7 +497,10 @@
                 if (hostAuthId > 0) {
                     HostAuth ha = HostAuth.restoreHostAuthWithId(context, hostAuthId);
                     if (ha != null && ha.mProtocol.equals("eas")) {
-                        accounts.add(new Account().restore(c));
+                        Account account = new Account().restore(c);
+                        // Cache the HostAuth
+                        account.mHostAuthRecv = ha;
+                        accounts.add(account);
                     }
                 }
             }
@@ -1030,7 +1037,7 @@
             if (contactsId != Mailbox.NO_MAILBOX) {
                 // Create an AccountManager style Account
                 android.accounts.Account acct =
-                    new android.accounts.Account(easAccount.mEmailAddress,
+                    new android.accounts.Account(easAccount.mHostAuthRecv.mLogin,
                             Eas.ACCOUNT_MANAGER_TYPE);
                 // Get the Contacts mailbox; this happens rarely so it's ok to get it all
                 Mailbox contacts = Mailbox.restoreMailboxWithId(this, contactsId);
@@ -1069,7 +1076,7 @@
             AccountManager.get(this).getAccountsByType(Eas.ACCOUNT_MANAGER_TYPE);
         List<Account> easAccounts = getAccountList();
         for (Account easAccount: easAccounts) {
-            String accountName = easAccount.mEmailAddress;
+            String accountName = easAccount.mHostAuthRecv.mLogin;
             boolean found = false;
             for (android.accounts.Account acct: accts) {
                 if (acct.name.equalsIgnoreCase(accountName)) {
@@ -1400,7 +1407,7 @@
                             getAccountById(c.getInt(Mailbox.CONTENT_ACCOUNT_KEY_COLUMN));
                         if (account != null) {
                             android.accounts.Account a =
-                                new android.accounts.Account(account.mEmailAddress,
+                                new android.accounts.Account(account.mHostAuthRecv.mLogin,
                                         Eas.ACCOUNT_MANAGER_TYPE);
                             if (!ContentResolver.getSyncAutomatically(a,
                                     ContactsContract.AUTHORITY)) {
diff --git a/src/com/android/exchange/adapter/ContactsSyncAdapter.java b/src/com/android/exchange/adapter/ContactsSyncAdapter.java
index 8aa07d4..b08724f 100644
--- a/src/com/android/exchange/adapter/ContactsSyncAdapter.java
+++ b/src/com/android/exchange/adapter/ContactsSyncAdapter.java
@@ -97,7 +97,9 @@
 
     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 @@
     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<Long> mDeletedIdList = new ArrayList<Long>();
     ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();
@@ -128,7 +132,7 @@
 
     interface UntypedRow {
         public void addValues(RowBuilder builder);
-        public boolean isSameAs(String value);
+        public boolean isSameAs(int type, String value);
     }
 
     /**
@@ -147,7 +151,7 @@
                 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 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 @@
             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 @@
             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 @@
         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 @@
             ArrayList<String> children = new ArrayList<String>();
             ArrayList<UntypedRow> emails = new ArrayList<UntypedRow>();
             ArrayList<UntypedRow> ims = new ArrayList<UntypedRow>();
+            ArrayList<UntypedRow> homePhones = new ArrayList<UntypedRow>();
+            ArrayList<UntypedRow> workPhones = new ArrayList<UntypedRow>();
             if (entity == null) {
                 ops.newContact(serverId);
             }
@@ -364,13 +390,11 @@
                         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 @@
                         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 @@
             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 @@
                 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 @@
                 if (tag == Tags.SYNC_ADD) {
                     addResponsesParser();
                 } else if (tag == Tags.SYNC_CHANGE) {
-                    //changeResponsesParser();
+                    changeResponsesParser();
                 } else
                     skipTag();
             }
@@ -832,7 +880,7 @@
 
     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 @@
          * @return the matching NCVs
          */
         private ArrayList<NamedContentValues> findUntypedData(ArrayList<NamedContentValues> list,
-                String contentItemType) {
+                int type, String contentItemType) {
             ArrayList<NamedContentValues> result = new ArrayList<NamedContentValues>();
 
             // Loop through the ncv's, looking for an existing row
@@ -994,6 +1042,12 @@
                 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 @@
          * that no longer matches.  This is similar to the way Emails are handled.
          */
         public void addUntyped(Entity entity, ArrayList<UntypedRow> rows, String mimeType,
-                int maxRows) {
+                int type, int maxRows) {
             // Make a list of all same type rows in the existing entity
             ArrayList<NamedContentValues> oldAccounts = new ArrayList<NamedContentValues>();
             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 @@
                 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;
@@ -1420,12 +1478,17 @@
         return "Contacts";
     }
 
-    private void sendEmail(Serializer s, ContentValues cv, int count) throws IOException {
+    private void sendEmail(Serializer s, ContentValues cv, int count, String displayName)
+            throws IOException {
         // Get both parts of the email address (a newly created one in the UI won't have a name)
         String addr = cv.getAsString(Email.DATA);
         String name = cv.getAsString(Email.DISPLAY_NAME);
         if (name == null) {
-            name = addr;
+            if (displayName != null) {
+                name = displayName;
+            } else {
+                name = addr;
+            }
         }
         // Compose address from name and addr
         if (addr != null) {
@@ -1479,7 +1542,8 @@
         }
     }
 
-    private void sendStructuredName(Serializer s, ContentValues cv) throws IOException {
+    private String sendStructuredName(Serializer s, ContentValues cv) throws IOException {
+        String displayName = null;
         if (cv.containsKey(StructuredName.FAMILY_NAME)) {
             s.data(Tags.CONTACTS_LAST_NAME, cv.getAsString(StructuredName.FAMILY_NAME));
         }
@@ -1504,8 +1568,10 @@
             s.data(Tags.CONTACTS_TITLE, cv.getAsString(StructuredName.PREFIX));
         }
         if (cv.containsKey(StructuredName.DISPLAY_NAME)) {
-            s.data(Tags.CONTACTS_FILE_AS, cv.getAsString(StructuredName.DISPLAY_NAME));
+            displayName = cv.getAsString(StructuredName.DISPLAY_NAME);
+            s.data(Tags.CONTACTS_FILE_AS, displayName);
         }
+        return displayName;
     }
 
     private void sendBusiness(Serializer s, ContentValues cv) throws IOException {
@@ -1591,17 +1657,17 @@
         }
     }
 
-    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:
@@ -1611,10 +1677,9 @@
                 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);
@@ -1659,7 +1724,7 @@
         // 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();
 
@@ -1709,11 +1774,15 @@
                     // Write out the data here
                     int imCount = 0;
                     int emailCount = 0;
+                    int homePhoneCount = 0;
+                    int workPhoneCount = 0;
+                    String displayName = null;
+                    ArrayList<ContentValues> emailValues = new ArrayList<ContentValues>();
                     for (NamedContentValues ncv: entity.getSubValues()) {
                         ContentValues cv = ncv.values;
                         String mimeType = cv.getAsString(Data.MIMETYPE);
                         if (mimeType.equals(Email.CONTENT_ITEM_TYPE)) {
-                            sendEmail(s, cv, emailCount++);
+                            emailValues.add(cv);
                         } else if (mimeType.equals(Nickname.CONTENT_ITEM_TYPE)) {
                             sendNickname(s, cv);
                         } else if (mimeType.equals(EasChildren.CONTENT_ITEM_TYPE)) {
@@ -1725,11 +1794,14 @@
                         } 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)) {
-                            sendStructuredName(s, cv);
+                            displayName = sendStructuredName(s, cv);
                         } else if (mimeType.equals(StructuredPostal.CONTENT_ITEM_TYPE)) {
                             sendStructuredPostal(s, cv);
                         } else if (mimeType.equals(Organization.CONTENT_ITEM_TYPE)) {
@@ -1749,6 +1821,12 @@
                         }
                     }
 
+                    // 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 rnow
+                    for (ContentValues cv: emailValues) {
+                        sendEmail(s, cv, emailCount++, displayName);
+                    }
+                    
                     // Now, we'll send up groups, if any
                     if (!groupIds.isEmpty()) {
                         boolean groupFirst = true;
diff --git a/src/com/android/exchange/adapter/EmailSyncAdapter.java b/src/com/android/exchange/adapter/EmailSyncAdapter.java
index e715a97..71eb7a7 100644
--- a/src/com/android/exchange/adapter/EmailSyncAdapter.java
+++ b/src/com/android/exchange/adapter/EmailSyncAdapter.java
@@ -316,8 +316,8 @@
                     WHERE_SERVER_ID_AND_MAILBOX_KEY, bindArguments, null);
         }
 
-        private void deleteParser(ArrayList<Long> deletes) throws IOException {
-            while (nextTag(Tags.SYNC_DELETE) != END) {
+        private void deleteParser(ArrayList<Long> deletes, int entryTag) throws IOException {
+            while (nextTag(entryTag) != END) {
                 switch (tag) {
                     case Tags.SYNC_SERVER_ID:
                         String serverId = getValue();
@@ -400,8 +400,8 @@
                 if (tag == Tags.SYNC_ADD) {
                     addParser(newEmails);
                     incrementChangeCount();
-                } else if (tag == Tags.SYNC_DELETE) {
-                    deleteParser(deletedEmails);
+                } else if (tag == Tags.SYNC_DELETE || tag == Tags.SYNC_SOFT_DELETE) {
+                    deleteParser(deletedEmails, tag);
                     incrementChangeCount();
                 } else if (tag == Tags.SYNC_CHANGE) {
                     changeParser(changedEmails);