am 5d2be5b3: Merge "Move ContactLoader related code to ContactsCommon" into klp-dev

* commit '5d2be5b3d6f467d044f5e8cbe819b811da05561f':
  Move ContactLoader related code to ContactsCommon
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dd0406b..0d25bb25 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -451,12 +451,6 @@
     <!-- The button to add an organization field to a contact in the Raw Contact Editor [CHAR LIMIT=15] -->
     <string name="group_edit_field_hint_text">Group name</string>
 
-    <!-- Attribution of a contact status update, when the time of update is unknown -->
-    <string name="contact_status_update_attribution">via <xliff:g id="source" example="Google Talk">%1$s</xliff:g></string>
-
-    <!-- Attribution of a contact status update, when the time of update is known -->
-    <string name="contact_status_update_attribution_with_date"><xliff:g id="date" example="3 hours ago">%1$s</xliff:g> via <xliff:g id="source" example="Google Talk">%2$s</xliff:g></string>
-
     <!-- String describing the Star/Favorite checkbox
 
          Used by AccessibilityService to announce the purpose of the view.
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 9f916fb..7a8f9f3 100644
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -49,9 +49,9 @@
 
 import com.android.contacts.common.database.ContactUpdateUtils;
 import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.model.RawContactDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.util.CallerInfoCacheUtils;
 import com.android.contacts.util.ContactPhotoUtils;
diff --git a/src/com/android/contacts/ContactsActivity.java b/src/com/android/contacts/ContactsActivity.java
index f3ac147..b94a237 100644
--- a/src/com/android/contacts/ContactsActivity.java
+++ b/src/com/android/contacts/ContactsActivity.java
@@ -26,7 +26,7 @@
 import android.view.View;
 
 import com.android.contacts.common.activity.TransactionSafeActivity;
-import com.android.contacts.test.InjectedServices;
+import com.android.contacts.common.test.InjectedServices;
 
 /**
  * A common superclass for Contacts activities that handles application-wide services.
diff --git a/src/com/android/contacts/ContactsApplication.java b/src/com/android/contacts/ContactsApplication.java
index 82b2a25..95fad48 100644
--- a/src/com/android/contacts/ContactsApplication.java
+++ b/src/com/android/contacts/ContactsApplication.java
@@ -32,7 +32,7 @@
 import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.common.list.ContactListFilterController;
 import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.test.InjectedServices;
+import com.android.contacts.common.test.InjectedServices;
 import com.android.contacts.common.util.Constants;
 import com.google.common.annotations.VisibleForTesting;
 
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
deleted file mode 100644
index 6b7114c..0000000
--- a/src/com/android/contacts/ContactsUtils.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.DisplayPhoto;
-import android.telephony.PhoneNumberUtils;
-import android.text.TextUtils;
-
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.test.NeededForTesting;
-import com.android.contacts.common.model.AccountTypeManager;
-
-import java.util.List;
-
-public class ContactsUtils {
-    private static final String TAG = "ContactsUtils";
-
-    private static int sThumbnailSize = -1;
-
-    // TODO find a proper place for the canonical version of these
-    public interface ProviderNames {
-        String YAHOO = "Yahoo";
-        String GTALK = "GTalk";
-        String MSN = "MSN";
-        String ICQ = "ICQ";
-        String AIM = "AIM";
-        String XMPP = "XMPP";
-        String JABBER = "JABBER";
-        String SKYPE = "SKYPE";
-        String QQ = "QQ";
-    }
-
-    /**
-     * This looks up the provider name defined in
-     * ProviderNames from the predefined IM protocol id.
-     * This is used for interacting with the IM application.
-     *
-     * @param protocol the protocol ID
-     * @return the provider name the IM app uses for the given protocol, or null if no
-     * provider is defined for the given protocol
-     * @hide
-     */
-    public static String lookupProviderNameFromId(int protocol) {
-        switch (protocol) {
-            case Im.PROTOCOL_GOOGLE_TALK:
-                return ProviderNames.GTALK;
-            case Im.PROTOCOL_AIM:
-                return ProviderNames.AIM;
-            case Im.PROTOCOL_MSN:
-                return ProviderNames.MSN;
-            case Im.PROTOCOL_YAHOO:
-                return ProviderNames.YAHOO;
-            case Im.PROTOCOL_ICQ:
-                return ProviderNames.ICQ;
-            case Im.PROTOCOL_JABBER:
-                return ProviderNames.JABBER;
-            case Im.PROTOCOL_SKYPE:
-                return ProviderNames.SKYPE;
-            case Im.PROTOCOL_QQ:
-                return ProviderNames.QQ;
-        }
-        return null;
-    }
-
-    /**
-     * Test if the given {@link CharSequence} contains any graphic characters,
-     * first checking {@link TextUtils#isEmpty(CharSequence)} to handle null.
-     */
-    public static boolean isGraphic(CharSequence str) {
-        return !TextUtils.isEmpty(str) && TextUtils.isGraphic(str);
-    }
-
-    /**
-     * Returns true if two objects are considered equal.  Two null references are equal here.
-     */
-    @NeededForTesting
-    public static boolean areObjectsEqual(Object a, Object b) {
-        return a == b || (a != null && a.equals(b));
-    }
-
-    /**
-     * Returns true if two {@link Intent}s are both null, or have the same action.
-     */
-    public static final boolean areIntentActionEqual(Intent a, Intent b) {
-        if (a == b) {
-            return true;
-        }
-        if (a == null || b == null) {
-            return false;
-        }
-        return TextUtils.equals(a.getAction(), b.getAction());
-    }
-
-    public static boolean areContactWritableAccountsAvailable(Context context) {
-        final List<AccountWithDataSet> accounts =
-                AccountTypeManager.getInstance(context).getAccounts(true /* writeable */);
-        return !accounts.isEmpty();
-    }
-
-    public static boolean areGroupWritableAccountsAvailable(Context context) {
-        final List<AccountWithDataSet> accounts =
-                AccountTypeManager.getInstance(context).getGroupWritableAccounts();
-        return !accounts.isEmpty();
-    }
-
-    /**
-     * Returns the size (width and height) of thumbnail pictures as configured in the provider. This
-     * can safely be called from the UI thread, as the provider can serve this without performing
-     * a database access
-     */
-    public static int getThumbnailSize(Context context) {
-        if (sThumbnailSize == -1) {
-            final Cursor c = context.getContentResolver().query(
-                    DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
-                    new String[] { DisplayPhoto.THUMBNAIL_MAX_DIM }, null, null, null);
-            try {
-                c.moveToFirst();
-                sThumbnailSize = c.getInt(0);
-            } finally {
-                c.close();
-            }
-        }
-        return sThumbnailSize;
-    }
-
-}
diff --git a/src/com/android/contacts/GroupMetaData.java b/src/com/android/contacts/GroupMetaData.java
deleted file mode 100644
index 462ac4a..0000000
--- a/src/com/android/contacts/GroupMetaData.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.contacts;
-
-/**
- * Meta-data for a contact group.  We load all groups associated with the contact's
- * constituent accounts.
- */
-public final class GroupMetaData {
-    private String mAccountName;
-    private String mAccountType;
-    private String mDataSet;
-    private long mGroupId;
-    private String mTitle;
-    private boolean mDefaultGroup;
-    private boolean mFavorites;
-
-    public GroupMetaData(String accountName, String accountType, String dataSet, long groupId,
-            String title, boolean defaultGroup, boolean favorites) {
-        this.mAccountName = accountName;
-        this.mAccountType = accountType;
-        this.mDataSet = dataSet;
-        this.mGroupId = groupId;
-        this.mTitle = title;
-        this.mDefaultGroup = defaultGroup;
-        this.mFavorites = favorites;
-    }
-
-    public String getAccountName() {
-        return mAccountName;
-    }
-
-    public String getAccountType() {
-        return mAccountType;
-    }
-
-    public String getDataSet() {
-        return mDataSet;
-    }
-
-    public long getGroupId() {
-        return mGroupId;
-    }
-
-    public String getTitle() {
-        return mTitle;
-    }
-
-    public boolean isDefaultGroup() {
-        return mDefaultGroup;
-    }
-
-    public boolean isFavorites() {
-        return mFavorites;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/contacts/TypePrecedence.java b/src/com/android/contacts/TypePrecedence.java
index 53b8343..0a193b5 100644
--- a/src/com/android/contacts/TypePrecedence.java
+++ b/src/com/android/contacts/TypePrecedence.java
@@ -23,7 +23,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactModifier;
 
 /**
  * This class contains utility functions for determining the precedence of
diff --git a/src/com/android/contacts/ViewNotificationService.java b/src/com/android/contacts/ViewNotificationService.java
index 3bc5ed2..0f2922a 100644
--- a/src/com/android/contacts/ViewNotificationService.java
+++ b/src/com/android/contacts/ViewNotificationService.java
@@ -23,8 +23,8 @@
 import android.os.IBinder;
 import android.util.Log;
 
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.ContactLoader;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
 
 
 /**
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index 78b482e..2d9e9f5 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -33,12 +33,12 @@
 
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.ContactsActivity;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.ContactLoader;
-import com.android.contacts.model.RawContactDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
+import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.util.ContactPhotoUtils;
diff --git a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
index fd12d7f..d60cc73 100644
--- a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
+++ b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
@@ -63,11 +63,11 @@
 import com.android.contacts.editor.EditorUiUtils;
 import com.android.contacts.editor.ViewIdGenerator;
 import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.model.dataitem.DataKind;
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 0f793e2..03821a7 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -46,7 +46,7 @@
 import com.android.contacts.detail.ContactLoaderFragment;
 import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
 import com.android.contacts.interactions.ContactDeletionInteraction;
-import com.android.contacts.model.Contact;
+import com.android.contacts.common.model.Contact;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.util.PhoneCapabilityTester;
 
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 2d69917..bfcd79e 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -51,7 +51,6 @@
 
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.ContactsActivity;
-import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
 import com.android.contacts.activities.ActionBarAdapter.TabState;
 import com.android.contacts.detail.ContactDetailFragment;
@@ -59,6 +58,7 @@
 import com.android.contacts.detail.ContactDetailUpdatesFragment;
 import com.android.contacts.detail.ContactLoaderFragment;
 import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
+import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.dialog.ClearFrequentsDialog;
 import com.android.contacts.group.GroupBrowseListFragment;
 import com.android.contacts.group.GroupBrowseListFragment.OnGroupBrowserActionListener;
@@ -81,7 +81,7 @@
 import com.android.contacts.list.OnContactsUnavailableActionListener;
 import com.android.contacts.list.ProviderStatusWatcher;
 import com.android.contacts.list.ProviderStatusWatcher.ProviderStatusListener;
-import com.android.contacts.model.Contact;
+import com.android.contacts.common.model.Contact;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.preference.ContactsPreferenceActivity;
 import com.android.contacts.preference.DisplayOptionsPreferenceFragment;
diff --git a/src/com/android/contacts/activities/PhotoSelectionActivity.java b/src/com/android/contacts/activities/PhotoSelectionActivity.java
index 6d74863..20892d6 100644
--- a/src/com/android/contacts/activities/PhotoSelectionActivity.java
+++ b/src/com/android/contacts/activities/PhotoSelectionActivity.java
@@ -39,7 +39,7 @@
 import com.android.contacts.R;
 import com.android.contacts.detail.PhotoSelectionHandler;
 import com.android.contacts.editor.PhotoActionPopup;
-import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactDeltaList;
 import com.android.contacts.util.ContactPhotoUtils;
 import com.android.contacts.util.SchedulingUtils;
 
diff --git a/src/com/android/contacts/datepicker/DatePickerDialog.java b/src/com/android/contacts/datepicker/DatePickerDialog.java
index 7681898..5ed143b 100644
--- a/src/com/android/contacts/datepicker/DatePickerDialog.java
+++ b/src/com/android/contacts/datepicker/DatePickerDialog.java
@@ -31,8 +31,8 @@
 import android.widget.TextView;
 
 import com.android.contacts.R;
+import com.android.contacts.common.util.DateUtils;
 import com.android.contacts.datepicker.DatePicker.OnDateChangedListener;
-import com.android.contacts.util.DateUtils;
 
 import java.text.DateFormat;
 import java.util.Calendar;
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index c856f97..e1aa217 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -42,15 +42,15 @@
 
 import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.R;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.dataitem.DataItem;
-import com.android.contacts.model.dataitem.OrganizationDataItem;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.dataitem.DataItem;
+import com.android.contacts.common.model.dataitem.OrganizationDataItem;
 import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.util.StreamItemEntry;
 import com.android.contacts.util.ContactBadgeUtil;
 import com.android.contacts.util.HtmlUtils;
 import com.android.contacts.util.MoreMath;
-import com.android.contacts.util.StreamItemEntry;
 import com.android.contacts.util.StreamItemPhotoEntry;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Iterables;
@@ -233,17 +233,6 @@
 
         CharSequence snippet = null;
         String photoUri = null;
-        if (!contactData.getStreamItems().isEmpty()) {
-            StreamItemEntry firstEntry = contactData.getStreamItems().get(0);
-            snippet = HtmlUtils.fromHtml(context, firstEntry.getText());
-            if (!firstEntry.getPhotos().isEmpty()) {
-                StreamItemPhotoEntry firstPhoto = firstEntry.getPhotos().get(0);
-                photoUri = firstPhoto.getPhotoUri();
-
-                // If displaying an image, hide the snippet text.
-                snippet = null;
-            }
-        }
         setDataOrHideIfNone(snippet, statusView);
         if (photoUri != null) {
             ContactPhotoManager.getInstance(context).loadPhoto(
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 34583dc..abaa8eb 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -70,14 +70,14 @@
 import android.widget.TextView;
 
 import com.android.contacts.ContactSaveService;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.GroupMetaData;
 import com.android.contacts.R;
 import com.android.contacts.TypePrecedence;
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.ClipboardUtils;
 import com.android.contacts.common.Collapser;
+import com.android.contacts.common.ContactsUtils;
+import com.android.contacts.common.GroupMetaData;
 import com.android.contacts.common.Collapser.Collapsible;
 import com.android.contacts.common.ContactPresenceIconUtil;
 import com.android.contacts.common.GeoUtil;
@@ -91,27 +91,27 @@
 import com.android.contacts.common.model.dataitem.DataKind;
 import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
 import com.android.contacts.common.util.ContactDisplayUtils;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.RawContactDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
-import com.android.contacts.model.dataitem.DataItem;
-import com.android.contacts.model.dataitem.EmailDataItem;
-import com.android.contacts.model.dataitem.EventDataItem;
-import com.android.contacts.model.dataitem.GroupMembershipDataItem;
-import com.android.contacts.model.dataitem.ImDataItem;
-import com.android.contacts.model.dataitem.NicknameDataItem;
-import com.android.contacts.model.dataitem.NoteDataItem;
-import com.android.contacts.model.dataitem.OrganizationDataItem;
-import com.android.contacts.model.dataitem.PhoneDataItem;
-import com.android.contacts.model.dataitem.RelationDataItem;
-import com.android.contacts.model.dataitem.SipAddressDataItem;
-import com.android.contacts.model.dataitem.StructuredNameDataItem;
-import com.android.contacts.model.dataitem.StructuredPostalDataItem;
-import com.android.contacts.model.dataitem.WebsiteDataItem;
-import com.android.contacts.util.DataStatus;
-import com.android.contacts.util.DateUtils;
+import com.android.contacts.common.util.DataStatus;
+import com.android.contacts.common.util.DateUtils;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
+import com.android.contacts.common.model.dataitem.DataItem;
+import com.android.contacts.common.model.dataitem.EmailDataItem;
+import com.android.contacts.common.model.dataitem.EventDataItem;
+import com.android.contacts.common.model.dataitem.GroupMembershipDataItem;
+import com.android.contacts.common.model.dataitem.ImDataItem;
+import com.android.contacts.common.model.dataitem.NicknameDataItem;
+import com.android.contacts.common.model.dataitem.NoteDataItem;
+import com.android.contacts.common.model.dataitem.OrganizationDataItem;
+import com.android.contacts.common.model.dataitem.PhoneDataItem;
+import com.android.contacts.common.model.dataitem.RelationDataItem;
+import com.android.contacts.common.model.dataitem.SipAddressDataItem;
+import com.android.contacts.common.model.dataitem.StructuredNameDataItem;
+import com.android.contacts.common.model.dataitem.StructuredPostalDataItem;
+import com.android.contacts.common.model.dataitem.WebsiteDataItem;
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.android.contacts.util.StructuredPostalUtils;
 import com.android.contacts.util.UiClosables;
@@ -412,9 +412,6 @@
             return;
         }
 
-        // Figure out if the contact has social updates or not
-        mContactHasSocialUpdates = !mContactData.getStreamItems().isEmpty();
-
         // Setup the photo if applicable
         if (mStaticPhotoContainer != null) {
             // The presence of a static photo container is not sufficient to determine whether or
@@ -1502,9 +1499,7 @@
         }
 
         private View getHeaderEntryView(View convertView, ViewGroup parent) {
-            final int desiredLayoutResourceId = mContactHasSocialUpdates ?
-                    R.layout.detail_header_contact_with_updates :
-                    R.layout.detail_header_contact_without_updates;
+            final int desiredLayoutResourceId = R.layout.detail_header_contact_without_updates;
             View result = null;
             HeaderViewCache viewCache = null;
 
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index 3c359ba..1ee31a5 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -37,7 +37,7 @@
 import com.android.contacts.NfcHandler;
 import com.android.contacts.R;
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.model.Contact;
+import com.android.contacts.common.model.Contact;
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.android.contacts.common.util.UriUtils;
 import com.android.contacts.widget.FrameLayoutWithOverlay;
@@ -285,7 +285,6 @@
                     !UriUtils.areEqual(mContactData.getLookupUri(), data.getLookupUri());
         }
         mContactData = data;
-        mContactHasUpdates = !data.getStreamItems().isEmpty();
 
         if (PhoneCapabilityTester.isUsingTwoPanes(mActivity)) {
             // Tablet: If we already showed data before, we want to cross-fade from screen to screen
@@ -302,12 +301,7 @@
             }
         }
 
-        if (mContactHasUpdates) {
-            showContactWithUpdates(
-                    contactWasLoaded && contactHadUpdates == false);
-        } else {
-            showContactWithoutUpdates();
-        }
+        showContactWithoutUpdates();
     }
 
     public void showEmptyState() {
diff --git a/src/com/android/contacts/detail/ContactDetailPhotoSetter.java b/src/com/android/contacts/detail/ContactDetailPhotoSetter.java
index 2c4c2c9..112621a 100644
--- a/src/com/android/contacts/detail/ContactDetailPhotoSetter.java
+++ b/src/com/android/contacts/detail/ContactDetailPhotoSetter.java
@@ -27,8 +27,8 @@
 
 import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.activities.PhotoSelectionActivity;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.RawContactDeltaList;
 import com.android.contacts.util.ImageViewDrawableSetter;
 
 /**
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
index 540f001..25bcac6 100644
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
@@ -30,7 +30,7 @@
 import android.widget.TextView;
 
 import com.android.contacts.R;
-import com.android.contacts.model.Contact;
+import com.android.contacts.common.model.Contact;
 import com.android.contacts.util.MoreMath;
 import com.android.contacts.util.SchedulingUtils;
 
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
index b578d28..71186fe 100644
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
@@ -31,10 +31,10 @@
 import com.android.contacts.R;
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
 import com.android.contacts.detail.ContactDetailDisplayUtils.StreamPhotoTag;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.model.Contact;
-import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.util.StreamItemEntry;
+import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.account.AccountType;
 
 public class ContactDetailUpdatesFragment extends ListFragment implements FragmentKeyListener {
 
@@ -111,14 +111,6 @@
                 mStreamItemPhotoItemClickListener);
         setListAdapter(mStreamItemAdapter);
         getListView().setOnScrollListener(mVerticalScrollListener);
-
-        // It is possible that the contact data was set to the fragment when it was first attached
-        // to the activity, but before this method was called because the fragment was not
-        // visible on screen yet (i.e. using a {@link ViewPager}), so display the data if we already
-        // have it.
-        if (mContactData != null) {
-            mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
-        }
     }
 
     public void setData(Uri lookupUri, Contact result) {
@@ -127,13 +119,6 @@
         }
         mLookupUri = lookupUri;
         mContactData = result;
-
-        // If the adapter has been created already, then try to set stream items. Otherwise,
-        // wait for the adapter to get initialized, after which we will try to set the stream items
-        // again.
-        if (mStreamItemAdapter != null) {
-            mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
-        }
     }
 
     /**
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
index 5f5a137..0b420f7 100644
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ b/src/com/android/contacts/detail/ContactLoaderFragment.java
@@ -44,8 +44,8 @@
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
 import com.android.contacts.common.list.ShortcutIntentBuilder;
 import com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.ContactLoader;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.google.common.base.Objects;
 
diff --git a/src/com/android/contacts/detail/PhotoSelectionHandler.java b/src/com/android/contacts/detail/PhotoSelectionHandler.java
index 6e2d4fa..52a292b 100644
--- a/src/com/android/contacts/detail/PhotoSelectionHandler.java
+++ b/src/com/android/contacts/detail/PhotoSelectionHandler.java
@@ -37,11 +37,11 @@
 import com.android.contacts.R;
 import com.android.contacts.editor.PhotoActionPopup;
 import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.model.RawContactModifier;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactDeltaList;
 import com.android.contacts.util.ContactPhotoUtils;
 import com.android.contacts.util.UiClosables;
 
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
index 5c827dc..6e1adc5 100644
--- a/src/com/android/contacts/detail/StreamItemAdapter.java
+++ b/src/com/android/contacts/detail/StreamItemAdapter.java
@@ -26,6 +26,7 @@
 import com.android.contacts.common.model.AccountTypeManager;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.util.StreamItemEntry;
+
 import com.google.common.collect.Lists;
 
 import java.util.List;
diff --git a/src/com/android/contacts/editor/BaseRawContactEditorView.java b/src/com/android/contacts/editor/BaseRawContactEditorView.java
index c39d472..7e74cfb 100644
--- a/src/com/android/contacts/editor/BaseRawContactEditorView.java
+++ b/src/com/android/contacts/editor/BaseRawContactEditorView.java
@@ -28,9 +28,9 @@
 import android.widget.LinearLayout;
 
 import com.android.contacts.R;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountType.EditType;
 
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 767cee2..9243625 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -78,12 +78,12 @@
 import com.android.contacts.detail.PhotoSelectionHandler;
 import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
 import com.android.contacts.editor.Editor.EditorListener;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.ContactLoader;
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.RawContactDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
+import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.util.ContactPhotoUtils;
 import com.android.contacts.util.HelpUtils;
 import com.android.contacts.util.UiClosables;
diff --git a/src/com/android/contacts/editor/Editor.java b/src/com/android/contacts/editor/Editor.java
index 12ea201..7990309 100644
--- a/src/com/android/contacts/editor/Editor.java
+++ b/src/com/android/contacts/editor/Editor.java
@@ -18,7 +18,7 @@
 
 import android.provider.ContactsContract.Data;
 
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.dataitem.DataKind;
 
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index 3589c89..4d9411f 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -29,12 +29,13 @@
 import com.android.contacts.datepicker.DatePicker;
 import com.android.contacts.datepicker.DatePickerDialog;
 import com.android.contacts.datepicker.DatePickerDialog.OnDateSetListener;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.account.AccountType.EditField;
 import com.android.contacts.common.model.account.AccountType.EventEditType;
 import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.util.DateUtils;
+import com.android.contacts.common.util.CommonDateUtils;
+import com.android.contacts.common.util.DateUtils;
 
 import java.text.ParsePosition;
 import java.util.Calendar;
@@ -45,10 +46,6 @@
  * Editor that allows editing Events using a {@link DatePickerDialog}
  */
 public class EventFieldEditorView extends LabeledEditorView {
-    /**
-     * Exchange requires 8:00 for birthdays
-     */
-    private final static int DEFAULT_HOUR = 8;
 
     /**
      * Default string to show when there is no date selected yet.
@@ -181,7 +178,7 @@
             // This value is missing the year. Add it now
             calendar.setTime(date2);
             calendar.set(defaultYear, calendar.get(Calendar.MONTH),
-                    calendar.get(Calendar.DAY_OF_MONTH), DEFAULT_HOUR, 0, 0);
+                    calendar.get(Calendar.DAY_OF_MONTH), CommonDateUtils.DEFAULT_HOUR, 0, 0);
 
             onFieldChanged(column, kind.dateFormatWithYear.format(calendar.getTime()));
             rebuildDateView();
@@ -237,7 +234,7 @@
                 // For formats other than Exchange, the time of the day is ignored
                 outCalendar.clear();
                 outCalendar.set(year == DatePickerDialog.NO_YEAR ? 2000 : year, monthOfYear,
-                        dayOfMonth, DEFAULT_HOUR, 0, 0);
+                        dayOfMonth, CommonDateUtils.DEFAULT_HOUR, 0, 0);
 
                 final String resultString;
                 if (year == 0) {
@@ -254,13 +251,6 @@
         return resultDialog;
     }
 
-    /**
-     * @return Default hour which should be used for birthday field.
-     */
-    public static int getDefaultHourForBirthday() {
-        return DEFAULT_HOUR;
-    }
-
     @Override
     public void clearAllFields() {
         // Update UI
diff --git a/src/com/android/contacts/editor/GroupMembershipView.java b/src/com/android/contacts/editor/GroupMembershipView.java
index d150be8..db389fb 100644
--- a/src/com/android/contacts/editor/GroupMembershipView.java
+++ b/src/com/android/contacts/editor/GroupMembershipView.java
@@ -40,9 +40,9 @@
 import com.android.contacts.common.model.dataitem.DataKind;
 import com.android.contacts.interactions.GroupCreationDialogFragment;
 import com.android.contacts.interactions.GroupCreationDialogFragment.OnGroupCreatedListener;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.util.UiClosables;
 import com.google.common.base.Objects;
 
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index fb9c253..261286e 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -28,8 +28,8 @@
 
 import com.android.contacts.R;
 import com.android.contacts.editor.Editor.EditorListener;
-import com.android.contacts.model.RawContactModifier;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.dataitem.DataKind;
 
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index 3c0774d..0a33b6d 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -44,11 +44,11 @@
 import android.widget.Spinner;
 import android.widget.TextView;
 
-import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.common.model.account.AccountType.EditType;
 import com.android.contacts.common.model.dataitem.DataKind;
 import com.android.contacts.util.DialogManager;
diff --git a/src/com/android/contacts/editor/PhoneticNameEditorView.java b/src/com/android/contacts/editor/PhoneticNameEditorView.java
index 2836c721..69e0719 100644
--- a/src/com/android/contacts/editor/PhoneticNameEditorView.java
+++ b/src/com/android/contacts/editor/PhoneticNameEditorView.java
@@ -17,14 +17,14 @@
 package com.android.contacts.editor;
 
 import android.content.Context;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.model.dataitem.StructuredNameDataItem;
+import com.android.contacts.common.model.dataitem.StructuredNameDataItem;
+import com.android.contacts.common.util.NameConverter;
 
 /**
  * A dedicated editor for phonetic name. It is similar to {@link StructuredNameEditorView}.
@@ -61,7 +61,7 @@
         }
 
         private void parsePhoneticName(String value) {
-            StructuredNameDataItem dataItem = PhoneticNameEditorView.parsePhoneticName(value, null);
+            StructuredNameDataItem dataItem = NameConverter.parsePhoneticName(value, null);
             mValues.setPhoneticFamilyName(dataItem.getPhoneticFamilyName());
             mValues.setPhoneticMiddleName(dataItem.getPhoneticMiddleName());
             mValues.setPhoneticGivenName(dataItem.getPhoneticGivenName());
@@ -71,7 +71,7 @@
             String family = mValues.getPhoneticFamilyName();
             String middle = mValues.getPhoneticMiddleName();
             String given = mValues.getPhoneticGivenName();
-            mPhoneticName = PhoneticNameEditorView.buildPhoneticName(family, middle, given);
+            mPhoneticName = NameConverter.buildPhoneticName(family, middle, given);
         }
 
         @Override
@@ -85,74 +85,6 @@
         }
     }
 
-    /**
-     * Parses phonetic name and returns parsed data (family, middle, given) as ContentValues.
-     * Parsed data should be {@link StructuredName#PHONETIC_FAMILY_NAME},
-     * {@link StructuredName#PHONETIC_MIDDLE_NAME}, and
-     * {@link StructuredName#PHONETIC_GIVEN_NAME}.
-     * If this method cannot parse given phoneticName, null values will be stored.
-     *
-     * @param phoneticName Phonetic name to be parsed
-     * @param values ContentValues to be used for storing data. If null, new instance will be
-     * created.
-     * @return ContentValues with parsed data. Those data can be null.
-     */
-    public static StructuredNameDataItem parsePhoneticName(String phoneticName,
-            StructuredNameDataItem item) {
-        String family = null;
-        String middle = null;
-        String given = null;
-
-        if (!TextUtils.isEmpty(phoneticName)) {
-            String[] strings = phoneticName.split(" ", 3);
-            switch (strings.length) {
-                case 1:
-                    family = strings[0];
-                    break;
-                case 2:
-                    family = strings[0];
-                    given = strings[1];
-                    break;
-                case 3:
-                    family = strings[0];
-                    middle = strings[1];
-                    given = strings[2];
-                    break;
-            }
-        }
-
-        if (item == null) {
-            item = new StructuredNameDataItem();
-        }
-        item.setPhoneticFamilyName(family);
-        item.setPhoneticMiddleName(middle);
-        item.setPhoneticGivenName(given);
-        return item;
-    }
-
-    /**
-     * Constructs and returns a phonetic full name from given parts.
-     */
-    public static String buildPhoneticName(String family, String middle, String given) {
-        if (!TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
-                || !TextUtils.isEmpty(given)) {
-            StringBuilder sb = new StringBuilder();
-            if (!TextUtils.isEmpty(family)) {
-                sb.append(family.trim()).append(' ');
-            }
-            if (!TextUtils.isEmpty(middle)) {
-                sb.append(middle.trim()).append(' ');
-            }
-            if (!TextUtils.isEmpty(given)) {
-                sb.append(given.trim()).append(' ');
-            }
-            sb.setLength(sb.length() - 1);  // Yank the last space
-            return sb.toString();
-        } else {
-            return null;
-        }
-    }
-
     public static boolean isUnstructuredPhoneticNameColumn(String column) {
         return DataKind.PSEUDO_COLUMN_PHONETIC_NAME.equals(column);
     }
diff --git a/src/com/android/contacts/editor/PhotoEditorView.java b/src/com/android/contacts/editor/PhotoEditorView.java
index 652c8e6..bee61f4 100644
--- a/src/com/android/contacts/editor/PhotoEditorView.java
+++ b/src/com/android/contacts/editor/PhotoEditorView.java
@@ -25,9 +25,9 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
-import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.dataitem.DataKind;
 import com.android.contacts.util.ContactPhotoUtils;
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index b52b0b2..c9d3c33 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -43,9 +43,9 @@
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountType.EditType;
 import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactModifier;
 import com.google.common.base.Objects;
 
 import java.util.ArrayList;
diff --git a/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java b/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
index 70a2b4e..d1fa282 100644
--- a/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
+++ b/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
@@ -39,8 +39,8 @@
 
 import com.android.contacts.R;
 import com.android.contacts.common.GeoUtil;
-import com.android.contacts.model.RawContactModifier;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactModifier;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountWithDataSet;
diff --git a/src/com/android/contacts/editor/StructuredNameEditorView.java b/src/com/android/contacts/editor/StructuredNameEditorView.java
index 4d72598..bf548f6 100644
--- a/src/com/android/contacts/editor/StructuredNameEditorView.java
+++ b/src/com/android/contacts/editor/StructuredNameEditorView.java
@@ -25,12 +25,12 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.common.model.dataitem.DataItem;
 import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.model.dataitem.StructuredNameDataItem;
-import com.android.contacts.util.NameConverter;
+import com.android.contacts.common.util.NameConverter;
+import com.android.contacts.common.model.dataitem.StructuredNameDataItem;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index a20ba77..85cbac8 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -35,9 +35,9 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
-import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.account.AccountType.EditField;
 import com.android.contacts.common.model.dataitem.DataKind;
diff --git a/src/com/android/contacts/editor/ViewIdGenerator.java b/src/com/android/contacts/editor/ViewIdGenerator.java
index 8494e1a..e7e7948 100644
--- a/src/com/android/contacts/editor/ViewIdGenerator.java
+++ b/src/com/android/contacts/editor/ViewIdGenerator.java
@@ -20,7 +20,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.dataitem.DataKind;
 
diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java
index f842db3..81cc28c 100644
--- a/src/com/android/contacts/group/GroupBrowseListFragment.java
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -42,10 +42,10 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import com.android.contacts.ContactsUtils;
 import com.android.contacts.GroupListLoader;
 import com.android.contacts.R;
 import com.android.contacts.group.GroupBrowseListAdapter.GroupListItemViewCache;
+import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.list.AutoScrollListView;
 
 /**
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index 78bc3eb..14e8949 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -40,7 +40,7 @@
 import com.android.contacts.common.list.ContactListAdapter;
 import com.android.contacts.common.list.ContactListFilter;
 import com.android.contacts.common.list.DirectoryPartition;
-import com.android.contacts.util.ContactLoaderUtils;
+import com.android.contacts.common.util.ContactLoaderUtils;
 
 import java.util.List;
 
diff --git a/src/com/android/contacts/model/Contact.java b/src/com/android/contacts/model/Contact.java
deleted file mode 100644
index 9f7f217..0000000
--- a/src/com/android/contacts/model/Contact.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Directory;
-import android.provider.ContactsContract.DisplayNameSources;
-
-import com.android.contacts.GroupMetaData;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.util.DataStatus;
-import com.android.contacts.util.StreamItemEntry;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-/**
- * A Contact represents a single person or logical entity as perceived by the user.  The information
- * about a contact can come from multiple data sources, which are each represented by a RawContact
- * object.  Thus, a Contact is associated with a collection of RawContact objects.
- *
- * The aggregation of raw contacts into a single contact is performed automatically, and it is
- * also possible for users to manually split and join raw contacts into various contacts.
- *
- * Only the {@link ContactLoader} class can create a Contact object with various flags to allow
- * partial loading of contact data.  Thus, an instance of this class should be treated as
- * a read-only object.
- */
-public class Contact {
-    private enum Status {
-        /** Contact is successfully loaded */
-        LOADED,
-        /** There was an error loading the contact */
-        ERROR,
-        /** Contact is not found */
-        NOT_FOUND,
-    }
-
-    private final Uri mRequestedUri;
-    private final Uri mLookupUri;
-    private final Uri mUri;
-    private final long mDirectoryId;
-    private final String mLookupKey;
-    private final long mId;
-    private final long mNameRawContactId;
-    private final int mDisplayNameSource;
-    private final long mPhotoId;
-    private final String mPhotoUri;
-    private final String mDisplayName;
-    private final String mAltDisplayName;
-    private final String mPhoneticName;
-    private final boolean mStarred;
-    private final Integer mPresence;
-    private ImmutableList<RawContact> mRawContacts;
-    private ImmutableMap<Long,DataStatus> mStatuses;
-    private ImmutableList<AccountType> mInvitableAccountTypes;
-
-    private String mDirectoryDisplayName;
-    private String mDirectoryType;
-    private String mDirectoryAccountType;
-    private String mDirectoryAccountName;
-    private int mDirectoryExportSupport;
-
-    private ImmutableList<GroupMetaData> mGroups;
-
-    private byte[] mPhotoBinaryData;
-    private final boolean mSendToVoicemail;
-    private final String mCustomRingtone;
-    private final boolean mIsUserProfile;
-
-    private final Contact.Status mStatus;
-    private final Exception mException;
-
-    /**
-     * Constructor for special results, namely "no contact found" and "error".
-     */
-    private Contact(Uri requestedUri, Contact.Status status, Exception exception) {
-        if (status == Status.ERROR && exception == null) {
-            throw new IllegalArgumentException("ERROR result must have exception");
-        }
-        mStatus = status;
-        mException = exception;
-        mRequestedUri = requestedUri;
-        mLookupUri = null;
-        mUri = null;
-        mDirectoryId = -1;
-        mLookupKey = null;
-        mId = -1;
-        mRawContacts = null;
-        mStatuses = null;
-        mNameRawContactId = -1;
-        mDisplayNameSource = DisplayNameSources.UNDEFINED;
-        mPhotoId = -1;
-        mPhotoUri = null;
-        mDisplayName = null;
-        mAltDisplayName = null;
-        mPhoneticName = null;
-        mStarred = false;
-        mPresence = null;
-        mInvitableAccountTypes = null;
-        mSendToVoicemail = false;
-        mCustomRingtone = null;
-        mIsUserProfile = false;
-    }
-
-    public static Contact forError(Uri requestedUri, Exception exception) {
-        return new Contact(requestedUri, Status.ERROR, exception);
-    }
-
-    public static Contact forNotFound(Uri requestedUri) {
-        return new Contact(requestedUri, Status.NOT_FOUND, null);
-    }
-
-    /**
-     * Constructor to call when contact was found
-     */
-    public Contact(Uri requestedUri, Uri uri, Uri lookupUri, long directoryId, String lookupKey,
-            long id, long nameRawContactId, int displayNameSource, long photoId,
-            String photoUri, String displayName, String altDisplayName, String phoneticName,
-            boolean starred, Integer presence, boolean sendToVoicemail, String customRingtone,
-            boolean isUserProfile) {
-        mStatus = Status.LOADED;
-        mException = null;
-        mRequestedUri = requestedUri;
-        mLookupUri = lookupUri;
-        mUri = uri;
-        mDirectoryId = directoryId;
-        mLookupKey = lookupKey;
-        mId = id;
-        mRawContacts = null;
-        mStatuses = null;
-        mNameRawContactId = nameRawContactId;
-        mDisplayNameSource = displayNameSource;
-        mPhotoId = photoId;
-        mPhotoUri = photoUri;
-        mDisplayName = displayName;
-        mAltDisplayName = altDisplayName;
-        mPhoneticName = phoneticName;
-        mStarred = starred;
-        mPresence = presence;
-        mInvitableAccountTypes = null;
-        mSendToVoicemail = sendToVoicemail;
-        mCustomRingtone = customRingtone;
-        mIsUserProfile = isUserProfile;
-    }
-
-    public Contact(Uri requestedUri, Contact from) {
-        mRequestedUri = requestedUri;
-
-        mStatus = from.mStatus;
-        mException = from.mException;
-        mLookupUri = from.mLookupUri;
-        mUri = from.mUri;
-        mDirectoryId = from.mDirectoryId;
-        mLookupKey = from.mLookupKey;
-        mId = from.mId;
-        mNameRawContactId = from.mNameRawContactId;
-        mDisplayNameSource = from.mDisplayNameSource;
-        mPhotoId = from.mPhotoId;
-        mPhotoUri = from.mPhotoUri;
-        mDisplayName = from.mDisplayName;
-        mAltDisplayName = from.mAltDisplayName;
-        mPhoneticName = from.mPhoneticName;
-        mStarred = from.mStarred;
-        mPresence = from.mPresence;
-        mRawContacts = from.mRawContacts;
-        mStatuses = from.mStatuses;
-        mInvitableAccountTypes = from.mInvitableAccountTypes;
-
-        mDirectoryDisplayName = from.mDirectoryDisplayName;
-        mDirectoryType = from.mDirectoryType;
-        mDirectoryAccountType = from.mDirectoryAccountType;
-        mDirectoryAccountName = from.mDirectoryAccountName;
-        mDirectoryExportSupport = from.mDirectoryExportSupport;
-
-        mGroups = from.mGroups;
-
-        mPhotoBinaryData = from.mPhotoBinaryData;
-        mSendToVoicemail = from.mSendToVoicemail;
-        mCustomRingtone = from.mCustomRingtone;
-        mIsUserProfile = from.mIsUserProfile;
-    }
-
-    /**
-     * @param exportSupport See {@link Directory#EXPORT_SUPPORT}.
-     */
-    public void setDirectoryMetaData(String displayName, String directoryType,
-            String accountType, String accountName, int exportSupport) {
-        mDirectoryDisplayName = displayName;
-        mDirectoryType = directoryType;
-        mDirectoryAccountType = accountType;
-        mDirectoryAccountName = accountName;
-        mDirectoryExportSupport = exportSupport;
-    }
-
-    /* package */ void setPhotoBinaryData(byte[] photoBinaryData) {
-        mPhotoBinaryData = photoBinaryData;
-    }
-
-    /**
-     * Returns the URI for the contact that contains both the lookup key and the ID. This is
-     * the best URI to reference a contact.
-     * For directory contacts, this is the same a the URI as returned by {@link #getUri()}
-     */
-    public Uri getLookupUri() {
-        return mLookupUri;
-    }
-
-    public String getLookupKey() {
-        return mLookupKey;
-    }
-
-    /**
-     * Returns the contact Uri that was passed to the provider to make the query. This is
-     * the same as the requested Uri, unless the requested Uri doesn't specify a Contact:
-     * If it either references a Raw-Contact or a Person (a pre-Eclair style Uri), this Uri will
-     * always reference the full aggregate contact.
-     */
-    public Uri getUri() {
-        return mUri;
-    }
-
-    /**
-     * Returns the URI for which this {@link ContactLoader) was initially requested.
-     */
-    public Uri getRequestedUri() {
-        return mRequestedUri;
-    }
-
-    /**
-     * Instantiate a new RawContactDeltaList for this contact.
-     */
-    public RawContactDeltaList createRawContactDeltaList() {
-        return RawContactDeltaList.fromIterator(getRawContacts().iterator());
-    }
-
-    /**
-     * Returns the contact ID.
-     */
-    @VisibleForTesting
-    /* package */ long getId() {
-        return mId;
-    }
-
-    /**
-     * @return true when an exception happened during loading, in which case
-     *     {@link #getException} returns the actual exception object.
-     *     Note {@link #isNotFound()} and {@link #isError()} are mutually exclusive; If
-     *     {@link #isError()} is {@code true}, {@link #isNotFound()} is always {@code false},
-     *     and vice versa.
-     */
-    public boolean isError() {
-        return mStatus == Status.ERROR;
-    }
-
-    public Exception getException() {
-        return mException;
-    }
-
-    /**
-     * @return true when the specified contact is not found.
-     *     Note {@link #isNotFound()} and {@link #isError()} are mutually exclusive; If
-     *     {@link #isError()} is {@code true}, {@link #isNotFound()} is always {@code false},
-     *     and vice versa.
-     */
-    public boolean isNotFound() {
-        return mStatus == Status.NOT_FOUND;
-    }
-
-    /**
-     * @return true if the specified contact is successfully loaded.
-     *     i.e. neither {@link #isError()} nor {@link #isNotFound()}.
-     */
-    public boolean isLoaded() {
-        return mStatus == Status.LOADED;
-    }
-
-    public long getNameRawContactId() {
-        return mNameRawContactId;
-    }
-
-    public int getDisplayNameSource() {
-        return mDisplayNameSource;
-    }
-
-    public long getPhotoId() {
-        return mPhotoId;
-    }
-
-    public String getPhotoUri() {
-        return mPhotoUri;
-    }
-
-    public String getDisplayName() {
-        return mDisplayName;
-    }
-
-    public String getAltDisplayName() {
-        return mAltDisplayName;
-    }
-
-    public String getPhoneticName() {
-        return mPhoneticName;
-    }
-
-    public boolean getStarred() {
-        return mStarred;
-    }
-
-    public Integer getPresence() {
-        return mPresence;
-    }
-
-    /**
-     * This can return non-null invitable account types only if the {@link ContactLoader} was
-     * configured to load invitable account types in its constructor.
-     * @return
-     */
-    public ImmutableList<AccountType> getInvitableAccountTypes() {
-        return mInvitableAccountTypes;
-    }
-
-    public ImmutableList<RawContact> getRawContacts() {
-        return mRawContacts;
-    }
-
-    /**
-     * This can return non-null stream items only if the {@link ContactLoader} was
-     * configured to load stream items in its constructor.
-     * @return
-     */
-    public ImmutableList<StreamItemEntry> getStreamItems() {
-        return ImmutableList.of();
-    }
-
-    public ImmutableMap<Long, DataStatus> getStatuses() {
-        return mStatuses;
-    }
-
-    public long getDirectoryId() {
-        return mDirectoryId;
-    }
-
-    public boolean isDirectoryEntry() {
-        return mDirectoryId != -1 && mDirectoryId != Directory.DEFAULT
-                && mDirectoryId != Directory.LOCAL_INVISIBLE;
-    }
-
-    /**
-     * @return true if this is a contact (not group, etc.) with at least one
-     *         writable raw-contact, and false otherwise.
-     */
-    public boolean isWritableContact(final Context context) {
-        return getFirstWritableRawContactId(context) != -1;
-    }
-
-    /**
-     * Return the ID of the first raw-contact in the contact data that belongs to a
-     * contact-writable account, or -1 if no such entity exists.
-     */
-    public long getFirstWritableRawContactId(final Context context) {
-        // Directory entries are non-writable
-        if (isDirectoryEntry()) return -1;
-
-        // Iterate through raw-contacts; if we find a writable on, return its ID.
-        for (RawContact rawContact : getRawContacts()) {
-            AccountType accountType = rawContact.getAccountType(context);
-            if (accountType != null && accountType.areContactsWritable()) {
-                return rawContact.getId();
-            }
-        }
-        // No writable raw-contact was found.
-        return -1;
-    }
-
-    public int getDirectoryExportSupport() {
-        return mDirectoryExportSupport;
-    }
-
-    public String getDirectoryDisplayName() {
-        return mDirectoryDisplayName;
-    }
-
-    public String getDirectoryType() {
-        return mDirectoryType;
-    }
-
-    public String getDirectoryAccountType() {
-        return mDirectoryAccountType;
-    }
-
-    public String getDirectoryAccountName() {
-        return mDirectoryAccountName;
-    }
-
-    public byte[] getPhotoBinaryData() {
-        return mPhotoBinaryData;
-    }
-
-    public ArrayList<ContentValues> getContentValues() {
-        if (mRawContacts.size() != 1) {
-            throw new IllegalStateException(
-                    "Cannot extract content values from an aggregated contact");
-        }
-
-        RawContact rawContact = mRawContacts.get(0);
-        ArrayList<ContentValues> result = rawContact.getContentValues();
-
-        // If the photo was loaded using the URI, create an entry for the photo
-        // binary data.
-        if (mPhotoId == 0 && mPhotoBinaryData != null) {
-            ContentValues photo = new ContentValues();
-            photo.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
-            photo.put(Photo.PHOTO, mPhotoBinaryData);
-            result.add(photo);
-        }
-
-        return result;
-    }
-
-    /**
-     * This can return non-null group meta-data only if the {@link ContactLoader} was configured to
-     * load group metadata in its constructor.
-     * @return
-     */
-    public ImmutableList<GroupMetaData> getGroupMetaData() {
-        return mGroups;
-    }
-
-    public boolean isSendToVoicemail() {
-        return mSendToVoicemail;
-    }
-
-    public String getCustomRingtone() {
-        return mCustomRingtone;
-    }
-
-    public boolean isUserProfile() {
-        return mIsUserProfile;
-    }
-
-    @Override
-    public String toString() {
-        return "{requested=" + mRequestedUri + ",lookupkey=" + mLookupKey +
-                ",uri=" + mUri + ",status=" + mStatus + "}";
-    }
-
-    /* package */ void setRawContacts(ImmutableList<RawContact> rawContacts) {
-        mRawContacts = rawContacts;
-    }
-
-    /* package */ void setStatuses(ImmutableMap<Long, DataStatus> statuses) {
-        mStatuses = statuses;
-    }
-
-    /* package */ void setInvitableAccountTypes(ImmutableList<AccountType> accountTypes) {
-        mInvitableAccountTypes = accountTypes;
-    }
-
-    /* package */ void setGroupMetaData(ImmutableList<GroupMetaData> groups) {
-        mGroups = groups;
-    }
-}
diff --git a/src/com/android/contacts/model/ContactLoader.java b/src/com/android/contacts/model/ContactLoader.java
deleted file mode 100644
index e10fc6c..0000000
--- a/src/com/android/contacts/model/ContactLoader.java
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.contacts.model;
-
-import android.content.AsyncTaskLoader;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Directory;
-import android.provider.ContactsContract.Groups;
-import android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.contacts.GroupMetaData;
-import com.android.contacts.common.GeoUtil;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountTypeWithDataSet;
-import com.android.contacts.common.util.Constants;
-import com.android.contacts.common.util.UriUtils;
-import com.android.contacts.model.dataitem.DataItem;
-import com.android.contacts.model.dataitem.PhoneDataItem;
-import com.android.contacts.model.dataitem.PhotoDataItem;
-import com.android.contacts.util.ContactLoaderUtils;
-import com.android.contacts.util.DataStatus;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Loads a single Contact and all it constituent RawContacts.
- */
-public class ContactLoader extends AsyncTaskLoader<Contact> {
-
-    private static final String TAG = ContactLoader.class.getSimpleName();
-
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    /** A short-lived cache that can be set by {@link #cacheResult()} */
-    private static Contact sCachedResult = null;
-
-    private final Uri mRequestedUri;
-    private Uri mLookupUri;
-    private boolean mLoadGroupMetaData;
-    private boolean mLoadInvitableAccountTypes;
-    private boolean mPostViewNotification;
-    private boolean mComputeFormattedPhoneNumber;
-    private Contact mContact;
-    private ForceLoadContentObserver mObserver;
-    private final Set<Long> mNotifiedRawContactIds = Sets.newHashSet();
-
-    public ContactLoader(Context context, Uri lookupUri, boolean postViewNotification) {
-        this(context, lookupUri, false, false, postViewNotification, false);
-    }
-
-    public ContactLoader(Context context, Uri lookupUri, boolean loadGroupMetaData,
-            boolean loadInvitableAccountTypes,
-            boolean postViewNotification, boolean computeFormattedPhoneNumber) {
-        super(context);
-        mLookupUri = lookupUri;
-        mRequestedUri = lookupUri;
-        mLoadGroupMetaData = loadGroupMetaData;
-        mLoadInvitableAccountTypes = loadInvitableAccountTypes;
-        mPostViewNotification = postViewNotification;
-        mComputeFormattedPhoneNumber = computeFormattedPhoneNumber;
-    }
-
-    /**
-     * Projection used for the query that loads all data for the entire contact (except for
-     * social stream items).
-     */
-    private static class ContactQuery {
-        static final String[] COLUMNS = new String[] {
-                Contacts.NAME_RAW_CONTACT_ID,
-                Contacts.DISPLAY_NAME_SOURCE,
-                Contacts.LOOKUP_KEY,
-                Contacts.DISPLAY_NAME,
-                Contacts.DISPLAY_NAME_ALTERNATIVE,
-                Contacts.PHONETIC_NAME,
-                Contacts.PHOTO_ID,
-                Contacts.STARRED,
-                Contacts.CONTACT_PRESENCE,
-                Contacts.CONTACT_STATUS,
-                Contacts.CONTACT_STATUS_TIMESTAMP,
-                Contacts.CONTACT_STATUS_RES_PACKAGE,
-                Contacts.CONTACT_STATUS_LABEL,
-                Contacts.Entity.CONTACT_ID,
-                Contacts.Entity.RAW_CONTACT_ID,
-
-                RawContacts.ACCOUNT_NAME,
-                RawContacts.ACCOUNT_TYPE,
-                RawContacts.DATA_SET,
-                RawContacts.ACCOUNT_TYPE_AND_DATA_SET,
-                RawContacts.DIRTY,
-                RawContacts.VERSION,
-                RawContacts.SOURCE_ID,
-                RawContacts.SYNC1,
-                RawContacts.SYNC2,
-                RawContacts.SYNC3,
-                RawContacts.SYNC4,
-                RawContacts.DELETED,
-                RawContacts.NAME_VERIFIED,
-
-                Contacts.Entity.DATA_ID,
-                Data.DATA1,
-                Data.DATA2,
-                Data.DATA3,
-                Data.DATA4,
-                Data.DATA5,
-                Data.DATA6,
-                Data.DATA7,
-                Data.DATA8,
-                Data.DATA9,
-                Data.DATA10,
-                Data.DATA11,
-                Data.DATA12,
-                Data.DATA13,
-                Data.DATA14,
-                Data.DATA15,
-                Data.SYNC1,
-                Data.SYNC2,
-                Data.SYNC3,
-                Data.SYNC4,
-                Data.DATA_VERSION,
-                Data.IS_PRIMARY,
-                Data.IS_SUPER_PRIMARY,
-                Data.MIMETYPE,
-                Data.RES_PACKAGE,
-
-                GroupMembership.GROUP_SOURCE_ID,
-
-                Data.PRESENCE,
-                Data.CHAT_CAPABILITY,
-                Data.STATUS,
-                Data.STATUS_RES_PACKAGE,
-                Data.STATUS_ICON,
-                Data.STATUS_LABEL,
-                Data.STATUS_TIMESTAMP,
-
-                Contacts.PHOTO_URI,
-                Contacts.SEND_TO_VOICEMAIL,
-                Contacts.CUSTOM_RINGTONE,
-                Contacts.IS_USER_PROFILE,
-        };
-
-        public static final int NAME_RAW_CONTACT_ID = 0;
-        public static final int DISPLAY_NAME_SOURCE = 1;
-        public static final int LOOKUP_KEY = 2;
-        public static final int DISPLAY_NAME = 3;
-        public static final int ALT_DISPLAY_NAME = 4;
-        public static final int PHONETIC_NAME = 5;
-        public static final int PHOTO_ID = 6;
-        public static final int STARRED = 7;
-        public static final int CONTACT_PRESENCE = 8;
-        public static final int CONTACT_STATUS = 9;
-        public static final int CONTACT_STATUS_TIMESTAMP = 10;
-        public static final int CONTACT_STATUS_RES_PACKAGE = 11;
-        public static final int CONTACT_STATUS_LABEL = 12;
-        public static final int CONTACT_ID = 13;
-        public static final int RAW_CONTACT_ID = 14;
-
-        public static final int ACCOUNT_NAME = 15;
-        public static final int ACCOUNT_TYPE = 16;
-        public static final int DATA_SET = 17;
-        public static final int ACCOUNT_TYPE_AND_DATA_SET = 18;
-        public static final int DIRTY = 19;
-        public static final int VERSION = 20;
-        public static final int SOURCE_ID = 21;
-        public static final int SYNC1 = 22;
-        public static final int SYNC2 = 23;
-        public static final int SYNC3 = 24;
-        public static final int SYNC4 = 25;
-        public static final int DELETED = 26;
-        public static final int NAME_VERIFIED = 27;
-
-        public static final int DATA_ID = 28;
-        public static final int DATA1 = 29;
-        public static final int DATA2 = 30;
-        public static final int DATA3 = 31;
-        public static final int DATA4 = 32;
-        public static final int DATA5 = 33;
-        public static final int DATA6 = 34;
-        public static final int DATA7 = 35;
-        public static final int DATA8 = 36;
-        public static final int DATA9 = 37;
-        public static final int DATA10 = 38;
-        public static final int DATA11 = 39;
-        public static final int DATA12 = 40;
-        public static final int DATA13 = 41;
-        public static final int DATA14 = 42;
-        public static final int DATA15 = 43;
-        public static final int DATA_SYNC1 = 44;
-        public static final int DATA_SYNC2 = 45;
-        public static final int DATA_SYNC3 = 46;
-        public static final int DATA_SYNC4 = 47;
-        public static final int DATA_VERSION = 48;
-        public static final int IS_PRIMARY = 49;
-        public static final int IS_SUPERPRIMARY = 50;
-        public static final int MIMETYPE = 51;
-        public static final int RES_PACKAGE = 52;
-
-        public static final int GROUP_SOURCE_ID = 53;
-
-        public static final int PRESENCE = 54;
-        public static final int CHAT_CAPABILITY = 55;
-        public static final int STATUS = 56;
-        public static final int STATUS_RES_PACKAGE = 57;
-        public static final int STATUS_ICON = 58;
-        public static final int STATUS_LABEL = 59;
-        public static final int STATUS_TIMESTAMP = 60;
-
-        public static final int PHOTO_URI = 61;
-        public static final int SEND_TO_VOICEMAIL = 62;
-        public static final int CUSTOM_RINGTONE = 63;
-        public static final int IS_USER_PROFILE = 64;
-    }
-
-    /**
-     * Projection used for the query that loads all data for the entire contact.
-     */
-    private static class DirectoryQuery {
-        static final String[] COLUMNS = new String[] {
-            Directory.DISPLAY_NAME,
-            Directory.PACKAGE_NAME,
-            Directory.TYPE_RESOURCE_ID,
-            Directory.ACCOUNT_TYPE,
-            Directory.ACCOUNT_NAME,
-            Directory.EXPORT_SUPPORT,
-        };
-
-        public static final int DISPLAY_NAME = 0;
-        public static final int PACKAGE_NAME = 1;
-        public static final int TYPE_RESOURCE_ID = 2;
-        public static final int ACCOUNT_TYPE = 3;
-        public static final int ACCOUNT_NAME = 4;
-        public static final int EXPORT_SUPPORT = 5;
-    }
-
-    private static class GroupQuery {
-        static final String[] COLUMNS = new String[] {
-            Groups.ACCOUNT_NAME,
-            Groups.ACCOUNT_TYPE,
-            Groups.DATA_SET,
-            Groups.ACCOUNT_TYPE_AND_DATA_SET,
-            Groups._ID,
-            Groups.TITLE,
-            Groups.AUTO_ADD,
-            Groups.FAVORITES,
-        };
-
-        public static final int ACCOUNT_NAME = 0;
-        public static final int ACCOUNT_TYPE = 1;
-        public static final int DATA_SET = 2;
-        public static final int ACCOUNT_TYPE_AND_DATA_SET = 3;
-        public static final int ID = 4;
-        public static final int TITLE = 5;
-        public static final int AUTO_ADD = 6;
-        public static final int FAVORITES = 7;
-    }
-
-    @Override
-    public Contact loadInBackground() {
-        try {
-            final ContentResolver resolver = getContext().getContentResolver();
-            final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(
-                    resolver, mLookupUri);
-            final Contact cachedResult = sCachedResult;
-            sCachedResult = null;
-            // Is this the same Uri as what we had before already? In that case, reuse that result
-            final Contact result;
-            final boolean resultIsCached;
-            if (cachedResult != null &&
-                    UriUtils.areEqual(cachedResult.getLookupUri(), mLookupUri)) {
-                // We are using a cached result from earlier. Below, we should make sure
-                // we are not doing any more network or disc accesses
-                result = new Contact(mRequestedUri, cachedResult);
-                resultIsCached = true;
-            } else {
-                if (uriCurrentFormat.getLastPathSegment().equals(Constants.LOOKUP_URI_ENCODED)) {
-                    result = loadEncodedContactEntity(uriCurrentFormat);
-                } else {
-                    result = loadContactEntity(resolver, uriCurrentFormat);
-                }
-                resultIsCached = false;
-            }
-            if (result.isLoaded()) {
-                if (result.isDirectoryEntry()) {
-                    if (!resultIsCached) {
-                        loadDirectoryMetaData(result);
-                    }
-                } else if (mLoadGroupMetaData) {
-                    if (result.getGroupMetaData() == null) {
-                        loadGroupMetaData(result);
-                    }
-                }
-                if (mComputeFormattedPhoneNumber) {
-                    computeFormattedPhoneNumbers(result);
-                }
-                if (!resultIsCached) loadPhotoBinaryData(result);
-
-                // Note ME profile should never have "Add connection"
-                if (mLoadInvitableAccountTypes && result.getInvitableAccountTypes() == null) {
-                    loadInvitableAccountTypes(result);
-                }
-            }
-            return result;
-        } catch (Exception e) {
-            Log.e(TAG, "Error loading the contact: " + mLookupUri, e);
-            return Contact.forError(mRequestedUri, e);
-        }
-    }
-
-    private Contact loadEncodedContactEntity(Uri uri) throws JSONException {
-        final String jsonString = uri.getEncodedFragment();
-        final JSONObject json = new JSONObject(jsonString);
-
-        final long directoryId =
-                Long.valueOf(uri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY));
-
-        final String displayName = json.getString(Contacts.DISPLAY_NAME);
-        final String altDisplayName = json.optString(
-                Contacts.DISPLAY_NAME_ALTERNATIVE, displayName);
-        final int displayNameSource = json.getInt(Contacts.DISPLAY_NAME_SOURCE);
-        final String photoUri = json.optString(Contacts.PHOTO_URI, null);
-        final Contact contact = new Contact(
-                uri, uri,
-                mLookupUri,
-                directoryId,
-                null /* lookupKey */,
-                -1 /* id */,
-                -1 /* nameRawContactId */,
-                displayNameSource,
-                0 /* photoId */,
-                photoUri,
-                displayName,
-                altDisplayName,
-                null /* phoneticName */,
-                false /* starred */,
-                null /* presence */,
-                false /* sendToVoicemail */,
-                null /* customRingtone */,
-                false /* isUserProfile */);
-
-        contact.setStatuses(new ImmutableMap.Builder<Long, DataStatus>().build());
-
-        final String accountName = json.optString(RawContacts.ACCOUNT_NAME, null);
-        final String directoryName = uri.getQueryParameter(Directory.DISPLAY_NAME);
-        if (accountName != null) {
-            final String accountType = json.getString(RawContacts.ACCOUNT_TYPE);
-            contact.setDirectoryMetaData(directoryName, null, accountName, accountType,
-                    json.optInt(Directory.EXPORT_SUPPORT,
-                            Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY));
-        } else {
-            contact.setDirectoryMetaData(directoryName, null, null, null,
-                    json.optInt(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_ANY_ACCOUNT));
-        }
-
-        final ContentValues values = new ContentValues();
-        values.put(Data._ID, -1);
-        values.put(Data.CONTACT_ID, -1);
-        final RawContact rawContact = new RawContact(values);
-
-        final JSONObject items = json.getJSONObject(Contacts.CONTENT_ITEM_TYPE);
-        final Iterator keys = items.keys();
-        while (keys.hasNext()) {
-            final String mimetype = (String) keys.next();
-
-            // Could be single object or array.
-            final JSONObject obj = items.optJSONObject(mimetype);
-            if (obj == null) {
-                final JSONArray array = items.getJSONArray(mimetype);
-                for (int i = 0; i < array.length(); i++) {
-                    final JSONObject item = array.getJSONObject(i);
-                    processOneRecord(rawContact, item, mimetype);
-                }
-            } else {
-                processOneRecord(rawContact, obj, mimetype);
-            }
-        }
-
-        contact.setRawContacts(new ImmutableList.Builder<RawContact>()
-                .add(rawContact)
-                .build());
-        return contact;
-    }
-
-    private void processOneRecord(RawContact rawContact, JSONObject item, String mimetype)
-            throws JSONException {
-        final ContentValues itemValues = new ContentValues();
-        itemValues.put(Data.MIMETYPE, mimetype);
-        itemValues.put(Data._ID, -1);
-
-        final Iterator iterator = item.keys();
-        while (iterator.hasNext()) {
-            String name = (String) iterator.next();
-            final Object o = item.get(name);
-            if (o instanceof String) {
-                itemValues.put(name, (String) o);
-            } else if (o instanceof Integer) {
-                itemValues.put(name, (Integer) o);
-            }
-        }
-        rawContact.addDataItemValues(itemValues);
-    }
-
-    private Contact loadContactEntity(ContentResolver resolver, Uri contactUri) {
-        Uri entityUri = Uri.withAppendedPath(contactUri, Contacts.Entity.CONTENT_DIRECTORY);
-        Cursor cursor = resolver.query(entityUri, ContactQuery.COLUMNS, null, null,
-                Contacts.Entity.RAW_CONTACT_ID);
-        if (cursor == null) {
-            Log.e(TAG, "No cursor returned in loadContactEntity");
-            return Contact.forNotFound(mRequestedUri);
-        }
-
-        try {
-            if (!cursor.moveToFirst()) {
-                cursor.close();
-                return Contact.forNotFound(mRequestedUri);
-            }
-
-            // Create the loaded contact starting with the header data.
-            Contact contact = loadContactHeaderData(cursor, contactUri);
-
-            // Fill in the raw contacts, which is wrapped in an Entity and any
-            // status data.  Initially, result has empty entities and statuses.
-            long currentRawContactId = -1;
-            RawContact rawContact = null;
-            ImmutableList.Builder<RawContact> rawContactsBuilder =
-                    new ImmutableList.Builder<RawContact>();
-            ImmutableMap.Builder<Long, DataStatus> statusesBuilder =
-                    new ImmutableMap.Builder<Long, DataStatus>();
-            do {
-                long rawContactId = cursor.getLong(ContactQuery.RAW_CONTACT_ID);
-                if (rawContactId != currentRawContactId) {
-                    // First time to see this raw contact id, so create a new entity, and
-                    // add it to the result's entities.
-                    currentRawContactId = rawContactId;
-                    rawContact = new RawContact(loadRawContactValues(cursor));
-                    rawContactsBuilder.add(rawContact);
-                }
-                if (!cursor.isNull(ContactQuery.DATA_ID)) {
-                    ContentValues data = loadDataValues(cursor);
-                    rawContact.addDataItemValues(data);
-
-                    if (!cursor.isNull(ContactQuery.PRESENCE)
-                            || !cursor.isNull(ContactQuery.STATUS)) {
-                        final DataStatus status = new DataStatus(cursor);
-                        final long dataId = cursor.getLong(ContactQuery.DATA_ID);
-                        statusesBuilder.put(dataId, status);
-                    }
-                }
-            } while (cursor.moveToNext());
-
-            contact.setRawContacts(rawContactsBuilder.build());
-            contact.setStatuses(statusesBuilder.build());
-
-            return contact;
-        } finally {
-            cursor.close();
-        }
-    }
-
-    /**
-     * Looks for the photo data item in entities. If found, creates a new Bitmap instance. If
-     * not found, returns null
-     */
-    private void loadPhotoBinaryData(Contact contactData) {
-        // If we have a photo URI, try loading that first.
-        String photoUri = contactData.getPhotoUri();
-        if (photoUri != null) {
-            try {
-                final InputStream inputStream;
-                final AssetFileDescriptor fd;
-                final Uri uri = Uri.parse(photoUri);
-                final String scheme = uri.getScheme();
-                if ("http".equals(scheme) || "https".equals(scheme)) {
-                    // Support HTTP urls that might come from extended directories
-                    inputStream = new URL(photoUri).openStream();
-                    fd = null;
-                } else {
-                    fd = getContext().getContentResolver().openAssetFileDescriptor(uri, "r");
-                    inputStream = fd.createInputStream();
-                }
-                byte[] buffer = new byte[16 * 1024];
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                try {
-                    int size;
-                    while ((size = inputStream.read(buffer)) != -1) {
-                        baos.write(buffer, 0, size);
-                    }
-                    contactData.setPhotoBinaryData(baos.toByteArray());
-                } finally {
-                    inputStream.close();
-                    if (fd != null) {
-                        fd.close();
-                    }
-                }
-                return;
-            } catch (IOException ioe) {
-                // Just fall back to the case below.
-            }
-        }
-
-        // If we couldn't load from a file, fall back to the data blob.
-        final long photoId = contactData.getPhotoId();
-        if (photoId <= 0) {
-            // No photo ID
-            return;
-        }
-
-        for (RawContact rawContact : contactData.getRawContacts()) {
-            for (DataItem dataItem : rawContact.getDataItems()) {
-                if (dataItem.getId() == photoId) {
-                    if (!(dataItem instanceof PhotoDataItem)) {
-                        break;
-                    }
-
-                    final PhotoDataItem photo = (PhotoDataItem) dataItem;
-                    contactData.setPhotoBinaryData(photo.getPhoto());
-                    break;
-                }
-            }
-        }
-    }
-
-    /**
-     * Sets the "invitable" account types to {@link Contact#mInvitableAccountTypes}.
-     */
-    private void loadInvitableAccountTypes(Contact contactData) {
-        final ImmutableList.Builder<AccountType> resultListBuilder =
-                new ImmutableList.Builder<AccountType>();
-        if (!contactData.isUserProfile()) {
-            Map<AccountTypeWithDataSet, AccountType> invitables =
-                    AccountTypeManager.getInstance(getContext()).getUsableInvitableAccountTypes();
-            if (!invitables.isEmpty()) {
-                final Map<AccountTypeWithDataSet, AccountType> resultMap =
-                        Maps.newHashMap(invitables);
-
-                // Remove the ones that already have a raw contact in the current contact
-                for (RawContact rawContact : contactData.getRawContacts()) {
-                    final AccountTypeWithDataSet type = AccountTypeWithDataSet.get(
-                            rawContact.getAccountTypeString(),
-                            rawContact.getDataSet());
-                    resultMap.remove(type);
-                }
-
-                resultListBuilder.addAll(resultMap.values());
-            }
-        }
-
-        // Set to mInvitableAccountTypes
-        contactData.setInvitableAccountTypes(resultListBuilder.build());
-    }
-
-    /**
-     * Extracts Contact level columns from the cursor.
-     */
-    private Contact loadContactHeaderData(final Cursor cursor, Uri contactUri) {
-        final String directoryParameter =
-                contactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
-        final long directoryId = directoryParameter == null
-                ? Directory.DEFAULT
-                : Long.parseLong(directoryParameter);
-        final long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
-        final String lookupKey = cursor.getString(ContactQuery.LOOKUP_KEY);
-        final long nameRawContactId = cursor.getLong(ContactQuery.NAME_RAW_CONTACT_ID);
-        final int displayNameSource = cursor.getInt(ContactQuery.DISPLAY_NAME_SOURCE);
-        final String displayName = cursor.getString(ContactQuery.DISPLAY_NAME);
-        final String altDisplayName = cursor.getString(ContactQuery.ALT_DISPLAY_NAME);
-        final String phoneticName = cursor.getString(ContactQuery.PHONETIC_NAME);
-        final long photoId = cursor.getLong(ContactQuery.PHOTO_ID);
-        final String photoUri = cursor.getString(ContactQuery.PHOTO_URI);
-        final boolean starred = cursor.getInt(ContactQuery.STARRED) != 0;
-        final Integer presence = cursor.isNull(ContactQuery.CONTACT_PRESENCE)
-                ? null
-                : cursor.getInt(ContactQuery.CONTACT_PRESENCE);
-        final boolean sendToVoicemail = cursor.getInt(ContactQuery.SEND_TO_VOICEMAIL) == 1;
-        final String customRingtone = cursor.getString(ContactQuery.CUSTOM_RINGTONE);
-        final boolean isUserProfile = cursor.getInt(ContactQuery.IS_USER_PROFILE) == 1;
-
-        Uri lookupUri;
-        if (directoryId == Directory.DEFAULT || directoryId == Directory.LOCAL_INVISIBLE) {
-            lookupUri = ContentUris.withAppendedId(
-                Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), contactId);
-        } else {
-            lookupUri = contactUri;
-        }
-
-        return new Contact(mRequestedUri, contactUri, lookupUri, directoryId, lookupKey,
-                contactId, nameRawContactId, displayNameSource, photoId, photoUri, displayName,
-                altDisplayName, phoneticName, starred, presence, sendToVoicemail,
-                customRingtone, isUserProfile);
-    }
-
-    /**
-     * Extracts RawContact level columns from the cursor.
-     */
-    private ContentValues loadRawContactValues(Cursor cursor) {
-        ContentValues cv = new ContentValues();
-
-        cv.put(RawContacts._ID, cursor.getLong(ContactQuery.RAW_CONTACT_ID));
-
-        cursorColumnToContentValues(cursor, cv, ContactQuery.ACCOUNT_NAME);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.ACCOUNT_TYPE);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA_SET);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.ACCOUNT_TYPE_AND_DATA_SET);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DIRTY);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.VERSION);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.SOURCE_ID);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.SYNC1);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.SYNC2);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.SYNC3);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.SYNC4);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DELETED);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.CONTACT_ID);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.STARRED);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.NAME_VERIFIED);
-
-        return cv;
-    }
-
-    /**
-     * Extracts Data level columns from the cursor.
-     */
-    private ContentValues loadDataValues(Cursor cursor) {
-        ContentValues cv = new ContentValues();
-
-        cv.put(Data._ID, cursor.getLong(ContactQuery.DATA_ID));
-
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA1);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA2);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA3);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA4);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA5);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA6);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA7);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA8);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA9);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA10);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA11);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA12);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA13);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA14);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA15);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA_SYNC1);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA_SYNC2);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA_SYNC3);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA_SYNC4);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.DATA_VERSION);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.IS_PRIMARY);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.IS_SUPERPRIMARY);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.MIMETYPE);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.RES_PACKAGE);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.GROUP_SOURCE_ID);
-        cursorColumnToContentValues(cursor, cv, ContactQuery.CHAT_CAPABILITY);
-
-        return cv;
-    }
-
-    private void cursorColumnToContentValues(
-            Cursor cursor, ContentValues values, int index) {
-        switch (cursor.getType(index)) {
-            case Cursor.FIELD_TYPE_NULL:
-                // don't put anything in the content values
-                break;
-            case Cursor.FIELD_TYPE_INTEGER:
-                values.put(ContactQuery.COLUMNS[index], cursor.getLong(index));
-                break;
-            case Cursor.FIELD_TYPE_STRING:
-                values.put(ContactQuery.COLUMNS[index], cursor.getString(index));
-                break;
-            case Cursor.FIELD_TYPE_BLOB:
-                values.put(ContactQuery.COLUMNS[index], cursor.getBlob(index));
-                break;
-            default:
-                throw new IllegalStateException("Invalid or unhandled data type");
-        }
-    }
-
-    private void loadDirectoryMetaData(Contact result) {
-        long directoryId = result.getDirectoryId();
-
-        Cursor cursor = getContext().getContentResolver().query(
-                ContentUris.withAppendedId(Directory.CONTENT_URI, directoryId),
-                DirectoryQuery.COLUMNS, null, null, null);
-        if (cursor == null) {
-            return;
-        }
-        try {
-            if (cursor.moveToFirst()) {
-                final String displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME);
-                final String packageName = cursor.getString(DirectoryQuery.PACKAGE_NAME);
-                final int typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID);
-                final String accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE);
-                final String accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME);
-                final int exportSupport = cursor.getInt(DirectoryQuery.EXPORT_SUPPORT);
-                String directoryType = null;
-                if (!TextUtils.isEmpty(packageName)) {
-                    PackageManager pm = getContext().getPackageManager();
-                    try {
-                        Resources resources = pm.getResourcesForApplication(packageName);
-                        directoryType = resources.getString(typeResourceId);
-                    } catch (NameNotFoundException e) {
-                        Log.w(TAG, "Contact directory resource not found: "
-                                + packageName + "." + typeResourceId);
-                    }
-                }
-
-                result.setDirectoryMetaData(
-                        displayName, directoryType, accountType, accountName, exportSupport);
-            }
-        } finally {
-            cursor.close();
-        }
-    }
-
-    /**
-     * Loads groups meta-data for all groups associated with all constituent raw contacts'
-     * accounts.
-     */
-    private void loadGroupMetaData(Contact result) {
-        StringBuilder selection = new StringBuilder();
-        ArrayList<String> selectionArgs = new ArrayList<String>();
-        for (RawContact rawContact : result.getRawContacts()) {
-            final String accountName = rawContact.getAccountName();
-            final String accountType = rawContact.getAccountTypeString();
-            final String dataSet = rawContact.getDataSet();
-            if (accountName != null && accountType != null) {
-                if (selection.length() != 0) {
-                    selection.append(" OR ");
-                }
-                selection.append(
-                        "(" + Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=?");
-                selectionArgs.add(accountName);
-                selectionArgs.add(accountType);
-
-                if (dataSet != null) {
-                    selection.append(" AND " + Groups.DATA_SET + "=?");
-                    selectionArgs.add(dataSet);
-                } else {
-                    selection.append(" AND " + Groups.DATA_SET + " IS NULL");
-                }
-                selection.append(")");
-            }
-        }
-        final ImmutableList.Builder<GroupMetaData> groupListBuilder =
-                new ImmutableList.Builder<GroupMetaData>();
-        final Cursor cursor = getContext().getContentResolver().query(Groups.CONTENT_URI,
-                GroupQuery.COLUMNS, selection.toString(), selectionArgs.toArray(new String[0]),
-                null);
-        try {
-            while (cursor.moveToNext()) {
-                final String accountName = cursor.getString(GroupQuery.ACCOUNT_NAME);
-                final String accountType = cursor.getString(GroupQuery.ACCOUNT_TYPE);
-                final String dataSet = cursor.getString(GroupQuery.DATA_SET);
-                final long groupId = cursor.getLong(GroupQuery.ID);
-                final String title = cursor.getString(GroupQuery.TITLE);
-                final boolean defaultGroup = cursor.isNull(GroupQuery.AUTO_ADD)
-                        ? false
-                        : cursor.getInt(GroupQuery.AUTO_ADD) != 0;
-                final boolean favorites = cursor.isNull(GroupQuery.FAVORITES)
-                        ? false
-                        : cursor.getInt(GroupQuery.FAVORITES) != 0;
-
-                groupListBuilder.add(new GroupMetaData(
-                        accountName, accountType, dataSet, groupId, title, defaultGroup,
-                        favorites));
-            }
-        } finally {
-            cursor.close();
-        }
-        result.setGroupMetaData(groupListBuilder.build());
-    }
-
-    /**
-     * Iterates over all data items that represent phone numbers are tries to calculate a formatted
-     * number. This function can safely be called several times as no unformatted data is
-     * overwritten
-     */
-    private void computeFormattedPhoneNumbers(Contact contactData) {
-        final String countryIso = GeoUtil.getCurrentCountryIso(getContext());
-        final ImmutableList<RawContact> rawContacts = contactData.getRawContacts();
-        final int rawContactCount = rawContacts.size();
-        for (int rawContactIndex = 0; rawContactIndex < rawContactCount; rawContactIndex++) {
-            final RawContact rawContact = rawContacts.get(rawContactIndex);
-            final List<DataItem> dataItems = rawContact.getDataItems();
-            final int dataCount = dataItems.size();
-            for (int dataIndex = 0; dataIndex < dataCount; dataIndex++) {
-                final DataItem dataItem = dataItems.get(dataIndex);
-                if (dataItem instanceof PhoneDataItem) {
-                    final PhoneDataItem phoneDataItem = (PhoneDataItem) dataItem;
-                    phoneDataItem.computeFormattedPhoneNumber(countryIso);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void deliverResult(Contact result) {
-        unregisterObserver();
-
-        // The creator isn't interested in any further updates
-        if (isReset() || result == null) {
-            return;
-        }
-
-        mContact = result;
-
-        if (result.isLoaded()) {
-            mLookupUri = result.getLookupUri();
-
-            if (!result.isDirectoryEntry()) {
-                Log.i(TAG, "Registering content observer for " + mLookupUri);
-                if (mObserver == null) {
-                    mObserver = new ForceLoadContentObserver();
-                }
-                getContext().getContentResolver().registerContentObserver(
-                        mLookupUri, true, mObserver);
-            }
-
-            if (mPostViewNotification) {
-                // inform the source of the data that this contact is being looked at
-                postViewNotificationToSyncAdapter();
-            }
-        }
-
-        super.deliverResult(mContact);
-    }
-
-    /**
-     * Posts a message to the contributing sync adapters that have opted-in, notifying them
-     * that the contact has just been loaded
-     */
-    private void postViewNotificationToSyncAdapter() {
-        Context context = getContext();
-        for (RawContact rawContact : mContact.getRawContacts()) {
-            final long rawContactId = rawContact.getId();
-            if (mNotifiedRawContactIds.contains(rawContactId)) {
-                continue; // Already notified for this raw contact.
-            }
-            mNotifiedRawContactIds.add(rawContactId);
-            final AccountType accountType = rawContact.getAccountType(context);
-            final String serviceName = accountType.getViewContactNotifyServiceClassName();
-            final String servicePackageName = accountType.getViewContactNotifyServicePackageName();
-            if (!TextUtils.isEmpty(serviceName) && !TextUtils.isEmpty(servicePackageName)) {
-                final Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
-                final Intent intent = new Intent();
-                intent.setClassName(servicePackageName, serviceName);
-                intent.setAction(Intent.ACTION_VIEW);
-                intent.setDataAndType(uri, RawContacts.CONTENT_ITEM_TYPE);
-                try {
-                    context.startService(intent);
-                } catch (Exception e) {
-                    Log.e(TAG, "Error sending message to source-app", e);
-                }
-            }
-        }
-    }
-
-    private void unregisterObserver() {
-        if (mObserver != null) {
-            getContext().getContentResolver().unregisterContentObserver(mObserver);
-            mObserver = null;
-        }
-    }
-
-    /**
-     * Fully upgrades this ContactLoader to one with all lists fully loaded. When done, the
-     * new result will be delivered
-     */
-    public void upgradeToFullContact() {
-        // Everything requested already? Nothing to do, so let's bail out
-        if (mLoadGroupMetaData && mLoadInvitableAccountTypes
-                && mPostViewNotification && mComputeFormattedPhoneNumber) return;
-
-        mLoadGroupMetaData = true;
-        mLoadInvitableAccountTypes = true;
-        mPostViewNotification = true;
-        mComputeFormattedPhoneNumber = true;
-
-        // Cache the current result, so that we only load the "missing" parts of the contact.
-        cacheResult();
-
-        // Our load parameters have changed, so let's pretend the data has changed. Its the same
-        // thing, essentially.
-        onContentChanged();
-    }
-
-    public Uri getLookupUri() {
-        return mLookupUri;
-    }
-
-    @Override
-    protected void onStartLoading() {
-        if (mContact != null) {
-            deliverResult(mContact);
-        }
-
-        if (takeContentChanged() || mContact == null) {
-            forceLoad();
-        }
-    }
-
-    @Override
-    protected void onStopLoading() {
-        cancelLoad();
-    }
-
-    @Override
-    protected void onReset() {
-        super.onReset();
-        cancelLoad();
-        unregisterObserver();
-        mContact = null;
-    }
-
-    /**
-     * Caches the result, which is useful when we switch from activity to activity, using the same
-     * contact. If the next load is for a different contact, the cached result will be dropped
-     */
-    public void cacheResult() {
-        if (mContact == null || !mContact.isLoaded()) {
-            sCachedResult = null;
-        } else {
-            sCachedResult = mContact;
-        }
-    }
-}
diff --git a/src/com/android/contacts/model/RawContact.java b/src/com/android/contacts/model/RawContact.java
deleted file mode 100644
index 096e377..0000000
--- a/src/com/android/contacts/model/RawContact.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Entity;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.model.dataitem.DataItem;
-import com.google.common.base.Objects;
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * RawContact represents a single raw contact in the raw contacts database.
- * It has specialized getters/setters for raw contact
- * items, and also contains a collection of DataItem objects.  A RawContact contains the information
- * from a single account.
- *
- * This allows RawContact objects to be thought of as a class with raw contact
- * fields (like account type, name, data set, sync state, etc.) and a list of
- * DataItem objects that represent contact information elements (like phone
- * numbers, email, address, etc.).
- */
-final public class RawContact implements Parcelable {
-
-    private AccountTypeManager mAccountTypeManager;
-    private final ContentValues mValues;
-    private final ArrayList<NamedDataItem> mDataItems;
-
-    final public static class NamedDataItem implements Parcelable {
-        public final Uri mUri;
-
-        // This use to be a DataItem. DataItem creation is now delayed until the point of request
-        // since there is no benefit to storing them here due to the multiple inheritance.
-        // Eventually instanceof still has to be used anyways to determine which sub-class of
-        // DataItem it is. And having parent DataItem's here makes it very difficult to serialize or
-        // parcelable.
-        //
-        // Instead of having a common DataItem super class, we should refactor this to be a generic
-        // Object where the object is a concrete class that no longer relies on ContentValues.
-        // (this will also make the classes easier to use).
-        // Since instanceof is used later anyways, having a list of Objects won't hurt and is no
-        // worse than having a DataItem.
-        public final ContentValues mContentValues;
-
-        public NamedDataItem(Uri uri, ContentValues values) {
-            this.mUri = uri;
-            this.mContentValues = values;
-        }
-
-        public NamedDataItem(Parcel parcel) {
-            this.mUri = parcel.readParcelable(Uri.class.getClassLoader());
-            this.mContentValues = parcel.readParcelable(ContentValues.class.getClassLoader());
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel parcel, int i) {
-            parcel.writeParcelable(mUri, i);
-            parcel.writeParcelable(mContentValues, i);
-        }
-
-        public static final Parcelable.Creator<NamedDataItem> CREATOR
-                = new Parcelable.Creator<NamedDataItem>() {
-
-            @Override
-            public NamedDataItem createFromParcel(Parcel parcel) {
-                return new NamedDataItem(parcel);
-            }
-
-            @Override
-            public NamedDataItem[] newArray(int i) {
-                return new NamedDataItem[i];
-            }
-        };
-
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(mUri, mContentValues);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) return false;
-            if (getClass() != obj.getClass()) return false;
-
-            final NamedDataItem other = (NamedDataItem) obj;
-            return Objects.equal(mUri, other.mUri) &&
-                    Objects.equal(mContentValues, other.mContentValues);
-        }
-    }
-
-    public static RawContact createFrom(Entity entity) {
-        final ContentValues values = entity.getEntityValues();
-        final ArrayList<Entity.NamedContentValues> subValues = entity.getSubValues();
-
-        RawContact rawContact = new RawContact(values);
-        for (Entity.NamedContentValues subValue : subValues) {
-            rawContact.addNamedDataItemValues(subValue.uri, subValue.values);
-        }
-        return rawContact;
-    }
-
-    /**
-     * A RawContact object can be created with or without a context.
-     */
-    public RawContact() {
-        this(new ContentValues());
-    }
-
-    public RawContact(ContentValues values) {
-        mValues = values;
-        mDataItems = new ArrayList<NamedDataItem>();
-    }
-
-    /**
-     * Constructor for the parcelable.
-     *
-     * @param parcel The parcel to de-serialize from.
-     */
-    private RawContact(Parcel parcel) {
-        mValues = parcel.readParcelable(ContentValues.class.getClassLoader());
-        mDataItems = Lists.newArrayList();
-        parcel.readTypedList(mDataItems, NamedDataItem.CREATOR);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int i) {
-        parcel.writeParcelable(mValues, i);
-        parcel.writeTypedList(mDataItems);
-    }
-
-    /**
-     * Create for building the parcelable.
-     */
-    public static final Parcelable.Creator<RawContact> CREATOR
-            = new Parcelable.Creator<RawContact>() {
-
-        @Override
-        public RawContact createFromParcel(Parcel parcel) {
-            return new RawContact(parcel);
-        }
-
-        @Override
-        public RawContact[] newArray(int i) {
-            return new RawContact[i];
-        }
-    };
-
-    public AccountTypeManager getAccountTypeManager(Context context) {
-        if (mAccountTypeManager == null) {
-            mAccountTypeManager = AccountTypeManager.getInstance(context);
-        }
-        return mAccountTypeManager;
-    }
-
-    public ContentValues getValues() {
-        return mValues;
-    }
-
-    /**
-     * Returns the id of the raw contact.
-     */
-    public Long getId() {
-        return getValues().getAsLong(RawContacts._ID);
-    }
-
-    /**
-     * Returns the account name of the raw contact.
-     */
-    public String getAccountName() {
-        return getValues().getAsString(RawContacts.ACCOUNT_NAME);
-    }
-
-    /**
-     * Returns the account type of the raw contact.
-     */
-    public String getAccountTypeString() {
-        return getValues().getAsString(RawContacts.ACCOUNT_TYPE);
-    }
-
-    /**
-     * Returns the data set of the raw contact.
-     */
-    public String getDataSet() {
-        return getValues().getAsString(RawContacts.DATA_SET);
-    }
-
-    /**
-     * Returns the account type and data set of the raw contact.
-     */
-    public String getAccountTypeAndDataSetString() {
-        return getValues().getAsString(RawContacts.ACCOUNT_TYPE_AND_DATA_SET);
-    }
-
-    public boolean isDirty() {
-        return getValues().getAsBoolean(RawContacts.DIRTY);
-    }
-
-    public String getSourceId() {
-        return getValues().getAsString(RawContacts.SOURCE_ID);
-    }
-
-    public String getSync1() {
-        return getValues().getAsString(RawContacts.SYNC1);
-    }
-
-    public String getSync2() {
-        return getValues().getAsString(RawContacts.SYNC2);
-    }
-
-    public String getSync3() {
-        return getValues().getAsString(RawContacts.SYNC3);
-    }
-
-    public String getSync4() {
-        return getValues().getAsString(RawContacts.SYNC4);
-    }
-
-    public boolean isDeleted() {
-        return getValues().getAsBoolean(RawContacts.DELETED);
-    }
-
-    public boolean isNameVerified() {
-        return getValues().getAsBoolean(RawContacts.NAME_VERIFIED);
-    }
-
-    public long getContactId() {
-        return getValues().getAsLong(Contacts.Entity.CONTACT_ID);
-    }
-
-    public boolean isStarred() {
-        return getValues().getAsBoolean(Contacts.STARRED);
-    }
-
-    public AccountType getAccountType(Context context) {
-        return getAccountTypeManager(context).getAccountType(getAccountTypeString(), getDataSet());
-    }
-
-    /**
-     * Sets the account name, account type, and data set strings.
-     * Valid combinations for account-name, account-type, data-set
-     * 1) null, null, null (local account)
-     * 2) non-null, non-null, null (valid account without data-set)
-     * 3) non-null, non-null, non-null (valid account with data-set)
-     */
-    private void setAccount(String accountName, String accountType, String dataSet) {
-        final ContentValues values = getValues();
-        if (accountName == null) {
-            if (accountType == null && dataSet == null) {
-                // This is a local account
-                values.putNull(RawContacts.ACCOUNT_NAME);
-                values.putNull(RawContacts.ACCOUNT_TYPE);
-                values.putNull(RawContacts.DATA_SET);
-                return;
-            }
-        } else {
-            if (accountType != null) {
-                // This is a valid account, either with or without a dataSet.
-                values.put(RawContacts.ACCOUNT_NAME, accountName);
-                values.put(RawContacts.ACCOUNT_TYPE, accountType);
-                if (dataSet == null) {
-                    values.putNull(RawContacts.DATA_SET);
-                } else {
-                    values.put(RawContacts.DATA_SET, dataSet);
-                }
-                return;
-            }
-        }
-        throw new IllegalArgumentException(
-                "Not a valid combination of account name, type, and data set.");
-    }
-
-    public void setAccount(AccountWithDataSet accountWithDataSet) {
-        setAccount(accountWithDataSet.name, accountWithDataSet.type, accountWithDataSet.dataSet);
-    }
-
-    public void setAccountToLocal() {
-        setAccount(null, null, null);
-    }
-
-    /**
-     * Creates and inserts a DataItem object that wraps the content values, and returns it.
-     */
-    public void addDataItemValues(ContentValues values) {
-        addNamedDataItemValues(Data.CONTENT_URI, values);
-    }
-
-    public NamedDataItem addNamedDataItemValues(Uri uri, ContentValues values) {
-        final NamedDataItem namedItem = new NamedDataItem(uri, values);
-        mDataItems.add(namedItem);
-        return namedItem;
-    }
-
-    public ArrayList<ContentValues> getContentValues() {
-        final ArrayList<ContentValues> list = Lists.newArrayListWithCapacity(mDataItems.size());
-        for (NamedDataItem dataItem : mDataItems) {
-            if (Data.CONTENT_URI.equals(dataItem.mUri)) {
-                list.add(dataItem.mContentValues);
-            }
-        }
-        return list;
-    }
-
-    public List<DataItem> getDataItems() {
-        final ArrayList<DataItem> list = Lists.newArrayListWithCapacity(mDataItems.size());
-        for (NamedDataItem dataItem : mDataItems) {
-            if (Data.CONTENT_URI.equals(dataItem.mUri)) {
-                list.add(DataItem.createFrom(dataItem.mContentValues));
-            }
-        }
-        return list;
-    }
-
-    public String toString() {
-        final StringBuilder sb = new StringBuilder();
-        sb.append("RawContact: ").append(mValues);
-        for (RawContact.NamedDataItem namedDataItem : mDataItems) {
-            sb.append("\n  ").append(namedDataItem.mUri);
-            sb.append("\n  -> ").append(namedDataItem.mContentValues);
-        }
-        return sb.toString();
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(mValues, mDataItems);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-
-        RawContact other = (RawContact) obj;
-        return Objects.equal(mValues, other.mValues) &&
-                Objects.equal(mDataItems, other.mDataItems);
-    }
-}
diff --git a/src/com/android/contacts/model/RawContactDelta.java b/src/com/android/contacts/model/RawContactDelta.java
deleted file mode 100644
index 373eabd..0000000
--- a/src/com/android/contacts/model/RawContactDelta.java
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model;
-
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderOperation.Builder;
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.provider.BaseColumns;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Profile;
-import android.provider.ContactsContract.RawContacts;
-import android.util.Log;
-
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.test.NeededForTesting;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * Contains a {@link RawContact} and records any modifications separately so the
- * original {@link RawContact} can be swapped out with a newer version and the
- * changes still cleanly applied.
- * <p>
- * One benefit of this approach is that we can build changes entirely on an
- * empty {@link RawContact}, which then becomes an insert {@link RawContacts} case.
- * <p>
- * When applying modifications over an {@link RawContact}, we try finding the
- * original {@link Data#_ID} rows where the modifications took place. If those
- * rows are missing from the new {@link RawContact}, we know the original data must
- * be deleted, but to preserve the user modifications we treat as an insert.
- */
-public class RawContactDelta implements Parcelable {
-    // TODO: optimize by using contentvalues pool, since we allocate so many of them
-
-    private static final String TAG = "EntityDelta";
-    private static final boolean LOGV = false;
-
-    /**
-     * Direct values from {@link Entity#getEntityValues()}.
-     */
-    private ValuesDelta mValues;
-
-    /**
-     * URI used for contacts queries, by default it is set to query raw contacts.
-     * It can be set to query the profile's raw contact(s).
-     */
-    private Uri mContactsQueryUri = RawContacts.CONTENT_URI;
-
-    /**
-     * Internal map of children values from {@link Entity#getSubValues()}, which
-     * we store here sorted into {@link Data#MIMETYPE} bins.
-     */
-    private final HashMap<String, ArrayList<ValuesDelta>> mEntries = Maps.newHashMap();
-
-    public RawContactDelta() {
-    }
-
-    public RawContactDelta(ValuesDelta values) {
-        mValues = values;
-    }
-
-    /**
-     * Build an {@link RawContactDelta} using the given {@link RawContact} as a
-     * starting point; the "before" snapshot.
-     */
-    public static RawContactDelta fromBefore(RawContact before) {
-        final RawContactDelta rawContactDelta = new RawContactDelta();
-        rawContactDelta.mValues = ValuesDelta.fromBefore(before.getValues());
-        rawContactDelta.mValues.setIdColumn(RawContacts._ID);
-        for (final ContentValues values : before.getContentValues()) {
-            rawContactDelta.addEntry(ValuesDelta.fromBefore(values));
-        }
-        return rawContactDelta;
-    }
-
-    /**
-     * Merge the "after" values from the given {@link RawContactDelta} onto the
-     * "before" state represented by this {@link RawContactDelta}, discarding any
-     * existing "after" states. This is typically used when re-parenting changes
-     * onto an updated {@link Entity}.
-     */
-    public static RawContactDelta mergeAfter(RawContactDelta local, RawContactDelta remote) {
-        // Bail early if trying to merge delete with missing local
-        final ValuesDelta remoteValues = remote.mValues;
-        if (local == null && (remoteValues.isDelete() || remoteValues.isTransient())) return null;
-
-        // Create local version if none exists yet
-        if (local == null) local = new RawContactDelta();
-
-        if (LOGV) {
-            final Long localVersion = (local.mValues == null) ? null : local.mValues
-                    .getAsLong(RawContacts.VERSION);
-            final Long remoteVersion = remote.mValues.getAsLong(RawContacts.VERSION);
-            Log.d(TAG, "Re-parenting from original version " + remoteVersion + " to "
-                    + localVersion);
-        }
-
-        // Create values if needed, and merge "after" changes
-        local.mValues = ValuesDelta.mergeAfter(local.mValues, remote.mValues);
-
-        // Find matching local entry for each remote values, or create
-        for (ArrayList<ValuesDelta> mimeEntries : remote.mEntries.values()) {
-            for (ValuesDelta remoteEntry : mimeEntries) {
-                final Long childId = remoteEntry.getId();
-
-                // Find or create local match and merge
-                final ValuesDelta localEntry = local.getEntry(childId);
-                final ValuesDelta merged = ValuesDelta.mergeAfter(localEntry, remoteEntry);
-
-                if (localEntry == null && merged != null) {
-                    // No local entry before, so insert
-                    local.addEntry(merged);
-                }
-            }
-        }
-
-        return local;
-    }
-
-    public ValuesDelta getValues() {
-        return mValues;
-    }
-
-    public boolean isContactInsert() {
-        return mValues.isInsert();
-    }
-
-    /**
-     * Get the {@link ValuesDelta} child marked as {@link Data#IS_PRIMARY},
-     * which may return null when no entry exists.
-     */
-    public ValuesDelta getPrimaryEntry(String mimeType) {
-        final ArrayList<ValuesDelta> mimeEntries = getMimeEntries(mimeType, false);
-        if (mimeEntries == null) return null;
-
-        for (ValuesDelta entry : mimeEntries) {
-            if (entry.isPrimary()) {
-                return entry;
-            }
-        }
-
-        // When no direct primary, return something
-        return mimeEntries.size() > 0 ? mimeEntries.get(0) : null;
-    }
-
-    /**
-     * calls {@link #getSuperPrimaryEntry(String, boolean)} with true
-     * @see #getSuperPrimaryEntry(String, boolean)
-     */
-    public ValuesDelta getSuperPrimaryEntry(String mimeType) {
-        return getSuperPrimaryEntry(mimeType, true);
-    }
-
-    /**
-     * Returns the super-primary entry for the given mime type
-     * @param forceSelection if true, will try to return some value even if a super-primary
-     *     doesn't exist (may be a primary, or just a random item
-     * @return
-     */
-    @NeededForTesting
-    public ValuesDelta getSuperPrimaryEntry(String mimeType, boolean forceSelection) {
-        final ArrayList<ValuesDelta> mimeEntries = getMimeEntries(mimeType, false);
-        if (mimeEntries == null) return null;
-
-        ValuesDelta primary = null;
-        for (ValuesDelta entry : mimeEntries) {
-            if (entry.isSuperPrimary()) {
-                return entry;
-            } else if (entry.isPrimary()) {
-                primary = entry;
-            }
-        }
-
-        if (!forceSelection) {
-            return null;
-        }
-
-        // When no direct super primary, return something
-        if (primary != null) {
-            return primary;
-        }
-        return mimeEntries.size() > 0 ? mimeEntries.get(0) : null;
-    }
-
-    /**
-     * Return the AccountType that this raw-contact belongs to.
-     */
-    public AccountType getRawContactAccountType(Context context) {
-        ContentValues entityValues = getValues().getCompleteValues();
-        String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
-        String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
-        return AccountTypeManager.getInstance(context).getAccountType(type, dataSet);
-    }
-
-    public Long getRawContactId() {
-        return getValues().getAsLong(RawContacts._ID);
-    }
-
-    public String getAccountName() {
-        return getValues().getAsString(RawContacts.ACCOUNT_NAME);
-    }
-
-    public String getAccountType() {
-        return getValues().getAsString(RawContacts.ACCOUNT_TYPE);
-    }
-
-    public String getDataSet() {
-        return getValues().getAsString(RawContacts.DATA_SET);
-    }
-
-    public AccountType getAccountType(AccountTypeManager manager) {
-        return manager.getAccountType(getAccountType(), getDataSet());
-    }
-
-    public boolean isVisible() {
-        return getValues().isVisible();
-    }
-
-    /**
-     * Return the list of child {@link ValuesDelta} from our optimized map,
-     * creating the list if requested.
-     */
-    private ArrayList<ValuesDelta> getMimeEntries(String mimeType, boolean lazyCreate) {
-        ArrayList<ValuesDelta> mimeEntries = mEntries.get(mimeType);
-        if (mimeEntries == null && lazyCreate) {
-            mimeEntries = Lists.newArrayList();
-            mEntries.put(mimeType, mimeEntries);
-        }
-        return mimeEntries;
-    }
-
-    public ArrayList<ValuesDelta> getMimeEntries(String mimeType) {
-        return getMimeEntries(mimeType, false);
-    }
-
-    public int getMimeEntriesCount(String mimeType, boolean onlyVisible) {
-        final ArrayList<ValuesDelta> mimeEntries = getMimeEntries(mimeType);
-        if (mimeEntries == null) return 0;
-
-        int count = 0;
-        for (ValuesDelta child : mimeEntries) {
-            // Skip deleted items when requesting only visible
-            if (onlyVisible && !child.isVisible()) continue;
-            count++;
-        }
-        return count;
-    }
-
-    public boolean hasMimeEntries(String mimeType) {
-        return mEntries.containsKey(mimeType);
-    }
-
-    public ValuesDelta addEntry(ValuesDelta entry) {
-        final String mimeType = entry.getMimetype();
-        getMimeEntries(mimeType, true).add(entry);
-        return entry;
-    }
-
-    public ArrayList<ContentValues> getContentValues() {
-        ArrayList<ContentValues> values = Lists.newArrayList();
-        for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-            for (ValuesDelta entry : mimeEntries) {
-                if (!entry.isDelete()) {
-                    values.add(entry.getCompleteValues());
-                }
-            }
-        }
-        return values;
-    }
-
-    /**
-     * Find entry with the given {@link BaseColumns#_ID} value.
-     */
-    public ValuesDelta getEntry(Long childId) {
-        if (childId == null) {
-            // Requesting an "insert" entry, which has no "before"
-            return null;
-        }
-
-        // Search all children for requested entry
-        for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-            for (ValuesDelta entry : mimeEntries) {
-                if (childId.equals(entry.getId())) {
-                    return entry;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Return the total number of {@link ValuesDelta} contained.
-     */
-    public int getEntryCount(boolean onlyVisible) {
-        int count = 0;
-        for (String mimeType : mEntries.keySet()) {
-            count += getMimeEntriesCount(mimeType, onlyVisible);
-        }
-        return count;
-    }
-
-    @Override
-    public boolean equals(Object object) {
-        if (object instanceof RawContactDelta) {
-            final RawContactDelta other = (RawContactDelta)object;
-
-            // Equality failed if parent values different
-            if (!other.mValues.equals(mValues)) return false;
-
-            for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-                for (ValuesDelta child : mimeEntries) {
-                    // Equality failed if any children unmatched
-                    if (!other.containsEntry(child)) return false;
-                }
-            }
-
-            // Passed all tests, so equal
-            return true;
-        }
-        return false;
-    }
-
-    private boolean containsEntry(ValuesDelta entry) {
-        for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-            for (ValuesDelta child : mimeEntries) {
-                // Contained if we find any child that matches
-                if (child.equals(entry)) return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Mark this entire object deleted, including any {@link ValuesDelta}.
-     */
-    public void markDeleted() {
-        this.mValues.markDeleted();
-        for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-            for (ValuesDelta child : mimeEntries) {
-                child.markDeleted();
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder builder = new StringBuilder();
-        builder.append("\n(");
-        builder.append("Uri=");
-        builder.append(mContactsQueryUri);
-        builder.append(", Values=");
-        builder.append(mValues != null ? mValues.toString() : "null");
-        builder.append(", Entries={");
-        for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-            for (ValuesDelta child : mimeEntries) {
-                builder.append("\n\t");
-                child.toString(builder);
-            }
-        }
-        builder.append("\n})\n");
-        return builder.toString();
-    }
-
-    /**
-     * Consider building the given {@link ContentProviderOperation.Builder} and
-     * appending it to the given list, which only happens if builder is valid.
-     */
-    private void possibleAdd(ArrayList<ContentProviderOperation> diff,
-            ContentProviderOperation.Builder builder) {
-        if (builder != null) {
-            diff.add(builder.build());
-        }
-    }
-
-    /**
-     * Build a list of {@link ContentProviderOperation} that will assert any
-     * "before" state hasn't changed. This is maintained separately so that all
-     * asserts can take place before any updates occur.
-     */
-    public void buildAssert(ArrayList<ContentProviderOperation> buildInto) {
-        final boolean isContactInsert = mValues.isInsert();
-        if (!isContactInsert) {
-            // Assert version is consistent while persisting changes
-            final Long beforeId = mValues.getId();
-            final Long beforeVersion = mValues.getAsLong(RawContacts.VERSION);
-            if (beforeId == null || beforeVersion == null) return;
-
-            final ContentProviderOperation.Builder builder = ContentProviderOperation
-                    .newAssertQuery(mContactsQueryUri);
-            builder.withSelection(RawContacts._ID + "=" + beforeId, null);
-            builder.withValue(RawContacts.VERSION, beforeVersion);
-            buildInto.add(builder.build());
-        }
-    }
-
-    /**
-     * Build a list of {@link ContentProviderOperation} that will transform the
-     * current "before" {@link Entity} state into the modified state which this
-     * {@link RawContactDelta} represents.
-     */
-    public void buildDiff(ArrayList<ContentProviderOperation> buildInto) {
-        final int firstIndex = buildInto.size();
-
-        final boolean isContactInsert = mValues.isInsert();
-        final boolean isContactDelete = mValues.isDelete();
-        final boolean isContactUpdate = !isContactInsert && !isContactDelete;
-
-        final Long beforeId = mValues.getId();
-
-        Builder builder;
-
-        if (isContactInsert) {
-            // TODO: for now simply disabling aggregation when a new contact is
-            // created on the phone.  In the future, will show aggregation suggestions
-            // after saving the contact.
-            mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
-        }
-
-        // Build possible operation at Contact level
-        builder = mValues.buildDiff(mContactsQueryUri);
-        possibleAdd(buildInto, builder);
-
-        // Build operations for all children
-        for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-            for (ValuesDelta child : mimeEntries) {
-                // Ignore children if parent was deleted
-                if (isContactDelete) continue;
-
-                // Use the profile data URI if the contact is the profile.
-                if (mContactsQueryUri.equals(Profile.CONTENT_RAW_CONTACTS_URI)) {
-                    builder = child.buildDiff(Uri.withAppendedPath(Profile.CONTENT_URI,
-                            RawContacts.Data.CONTENT_DIRECTORY));
-                } else {
-                    builder = child.buildDiff(Data.CONTENT_URI);
-                }
-
-                if (child.isInsert()) {
-                    if (isContactInsert) {
-                        // Parent is brand new insert, so back-reference _id
-                        builder.withValueBackReference(Data.RAW_CONTACT_ID, firstIndex);
-                    } else {
-                        // Inserting under existing, so fill with known _id
-                        builder.withValue(Data.RAW_CONTACT_ID, beforeId);
-                    }
-                } else if (isContactInsert && builder != null) {
-                    // Child must be insert when Contact insert
-                    throw new IllegalArgumentException("When parent insert, child must be also");
-                }
-                possibleAdd(buildInto, builder);
-            }
-        }
-
-        final boolean addedOperations = buildInto.size() > firstIndex;
-        if (addedOperations && isContactUpdate) {
-            // Suspend aggregation while persisting updates
-            builder = buildSetAggregationMode(beforeId, RawContacts.AGGREGATION_MODE_SUSPENDED);
-            buildInto.add(firstIndex, builder.build());
-
-            // Restore aggregation mode as last operation
-            builder = buildSetAggregationMode(beforeId, RawContacts.AGGREGATION_MODE_DEFAULT);
-            buildInto.add(builder.build());
-        } else if (isContactInsert) {
-            // Restore aggregation mode as last operation
-            builder = ContentProviderOperation.newUpdate(mContactsQueryUri);
-            builder.withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DEFAULT);
-            builder.withSelection(RawContacts._ID + "=?", new String[1]);
-            builder.withSelectionBackReference(0, firstIndex);
-            buildInto.add(builder.build());
-        }
-    }
-
-    /**
-     * Build a {@link ContentProviderOperation} that changes
-     * {@link RawContacts#AGGREGATION_MODE} to the given value.
-     */
-    protected Builder buildSetAggregationMode(Long beforeId, int mode) {
-        Builder builder = ContentProviderOperation.newUpdate(mContactsQueryUri);
-        builder.withValue(RawContacts.AGGREGATION_MODE, mode);
-        builder.withSelection(RawContacts._ID + "=" + beforeId, null);
-        return builder;
-    }
-
-    /** {@inheritDoc} */
-    public int describeContents() {
-        // Nothing special about this parcel
-        return 0;
-    }
-
-    /** {@inheritDoc} */
-    public void writeToParcel(Parcel dest, int flags) {
-        final int size = this.getEntryCount(false);
-        dest.writeInt(size);
-        dest.writeParcelable(mValues, flags);
-        dest.writeParcelable(mContactsQueryUri, flags);
-        for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
-            for (ValuesDelta child : mimeEntries) {
-                dest.writeParcelable(child, flags);
-            }
-        }
-    }
-
-    public void readFromParcel(Parcel source) {
-        final ClassLoader loader = getClass().getClassLoader();
-        final int size = source.readInt();
-        mValues = source.<ValuesDelta> readParcelable(loader);
-        mContactsQueryUri = source.<Uri> readParcelable(loader);
-        for (int i = 0; i < size; i++) {
-            final ValuesDelta child = source.<ValuesDelta> readParcelable(loader);
-            this.addEntry(child);
-        }
-    }
-
-    /**
-     * Used to set the query URI to the profile URI to store profiles.
-     */
-    public void setProfileQueryUri() {
-        mContactsQueryUri = Profile.CONTENT_RAW_CONTACTS_URI;
-    }
-
-    public static final Parcelable.Creator<RawContactDelta> CREATOR =
-            new Parcelable.Creator<RawContactDelta>() {
-        public RawContactDelta createFromParcel(Parcel in) {
-            final RawContactDelta state = new RawContactDelta();
-            state.readFromParcel(in);
-            return state;
-        }
-
-        public RawContactDelta[] newArray(int size) {
-            return new RawContactDelta[size];
-        }
-    };
-
-}
diff --git a/src/com/android/contacts/model/RawContactDeltaList.java b/src/com/android/contacts/model/RawContactDeltaList.java
deleted file mode 100644
index 1a9eb71..0000000
--- a/src/com/android/contacts/model/RawContactDeltaList.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model;
-
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderOperation.Builder;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Entity;
-import android.content.EntityIterator;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.provider.ContactsContract.AggregationExceptions;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.RawContacts;
-import android.util.Log;
-
-import com.android.contacts.common.model.ValuesDelta;
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-
-/**
- * Container for multiple {@link RawContactDelta} objects, usually when editing
- * together as an entire aggregate. Provides convenience methods for parceling
- * and applying another {@link RawContactDeltaList} over it.
- */
-public class RawContactDeltaList extends ArrayList<RawContactDelta> implements Parcelable {
-    private static final String TAG = RawContactDeltaList.class.getSimpleName();
-    private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE);
-
-    private boolean mSplitRawContacts;
-    private long[] mJoinWithRawContactIds;
-
-    public RawContactDeltaList() {
-    }
-
-    /**
-     * Create an {@link RawContactDeltaList} based on {@link Contacts} specified by the
-     * given query parameters. This closes the {@link EntityIterator} when
-     * finished, so it doesn't subscribe to updates.
-     */
-    public static RawContactDeltaList fromQuery(Uri entityUri, ContentResolver resolver,
-            String selection, String[] selectionArgs, String sortOrder) {
-        final EntityIterator iterator = RawContacts.newEntityIterator(
-                resolver.query(entityUri, null, selection, selectionArgs, sortOrder));
-        try {
-            return fromIterator(iterator);
-        } finally {
-            iterator.close();
-        }
-    }
-
-    /**
-     * Create an {@link RawContactDeltaList} that contains the entities of the Iterator as before
-     * values.  This function can be passed an iterator of Entity objects or an iterator of
-     * RawContact objects.
-     */
-    public static RawContactDeltaList fromIterator(Iterator<?> iterator) {
-        final RawContactDeltaList state = new RawContactDeltaList();
-        state.addAll(iterator);
-        return state;
-    }
-
-    public void addAll(Iterator<?> iterator) {
-        // Perform background query to pull contact details
-        while (iterator.hasNext()) {
-            // Read all contacts into local deltas to prepare for edits
-            Object nextObject = iterator.next();
-            final RawContact before = nextObject instanceof Entity
-                    ? RawContact.createFrom((Entity) nextObject)
-                    : (RawContact) nextObject;
-            final RawContactDelta rawContactDelta = RawContactDelta.fromBefore(before);
-            add(rawContactDelta);
-        }
-    }
-
-    /**
-     * Merge the "after" values from the given {@link RawContactDeltaList}, discarding any
-     * previous "after" states. This is typically used when re-parenting user
-     * edits onto an updated {@link RawContactDeltaList}.
-     */
-    public static RawContactDeltaList mergeAfter(RawContactDeltaList local,
-            RawContactDeltaList remote) {
-        if (local == null) local = new RawContactDeltaList();
-
-        // For each entity in the remote set, try matching over existing
-        for (RawContactDelta remoteEntity : remote) {
-            final Long rawContactId = remoteEntity.getValues().getId();
-
-            // Find or create local match and merge
-            final RawContactDelta localEntity = local.getByRawContactId(rawContactId);
-            final RawContactDelta merged = RawContactDelta.mergeAfter(localEntity, remoteEntity);
-
-            if (localEntity == null && merged != null) {
-                // No local entry before, so insert
-                local.add(merged);
-            }
-        }
-
-        return local;
-    }
-
-    /**
-     * Build a list of {@link ContentProviderOperation} that will transform all
-     * the "before" {@link Entity} states into the modified state which all
-     * {@link RawContactDelta} objects represent. This method specifically creates
-     * any {@link AggregationExceptions} rules needed to groups edits together.
-     */
-    public ArrayList<ContentProviderOperation> buildDiff() {
-        if (VERBOSE_LOGGING) {
-            Log.v(TAG, "buildDiff: list=" + toString());
-        }
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-
-        final long rawContactId = this.findRawContactId();
-        int firstInsertRow = -1;
-
-        // First pass enforces versions remain consistent
-        for (RawContactDelta delta : this) {
-            delta.buildAssert(diff);
-        }
-
-        final int assertMark = diff.size();
-        int backRefs[] = new int[size()];
-
-        int rawContactIndex = 0;
-
-        // Second pass builds actual operations
-        for (RawContactDelta delta : this) {
-            final int firstBatch = diff.size();
-            final boolean isInsert = delta.isContactInsert();
-            backRefs[rawContactIndex++] = isInsert ? firstBatch : -1;
-
-            delta.buildDiff(diff);
-
-            // If the user chose to join with some other existing raw contact(s) at save time,
-            // add aggregation exceptions for all those raw contacts.
-            if (mJoinWithRawContactIds != null) {
-                for (Long joinedRawContactId : mJoinWithRawContactIds) {
-                    final Builder builder = beginKeepTogether();
-                    builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, joinedRawContactId);
-                    if (rawContactId != -1) {
-                        builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId);
-                    } else {
-                        builder.withValueBackReference(
-                                AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
-                    }
-                    diff.add(builder.build());
-                }
-            }
-
-            // Only create rules for inserts
-            if (!isInsert) continue;
-
-            // If we are going to split all contacts, there is no point in first combining them
-            if (mSplitRawContacts) continue;
-
-            if (rawContactId != -1) {
-                // Has existing contact, so bind to it strongly
-                final Builder builder = beginKeepTogether();
-                builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId);
-                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
-                diff.add(builder.build());
-
-            } else if (firstInsertRow == -1) {
-                // First insert case, so record row
-                firstInsertRow = firstBatch;
-
-            } else {
-                // Additional insert case, so point at first insert
-                final Builder builder = beginKeepTogether();
-                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1,
-                        firstInsertRow);
-                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
-                diff.add(builder.build());
-            }
-        }
-
-        if (mSplitRawContacts) {
-            buildSplitContactDiff(diff, backRefs);
-        }
-
-        // No real changes if only left with asserts
-        if (diff.size() == assertMark) {
-            diff.clear();
-        }
-        if (VERBOSE_LOGGING) {
-            Log.v(TAG, "buildDiff: ops=" + diffToString(diff));
-        }
-        return diff;
-    }
-
-    private static String diffToString(ArrayList<ContentProviderOperation> ops) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("[\n");
-        for (ContentProviderOperation op : ops) {
-            sb.append(op.toString());
-            sb.append(",\n");
-        }
-        sb.append("]\n");
-        return sb.toString();
-    }
-
-    /**
-     * Start building a {@link ContentProviderOperation} that will keep two
-     * {@link RawContacts} together.
-     */
-    protected Builder beginKeepTogether() {
-        final Builder builder = ContentProviderOperation
-                .newUpdate(AggregationExceptions.CONTENT_URI);
-        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
-        return builder;
-    }
-
-    /**
-     * Builds {@link AggregationExceptions} to split all constituent raw contacts into
-     * separate contacts.
-     */
-    private void buildSplitContactDiff(final ArrayList<ContentProviderOperation> diff,
-            int[] backRefs) {
-        int count = size();
-        for (int i = 0; i < count; i++) {
-            for (int j = 0; j < count; j++) {
-                if (i != j) {
-                    buildSplitContactDiff(diff, i, j, backRefs);
-                }
-            }
-        }
-    }
-
-    /**
-     * Construct a {@link AggregationExceptions#TYPE_KEEP_SEPARATE}.
-     */
-    private void buildSplitContactDiff(ArrayList<ContentProviderOperation> diff, int index1,
-            int index2, int[] backRefs) {
-        Builder builder =
-                ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI);
-        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_SEPARATE);
-
-        Long rawContactId1 = get(index1).getValues().getAsLong(RawContacts._ID);
-        int backRef1 = backRefs[index1];
-        if (rawContactId1 != null && rawContactId1 >= 0) {
-            builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1);
-        } else if (backRef1 >= 0) {
-            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1, backRef1);
-        } else {
-            return;
-        }
-
-        Long rawContactId2 = get(index2).getValues().getAsLong(RawContacts._ID);
-        int backRef2 = backRefs[index2];
-        if (rawContactId2 != null && rawContactId2 >= 0) {
-            builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2);
-        } else if (backRef2 >= 0) {
-            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, backRef2);
-        } else {
-            return;
-        }
-
-        diff.add(builder.build());
-    }
-
-    /**
-     * Search all contained {@link RawContactDelta} for the first one with an
-     * existing {@link RawContacts#_ID} value. Usually used when creating
-     * {@link AggregationExceptions} during an update.
-     */
-    public long findRawContactId() {
-        for (RawContactDelta delta : this) {
-            final Long rawContactId = delta.getValues().getAsLong(RawContacts._ID);
-            if (rawContactId != null && rawContactId >= 0) {
-                return rawContactId;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Find {@link RawContacts#_ID} of the requested {@link RawContactDelta}.
-     */
-    public Long getRawContactId(int index) {
-        if (index >= 0 && index < this.size()) {
-            final RawContactDelta delta = this.get(index);
-            final ValuesDelta values = delta.getValues();
-            if (values.isVisible()) {
-                return values.getAsLong(RawContacts._ID);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Find the raw-contact (an {@link RawContactDelta}) with the specified ID.
-     */
-    public RawContactDelta getByRawContactId(Long rawContactId) {
-        final int index = this.indexOfRawContactId(rawContactId);
-        return (index == -1) ? null : this.get(index);
-    }
-
-    /**
-     * Find index of given {@link RawContacts#_ID} when present.
-     */
-    public int indexOfRawContactId(Long rawContactId) {
-        if (rawContactId == null) return -1;
-        final int size = this.size();
-        for (int i = 0; i < size; i++) {
-            final Long currentId = getRawContactId(i);
-            if (rawContactId.equals(currentId)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Return the index of the first RawContactDelta corresponding to a writable raw-contact, or -1.
-     * */
-    public int indexOfFirstWritableRawContact(Context context) {
-        // Find the first writable entity.
-        int entityIndex = 0;
-        for (RawContactDelta delta : this) {
-            if (delta.getRawContactAccountType(context).areContactsWritable()) return entityIndex;
-            entityIndex++;
-        }
-        return -1;
-    }
-
-    /**  Return the first RawContactDelta corresponding to a writable raw-contact, or null. */
-    public RawContactDelta getFirstWritableRawContact(Context context) {
-        final int index = indexOfFirstWritableRawContact(context);
-        return (index == -1) ? null : get(index);
-    }
-
-    public ValuesDelta getSuperPrimaryEntry(final String mimeType) {
-        ValuesDelta primary = null;
-        ValuesDelta randomEntry = null;
-        for (RawContactDelta delta : this) {
-            final ArrayList<ValuesDelta> mimeEntries = delta.getMimeEntries(mimeType);
-            if (mimeEntries == null) return null;
-
-            for (ValuesDelta entry : mimeEntries) {
-                if (entry.isSuperPrimary()) {
-                    return entry;
-                } else if (primary == null && entry.isPrimary()) {
-                    primary = entry;
-                } else if (randomEntry == null) {
-                    randomEntry = entry;
-                }
-            }
-        }
-        // When no direct super primary, return something
-        if (primary != null) {
-            return primary;
-        }
-        return randomEntry;
-    }
-
-    /**
-     * Sets a flag that will split ("explode") the raw_contacts into seperate contacts
-     */
-    public void markRawContactsForSplitting() {
-        mSplitRawContacts = true;
-    }
-
-    public boolean isMarkedForSplitting() {
-        return mSplitRawContacts;
-    }
-
-    public void setJoinWithRawContacts(long[] rawContactIds) {
-        mJoinWithRawContactIds = rawContactIds;
-    }
-
-    public boolean isMarkedForJoining() {
-        return mJoinWithRawContactIds != null && mJoinWithRawContactIds.length > 0;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public int describeContents() {
-        // Nothing special about this parcel
-        return 0;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        final int size = this.size();
-        dest.writeInt(size);
-        for (RawContactDelta delta : this) {
-            dest.writeParcelable(delta, flags);
-        }
-        dest.writeLongArray(mJoinWithRawContactIds);
-        dest.writeInt(mSplitRawContacts ? 1 : 0);
-    }
-
-    @SuppressWarnings("unchecked")
-    public void readFromParcel(Parcel source) {
-        final ClassLoader loader = getClass().getClassLoader();
-        final int size = source.readInt();
-        for (int i = 0; i < size; i++) {
-            this.add(source.<RawContactDelta> readParcelable(loader));
-        }
-        mJoinWithRawContactIds = source.createLongArray();
-        mSplitRawContacts = source.readInt() != 0;
-    }
-
-    public static final Parcelable.Creator<RawContactDeltaList> CREATOR =
-            new Parcelable.Creator<RawContactDeltaList>() {
-        @Override
-        public RawContactDeltaList createFromParcel(Parcel in) {
-            final RawContactDeltaList state = new RawContactDeltaList();
-            state.readFromParcel(in);
-            return state;
-        }
-
-        @Override
-        public RawContactDeltaList[] newArray(int size) {
-            return new RawContactDeltaList[size];
-        }
-    };
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("(");
-        sb.append("Split=");
-        sb.append(mSplitRawContacts);
-        sb.append(", Join=[");
-        sb.append(Arrays.toString(mJoinWithRawContactIds));
-        sb.append("], Values=");
-        sb.append(super.toString());
-        sb.append(")");
-        return sb.toString();
-    }
-}
diff --git a/src/com/android/contacts/model/RawContactModifier.java b/src/com/android/contacts/model/RawContactModifier.java
deleted file mode 100644
index 5f8b410..0000000
--- a/src/com/android/contacts/model/RawContactModifier.java
+++ /dev/null
@@ -1,1429 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Event;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Nickname;
-import android.provider.ContactsContract.CommonDataKinds.Note;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.Relation;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Intents;
-import android.provider.ContactsContract.Intents.Insert;
-import android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.common.util.CommonDateUtils;
-import com.android.contacts.editor.EventFieldEditorView;
-import com.android.contacts.editor.PhoneticNameEditorView;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountType.EditField;
-import com.android.contacts.common.model.account.AccountType.EditType;
-import com.android.contacts.common.model.account.AccountType.EventEditType;
-import com.android.contacts.common.model.account.GoogleAccountType;
-import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.model.dataitem.PhoneDataItem;
-import com.android.contacts.model.dataitem.StructuredNameDataItem;
-import com.android.contacts.util.DateUtils;
-import com.android.contacts.util.NameConverter;
-
-import java.text.ParsePosition;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Helper methods for modifying an {@link RawContactDelta}, such as inserting
- * new rows, or enforcing {@link AccountType}.
- */
-public class RawContactModifier {
-    private static final String TAG = RawContactModifier.class.getSimpleName();
-
-    /** Set to true in order to view logs on entity operations */
-    private static final boolean DEBUG = false;
-
-    /**
-     * For the given {@link RawContactDelta}, determine if the given
-     * {@link DataKind} could be inserted under specific
-     * {@link AccountType}.
-     */
-    public static boolean canInsert(RawContactDelta state, DataKind kind) {
-        // Insert possible when have valid types and under overall maximum
-        final int visibleCount = state.getMimeEntriesCount(kind.mimeType, true);
-        final boolean validTypes = hasValidTypes(state, kind);
-        final boolean validOverall = (kind.typeOverallMax == -1)
-                || (visibleCount < kind.typeOverallMax);
-        return (validTypes && validOverall);
-    }
-
-    public static boolean hasValidTypes(RawContactDelta state, DataKind kind) {
-        if (RawContactModifier.hasEditTypes(kind)) {
-            return (getValidTypes(state, kind).size() > 0);
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * Ensure that at least one of the given {@link DataKind} exists in the
-     * given {@link RawContactDelta} state, and try creating one if none exist.
-     * @return The child (either newly created or the first existing one), or null if the
-     *     account doesn't support this {@link DataKind}.
-     */
-    public static ValuesDelta ensureKindExists(
-            RawContactDelta state, AccountType accountType, String mimeType) {
-        final DataKind kind = accountType.getKindForMimetype(mimeType);
-        final boolean hasChild = state.getMimeEntriesCount(mimeType, true) > 0;
-
-        if (kind != null) {
-            if (hasChild) {
-                // Return the first entry.
-                return state.getMimeEntries(mimeType).get(0);
-            } else {
-                // Create child when none exists and valid kind
-                final ValuesDelta child = insertChild(state, kind);
-                if (kind.mimeType.equals(Photo.CONTENT_ITEM_TYPE)) {
-                    child.setFromTemplate(true);
-                }
-                return child;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * For the given {@link RawContactDelta} and {@link DataKind}, return the
-     * list possible {@link EditType} options available based on
-     * {@link AccountType}.
-     */
-    public static ArrayList<EditType> getValidTypes(RawContactDelta state, DataKind kind) {
-        return getValidTypes(state, kind, null, true, null);
-    }
-
-    /**
-     * For the given {@link RawContactDelta} and {@link DataKind}, return the
-     * list possible {@link EditType} options available based on
-     * {@link AccountType}.
-     *
-     * @param forceInclude Always include this {@link EditType} in the returned
-     *            list, even when an otherwise-invalid choice. This is useful
-     *            when showing a dialog that includes the current type.
-     */
-    public static ArrayList<EditType> getValidTypes(RawContactDelta state, DataKind kind,
-            EditType forceInclude) {
-        return getValidTypes(state, kind, forceInclude, true, null);
-    }
-
-    /**
-     * For the given {@link RawContactDelta} and {@link DataKind}, return the
-     * list possible {@link EditType} options available based on
-     * {@link AccountType}.
-     *
-     * @param forceInclude Always include this {@link EditType} in the returned
-     *            list, even when an otherwise-invalid choice. This is useful
-     *            when showing a dialog that includes the current type.
-     * @param includeSecondary If true, include any valid types marked as
-     *            {@link EditType#secondary}.
-     * @param typeCount When provided, will be used for the frequency count of
-     *            each {@link EditType}, otherwise built using
-     *            {@link #getTypeFrequencies(RawContactDelta, DataKind)}.
-     */
-    private static ArrayList<EditType> getValidTypes(RawContactDelta state, DataKind kind,
-            EditType forceInclude, boolean includeSecondary, SparseIntArray typeCount) {
-        final ArrayList<EditType> validTypes = new ArrayList<EditType>();
-
-        // Bail early if no types provided
-        if (!hasEditTypes(kind)) return validTypes;
-
-        if (typeCount == null) {
-            // Build frequency counts if not provided
-            typeCount = getTypeFrequencies(state, kind);
-        }
-
-        // Build list of valid types
-        final int overallCount = typeCount.get(FREQUENCY_TOTAL);
-        for (EditType type : kind.typeList) {
-            final boolean validOverall = (kind.typeOverallMax == -1 ? true
-                    : overallCount < kind.typeOverallMax);
-            final boolean validSpecific = (type.specificMax == -1 ? true : typeCount
-                    .get(type.rawValue) < type.specificMax);
-            final boolean validSecondary = (includeSecondary ? true : !type.secondary);
-            final boolean forcedInclude = type.equals(forceInclude);
-            if (forcedInclude || (validOverall && validSpecific && validSecondary)) {
-                // Type is valid when no limit, under limit, or forced include
-                validTypes.add(type);
-            }
-        }
-
-        return validTypes;
-    }
-
-    private static final int FREQUENCY_TOTAL = Integer.MIN_VALUE;
-
-    /**
-     * Count up the frequency that each {@link EditType} appears in the given
-     * {@link RawContactDelta}. The returned {@link SparseIntArray} maps from
-     * {@link EditType#rawValue} to counts, with the total overall count stored
-     * as {@link #FREQUENCY_TOTAL}.
-     */
-    private static SparseIntArray getTypeFrequencies(RawContactDelta state, DataKind kind) {
-        final SparseIntArray typeCount = new SparseIntArray();
-
-        // Find all entries for this kind, bailing early if none found
-        final List<ValuesDelta> mimeEntries = state.getMimeEntries(kind.mimeType);
-        if (mimeEntries == null) return typeCount;
-
-        int totalCount = 0;
-        for (ValuesDelta entry : mimeEntries) {
-            // Only count visible entries
-            if (!entry.isVisible()) continue;
-            totalCount++;
-
-            final EditType type = getCurrentType(entry, kind);
-            if (type != null) {
-                final int count = typeCount.get(type.rawValue);
-                typeCount.put(type.rawValue, count + 1);
-            }
-        }
-        typeCount.put(FREQUENCY_TOTAL, totalCount);
-        return typeCount;
-    }
-
-    /**
-     * Check if the given {@link DataKind} has multiple types that should be
-     * displayed for users to pick.
-     */
-    public static boolean hasEditTypes(DataKind kind) {
-        return kind.typeList != null && kind.typeList.size() > 0;
-    }
-
-    /**
-     * Find the {@link EditType} that describes the given
-     * {@link ValuesDelta} row, assuming the given {@link DataKind} dictates
-     * the possible types.
-     */
-    public static EditType getCurrentType(ValuesDelta entry, DataKind kind) {
-        final Long rawValue = entry.getAsLong(kind.typeColumn);
-        if (rawValue == null) return null;
-        return getType(kind, rawValue.intValue());
-    }
-
-    /**
-     * Find the {@link EditType} that describes the given {@link ContentValues} row,
-     * assuming the given {@link DataKind} dictates the possible types.
-     */
-    public static EditType getCurrentType(ContentValues entry, DataKind kind) {
-        if (kind.typeColumn == null) return null;
-        final Integer rawValue = entry.getAsInteger(kind.typeColumn);
-        if (rawValue == null) return null;
-        return getType(kind, rawValue);
-    }
-
-    /**
-     * Find the {@link EditType} that describes the given {@link Cursor} row,
-     * assuming the given {@link DataKind} dictates the possible types.
-     */
-    public static EditType getCurrentType(Cursor cursor, DataKind kind) {
-        if (kind.typeColumn == null) return null;
-        final int index = cursor.getColumnIndex(kind.typeColumn);
-        if (index == -1) return null;
-        final int rawValue = cursor.getInt(index);
-        return getType(kind, rawValue);
-    }
-
-    /**
-     * Find the {@link EditType} with the given {@link EditType#rawValue}.
-     */
-    public static EditType getType(DataKind kind, int rawValue) {
-        for (EditType type : kind.typeList) {
-            if (type.rawValue == rawValue) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Return the precedence for the the given {@link EditType#rawValue}, where
-     * lower numbers are higher precedence.
-     */
-    public static int getTypePrecedence(DataKind kind, int rawValue) {
-        for (int i = 0; i < kind.typeList.size(); i++) {
-            final EditType type = kind.typeList.get(i);
-            if (type.rawValue == rawValue) {
-                return i;
-            }
-        }
-        return Integer.MAX_VALUE;
-    }
-
-    /**
-     * Find the best {@link EditType} for a potential insert. The "best" is the
-     * first primary type that doesn't already exist. When all valid types
-     * exist, we pick the last valid option.
-     */
-    public static EditType getBestValidType(RawContactDelta state, DataKind kind,
-            boolean includeSecondary, int exactValue) {
-        // Shortcut when no types
-        if (kind.typeColumn == null) return null;
-
-        // Find type counts and valid primary types, bail if none
-        final SparseIntArray typeCount = getTypeFrequencies(state, kind);
-        final ArrayList<EditType> validTypes = getValidTypes(state, kind, null, includeSecondary,
-                typeCount);
-        if (validTypes.size() == 0) return null;
-
-        // Keep track of the last valid type
-        final EditType lastType = validTypes.get(validTypes.size() - 1);
-
-        // Remove any types that already exist
-        Iterator<EditType> iterator = validTypes.iterator();
-        while (iterator.hasNext()) {
-            final EditType type = iterator.next();
-            final int count = typeCount.get(type.rawValue);
-
-            if (exactValue == type.rawValue) {
-                // Found exact value match
-                return type;
-            }
-
-            if (count > 0) {
-                // Type already appears, so don't consider
-                iterator.remove();
-            }
-        }
-
-        // Use the best remaining, otherwise the last valid
-        if (validTypes.size() > 0) {
-            return validTypes.get(0);
-        } else {
-            return lastType;
-        }
-    }
-
-    /**
-     * Insert a new child of kind {@link DataKind} into the given
-     * {@link RawContactDelta}. Tries using the best {@link EditType} found using
-     * {@link #getBestValidType(RawContactDelta, DataKind, boolean, int)}.
-     */
-    public static ValuesDelta insertChild(RawContactDelta state, DataKind kind) {
-        // First try finding a valid primary
-        EditType bestType = getBestValidType(state, kind, false, Integer.MIN_VALUE);
-        if (bestType == null) {
-            // No valid primary found, so expand search to secondary
-            bestType = getBestValidType(state, kind, true, Integer.MIN_VALUE);
-        }
-        return insertChild(state, kind, bestType);
-    }
-
-    /**
-     * Insert a new child of kind {@link DataKind} into the given
-     * {@link RawContactDelta}, marked with the given {@link EditType}.
-     */
-    public static ValuesDelta insertChild(RawContactDelta state, DataKind kind, EditType type) {
-        // Bail early if invalid kind
-        if (kind == null) return null;
-        final ContentValues after = new ContentValues();
-
-        // Our parent CONTACT_ID is provided later
-        after.put(Data.MIMETYPE, kind.mimeType);
-
-        // Fill-in with any requested default values
-        if (kind.defaultValues != null) {
-            after.putAll(kind.defaultValues);
-        }
-
-        if (kind.typeColumn != null && type != null) {
-            // Set type, if provided
-            after.put(kind.typeColumn, type.rawValue);
-        }
-
-        final ValuesDelta child = ValuesDelta.fromAfter(after);
-        state.addEntry(child);
-        return child;
-    }
-
-    /**
-     * Processing to trim any empty {@link ValuesDelta} and {@link RawContactDelta}
-     * from the given {@link RawContactDeltaList}, assuming the given {@link AccountTypeManager}
-     * dictates the structure for various fields. This method ignores rows not
-     * described by the {@link AccountType}.
-     */
-    public static void trimEmpty(RawContactDeltaList set, AccountTypeManager accountTypes) {
-        for (RawContactDelta state : set) {
-            ValuesDelta values = state.getValues();
-            final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = values.getAsString(RawContacts.DATA_SET);
-            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
-            trimEmpty(state, type);
-        }
-    }
-
-    public static boolean hasChanges(RawContactDeltaList set, AccountTypeManager accountTypes) {
-        if (set.isMarkedForSplitting() || set.isMarkedForJoining()) {
-            return true;
-        }
-
-        for (RawContactDelta state : set) {
-            ValuesDelta values = state.getValues();
-            final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = values.getAsString(RawContacts.DATA_SET);
-            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
-            if (hasChanges(state, type)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Processing to trim any empty {@link ValuesDelta} rows from the given
-     * {@link RawContactDelta}, assuming the given {@link AccountType} dictates
-     * the structure for various fields. This method ignores rows not described
-     * by the {@link AccountType}.
-     */
-    public static void trimEmpty(RawContactDelta state, AccountType accountType) {
-        boolean hasValues = false;
-
-        // Walk through entries for each well-known kind
-        for (DataKind kind : accountType.getSortedDataKinds()) {
-            final String mimeType = kind.mimeType;
-            final ArrayList<ValuesDelta> entries = state.getMimeEntries(mimeType);
-            if (entries == null) continue;
-
-            for (ValuesDelta entry : entries) {
-                // Skip any values that haven't been touched
-                final boolean touched = entry.isInsert() || entry.isUpdate();
-                if (!touched) {
-                    hasValues = true;
-                    continue;
-                }
-
-                // Test and remove this row if empty and it isn't a photo from google
-                final boolean isGoogleAccount = TextUtils.equals(GoogleAccountType.ACCOUNT_TYPE,
-                        state.getValues().getAsString(RawContacts.ACCOUNT_TYPE));
-                final boolean isPhoto = TextUtils.equals(Photo.CONTENT_ITEM_TYPE, kind.mimeType);
-                final boolean isGooglePhoto = isPhoto && isGoogleAccount;
-
-                if (RawContactModifier.isEmpty(entry, kind) && !isGooglePhoto) {
-                    if (DEBUG) {
-                        Log.v(TAG, "Trimming: " + entry.toString());
-                    }
-                    entry.markDeleted();
-                } else if (!entry.isFromTemplate()) {
-                    hasValues = true;
-                }
-            }
-        }
-        if (!hasValues) {
-            // Trim overall entity if no children exist
-            state.markDeleted();
-        }
-    }
-
-    private static boolean hasChanges(RawContactDelta state, AccountType accountType) {
-        for (DataKind kind : accountType.getSortedDataKinds()) {
-            final String mimeType = kind.mimeType;
-            final ArrayList<ValuesDelta> entries = state.getMimeEntries(mimeType);
-            if (entries == null) continue;
-
-            for (ValuesDelta entry : entries) {
-                // An empty Insert must be ignored, because it won't save anything (an example
-                // is an empty name that stays empty)
-                final boolean isRealInsert = entry.isInsert() && !isEmpty(entry, kind);
-                if (isRealInsert || entry.isUpdate() || entry.isDelete()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Test if the given {@link ValuesDelta} would be considered "empty" in
-     * terms of {@link DataKind#fieldList}.
-     */
-    public static boolean isEmpty(ValuesDelta values, DataKind kind) {
-        if (Photo.CONTENT_ITEM_TYPE.equals(kind.mimeType)) {
-            return values.isInsert() && values.getAsByteArray(Photo.PHOTO) == null;
-        }
-
-        // No defined fields mean this row is always empty
-        if (kind.fieldList == null) return true;
-
-        for (EditField field : kind.fieldList) {
-            // If any field has values, we're not empty
-            final String value = values.getAsString(field.column);
-            if (ContactsUtils.isGraphic(value)) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Compares corresponding fields in values1 and values2. Only the fields
-     * declared by the DataKind are taken into consideration.
-     */
-    protected static boolean areEqual(ValuesDelta values1, ContentValues values2, DataKind kind) {
-        if (kind.fieldList == null) return false;
-
-        for (EditField field : kind.fieldList) {
-            final String value1 = values1.getAsString(field.column);
-            final String value2 = values2.getAsString(field.column);
-            if (!TextUtils.equals(value1, value2)) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Parse the given {@link Bundle} into the given {@link RawContactDelta} state,
-     * assuming the extras defined through {@link Intents}.
-     */
-    public static void parseExtras(Context context, AccountType accountType, RawContactDelta state,
-            Bundle extras) {
-        if (extras == null || extras.size() == 0) {
-            // Bail early if no useful data
-            return;
-        }
-
-        parseStructuredNameExtra(context, accountType, state, extras);
-        parseStructuredPostalExtra(accountType, state, extras);
-
-        {
-            // Phone
-            final DataKind kind = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-            parseExtras(state, kind, extras, Insert.PHONE_TYPE, Insert.PHONE, Phone.NUMBER);
-            parseExtras(state, kind, extras, Insert.SECONDARY_PHONE_TYPE, Insert.SECONDARY_PHONE,
-                    Phone.NUMBER);
-            parseExtras(state, kind, extras, Insert.TERTIARY_PHONE_TYPE, Insert.TERTIARY_PHONE,
-                    Phone.NUMBER);
-        }
-
-        {
-            // Email
-            final DataKind kind = accountType.getKindForMimetype(Email.CONTENT_ITEM_TYPE);
-            parseExtras(state, kind, extras, Insert.EMAIL_TYPE, Insert.EMAIL, Email.DATA);
-            parseExtras(state, kind, extras, Insert.SECONDARY_EMAIL_TYPE, Insert.SECONDARY_EMAIL,
-                    Email.DATA);
-            parseExtras(state, kind, extras, Insert.TERTIARY_EMAIL_TYPE, Insert.TERTIARY_EMAIL,
-                    Email.DATA);
-        }
-
-        {
-            // Im
-            final DataKind kind = accountType.getKindForMimetype(Im.CONTENT_ITEM_TYPE);
-            fixupLegacyImType(extras);
-            parseExtras(state, kind, extras, Insert.IM_PROTOCOL, Insert.IM_HANDLE, Im.DATA);
-        }
-
-        // Organization
-        final boolean hasOrg = extras.containsKey(Insert.COMPANY)
-                || extras.containsKey(Insert.JOB_TITLE);
-        final DataKind kindOrg = accountType.getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
-        if (hasOrg && RawContactModifier.canInsert(state, kindOrg)) {
-            final ValuesDelta child = RawContactModifier.insertChild(state, kindOrg);
-
-            final String company = extras.getString(Insert.COMPANY);
-            if (ContactsUtils.isGraphic(company)) {
-                child.put(Organization.COMPANY, company);
-            }
-
-            final String title = extras.getString(Insert.JOB_TITLE);
-            if (ContactsUtils.isGraphic(title)) {
-                child.put(Organization.TITLE, title);
-            }
-        }
-
-        // Notes
-        final boolean hasNotes = extras.containsKey(Insert.NOTES);
-        final DataKind kindNotes = accountType.getKindForMimetype(Note.CONTENT_ITEM_TYPE);
-        if (hasNotes && RawContactModifier.canInsert(state, kindNotes)) {
-            final ValuesDelta child = RawContactModifier.insertChild(state, kindNotes);
-
-            final String notes = extras.getString(Insert.NOTES);
-            if (ContactsUtils.isGraphic(notes)) {
-                child.put(Note.NOTE, notes);
-            }
-        }
-
-        // Arbitrary additional data
-        ArrayList<ContentValues> values = extras.getParcelableArrayList(Insert.DATA);
-        if (values != null) {
-            parseValues(state, accountType, values);
-        }
-    }
-
-    private static void parseStructuredNameExtra(
-            Context context, AccountType accountType, RawContactDelta state, Bundle extras) {
-        // StructuredName
-        RawContactModifier.ensureKindExists(state, accountType, StructuredName.CONTENT_ITEM_TYPE);
-        final ValuesDelta child = state.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
-
-        final String name = extras.getString(Insert.NAME);
-        if (ContactsUtils.isGraphic(name)) {
-            final DataKind kind = accountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
-            boolean supportsDisplayName = false;
-            if (kind.fieldList != null) {
-                for (EditField field : kind.fieldList) {
-                    if (StructuredName.DISPLAY_NAME.equals(field.column)) {
-                        supportsDisplayName = true;
-                        break;
-                    }
-                }
-            }
-
-            if (supportsDisplayName) {
-                child.put(StructuredName.DISPLAY_NAME, name);
-            } else {
-                Uri uri = ContactsContract.AUTHORITY_URI.buildUpon()
-                        .appendPath("complete_name")
-                        .appendQueryParameter(StructuredName.DISPLAY_NAME, name)
-                        .build();
-                Cursor cursor = context.getContentResolver().query(uri,
-                        new String[]{
-                                StructuredName.PREFIX,
-                                StructuredName.GIVEN_NAME,
-                                StructuredName.MIDDLE_NAME,
-                                StructuredName.FAMILY_NAME,
-                                StructuredName.SUFFIX,
-                        }, null, null, null);
-
-                try {
-                    if (cursor.moveToFirst()) {
-                        child.put(StructuredName.PREFIX, cursor.getString(0));
-                        child.put(StructuredName.GIVEN_NAME, cursor.getString(1));
-                        child.put(StructuredName.MIDDLE_NAME, cursor.getString(2));
-                        child.put(StructuredName.FAMILY_NAME, cursor.getString(3));
-                        child.put(StructuredName.SUFFIX, cursor.getString(4));
-                    }
-                } finally {
-                    cursor.close();
-                }
-            }
-        }
-
-        final String phoneticName = extras.getString(Insert.PHONETIC_NAME);
-        if (ContactsUtils.isGraphic(phoneticName)) {
-            child.put(StructuredName.PHONETIC_GIVEN_NAME, phoneticName);
-        }
-    }
-
-    private static void parseStructuredPostalExtra(
-            AccountType accountType, RawContactDelta state, Bundle extras) {
-        // StructuredPostal
-        final DataKind kind = accountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
-        final ValuesDelta child = parseExtras(state, kind, extras, Insert.POSTAL_TYPE,
-                Insert.POSTAL, StructuredPostal.FORMATTED_ADDRESS);
-        String address = child == null ? null
-                : child.getAsString(StructuredPostal.FORMATTED_ADDRESS);
-        if (!TextUtils.isEmpty(address)) {
-            boolean supportsFormatted = false;
-            if (kind.fieldList != null) {
-                for (EditField field : kind.fieldList) {
-                    if (StructuredPostal.FORMATTED_ADDRESS.equals(field.column)) {
-                        supportsFormatted = true;
-                        break;
-                    }
-                }
-            }
-
-            if (!supportsFormatted) {
-                child.put(StructuredPostal.STREET, address);
-                child.putNull(StructuredPostal.FORMATTED_ADDRESS);
-            }
-        }
-    }
-
-    private static void parseValues(
-            RawContactDelta state, AccountType accountType,
-            ArrayList<ContentValues> dataValueList) {
-        for (ContentValues values : dataValueList) {
-            String mimeType = values.getAsString(Data.MIMETYPE);
-            if (TextUtils.isEmpty(mimeType)) {
-                Log.e(TAG, "Mimetype is required. Ignoring: " + values);
-                continue;
-            }
-
-            // Won't override the contact name
-            if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                continue;
-            } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                values.remove(PhoneDataItem.KEY_FORMATTED_PHONE_NUMBER);
-                final Integer type = values.getAsInteger(Phone.TYPE);
-                // If the provided phone number provides a custom phone type but not a label,
-                // replace it with mobile (by default) to avoid the "Enter custom label" from
-                // popping up immediately upon entering the ContactEditorFragment
-                if (type != null && type == Phone.TYPE_CUSTOM &&
-                        TextUtils.isEmpty(values.getAsString(Phone.LABEL))) {
-                    values.put(Phone.TYPE, Phone.TYPE_MOBILE);
-                }
-            }
-
-            DataKind kind = accountType.getKindForMimetype(mimeType);
-            if (kind == null) {
-                Log.e(TAG, "Mimetype not supported for account type "
-                        + accountType.getAccountTypeAndDataSet() + ". Ignoring: " + values);
-                continue;
-            }
-
-            ValuesDelta entry = ValuesDelta.fromAfter(values);
-            if (isEmpty(entry, kind)) {
-                continue;
-            }
-
-            ArrayList<ValuesDelta> entries = state.getMimeEntries(mimeType);
-
-            if ((kind.typeOverallMax != 1) || GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                // Check for duplicates
-                boolean addEntry = true;
-                int count = 0;
-                if (entries != null && entries.size() > 0) {
-                    for (ValuesDelta delta : entries) {
-                        if (!delta.isDelete()) {
-                            if (areEqual(delta, values, kind)) {
-                                addEntry = false;
-                                break;
-                            }
-                            count++;
-                        }
-                    }
-                }
-
-                if (kind.typeOverallMax != -1 && count >= kind.typeOverallMax) {
-                    Log.e(TAG, "Mimetype allows at most " + kind.typeOverallMax
-                            + " entries. Ignoring: " + values);
-                    addEntry = false;
-                }
-
-                if (addEntry) {
-                    addEntry = adjustType(entry, entries, kind);
-                }
-
-                if (addEntry) {
-                    state.addEntry(entry);
-                }
-            } else {
-                // Non-list entries should not be overridden
-                boolean addEntry = true;
-                if (entries != null && entries.size() > 0) {
-                    for (ValuesDelta delta : entries) {
-                        if (!delta.isDelete() && !isEmpty(delta, kind)) {
-                            addEntry = false;
-                            break;
-                        }
-                    }
-                    if (addEntry) {
-                        for (ValuesDelta delta : entries) {
-                            delta.markDeleted();
-                        }
-                    }
-                }
-
-                if (addEntry) {
-                    addEntry = adjustType(entry, entries, kind);
-                }
-
-                if (addEntry) {
-                    state.addEntry(entry);
-                } else if (Note.CONTENT_ITEM_TYPE.equals(mimeType)){
-                    // Note is most likely to contain large amounts of text
-                    // that we don't want to drop on the ground.
-                    for (ValuesDelta delta : entries) {
-                        if (!isEmpty(delta, kind)) {
-                            delta.put(Note.NOTE, delta.getAsString(Note.NOTE) + "\n"
-                                    + values.getAsString(Note.NOTE));
-                            break;
-                        }
-                    }
-                } else {
-                    Log.e(TAG, "Will not override mimetype " + mimeType + ". Ignoring: "
-                            + values);
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks if the data kind allows addition of another entry (e.g. Exchange only
-     * supports two "work" phone numbers).  If not, tries to switch to one of the
-     * unused types.  If successful, returns true.
-     */
-    private static boolean adjustType(
-            ValuesDelta entry, ArrayList<ValuesDelta> entries, DataKind kind) {
-        if (kind.typeColumn == null || kind.typeList == null || kind.typeList.size() == 0) {
-            return true;
-        }
-
-        Integer typeInteger = entry.getAsInteger(kind.typeColumn);
-        int type = typeInteger != null ? typeInteger : kind.typeList.get(0).rawValue;
-
-        if (isTypeAllowed(type, entries, kind)) {
-            entry.put(kind.typeColumn, type);
-            return true;
-        }
-
-        // Specified type is not allowed - choose the first available type that is allowed
-        int size = kind.typeList.size();
-        for (int i = 0; i < size; i++) {
-            EditType editType = kind.typeList.get(i);
-            if (isTypeAllowed(editType.rawValue, entries, kind)) {
-                entry.put(kind.typeColumn, editType.rawValue);
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Checks if a new entry of the specified type can be added to the raw
-     * contact. For example, Exchange only supports two "work" phone numbers, so
-     * addition of a third would not be allowed.
-     */
-    private static boolean isTypeAllowed(int type, ArrayList<ValuesDelta> entries, DataKind kind) {
-        int max = 0;
-        int size = kind.typeList.size();
-        for (int i = 0; i < size; i++) {
-            EditType editType = kind.typeList.get(i);
-            if (editType.rawValue == type) {
-                max = editType.specificMax;
-                break;
-            }
-        }
-
-        if (max == 0) {
-            // This type is not allowed at all
-            return false;
-        }
-
-        if (max == -1) {
-            // Unlimited instances of this type are allowed
-            return true;
-        }
-
-        return getEntryCountByType(entries, kind.typeColumn, type) < max;
-    }
-
-    /**
-     * Counts occurrences of the specified type in the supplied entry list.
-     *
-     * @return The count of occurrences of the type in the entry list. 0 if entries is
-     * {@literal null}
-     */
-    private static int getEntryCountByType(ArrayList<ValuesDelta> entries, String typeColumn,
-            int type) {
-        int count = 0;
-        if (entries != null) {
-            for (ValuesDelta entry : entries) {
-                Integer typeInteger = entry.getAsInteger(typeColumn);
-                if (typeInteger != null && typeInteger == type) {
-                    count++;
-                }
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Attempt to parse legacy {@link Insert#IM_PROTOCOL} values, replacing them
-     * with updated values.
-     */
-    @SuppressWarnings("deprecation")
-    private static void fixupLegacyImType(Bundle bundle) {
-        final String encodedString = bundle.getString(Insert.IM_PROTOCOL);
-        if (encodedString == null) return;
-
-        try {
-            final Object protocol = android.provider.Contacts.ContactMethods
-                    .decodeImProtocol(encodedString);
-            if (protocol instanceof Integer) {
-                bundle.putInt(Insert.IM_PROTOCOL, (Integer)protocol);
-            } else {
-                bundle.putString(Insert.IM_PROTOCOL, (String)protocol);
-            }
-        } catch (IllegalArgumentException e) {
-            // Ignore exception when legacy parser fails
-        }
-    }
-
-    /**
-     * Parse a specific entry from the given {@link Bundle} and insert into the
-     * given {@link RawContactDelta}. Silently skips the insert when missing value
-     * or no valid {@link EditType} found.
-     *
-     * @param typeExtra {@link Bundle} key that holds the incoming
-     *            {@link EditType#rawValue} value.
-     * @param valueExtra {@link Bundle} key that holds the incoming value.
-     * @param valueColumn Column to write value into {@link ValuesDelta}.
-     */
-    public static ValuesDelta parseExtras(RawContactDelta state, DataKind kind, Bundle extras,
-            String typeExtra, String valueExtra, String valueColumn) {
-        final CharSequence value = extras.getCharSequence(valueExtra);
-
-        // Bail early if account type doesn't handle this MIME type
-        if (kind == null) return null;
-
-        // Bail when can't insert type, or value missing
-        final boolean canInsert = RawContactModifier.canInsert(state, kind);
-        final boolean validValue = (value != null && TextUtils.isGraphic(value));
-        if (!validValue || !canInsert) return null;
-
-        // Find exact type when requested, otherwise best available type
-        final boolean hasType = extras.containsKey(typeExtra);
-        final int typeValue = extras.getInt(typeExtra, hasType ? BaseTypes.TYPE_CUSTOM
-                : Integer.MIN_VALUE);
-        final EditType editType = RawContactModifier.getBestValidType(state, kind, true, typeValue);
-
-        // Create data row and fill with value
-        final ValuesDelta child = RawContactModifier.insertChild(state, kind, editType);
-        child.put(valueColumn, value.toString());
-
-        if (editType != null && editType.customColumn != null) {
-            // Write down label when custom type picked
-            final String customType = extras.getString(typeExtra);
-            child.put(editType.customColumn, customType);
-        }
-
-        return child;
-    }
-
-    /**
-     * Generic mime types with type support (e.g. TYPE_HOME).
-     * Here, "type support" means if the data kind has CommonColumns#TYPE or not. Data kinds which
-     * have their own migrate methods aren't listed here.
-     */
-    private static final Set<String> sGenericMimeTypesWithTypeSupport = new HashSet<String>(
-            Arrays.asList(Phone.CONTENT_ITEM_TYPE,
-                    Email.CONTENT_ITEM_TYPE,
-                    Im.CONTENT_ITEM_TYPE,
-                    Nickname.CONTENT_ITEM_TYPE,
-                    Website.CONTENT_ITEM_TYPE,
-                    Relation.CONTENT_ITEM_TYPE,
-                    SipAddress.CONTENT_ITEM_TYPE));
-    private static final Set<String> sGenericMimeTypesWithoutTypeSupport = new HashSet<String>(
-            Arrays.asList(Organization.CONTENT_ITEM_TYPE,
-                    Note.CONTENT_ITEM_TYPE,
-                    Photo.CONTENT_ITEM_TYPE,
-                    GroupMembership.CONTENT_ITEM_TYPE));
-    // CommonColumns.TYPE cannot be accessed as it is protected interface, so use
-    // Phone.TYPE instead.
-    private static final String COLUMN_FOR_TYPE  = Phone.TYPE;
-    private static final String COLUMN_FOR_LABEL  = Phone.LABEL;
-    private static final int TYPE_CUSTOM = Phone.TYPE_CUSTOM;
-
-    /**
-     * Migrates old RawContactDelta to newly created one with a new restriction supplied from
-     * newAccountType.
-     *
-     * This is only for account switch during account creation (which must be insert operation).
-     */
-    public static void migrateStateForNewContact(Context context,
-            RawContactDelta oldState, RawContactDelta newState,
-            AccountType oldAccountType, AccountType newAccountType) {
-        if (newAccountType == oldAccountType) {
-            // Just copying all data in oldState isn't enough, but we can still rely on a lot of
-            // shortcuts.
-            for (DataKind kind : newAccountType.getSortedDataKinds()) {
-                final String mimeType = kind.mimeType;
-                // The fields with short/long form capability must be treated properly.
-                if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    migrateStructuredName(context, oldState, newState, kind);
-                } else {
-                    List<ValuesDelta> entryList = oldState.getMimeEntries(mimeType);
-                    if (entryList != null && !entryList.isEmpty()) {
-                        for (ValuesDelta entry : entryList) {
-                            ContentValues values = entry.getAfter();
-                            if (values != null) {
-                                newState.addEntry(ValuesDelta.fromAfter(values));
-                            }
-                        }
-                    }
-                }
-            }
-        } else {
-            // Migrate data supported by the new account type.
-            // All the other data inside oldState are silently dropped.
-            for (DataKind kind : newAccountType.getSortedDataKinds()) {
-                if (!kind.editable) continue;
-                final String mimeType = kind.mimeType;
-                if (DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME.equals(mimeType)
-                        || DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(mimeType)) {
-                    // Ignore pseudo data.
-                    continue;
-                } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    migrateStructuredName(context, oldState, newState, kind);
-                } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    migratePostal(oldState, newState, kind);
-                } else if (Event.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    migrateEvent(oldState, newState, kind, null /* default Year */);
-                } else if (sGenericMimeTypesWithoutTypeSupport.contains(mimeType)) {
-                    migrateGenericWithoutTypeColumn(oldState, newState, kind);
-                } else if (sGenericMimeTypesWithTypeSupport.contains(mimeType)) {
-                    migrateGenericWithTypeColumn(oldState, newState, kind);
-                } else {
-                    throw new IllegalStateException("Unexpected editable mime-type: " + mimeType);
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks {@link DataKind#isList} and {@link DataKind#typeOverallMax}, and restricts
-     * the number of entries (ValuesDelta) inside newState.
-     */
-    private static ArrayList<ValuesDelta> ensureEntryMaxSize(RawContactDelta newState,
-            DataKind kind, ArrayList<ValuesDelta> mimeEntries) {
-        if (mimeEntries == null) {
-            return null;
-        }
-
-        final int typeOverallMax = kind.typeOverallMax;
-        if (typeOverallMax >= 0 && (mimeEntries.size() > typeOverallMax)) {
-            ArrayList<ValuesDelta> newMimeEntries = new ArrayList<ValuesDelta>(typeOverallMax);
-            for (int i = 0; i < typeOverallMax; i++) {
-                newMimeEntries.add(mimeEntries.get(i));
-            }
-            mimeEntries = newMimeEntries;
-        }
-        return mimeEntries;
-    }
-
-    /** @hide Public only for testing. */
-    public static void migrateStructuredName(
-            Context context, RawContactDelta oldState, RawContactDelta newState,
-            DataKind newDataKind) {
-        final ContentValues values =
-                oldState.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE).getAfter();
-        if (values == null) {
-            return;
-        }
-
-        boolean supportDisplayName = false;
-        boolean supportPhoneticFullName = false;
-        boolean supportPhoneticFamilyName = false;
-        boolean supportPhoneticMiddleName = false;
-        boolean supportPhoneticGivenName = false;
-        for (EditField editField : newDataKind.fieldList) {
-            if (StructuredName.DISPLAY_NAME.equals(editField.column)) {
-                supportDisplayName = true;
-            }
-            if (DataKind.PSEUDO_COLUMN_PHONETIC_NAME.equals(editField.column)) {
-                supportPhoneticFullName = true;
-            }
-            if (StructuredName.PHONETIC_FAMILY_NAME.equals(editField.column)) {
-                supportPhoneticFamilyName = true;
-            }
-            if (StructuredName.PHONETIC_MIDDLE_NAME.equals(editField.column)) {
-                supportPhoneticMiddleName = true;
-            }
-            if (StructuredName.PHONETIC_GIVEN_NAME.equals(editField.column)) {
-                supportPhoneticGivenName = true;
-            }
-        }
-
-        // DISPLAY_NAME <-> PREFIX, GIVEN_NAME, MIDDLE_NAME, FAMILY_NAME, SUFFIX
-        final String displayName = values.getAsString(StructuredName.DISPLAY_NAME);
-        if (!TextUtils.isEmpty(displayName)) {
-            if (!supportDisplayName) {
-                // Old data has a display name, while the new account doesn't allow it.
-                NameConverter.displayNameToStructuredName(context, displayName, values);
-
-                // We don't want to migrate unseen data which may confuse users after the creation.
-                values.remove(StructuredName.DISPLAY_NAME);
-            }
-        } else {
-            if (supportDisplayName) {
-                // Old data does not have display name, while the new account requires it.
-                values.put(StructuredName.DISPLAY_NAME,
-                        NameConverter.structuredNameToDisplayName(context, values));
-                for (String field : NameConverter.STRUCTURED_NAME_FIELDS) {
-                    values.remove(field);
-                }
-            }
-        }
-
-        // Phonetic (full) name <-> PHONETIC_FAMILY_NAME, PHONETIC_MIDDLE_NAME, PHONETIC_GIVEN_NAME
-        final String phoneticFullName = values.getAsString(DataKind.PSEUDO_COLUMN_PHONETIC_NAME);
-        if (!TextUtils.isEmpty(phoneticFullName)) {
-            if (!supportPhoneticFullName) {
-                // Old data has a phonetic (full) name, while the new account doesn't allow it.
-                final StructuredNameDataItem tmpItem =
-                        PhoneticNameEditorView.parsePhoneticName(phoneticFullName, null);
-                values.remove(DataKind.PSEUDO_COLUMN_PHONETIC_NAME);
-                if (supportPhoneticFamilyName) {
-                    values.put(StructuredName.PHONETIC_FAMILY_NAME,
-                            tmpItem.getPhoneticFamilyName());
-                } else {
-                    values.remove(StructuredName.PHONETIC_FAMILY_NAME);
-                }
-                if (supportPhoneticMiddleName) {
-                    values.put(StructuredName.PHONETIC_MIDDLE_NAME,
-                            tmpItem.getPhoneticMiddleName());
-                } else {
-                    values.remove(StructuredName.PHONETIC_MIDDLE_NAME);
-                }
-                if (supportPhoneticGivenName) {
-                    values.put(StructuredName.PHONETIC_GIVEN_NAME,
-                            tmpItem.getPhoneticGivenName());
-                } else {
-                    values.remove(StructuredName.PHONETIC_GIVEN_NAME);
-                }
-            }
-        } else {
-            if (supportPhoneticFullName) {
-                // Old data does not have a phonetic (full) name, while the new account requires it.
-                values.put(DataKind.PSEUDO_COLUMN_PHONETIC_NAME,
-                        PhoneticNameEditorView.buildPhoneticName(
-                                values.getAsString(StructuredName.PHONETIC_FAMILY_NAME),
-                                values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME),
-                                values.getAsString(StructuredName.PHONETIC_GIVEN_NAME)));
-            }
-            if (!supportPhoneticFamilyName) {
-                values.remove(StructuredName.PHONETIC_FAMILY_NAME);
-            }
-            if (!supportPhoneticMiddleName) {
-                values.remove(StructuredName.PHONETIC_MIDDLE_NAME);
-            }
-            if (!supportPhoneticGivenName) {
-                values.remove(StructuredName.PHONETIC_GIVEN_NAME);
-            }
-        }
-
-        newState.addEntry(ValuesDelta.fromAfter(values));
-    }
-
-    /** @hide Public only for testing. */
-    public static void migratePostal(RawContactDelta oldState, RawContactDelta newState,
-            DataKind newDataKind) {
-        final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
-                oldState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE));
-        if (mimeEntries == null || mimeEntries.isEmpty()) {
-            return;
-        }
-
-        boolean supportFormattedAddress = false;
-        boolean supportStreet = false;
-        final String firstColumn = newDataKind.fieldList.get(0).column;
-        for (EditField editField : newDataKind.fieldList) {
-            if (StructuredPostal.FORMATTED_ADDRESS.equals(editField.column)) {
-                supportFormattedAddress = true;
-            }
-            if (StructuredPostal.STREET.equals(editField.column)) {
-                supportStreet = true;
-            }
-        }
-
-        final Set<Integer> supportedTypes = new HashSet<Integer>();
-        if (newDataKind.typeList != null && !newDataKind.typeList.isEmpty()) {
-            for (EditType editType : newDataKind.typeList) {
-                supportedTypes.add(editType.rawValue);
-            }
-        }
-
-        for (ValuesDelta entry : mimeEntries) {
-            final ContentValues values = entry.getAfter();
-            if (values == null) {
-                continue;
-            }
-            final Integer oldType = values.getAsInteger(StructuredPostal.TYPE);
-            if (!supportedTypes.contains(oldType)) {
-                int defaultType;
-                if (newDataKind.defaultValues != null) {
-                    defaultType = newDataKind.defaultValues.getAsInteger(StructuredPostal.TYPE);
-                } else {
-                    defaultType = newDataKind.typeList.get(0).rawValue;
-                }
-                values.put(StructuredPostal.TYPE, defaultType);
-                if (oldType != null && oldType == StructuredPostal.TYPE_CUSTOM) {
-                    values.remove(StructuredPostal.LABEL);
-                }
-            }
-
-            final String formattedAddress = values.getAsString(StructuredPostal.FORMATTED_ADDRESS);
-            if (!TextUtils.isEmpty(formattedAddress)) {
-                if (!supportFormattedAddress) {
-                    // Old data has a formatted address, while the new account doesn't allow it.
-                    values.remove(StructuredPostal.FORMATTED_ADDRESS);
-
-                    // Unlike StructuredName we don't have logic to split it, so first
-                    // try to use street field and. If the new account doesn't have one,
-                    // then select first one anyway.
-                    if (supportStreet) {
-                        values.put(StructuredPostal.STREET, formattedAddress);
-                    } else {
-                        values.put(firstColumn, formattedAddress);
-                    }
-                }
-            } else {
-                if (supportFormattedAddress) {
-                    // Old data does not have formatted address, while the new account requires it.
-                    // Unlike StructuredName we don't have logic to join multiple address values.
-                    // Use poor join heuristics for now.
-                    String[] structuredData;
-                    final boolean useJapaneseOrder =
-                            Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage());
-                    if (useJapaneseOrder) {
-                        structuredData = new String[] {
-                                values.getAsString(StructuredPostal.COUNTRY),
-                                values.getAsString(StructuredPostal.POSTCODE),
-                                values.getAsString(StructuredPostal.REGION),
-                                values.getAsString(StructuredPostal.CITY),
-                                values.getAsString(StructuredPostal.NEIGHBORHOOD),
-                                values.getAsString(StructuredPostal.STREET),
-                                values.getAsString(StructuredPostal.POBOX) };
-                    } else {
-                        structuredData = new String[] {
-                                values.getAsString(StructuredPostal.POBOX),
-                                values.getAsString(StructuredPostal.STREET),
-                                values.getAsString(StructuredPostal.NEIGHBORHOOD),
-                                values.getAsString(StructuredPostal.CITY),
-                                values.getAsString(StructuredPostal.REGION),
-                                values.getAsString(StructuredPostal.POSTCODE),
-                                values.getAsString(StructuredPostal.COUNTRY) };
-                    }
-                    final StringBuilder builder = new StringBuilder();
-                    for (String elem : structuredData) {
-                        if (!TextUtils.isEmpty(elem)) {
-                            builder.append(elem + "\n");
-                        }
-                    }
-                    values.put(StructuredPostal.FORMATTED_ADDRESS, builder.toString());
-
-                    values.remove(StructuredPostal.POBOX);
-                    values.remove(StructuredPostal.STREET);
-                    values.remove(StructuredPostal.NEIGHBORHOOD);
-                    values.remove(StructuredPostal.CITY);
-                    values.remove(StructuredPostal.REGION);
-                    values.remove(StructuredPostal.POSTCODE);
-                    values.remove(StructuredPostal.COUNTRY);
-                }
-            }
-
-            newState.addEntry(ValuesDelta.fromAfter(values));
-        }
-    }
-
-    /** @hide Public only for testing. */
-    public static void migrateEvent(RawContactDelta oldState, RawContactDelta newState,
-            DataKind newDataKind, Integer defaultYear) {
-        final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
-                oldState.getMimeEntries(Event.CONTENT_ITEM_TYPE));
-        if (mimeEntries == null || mimeEntries.isEmpty()) {
-            return;
-        }
-
-        final SparseArray<EventEditType> allowedTypes = new SparseArray<EventEditType>();
-        for (EditType editType : newDataKind.typeList) {
-            allowedTypes.put(editType.rawValue, (EventEditType) editType);
-        }
-        for (ValuesDelta entry : mimeEntries) {
-            final ContentValues values = entry.getAfter();
-            if (values == null) {
-                continue;
-            }
-            final String dateString = values.getAsString(Event.START_DATE);
-            final Integer type = values.getAsInteger(Event.TYPE);
-            if (type != null && (allowedTypes.indexOfKey(type) >= 0)
-                    && !TextUtils.isEmpty(dateString)) {
-                EventEditType suitableType = allowedTypes.get(type);
-
-                final ParsePosition position = new ParsePosition(0);
-                boolean yearOptional = false;
-                Date date = CommonDateUtils.DATE_AND_TIME_FORMAT.parse(dateString, position);
-                if (date == null) {
-                    yearOptional = true;
-                    date = CommonDateUtils.NO_YEAR_DATE_FORMAT.parse(dateString, position);
-                }
-                if (date != null) {
-                    if (yearOptional && !suitableType.isYearOptional()) {
-                        // The new EditType doesn't allow optional year. Supply default.
-                        final Calendar calendar = Calendar.getInstance(DateUtils.UTC_TIMEZONE,
-                                Locale.US);
-                        if (defaultYear == null) {
-                            defaultYear = calendar.get(Calendar.YEAR);
-                        }
-                        calendar.setTime(date);
-                        final int month = calendar.get(Calendar.MONTH);
-                        final int day = calendar.get(Calendar.DAY_OF_MONTH);
-                        // Exchange requires 8:00 for birthdays
-                        calendar.set(defaultYear, month, day,
-                                EventFieldEditorView.getDefaultHourForBirthday(), 0, 0);
-                        values.put(Event.START_DATE,
-                                CommonDateUtils.FULL_DATE_FORMAT.format(calendar.getTime()));
-                    }
-                }
-                newState.addEntry(ValuesDelta.fromAfter(values));
-            } else {
-                // Just drop it.
-            }
-        }
-    }
-
-    /** @hide Public only for testing. */
-    public static void migrateGenericWithoutTypeColumn(
-            RawContactDelta oldState, RawContactDelta newState, DataKind newDataKind) {
-        final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
-                oldState.getMimeEntries(newDataKind.mimeType));
-        if (mimeEntries == null || mimeEntries.isEmpty()) {
-            return;
-        }
-
-        for (ValuesDelta entry : mimeEntries) {
-            ContentValues values = entry.getAfter();
-            if (values != null) {
-                newState.addEntry(ValuesDelta.fromAfter(values));
-            }
-        }
-    }
-
-    /** @hide Public only for testing. */
-    public static void migrateGenericWithTypeColumn(
-            RawContactDelta oldState, RawContactDelta newState, DataKind newDataKind) {
-        final ArrayList<ValuesDelta> mimeEntries = oldState.getMimeEntries(newDataKind.mimeType);
-        if (mimeEntries == null || mimeEntries.isEmpty()) {
-            return;
-        }
-
-        // Note that type specified with the old account may be invalid with the new account, while
-        // we want to preserve its data as much as possible. e.g. if a user typed a phone number
-        // with a type which is valid with an old account but not with a new account, the user
-        // probably wants to have the number with default type, rather than seeing complete data
-        // loss.
-        //
-        // Specifically, this method works as follows:
-        // 1. detect defaultType
-        // 2. prepare constants & variables for iteration
-        // 3. iterate over mimeEntries:
-        // 3.1 stop iteration if total number of mimeEntries reached typeOverallMax specified in
-        //     DataKind
-        // 3.2 replace unallowed types with defaultType
-        // 3.3 check if the number of entries is below specificMax specified in AccountType
-
-        // Here, defaultType can be supplied in two ways
-        // - via kind.defaultValues
-        // - via kind.typeList.get(0).rawValue
-        Integer defaultType = null;
-        if (newDataKind.defaultValues != null) {
-            defaultType = newDataKind.defaultValues.getAsInteger(COLUMN_FOR_TYPE);
-        }
-        final Set<Integer> allowedTypes = new HashSet<Integer>();
-        // key: type, value: the number of entries allowed for the type (specificMax)
-        final SparseIntArray typeSpecificMaxMap = new SparseIntArray();
-        if (defaultType != null) {
-            allowedTypes.add(defaultType);
-            typeSpecificMaxMap.put(defaultType, -1);
-        }
-        // Note: typeList may be used in different purposes when defaultValues are specified.
-        // Especially in IM, typeList contains available protocols (e.g. PROTOCOL_GOOGLE_TALK)
-        // instead of "types" which we want to treate here (e.g. TYPE_HOME). So we don't add
-        // anything other than defaultType into allowedTypes and typeSpecificMapMax.
-        if (!Im.CONTENT_ITEM_TYPE.equals(newDataKind.mimeType) &&
-                newDataKind.typeList != null && !newDataKind.typeList.isEmpty()) {
-            for (EditType editType : newDataKind.typeList) {
-                allowedTypes.add(editType.rawValue);
-                typeSpecificMaxMap.put(editType.rawValue, editType.specificMax);
-            }
-            if (defaultType == null) {
-                defaultType = newDataKind.typeList.get(0).rawValue;
-            }
-        }
-
-        if (defaultType == null) {
-            Log.w(TAG, "Default type isn't available for mimetype " + newDataKind.mimeType);
-        }
-
-        final int typeOverallMax = newDataKind.typeOverallMax;
-
-        // key: type, value: the number of current entries.
-        final SparseIntArray currentEntryCount = new SparseIntArray();
-        int totalCount = 0;
-
-        for (ValuesDelta entry : mimeEntries) {
-            if (typeOverallMax != -1 && totalCount >= typeOverallMax) {
-                break;
-            }
-
-            final ContentValues values = entry.getAfter();
-            if (values == null) {
-                continue;
-            }
-
-            final Integer oldType = entry.getAsInteger(COLUMN_FOR_TYPE);
-            final Integer typeForNewAccount;
-            if (!allowedTypes.contains(oldType)) {
-                // The new account doesn't support the type.
-                if (defaultType != null) {
-                    typeForNewAccount = defaultType.intValue();
-                    values.put(COLUMN_FOR_TYPE, defaultType.intValue());
-                    if (oldType != null && oldType == TYPE_CUSTOM) {
-                        values.remove(COLUMN_FOR_LABEL);
-                    }
-                } else {
-                    typeForNewAccount = null;
-                    values.remove(COLUMN_FOR_TYPE);
-                }
-            } else {
-                typeForNewAccount = oldType;
-            }
-            if (typeForNewAccount != null) {
-                final int specificMax = typeSpecificMaxMap.get(typeForNewAccount, 0);
-                if (specificMax >= 0) {
-                    final int currentCount = currentEntryCount.get(typeForNewAccount, 0);
-                    if (currentCount >= specificMax) {
-                        continue;
-                    }
-                    currentEntryCount.put(typeForNewAccount, currentCount + 1);
-                }
-            }
-            newState.addEntry(ValuesDelta.fromAfter(values));
-            totalCount++;
-        }
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/DataItem.java b/src/com/android/contacts/model/dataitem/DataItem.java
deleted file mode 100644
index 36f3cb2..0000000
--- a/src/com/android/contacts/model/dataitem/DataItem.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Event;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.Identity;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Nickname;
-import android.provider.ContactsContract.CommonDataKinds.Note;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.Relation;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.provider.ContactsContract.Contacts.Data;
-
-import com.android.contacts.common.model.dataitem.DataKind;
-
-/**
- * This is the base class for data items, which represents a row from the Data table.
- */
-public class DataItem {
-
-    private final ContentValues mContentValues;
-
-    protected DataItem(ContentValues values) {
-        mContentValues = values;
-    }
-
-    /**
-     * Factory for creating subclasses of DataItem objects based on the mimetype in the
-     * content values.  Raw contact is the raw contact that this data item is associated with.
-     */
-    public static DataItem createFrom(ContentValues values) {
-        final String mimeType = values.getAsString(Data.MIMETYPE);
-        if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new GroupMembershipDataItem(values);
-        } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new StructuredNameDataItem(values);
-        } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new PhoneDataItem(values);
-        } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new EmailDataItem(values);
-        } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new StructuredPostalDataItem(values);
-        } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new ImDataItem(values);
-        } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new OrganizationDataItem(values);
-        } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new NicknameDataItem(values);
-        } else if (Note.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new NoteDataItem(values);
-        } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new WebsiteDataItem(values);
-        } else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new SipAddressDataItem(values);
-        } else if (Event.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new EventDataItem(values);
-        } else if (Relation.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new RelationDataItem(values);
-        } else if (Identity.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new IdentityDataItem(values);
-        } else if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            return new PhotoDataItem(values);
-        }
-
-        // generic
-        return new DataItem(values);
-    }
-
-    public ContentValues getContentValues() {
-        return mContentValues;
-    }
-
-    public void setRawContactId(long rawContactId) {
-        mContentValues.put(Data.RAW_CONTACT_ID, rawContactId);
-    }
-
-    /**
-     * Returns the data id.
-     */
-    public long getId() {
-        return mContentValues.getAsLong(Data._ID);
-    }
-
-    /**
-     * Returns the mimetype of the data.
-     */
-    public String getMimeType() {
-        return mContentValues.getAsString(Data.MIMETYPE);
-    }
-
-    public void setMimeType(String mimeType) {
-        mContentValues.put(Data.MIMETYPE, mimeType);
-    }
-
-    public boolean isPrimary() {
-        Integer primary = mContentValues.getAsInteger(Data.IS_PRIMARY);
-        return primary != null && primary != 0;
-    }
-
-    public boolean isSuperPrimary() {
-        Integer superPrimary = mContentValues.getAsInteger(Data.IS_SUPER_PRIMARY);
-        return superPrimary != null && superPrimary != 0;
-    }
-
-    public boolean hasKindTypeColumn(DataKind kind) {
-        final String key = kind.typeColumn;
-        return key != null && mContentValues.containsKey(key) &&
-            mContentValues.getAsInteger(key) != null;
-    }
-
-    public int getKindTypeColumn(DataKind kind) {
-        final String key = kind.typeColumn;
-        return mContentValues.getAsInteger(key);
-    }
-
-    /**
-     * This builds the data string depending on the type of data item by using the generic
-     * DataKind object underneath.
-     */
-    public String buildDataString(Context context, DataKind kind) {
-        if (kind.actionBody == null) {
-            return null;
-        }
-        CharSequence actionBody = kind.actionBody.inflateUsing(context, mContentValues);
-        return actionBody == null ? null : actionBody.toString();
-    }
-
-    /**
-     * This builds the data string(intended for display) depending on the type of data item. It
-     * returns the same value as {@link #buildDataString} by default, but certain data items can
-     * override it to provide their version of formatted data strings.
-     *
-     * @return Data string representing the data item, possibly formatted for display
-     */
-    public String buildDataStringForDisplay(Context context, DataKind kind) {
-        return buildDataString(context, kind);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/EmailDataItem.java b/src/com/android/contacts/model/dataitem/EmailDataItem.java
deleted file mode 100644
index 77ad126..0000000
--- a/src/com/android/contacts/model/dataitem/EmailDataItem.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-
-/**
- * Represents an email data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Email}.
- */
-public class EmailDataItem extends DataItem {
-
-    /* package */ EmailDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getAddress() {
-        return getContentValues().getAsString(Email.ADDRESS);
-    }
-
-    public String getDisplayName() {
-        return getContentValues().getAsString(Email.DISPLAY_NAME);
-    }
-
-    public String getData() {
-        return getContentValues().getAsString(Email.DATA);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Email.LABEL);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/EventDataItem.java b/src/com/android/contacts/model/dataitem/EventDataItem.java
deleted file mode 100644
index 9820c8f..0000000
--- a/src/com/android/contacts/model/dataitem/EventDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Event;
-
-/**
- * Represents an event data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Event}.
- */
-public class EventDataItem extends DataItem {
-
-    /* package */ EventDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getStartDate() {
-        return getContentValues().getAsString(Event.START_DATE);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Event.LABEL);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/GroupMembershipDataItem.java b/src/com/android/contacts/model/dataitem/GroupMembershipDataItem.java
deleted file mode 100644
index 00558d0..0000000
--- a/src/com/android/contacts/model/dataitem/GroupMembershipDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-
-/**
- * Represents a group memebership data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.GroupMembership}.
- */
-public class GroupMembershipDataItem extends DataItem {
-
-    /* package */ GroupMembershipDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public Long getGroupRowId() {
-        return getContentValues().getAsLong(GroupMembership.GROUP_ROW_ID);
-    }
-
-    public String getGroupSourceId() {
-        return getContentValues().getAsString(GroupMembership.GROUP_SOURCE_ID);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/IdentityDataItem.java b/src/com/android/contacts/model/dataitem/IdentityDataItem.java
deleted file mode 100644
index 045867a..0000000
--- a/src/com/android/contacts/model/dataitem/IdentityDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Identity;
-
-/**
- * Represents an identity data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Identity}.
- */
-public class IdentityDataItem extends DataItem {
-
-    /* package */ IdentityDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getIdentity() {
-        return getContentValues().getAsString(Identity.IDENTITY);
-    }
-
-    public String getNamespace() {
-        return getContentValues().getAsString(Identity.NAMESPACE);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/ImDataItem.java b/src/com/android/contacts/model/dataitem/ImDataItem.java
deleted file mode 100644
index 2513b57..0000000
--- a/src/com/android/contacts/model/dataitem/ImDataItem.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-
-/**
- * Represents an IM data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Im}.
- */
-public class ImDataItem extends DataItem {
-
-    private final boolean mCreatedFromEmail;
-
-    /* package */ ImDataItem(ContentValues values) {
-        super(values);
-        mCreatedFromEmail = false;
-    }
-
-    private ImDataItem(ContentValues values, boolean createdFromEmail) {
-        super(values);
-        mCreatedFromEmail = createdFromEmail;
-    }
-
-    public static ImDataItem createFromEmail(EmailDataItem item) {
-        ImDataItem im = new ImDataItem(new ContentValues(item.getContentValues()), true);
-        im.setMimeType(Im.CONTENT_ITEM_TYPE);
-        return im;
-    }
-
-    public String getData() {
-        if (mCreatedFromEmail) {
-            return getContentValues().getAsString(Email.DATA);
-        } else {
-            return getContentValues().getAsString(Im.DATA);
-        }
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Im.LABEL);
-    }
-
-    /**
-     * Values are one of Im.PROTOCOL_
-     */
-    public Integer getProtocol() {
-        return getContentValues().getAsInteger(Im.PROTOCOL);
-    }
-
-    public boolean isProtocolValid() {
-        return getProtocol() != null;
-    }
-
-    public String getCustomProtocol() {
-        return getContentValues().getAsString(Im.CUSTOM_PROTOCOL);
-    }
-
-    public int getChatCapability() {
-        Integer result = getContentValues().getAsInteger(Im.CHAT_CAPABILITY);
-        return result == null ? 0 : result;
-    }
-
-    public boolean isCreatedFromEmail() {
-        return mCreatedFromEmail;
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/NicknameDataItem.java b/src/com/android/contacts/model/dataitem/NicknameDataItem.java
deleted file mode 100644
index 2d44751..0000000
--- a/src/com/android/contacts/model/dataitem/NicknameDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Nickname;
-
-/**
- * Represents a nickname data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Nickname}.
- */
-public class NicknameDataItem extends DataItem {
-
-    public NicknameDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getName() {
-        return getContentValues().getAsString(Nickname.NAME);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Nickname.LABEL);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/NoteDataItem.java b/src/com/android/contacts/model/dataitem/NoteDataItem.java
deleted file mode 100644
index 9a572cb..0000000
--- a/src/com/android/contacts/model/dataitem/NoteDataItem.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Note;
-
-/**
- * Represents a note data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Note}.
- */
-public class NoteDataItem extends DataItem {
-
-    /* package */ NoteDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getNote() {
-        return getContentValues().getAsString(Note.NOTE);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/OrganizationDataItem.java b/src/com/android/contacts/model/dataitem/OrganizationDataItem.java
deleted file mode 100644
index e5b142e..0000000
--- a/src/com/android/contacts/model/dataitem/OrganizationDataItem.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-
-/**
- * Represents an organization data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Organization}.
- */
-public class OrganizationDataItem extends DataItem {
-
-    /* package */ OrganizationDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getCompany() {
-        return getContentValues().getAsString(Organization.COMPANY);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Organization.LABEL);
-    }
-
-    public String getTitle() {
-        return getContentValues().getAsString(Organization.TITLE);
-    }
-
-    public String getDepartment() {
-        return getContentValues().getAsString(Organization.DEPARTMENT);
-    }
-
-    public String getJobDescription() {
-        return getContentValues().getAsString(Organization.JOB_DESCRIPTION);
-    }
-
-    public String getSymbol() {
-        return getContentValues().getAsString(Organization.SYMBOL);
-    }
-
-    public String getPhoneticName() {
-        return getContentValues().getAsString(Organization.PHONETIC_NAME);
-    }
-
-    public String getOfficeLocation() {
-        return getContentValues().getAsString(Organization.OFFICE_LOCATION);
-    }
-
-    public String getPhoneticNameStyle() {
-        return getContentValues().getAsString(Organization.PHONETIC_NAME_STYLE);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/PhoneDataItem.java b/src/com/android/contacts/model/dataitem/PhoneDataItem.java
deleted file mode 100644
index 9196369..0000000
--- a/src/com/android/contacts/model/dataitem/PhoneDataItem.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.telephony.PhoneNumberUtils;
-
-import com.android.contacts.common.model.dataitem.DataKind;
-
-/**
- * Represents a phone data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Phone}.
- */
-public class PhoneDataItem extends DataItem {
-
-    public static final String KEY_FORMATTED_PHONE_NUMBER = "formattedPhoneNumber";
-
-    /* package */ PhoneDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getNumber() {
-        return getContentValues().getAsString(Phone.NUMBER);
-    }
-
-    /**
-     * Returns the normalized phone number in E164 format.
-     */
-    public String getNormalizedNumber() {
-        return getContentValues().getAsString(Phone.NORMALIZED_NUMBER);
-    }
-
-    public String getFormattedPhoneNumber() {
-        return getContentValues().getAsString(KEY_FORMATTED_PHONE_NUMBER);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Phone.LABEL);
-    }
-
-    public void computeFormattedPhoneNumber(String defaultCountryIso) {
-        final String phoneNumber = getNumber();
-        if (phoneNumber != null) {
-            final String formattedPhoneNumber = PhoneNumberUtils.formatNumber(phoneNumber,
-                    getNormalizedNumber(), defaultCountryIso);
-            getContentValues().put(KEY_FORMATTED_PHONE_NUMBER, formattedPhoneNumber);
-        }
-    }
-
-    /**
-     * Returns the formatted phone number (if already computed using {@link
-     * #computeFormattedPhoneNumber}). Otherwise this method returns the unformatted phone number.
-     */
-    @Override
-    public String buildDataStringForDisplay(Context context, DataKind kind) {
-        final String formatted = getFormattedPhoneNumber();
-        if (formatted != null) {
-            return formatted;
-        } else {
-            return getNumber();
-        }
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/PhotoDataItem.java b/src/com/android/contacts/model/dataitem/PhotoDataItem.java
deleted file mode 100644
index 2ba13fb..0000000
--- a/src/com/android/contacts/model/dataitem/PhotoDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.Contacts.Photo;
-
-/**
- * Represents a photo data item, wrapping the columns in
- * {@link ContactsContract.Contacts.Photo}.
- */
-public class PhotoDataItem extends DataItem {
-
-    /* package */ PhotoDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public Long getPhotoFileId() {
-        return getContentValues().getAsLong(Photo.PHOTO_FILE_ID);
-    }
-
-    public byte[] getPhoto() {
-        return getContentValues().getAsByteArray(Photo.PHOTO);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/RelationDataItem.java b/src/com/android/contacts/model/dataitem/RelationDataItem.java
deleted file mode 100644
index 4e11ecb..0000000
--- a/src/com/android/contacts/model/dataitem/RelationDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Relation;
-
-/**
- * Represents a relation data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Relation}.
- */
-public class RelationDataItem extends DataItem {
-
-    /* package */ RelationDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getName() {
-        return getContentValues().getAsString(Relation.NAME);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Relation.LABEL);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/SipAddressDataItem.java b/src/com/android/contacts/model/dataitem/SipAddressDataItem.java
deleted file mode 100644
index 45ebeee..0000000
--- a/src/com/android/contacts/model/dataitem/SipAddressDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-
-/**
- * Represents a sip address data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.SipAddress}.
- */
-public class SipAddressDataItem extends DataItem {
-
-    /* package */ SipAddressDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getSipAddress() {
-        return getContentValues().getAsString(SipAddress.SIP_ADDRESS);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(SipAddress.LABEL);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/StructuredNameDataItem.java b/src/com/android/contacts/model/dataitem/StructuredNameDataItem.java
deleted file mode 100644
index 7d1a44d..0000000
--- a/src/com/android/contacts/model/dataitem/StructuredNameDataItem.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.Contacts.Data;
-
-/**
- * Represents a structured name data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.StructuredName}.
- */
-public class StructuredNameDataItem extends DataItem {
-
-    public StructuredNameDataItem() {
-        super(new ContentValues());
-        getContentValues().put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
-    }
-
-    /* package */ StructuredNameDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getDisplayName() {
-        return getContentValues().getAsString(StructuredName.DISPLAY_NAME);
-    }
-
-    public void setDisplayName(String name) {
-        getContentValues().put(StructuredName.DISPLAY_NAME, name);
-    }
-
-    public String getGivenName() {
-        return getContentValues().getAsString(StructuredName.GIVEN_NAME);
-    }
-
-    public String getFamilyName() {
-        return getContentValues().getAsString(StructuredName.FAMILY_NAME);
-    }
-
-    public String getPrefix() {
-        return getContentValues().getAsString(StructuredName.PREFIX);
-    }
-
-    public String getMiddleName() {
-        return getContentValues().getAsString(StructuredName.MIDDLE_NAME);
-    }
-
-    public String getSuffix() {
-        return getContentValues().getAsString(StructuredName.SUFFIX);
-    }
-
-    public String getPhoneticGivenName() {
-        return getContentValues().getAsString(StructuredName.PHONETIC_GIVEN_NAME);
-    }
-
-    public String getPhoneticMiddleName() {
-        return getContentValues().getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
-    }
-
-    public String getPhoneticFamilyName() {
-        return getContentValues().getAsString(StructuredName.PHONETIC_FAMILY_NAME);
-    }
-
-    public String getFullNameStyle() {
-        return getContentValues().getAsString(StructuredName.FULL_NAME_STYLE);
-    }
-
-    public String getPhoneticNameStyle() {
-        return getContentValues().getAsString(StructuredName.PHONETIC_NAME_STYLE);
-    }
-
-    public void setPhoneticFamilyName(String name) {
-        getContentValues().put(StructuredName.PHONETIC_FAMILY_NAME, name);
-    }
-
-    public void setPhoneticMiddleName(String name) {
-        getContentValues().put(StructuredName.PHONETIC_MIDDLE_NAME, name);
-    }
-
-    public void setPhoneticGivenName(String name) {
-        getContentValues().put(StructuredName.PHONETIC_GIVEN_NAME, name);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/StructuredPostalDataItem.java b/src/com/android/contacts/model/dataitem/StructuredPostalDataItem.java
deleted file mode 100644
index cf46c07..0000000
--- a/src/com/android/contacts/model/dataitem/StructuredPostalDataItem.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-
-/**
- * Represents a structured postal data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.StructuredPostal}.
- */
-public class StructuredPostalDataItem extends DataItem {
-
-    /* package */ StructuredPostalDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getFormattedAddress() {
-        return getContentValues().getAsString(StructuredPostal.FORMATTED_ADDRESS);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(StructuredPostal.LABEL);
-    }
-
-    public String getStreet() {
-        return getContentValues().getAsString(StructuredPostal.STREET);
-    }
-
-    public String getPOBox() {
-        return getContentValues().getAsString(StructuredPostal.POBOX);
-    }
-
-    public String getNeighborhood() {
-        return getContentValues().getAsString(StructuredPostal.NEIGHBORHOOD);
-    }
-
-    public String getCity() {
-        return getContentValues().getAsString(StructuredPostal.CITY);
-    }
-
-    public String getRegion() {
-        return getContentValues().getAsString(StructuredPostal.REGION);
-    }
-
-    public String getPostcode() {
-        return getContentValues().getAsString(StructuredPostal.POSTCODE);
-    }
-
-    public String getCountry() {
-        return getContentValues().getAsString(StructuredPostal.COUNTRY);
-    }
-}
diff --git a/src/com/android/contacts/model/dataitem/WebsiteDataItem.java b/src/com/android/contacts/model/dataitem/WebsiteDataItem.java
deleted file mode 100644
index 4439be7..0000000
--- a/src/com/android/contacts/model/dataitem/WebsiteDataItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model.dataitem;
-
-import android.content.ContentValues;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Website;
-
-/**
- * Represents a website data item, wrapping the columns in
- * {@link ContactsContract.CommonDataKinds.Website}.
- */
-public class WebsiteDataItem extends DataItem {
-
-    /* package */ WebsiteDataItem(ContentValues values) {
-        super(values);
-    }
-
-    public String getUrl() {
-        return getContentValues().getAsString(Website.URL);
-    }
-
-    public String getLabel() {
-        return getContentValues().getAsString(Website.LABEL);
-    }
-}
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index 0e3495c..e29b3ef 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -30,18 +30,18 @@
 import android.util.Log;
 
 import com.android.contacts.common.CallUtil;
-import com.android.contacts.ContactsUtils;
+import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.R;
 import com.android.contacts.common.MoreContactUtils;
 import com.android.contacts.common.model.account.AccountType.EditType;
-import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.common.model.dataitem.DataItem;
 import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.model.dataitem.EmailDataItem;
-import com.android.contacts.model.dataitem.ImDataItem;
-import com.android.contacts.model.dataitem.PhoneDataItem;
-import com.android.contacts.model.dataitem.SipAddressDataItem;
-import com.android.contacts.model.dataitem.StructuredPostalDataItem;
-import com.android.contacts.model.dataitem.WebsiteDataItem;
+import com.android.contacts.common.model.dataitem.EmailDataItem;
+import com.android.contacts.common.model.dataitem.ImDataItem;
+import com.android.contacts.common.model.dataitem.PhoneDataItem;
+import com.android.contacts.common.model.dataitem.SipAddressDataItem;
+import com.android.contacts.common.model.dataitem.StructuredPostalDataItem;
+import com.android.contacts.common.model.dataitem.WebsiteDataItem;
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.android.contacts.util.StructuredPostalUtils;
 
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index c7d6e51..0ff7a8d 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -63,17 +63,17 @@
 import com.android.contacts.common.Collapser;
 import com.android.contacts.R;
 import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.ContactLoader;
-import com.android.contacts.model.RawContact;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
+import com.android.contacts.common.model.RawContact;
 import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.common.model.dataitem.DataItem;
 import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.model.dataitem.EmailDataItem;
-import com.android.contacts.model.dataitem.ImDataItem;
+import com.android.contacts.common.model.dataitem.EmailDataItem;
+import com.android.contacts.common.model.dataitem.ImDataItem;
 import com.android.contacts.common.util.Constants;
+import com.android.contacts.common.util.DataStatus;
 import com.android.contacts.common.util.UriUtils;
-import com.android.contacts.util.DataStatus;
 import com.android.contacts.util.ImageViewDrawableSetter;
 import com.android.contacts.util.SchedulingUtils;
 import com.android.contacts.common.util.StopWatch;
diff --git a/src/com/android/contacts/test/InjectedServices.java b/src/com/android/contacts/test/InjectedServices.java
deleted file mode 100644
index 4dd955f..0000000
--- a/src/com/android/contacts/test/InjectedServices.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.test;
-
-import android.content.ContentResolver;
-import android.content.SharedPreferences;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-
-import java.util.HashMap;
-
-/**
- * A mechanism for providing alternative (mock) services to the application
- * while running tests. Activities, Services and the Application should check
- * with this class to see if a particular service has been overridden.
- */
-public class InjectedServices {
-
-    private ContentResolver mContentResolver;
-    private SharedPreferences mSharedPreferences;
-    private HashMap<String, Object> mSystemServices;
-
-    @VisibleForTesting
-    public void setContentResolver(ContentResolver contentResolver) {
-        this.mContentResolver = contentResolver;
-    }
-
-    public ContentResolver getContentResolver() {
-        return mContentResolver;
-    }
-
-    @VisibleForTesting
-    public void setSharedPreferences(SharedPreferences sharedPreferences) {
-        this.mSharedPreferences = sharedPreferences;
-    }
-
-    public SharedPreferences getSharedPreferences() {
-        return mSharedPreferences;
-    }
-
-    @VisibleForTesting
-    public void setSystemService(String name, Object service) {
-        if (mSystemServices == null) {
-            mSystemServices = Maps.newHashMap();
-        }
-
-        mSystemServices.put(name, service);
-    }
-
-    public Object getSystemService(String name) {
-        if (mSystemServices != null) {
-            return mSystemServices.get(name);
-        }
-        return null;
-    }
-}
diff --git a/src/com/android/contacts/util/ContactBadgeUtil.java b/src/com/android/contacts/util/ContactBadgeUtil.java
index fa1a60c..82a6820 100644
--- a/src/com/android/contacts/util/ContactBadgeUtil.java
+++ b/src/com/android/contacts/util/ContactBadgeUtil.java
@@ -27,6 +27,7 @@
 import android.util.Log;
 
 import com.android.contacts.common.ContactPhotoManager;
+import com.android.contacts.util.StreamItemEntry;
 import com.android.contacts.R;
 
 /**
diff --git a/src/com/android/contacts/util/ContactLoaderUtils.java b/src/com/android/contacts/util/ContactLoaderUtils.java
deleted file mode 100644
index 91c683f..0000000
--- a/src/com/android/contacts/util/ContactLoaderUtils.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.util;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.net.Uri;
-import android.provider.Contacts;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.RawContacts;
-
-/**
- * Utility methods for the {@link ContactLoader}.
- */
-public final class ContactLoaderUtils {
-
-    /** Static helper, not instantiable. */
-    private ContactLoaderUtils() {}
-
-    /**
-     * Transforms the given Uri and returns a Lookup-Uri that represents the contact.
-     * For legacy contacts, a raw-contact lookup is performed. An {@link IllegalArgumentException}
-     * can be thrown if the URI is null or the authority is not recognized.
-     *
-     * Do not call from the UI thread.
-     */
-    @SuppressWarnings("deprecation")
-    public static Uri ensureIsContactUri(final ContentResolver resolver, final Uri uri)
-            throws IllegalArgumentException {
-        if (uri == null) throw new IllegalArgumentException("uri must not be null");
-
-        final String authority = uri.getAuthority();
-
-        // Current Style Uri?
-        if (ContactsContract.AUTHORITY.equals(authority)) {
-            final String type = resolver.getType(uri);
-            // Contact-Uri? Good, return it
-            if (ContactsContract.Contacts.CONTENT_ITEM_TYPE.equals(type)) {
-                return uri;
-            }
-
-            // RawContact-Uri? Transform it to ContactUri
-            if (RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
-                final long rawContactId = ContentUris.parseId(uri);
-                return RawContacts.getContactLookupUri(resolver,
-                        ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
-            }
-
-            // Anything else? We don't know what this is
-            throw new IllegalArgumentException("uri format is unknown");
-        }
-
-        // Legacy Style? Convert to RawContact
-        final String OBSOLETE_AUTHORITY = Contacts.AUTHORITY;
-        if (OBSOLETE_AUTHORITY.equals(authority)) {
-            // Legacy Format. Convert to RawContact-Uri and then lookup the contact
-            final long rawContactId = ContentUris.parseId(uri);
-            return RawContacts.getContactLookupUri(resolver,
-                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
-        }
-
-        throw new IllegalArgumentException("uri authority is unknown");
-    }
-}
diff --git a/src/com/android/contacts/util/DataStatus.java b/src/com/android/contacts/util/DataStatus.java
deleted file mode 100644
index f267615..0000000
--- a/src/com/android/contacts/util/DataStatus.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.util;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.provider.ContactsContract.Data;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-
-import com.android.contacts.R;
-
-/**
- * Storage for a social status update. Holds a single update, but can use
- * {@link #possibleUpdate(Cursor)} to consider updating when a better status
- * exists. Statuses with timestamps, or with newer timestamps win.
- */
-public class DataStatus {
-    private int mPresence = -1;
-    private String mStatus = null;
-    private long mTimestamp = -1;
-
-    private String mResPackage = null;
-    private int mIconRes = -1;
-    private int mLabelRes = -1;
-
-    public DataStatus() {
-    }
-
-    public DataStatus(Cursor cursor) {
-        // When creating from cursor row, fill normally
-        fromCursor(cursor);
-    }
-
-    /**
-     * Attempt updating this {@link DataStatus} based on values at the
-     * current row of the given {@link Cursor}.
-     */
-    public void possibleUpdate(Cursor cursor) {
-        final boolean hasStatus = !isNull(cursor, Data.STATUS);
-        final boolean hasTimestamp = !isNull(cursor, Data.STATUS_TIMESTAMP);
-
-        // Bail early when not valid status, or when previous status was
-        // found and we can't compare this one.
-        if (!hasStatus) return;
-        if (isValid() && !hasTimestamp) return;
-
-        if (hasTimestamp) {
-            // Compare timestamps and bail if older status
-            final long newTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1);
-            if (newTimestamp < mTimestamp) return;
-
-            mTimestamp = newTimestamp;
-        }
-
-        // Fill in remaining details from cursor
-        fromCursor(cursor);
-    }
-
-    private void fromCursor(Cursor cursor) {
-        mPresence = getInt(cursor, Data.PRESENCE, -1);
-        mStatus = getString(cursor, Data.STATUS);
-        mTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1);
-        mResPackage = getString(cursor, Data.STATUS_RES_PACKAGE);
-        mIconRes = getInt(cursor, Data.STATUS_ICON, -1);
-        mLabelRes = getInt(cursor, Data.STATUS_LABEL, -1);
-    }
-
-    public boolean isValid() {
-        return !TextUtils.isEmpty(mStatus);
-    }
-
-    public int getPresence() {
-        return mPresence;
-    }
-
-    public CharSequence getStatus() {
-        return mStatus;
-    }
-
-    public long getTimestamp() {
-        return mTimestamp;
-    }
-
-    /**
-     * Build any timestamp and label into a single string.
-     */
-    public CharSequence getTimestampLabel(Context context) {
-        final PackageManager pm = context.getPackageManager();
-
-        // Use local package for resources when none requested
-        if (mResPackage == null) mResPackage = context.getPackageName();
-
-        final boolean validTimestamp = mTimestamp > 0;
-        final boolean validLabel = mResPackage != null && mLabelRes != -1;
-
-        final CharSequence timeClause = validTimestamp ? DateUtils.getRelativeTimeSpanString(
-                mTimestamp, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS,
-                DateUtils.FORMAT_ABBREV_RELATIVE) : null;
-        final CharSequence labelClause = validLabel ? pm.getText(mResPackage, mLabelRes,
-                null) : null;
-
-        if (validTimestamp && validLabel) {
-            return context.getString(
-                    R.string.contact_status_update_attribution_with_date,
-                    timeClause, labelClause);
-        } else if (validLabel) {
-            return context.getString(
-                    R.string.contact_status_update_attribution,
-                    labelClause);
-        } else if (validTimestamp) {
-            return timeClause;
-        } else {
-            return null;
-        }
-    }
-
-    public Drawable getIcon(Context context) {
-        final PackageManager pm = context.getPackageManager();
-
-        // Use local package for resources when none requested
-        if (mResPackage == null) mResPackage = context.getPackageName();
-
-        final boolean validIcon = mResPackage != null && mIconRes != -1;
-        return validIcon ? pm.getDrawable(mResPackage, mIconRes, null) : null;
-    }
-
-    private static String getString(Cursor cursor, String columnName) {
-        return cursor.getString(cursor.getColumnIndex(columnName));
-    }
-
-    private static int getInt(Cursor cursor, String columnName) {
-        return cursor.getInt(cursor.getColumnIndex(columnName));
-    }
-
-    private static int getInt(Cursor cursor, String columnName, int missingValue) {
-        final int columnIndex = cursor.getColumnIndex(columnName);
-        return cursor.isNull(columnIndex) ? missingValue : cursor.getInt(columnIndex);
-    }
-
-    private static long getLong(Cursor cursor, String columnName, long missingValue) {
-        final int columnIndex = cursor.getColumnIndex(columnName);
-        return cursor.isNull(columnIndex) ? missingValue : cursor.getLong(columnIndex);
-    }
-
-    private static boolean isNull(Cursor cursor, String columnName) {
-        return cursor.isNull(cursor.getColumnIndex(columnName));
-    }
-}
diff --git a/src/com/android/contacts/util/DateUtils.java b/src/com/android/contacts/util/DateUtils.java
deleted file mode 100644
index e20aadf..0000000
--- a/src/com/android/contacts/util/DateUtils.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.util;
-
-import android.content.Context;
-import android.text.format.DateFormat;
-
-import com.android.contacts.common.util.CommonDateUtils;
-
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- * Utility methods for processing dates.
- */
-public class DateUtils {
-    public static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC");
-
-    /**
-     * When parsing a date without a year, the system assumes 1970, which wasn't a leap-year.
-     * Let's add a one-off hack for that day of the year
-     */
-    public static final String NO_YEAR_DATE_FEB29TH = "--02-29";
-
-    // Variations of ISO 8601 date format.  Do not change the order - it does affect the
-    // result in ambiguous cases.
-    private static final SimpleDateFormat[] DATE_FORMATS = {
-        CommonDateUtils.FULL_DATE_FORMAT,
-        CommonDateUtils.DATE_AND_TIME_FORMAT,
-        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US),
-        new SimpleDateFormat("yyyyMMdd", Locale.US),
-        new SimpleDateFormat("yyyyMMdd'T'HHmmssSSS'Z'", Locale.US),
-        new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.US),
-        new SimpleDateFormat("yyyyMMdd'T'HHmm'Z'", Locale.US),
-    };
-
-    static {
-        for (SimpleDateFormat format : DATE_FORMATS) {
-            format.setLenient(true);
-            format.setTimeZone(UTC_TIMEZONE);
-        }
-        CommonDateUtils.NO_YEAR_DATE_FORMAT.setTimeZone(UTC_TIMEZONE);
-    }
-
-    /**
-     * Parses the supplied string to see if it looks like a date.
-     *
-     * @param string The string representation of the provided date
-     * @param mustContainYear If true, the string is parsed as a date containing a year. If false,
-     * the string is parsed into a valid date even if the year field is missing.
-     * @return A Calendar object corresponding to the date if the string is successfully parsed.
-     * If not, null is returned.
-     */
-    public static Calendar parseDate(String string, boolean mustContainYear) {
-        ParsePosition parsePosition = new ParsePosition(0);
-        Date date;
-        if (!mustContainYear) {
-            final boolean noYearParsed;
-            // Unfortunately, we can't parse Feb 29th correctly, so let's handle this day seperately
-            if (NO_YEAR_DATE_FEB29TH.equals(string)) {
-                return getUtcDate(0, Calendar.FEBRUARY, 29);
-            } else {
-                synchronized (CommonDateUtils.NO_YEAR_DATE_FORMAT) {
-                    date = CommonDateUtils.NO_YEAR_DATE_FORMAT.parse(string, parsePosition);
-                }
-                noYearParsed = parsePosition.getIndex() == string.length();
-            }
-
-            if (noYearParsed) {
-                return getUtcDate(date, true);
-            }
-        }
-        for (int i = 0; i < DATE_FORMATS.length; i++) {
-            SimpleDateFormat f = DATE_FORMATS[i];
-            synchronized (f) {
-                parsePosition.setIndex(0);
-                date = f.parse(string, parsePosition);
-                if (parsePosition.getIndex() == string.length()) {
-                    return getUtcDate(date, false);
-                }
-            }
-        }
-        return null;
-    }
-
-    private static final Calendar getUtcDate(Date date, boolean noYear) {
-        final Calendar calendar = Calendar.getInstance(UTC_TIMEZONE, Locale.US);
-        calendar.setTime(date);
-        if (noYear) {
-            calendar.set(Calendar.YEAR, 0);
-        }
-        return calendar;
-    }
-
-    private static final Calendar getUtcDate(int year, int month, int dayOfMonth) {
-        final Calendar calendar = Calendar.getInstance(UTC_TIMEZONE, Locale.US);
-        calendar.clear();
-        calendar.set(Calendar.YEAR, year);
-        calendar.set(Calendar.MONTH, month);
-        calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
-        return calendar;
-    }
-
-    public static boolean isYearSet(Calendar cal) {
-        // use the Calendar.YEAR field to track whether or not the year is set instead of
-        // Calendar.isSet() because doing Calendar.get() causes Calendar.isSet() to become
-        // true irregardless of what the previous value was
-        return cal.get(Calendar.YEAR) > 1;
-    }
-
-    /**
-     * Same as {@link #formatDate(Context context, String string, boolean longForm)}, with
-     * longForm set to {@code true} by default.
-     *
-     * @param context Valid context
-     * @param string String representation of a date to parse
-     * @return Returns the same date in a cleaned up format. If the supplied string does not look
-     * like a date, return it unchanged.
-     */
-
-    public static String formatDate(Context context, String string) {
-        return formatDate(context, string, true);
-    }
-
-    /**
-     * Parses the supplied string to see if it looks like a date.
-     *
-     * @param context Valid context
-     * @param string String representation of a date to parse
-     * @param longForm If true, return the date formatted into its long string representation.
-     * If false, return the date formatted using its short form representation (i.e. 12/11/2012)
-     * @return Returns the same date in a cleaned up format. If the supplied string does not look
-     * like a date, return it unchanged.
-     */
-    public static String formatDate(Context context, String string, boolean longForm) {
-        if (string == null) {
-            return null;
-        }
-
-        string = string.trim();
-        if (string.length() == 0) {
-            return string;
-        }
-        final Calendar cal = parseDate(string, false);
-
-        // we weren't able to parse the string successfully so just return it unchanged
-        if (cal == null) {
-            return string;
-        }
-
-        final boolean isYearSet = isYearSet(cal);
-        final java.text.DateFormat outFormat;
-        if (!isYearSet) {
-            outFormat = getLocalizedDateFormatWithoutYear(context);
-        } else {
-            outFormat =
-                    longForm ? DateFormat.getLongDateFormat(context) :
-                    DateFormat.getDateFormat(context);
-        }
-        synchronized (outFormat) {
-            outFormat.setTimeZone(UTC_TIMEZONE);
-            return outFormat.format(cal.getTime());
-        }
-    }
-
-    public static boolean isMonthBeforeDay(Context context) {
-        char[] dateFormatOrder = DateFormat.getDateFormatOrder(context);
-        for (int i = 0; i < dateFormatOrder.length; i++) {
-            if (dateFormatOrder[i] == DateFormat.DATE) {
-                return false;
-            }
-            if (dateFormatOrder[i] == DateFormat.MONTH) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns a SimpleDateFormat object without the year fields by using a regular expression
-     * to eliminate the year in the string pattern. In the rare occurence that the resulting
-     * pattern cannot be reconverted into a SimpleDateFormat, it uses the provided context to
-     * determine whether the month field should be displayed before the day field, and returns
-     * either "MMMM dd" or "dd MMMM" converted into a SimpleDateFormat.
-     */
-    public static java.text.DateFormat getLocalizedDateFormatWithoutYear(Context context) {
-        final String pattern = ((SimpleDateFormat) SimpleDateFormat.getDateInstance(
-                java.text.DateFormat.LONG)).toPattern();
-        // Determine the correct regex pattern for year.
-        // Special case handling for Spanish locale by checking for "de"
-        final String yearPattern = pattern.contains(
-                "de") ? "[^Mm]*[Yy]+[^Mm]*" : "[^DdMm]*[Yy]+[^DdMm]*";
-        try {
-         // Eliminate the substring in pattern that matches the format for that of year
-            return new SimpleDateFormat(pattern.replaceAll(yearPattern, ""));
-        } catch (IllegalArgumentException e) {
-            return new SimpleDateFormat(
-                    DateUtils.isMonthBeforeDay(context) ? "MMMM dd" : "dd MMMM");
-        }
-    }
-
-    /**
-     * Given a calendar (possibly containing only a day of the year), returns the earliest possible
-     * anniversary of the date that is equal to or after the current point in time if the date
-     * does not contain a year, or the date converted to the local time zone (if the date contains
-     * a year.
-     *
-     * @param target The date we wish to convert(in the UTC time zone).
-     * @return If date does not contain a year (year < 1900), returns the next earliest anniversary
-     * that is after the current point in time (in the local time zone). Otherwise, returns the
-     * adjusted Date in the local time zone.
-     */
-    public static Date getNextAnnualDate(Calendar target) {
-        final Calendar today = Calendar.getInstance();
-        today.setTime(new Date());
-
-        // Round the current time to the exact start of today so that when we compare
-        // today against the target date, both dates are set to exactly 0000H.
-        today.set(Calendar.HOUR_OF_DAY, 0);
-        today.set(Calendar.MINUTE, 0);
-        today.set(Calendar.SECOND, 0);
-        today.set(Calendar.MILLISECOND, 0);
-
-        final boolean isYearSet = isYearSet(target);
-        final int targetYear = target.get(Calendar.YEAR);
-        final int targetMonth = target.get(Calendar.MONTH);
-        final int targetDay = target.get(Calendar.DAY_OF_MONTH);
-        final boolean isFeb29 = (targetMonth == Calendar.FEBRUARY && targetDay == 29);
-        final GregorianCalendar anniversary = new GregorianCalendar();
-        // Convert from the UTC date to the local date. Set the year to today's year if the
-        // there is no provided year (targetYear < 1900)
-        anniversary.set(!isYearSet ? today.get(Calendar.YEAR) : targetYear,
-                targetMonth, targetDay);
-        // If the anniversary's date is before the start of today and there is no year set,
-        // increment the year by 1 so that the returned date is always equal to or greater than
-        // today. If the day is a leap year, keep going until we get the next leap year anniversary
-        // Otherwise if there is already a year set, simply return the exact date.
-        if (!isYearSet) {
-            int anniversaryYear = today.get(Calendar.YEAR);
-            if (anniversary.before(today) ||
-                    (isFeb29 && !anniversary.isLeapYear(anniversaryYear))) {
-                // If the target date is not Feb 29, then set the anniversary to the next year.
-                // Otherwise, keep going until we find the next leap year (this is not guaranteed
-                // to be in 4 years time).
-                do {
-                    anniversaryYear +=1;
-                } while (isFeb29 && !anniversary.isLeapYear(anniversaryYear));
-                anniversary.set(anniversaryYear, targetMonth, targetDay);
-            }
-        }
-        return anniversary.getTime();
-    }
-}
diff --git a/src/com/android/contacts/util/HtmlUtils.java b/src/com/android/contacts/util/HtmlUtils.java
index cea300e..edcda13 100644
--- a/src/com/android/contacts/util/HtmlUtils.java
+++ b/src/com/android/contacts/util/HtmlUtils.java
@@ -35,6 +35,7 @@
  * Specifically, it adjusts the color and padding of the vertical
  * stripe on block quotes and alignment of inlined images.
  */
+@VisibleForTesting
 public class HtmlUtils {
 
     /**
diff --git a/src/com/android/contacts/util/ImageViewDrawableSetter.java b/src/com/android/contacts/util/ImageViewDrawableSetter.java
index 91ecd61..a189f58 100644
--- a/src/com/android/contacts/util/ImageViewDrawableSetter.java
+++ b/src/com/android/contacts/util/ImageViewDrawableSetter.java
@@ -27,7 +27,7 @@
 import android.widget.ImageView;
 
 import com.android.contacts.common.ContactPhotoManager;
-import com.android.contacts.model.Contact;
+import com.android.contacts.common.model.Contact;
 
 import java.util.Arrays;
 
diff --git a/src/com/android/contacts/util/NameConverter.java b/src/com/android/contacts/util/NameConverter.java
deleted file mode 100644
index 9853821..0000000
--- a/src/com/android/contacts/util/NameConverter.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.contacts.util;
-
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.net.Uri.Builder;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.text.TextUtils;
-
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Utility class for converting between a display name and structured name (and vice-versa), via
- * calls to the contact provider.
- */
-public class NameConverter {
-
-    /**
-     * The array of fields that comprise a structured name.
-     */
-    public static final String[] STRUCTURED_NAME_FIELDS = new String[] {
-            StructuredName.PREFIX,
-            StructuredName.GIVEN_NAME,
-            StructuredName.MIDDLE_NAME,
-            StructuredName.FAMILY_NAME,
-            StructuredName.SUFFIX
-    };
-
-    /**
-     * Converts the given structured name (provided as a map from {@link StructuredName} fields to
-     * corresponding values) into a display name string.
-     * <p>
-     * Note that this operates via a call back to the ContactProvider, but it does not access the
-     * database, so it should be safe to call from the UI thread.  See
-     * ContactsProvider2.completeName() for the underlying method call.
-     * @param context Activity context.
-     * @param structuredName The structured name map to convert.
-     * @return The display name computed from the structured name map.
-     */
-    public static String structuredNameToDisplayName(Context context,
-            Map<String, String> structuredName) {
-        Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
-        for (String key : STRUCTURED_NAME_FIELDS) {
-            if (structuredName.containsKey(key)) {
-                appendQueryParameter(builder, key, structuredName.get(key));
-            }
-        }
-        return fetchDisplayName(context, builder.build());
-    }
-
-    /**
-     * Converts the given structured name (provided as ContentValues) into a display name string.
-     * @param context Activity context.
-     * @param values The content values containing values comprising the structured name.
-     * @return
-     */
-    public static String structuredNameToDisplayName(Context context, ContentValues values) {
-        Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
-        for (String key : STRUCTURED_NAME_FIELDS) {
-            if (values.containsKey(key)) {
-                appendQueryParameter(builder, key, values.getAsString(key));
-            }
-        }
-        return fetchDisplayName(context, builder.build());
-    }
-
-    /**
-     * Helper method for fetching the display name via the given URI.
-     */
-    private static String fetchDisplayName(Context context, Uri uri) {
-        String displayName = null;
-        Cursor cursor = context.getContentResolver().query(uri, new String[]{
-                StructuredName.DISPLAY_NAME,
-        }, null, null, null);
-
-        try {
-            if (cursor.moveToFirst()) {
-                displayName = cursor.getString(0);
-            }
-        } finally {
-            cursor.close();
-        }
-        return displayName;
-    }
-
-    /**
-     * Converts the given display name string into a structured name (as a map from
-     * {@link StructuredName} fields to corresponding values).
-     * <p>
-     * Note that this operates via a call back to the ContactProvider, but it does not access the
-     * database, so it should be safe to call from the UI thread.
-     * @param context Activity context.
-     * @param displayName The display name to convert.
-     * @return The structured name map computed from the display name.
-     */
-    public static Map<String, String> displayNameToStructuredName(Context context,
-            String displayName) {
-        Map<String, String> structuredName = new TreeMap<String, String>();
-        Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
-
-        appendQueryParameter(builder, StructuredName.DISPLAY_NAME, displayName);
-        Cursor cursor = context.getContentResolver().query(builder.build(), STRUCTURED_NAME_FIELDS,
-                null, null, null);
-
-        try {
-            if (cursor.moveToFirst()) {
-                for (int i = 0; i < STRUCTURED_NAME_FIELDS.length; i++) {
-                    structuredName.put(STRUCTURED_NAME_FIELDS[i], cursor.getString(i));
-                }
-            }
-        } finally {
-            cursor.close();
-        }
-        return structuredName;
-    }
-
-    /**
-     * Converts the given display name string into a structured name (inserting the structured
-     * values into a new or existing ContentValues object).
-     * <p>
-     * Note that this operates via a call back to the ContactProvider, but it does not access the
-     * database, so it should be safe to call from the UI thread.
-     * @param context Activity context.
-     * @param displayName The display name to convert.
-     * @param contentValues The content values object to place the structured name values into.  If
-     *     null, a new one will be created and returned.
-     * @return The ContentValues object containing the structured name fields derived from the
-     *     display name.
-     */
-    public static ContentValues displayNameToStructuredName(Context context, String displayName,
-            ContentValues contentValues) {
-        if (contentValues == null) {
-            contentValues = new ContentValues();
-        }
-        Map<String, String> mapValues = displayNameToStructuredName(context, displayName);
-        for (String key : mapValues.keySet()) {
-            contentValues.put(key, mapValues.get(key));
-        }
-        return contentValues;
-    }
-
-    private static void appendQueryParameter(Builder builder, String field, String value) {
-        if (!TextUtils.isEmpty(value)) {
-            builder.appendQueryParameter(field, value);
-        }
-    }
-}
diff --git a/src/com/android/contacts/util/StreamItemEntry.java b/src/com/android/contacts/util/StreamItemEntry.java
index 2332c0e..e5696a1 100644
--- a/src/com/android/contacts/util/StreamItemEntry.java
+++ b/src/com/android/contacts/util/StreamItemEntry.java
@@ -24,6 +24,8 @@
 import com.android.contacts.detail.ContactDetailDisplayUtils;
 import com.android.contacts.common.test.NeededForTesting;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -156,6 +158,7 @@
      *
      * We can't do this automatically in the getters, because it'll require a {@link Context}.
      */
+    @VisibleForTesting
     public void decodeHtml(Context context) {
         final Html.ImageGetter imageGetter = ContactDetailDisplayUtils.getImageGetter(context);
         if (mText != null) {
diff --git a/tests/src/com/android/contacts/ContactsUtilsTests.java b/tests/src/com/android/contacts/ContactsUtilsTests.java
deleted file mode 100644
index e8f05e0..0000000
--- a/tests/src/com/android/contacts/ContactsUtilsTests.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import android.content.Intent;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.contacts.common.MoreContactUtils;
-
-/**
- * Tests for {@link ContactsUtils}.
- */
-@SmallTest
-public class ContactsUtilsTests extends AndroidTestCase {
-
-    public void testIsGraphicNull() throws Exception {
-        assertFalse(ContactsUtils.isGraphic(null));
-    }
-
-    public void testIsGraphicEmpty() throws Exception {
-        assertFalse(ContactsUtils.isGraphic(""));
-    }
-
-    public void testIsGraphicSpaces() throws Exception {
-        assertFalse(ContactsUtils.isGraphic("  "));
-    }
-
-    public void testIsGraphicPunctuation() throws Exception {
-        assertTrue(ContactsUtils.isGraphic("."));
-    }
-
-    public void testAreObjectsEqual() throws Exception {
-        assertTrue("null:null", ContactsUtils.areObjectsEqual(null, null));
-        assertTrue("1:1", ContactsUtils.areObjectsEqual(1, 1));
-
-        assertFalse("null:1", ContactsUtils.areObjectsEqual(null, 1));
-        assertFalse("1:null", ContactsUtils.areObjectsEqual(1, null));
-        assertFalse("1:2", ContactsUtils.areObjectsEqual(1, 2));
-    }
-
-    public void testAreIntentActionEqual() throws Exception {
-        assertTrue("1", ContactsUtils.areIntentActionEqual(null, null));
-        assertTrue("1", ContactsUtils.areIntentActionEqual(new Intent("a"), new Intent("a")));
-
-        assertFalse("11", ContactsUtils.areIntentActionEqual(new Intent("a"), null));
-        assertFalse("12", ContactsUtils.areIntentActionEqual(null, new Intent("a")));
-
-        assertFalse("21", ContactsUtils.areIntentActionEqual(new Intent("a"), new Intent()));
-        assertFalse("22", ContactsUtils.areIntentActionEqual(new Intent(), new Intent("b")));
-        assertFalse("23", ContactsUtils.areIntentActionEqual(new Intent("a"), new Intent("b")));
-    }
-}
diff --git a/tests/src/com/android/contacts/RawContactDeltaListTests.java b/tests/src/com/android/contacts/RawContactDeltaListTests.java
deleted file mode 100644
index 6a75b81..0000000
--- a/tests/src/com/android/contacts/RawContactDeltaListTests.java
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import static android.content.ContentProviderOperation.TYPE_ASSERT;
-import static android.content.ContentProviderOperation.TYPE_DELETE;
-import static android.content.ContentProviderOperation.TYPE_INSERT;
-import static android.content.ContentProviderOperation.TYPE_UPDATE;
-
-import android.content.ContentProviderOperation;
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import android.provider.BaseColumns;
-import android.provider.ContactsContract.AggregationExceptions;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import com.android.contacts.RawContactModifierTests.MockContactsSource;
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.RawContactDelta;
-import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
-import com.android.contacts.common.model.account.AccountType;
-import com.google.common.collect.Lists;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-
-/**
- * Tests for {@link RawContactDeltaList} which focus on "diff" operations that should
- * create {@link AggregationExceptions} in certain cases.
- */
-@LargeTest
-public class RawContactDeltaListTests extends AndroidTestCase {
-    public static final String TAG = RawContactDeltaListTests.class.getSimpleName();
-
-    private static final long CONTACT_FIRST = 1;
-    private static final long CONTACT_SECOND = 2;
-
-    public static final long CONTACT_BOB = 10;
-    public static final long CONTACT_MARY = 11;
-
-    public static final long PHONE_RED = 20;
-    public static final long PHONE_GREEN = 21;
-    public static final long PHONE_BLUE = 22;
-
-    public static final long EMAIL_YELLOW = 25;
-
-    public static final long VER_FIRST = 100;
-    public static final long VER_SECOND = 200;
-
-    public static final String TEST_PHONE = "555-1212";
-    public static final String TEST_ACCOUNT = "org.example.test";
-
-    public RawContactDeltaListTests() {
-        super();
-    }
-
-    @Override
-    public void setUp() {
-        mContext = getContext();
-    }
-
-    /**
-     * Build a {@link AccountType} that has various odd constraints for
-     * testing purposes.
-     */
-    protected AccountType getAccountType() {
-        return new MockContactsSource();
-    }
-
-    static ContentValues getValues(ContentProviderOperation operation)
-            throws NoSuchFieldException, IllegalAccessException {
-        final Field field = ContentProviderOperation.class.getDeclaredField("mValues");
-        field.setAccessible(true);
-        return (ContentValues) field.get(operation);
-    }
-
-    static RawContactDelta getUpdate(Context context, long rawContactId) {
-        final RawContact before = RawContactDeltaTests.getRawContact(context, rawContactId,
-                RawContactDeltaTests.TEST_PHONE_ID);
-        return RawContactDelta.fromBefore(before);
-    }
-
-    static RawContactDelta getInsert() {
-        final ContentValues after = new ContentValues();
-        after.put(RawContacts.ACCOUNT_NAME, RawContactDeltaTests.TEST_ACCOUNT_NAME);
-        after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
-
-        final ValuesDelta values = ValuesDelta.fromAfter(after);
-        return new RawContactDelta(values);
-    }
-
-    static RawContactDeltaList buildSet(RawContactDelta... deltas) {
-        final RawContactDeltaList set = new RawContactDeltaList();
-        Collections.addAll(set, deltas);
-        return set;
-    }
-
-    static RawContactDelta buildBeforeEntity(Context context, long rawContactId, long version,
-            ContentValues... entries) {
-        // Build an existing contact read from database
-        final ContentValues contact = new ContentValues();
-        contact.put(RawContacts.VERSION, version);
-        contact.put(RawContacts._ID, rawContactId);
-        final RawContact before = new RawContact(contact);
-        for (ContentValues entry : entries) {
-            before.addDataItemValues(entry);
-        }
-        return RawContactDelta.fromBefore(before);
-    }
-
-    static RawContactDelta buildAfterEntity(ContentValues... entries) {
-        // Build an existing contact read from database
-        final ContentValues contact = new ContentValues();
-        contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT);
-        final RawContactDelta after = new RawContactDelta(ValuesDelta.fromAfter(contact));
-        for (ContentValues entry : entries) {
-            after.addEntry(ValuesDelta.fromAfter(entry));
-        }
-        return after;
-    }
-
-    static ContentValues buildPhone(long phoneId) {
-        return buildPhone(phoneId, Long.toString(phoneId));
-    }
-
-    static ContentValues buildPhone(long phoneId, String value) {
-        final ContentValues values = new ContentValues();
-        values.put(Data._ID, phoneId);
-        values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        values.put(Phone.NUMBER, value);
-        values.put(Phone.TYPE, Phone.TYPE_HOME);
-        return values;
-    }
-
-    static ContentValues buildEmail(long emailId) {
-        final ContentValues values = new ContentValues();
-        values.put(Data._ID, emailId);
-        values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-        values.put(Email.DATA, Long.toString(emailId));
-        values.put(Email.TYPE, Email.TYPE_HOME);
-        return values;
-    }
-
-    static void insertPhone(RawContactDeltaList set, long rawContactId, ContentValues values) {
-        final RawContactDelta match = set.getByRawContactId(rawContactId);
-        match.addEntry(ValuesDelta.fromAfter(values));
-    }
-
-    static ValuesDelta getPhone(RawContactDeltaList set, long rawContactId, long dataId) {
-        final RawContactDelta match = set.getByRawContactId(rawContactId);
-        return match.getEntry(dataId);
-    }
-
-    static void assertDiffPattern(RawContactDelta delta, ContentProviderOperation... pattern) {
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        delta.buildAssert(diff);
-        delta.buildDiff(diff);
-        assertDiffPattern(diff, pattern);
-    }
-
-    static void assertDiffPattern(RawContactDeltaList set, ContentProviderOperation... pattern) {
-        assertDiffPattern(set.buildDiff(), pattern);
-    }
-
-    static void assertDiffPattern(ArrayList<ContentProviderOperation> diff,
-            ContentProviderOperation... pattern) {
-        assertEquals("Unexpected operations", pattern.length, diff.size());
-        for (int i = 0; i < pattern.length; i++) {
-            final ContentProviderOperation expected = pattern[i];
-            final ContentProviderOperation found = diff.get(i);
-
-            assertEquals("Unexpected uri", expected.getUri(), found.getUri());
-
-            final String expectedType = getStringForType(expected.getType());
-            final String foundType = getStringForType(found.getType());
-            assertEquals("Unexpected type", expectedType, foundType);
-
-            if (expected.getType() == TYPE_DELETE) continue;
-
-            try {
-                final ContentValues expectedValues = getValues(expected);
-                final ContentValues foundValues = getValues(found);
-
-                expectedValues.remove(BaseColumns._ID);
-                foundValues.remove(BaseColumns._ID);
-
-                assertEquals("Unexpected values", expectedValues, foundValues);
-            } catch (NoSuchFieldException e) {
-                fail(e.toString());
-            } catch (IllegalAccessException e) {
-                fail(e.toString());
-            }
-        }
-    }
-
-    static String getStringForType(int type) {
-        switch (type) {
-            case TYPE_ASSERT: return "TYPE_ASSERT";
-            case TYPE_INSERT: return "TYPE_INSERT";
-            case TYPE_UPDATE: return "TYPE_UPDATE";
-            case TYPE_DELETE: return "TYPE_DELETE";
-            default: return Integer.toString(type);
-        }
-    }
-
-    static ContentProviderOperation buildAssertVersion(long version) {
-        final ContentValues values = new ContentValues();
-        values.put(RawContacts.VERSION, version);
-        return buildOper(RawContacts.CONTENT_URI, TYPE_ASSERT, values);
-    }
-
-    static ContentProviderOperation buildAggregationModeUpdate(int mode) {
-        final ContentValues values = new ContentValues();
-        values.put(RawContacts.AGGREGATION_MODE, mode);
-        return buildOper(RawContacts.CONTENT_URI, TYPE_UPDATE, values);
-    }
-
-    static ContentProviderOperation buildUpdateAggregationSuspended() {
-        return buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_SUSPENDED);
-    }
-
-    static ContentProviderOperation buildUpdateAggregationDefault() {
-        return buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT);
-    }
-
-    static ContentProviderOperation buildUpdateAggregationKeepTogether(long rawContactId) {
-        final ContentValues values = new ContentValues();
-        values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId);
-        values.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
-        return buildOper(AggregationExceptions.CONTENT_URI, TYPE_UPDATE, values);
-    }
-
-    static ContentValues buildDataInsert(ValuesDelta values, long rawContactId) {
-        final ContentValues insertValues = values.getCompleteValues();
-        insertValues.put(Data.RAW_CONTACT_ID, rawContactId);
-        return insertValues;
-    }
-
-    static ContentProviderOperation buildDelete(Uri uri) {
-        return buildOper(uri, TYPE_DELETE, (ContentValues)null);
-    }
-
-    static ContentProviderOperation buildOper(Uri uri, int type, ValuesDelta values) {
-        return buildOper(uri, type, values.getCompleteValues());
-    }
-
-    static ContentProviderOperation buildOper(Uri uri, int type, ContentValues values) {
-        switch (type) {
-            case TYPE_ASSERT:
-                return ContentProviderOperation.newAssertQuery(uri).withValues(values).build();
-            case TYPE_INSERT:
-                return ContentProviderOperation.newInsert(uri).withValues(values).build();
-            case TYPE_UPDATE:
-                return ContentProviderOperation.newUpdate(uri).withValues(values).build();
-            case TYPE_DELETE:
-                return ContentProviderOperation.newDelete(uri).build();
-        }
-        return null;
-    }
-
-    static Long getVersion(RawContactDeltaList set, Long rawContactId) {
-        return set.getByRawContactId(rawContactId).getValues().getAsLong(RawContacts.VERSION);
-    }
-
-    /**
-     * Count number of {@link AggregationExceptions} updates contained in the
-     * given list of {@link ContentProviderOperation}.
-     */
-    static int countExceptionUpdates(ArrayList<ContentProviderOperation> diff) {
-        int updateCount = 0;
-        for (ContentProviderOperation oper : diff) {
-            if (AggregationExceptions.CONTENT_URI.equals(oper.getUri())
-                    && oper.getType() == ContentProviderOperation.TYPE_UPDATE) {
-                updateCount++;
-            }
-        }
-        return updateCount;
-    }
-
-    public void testInsert() {
-        final RawContactDelta insert = getInsert();
-        final RawContactDeltaList set = buildSet(insert);
-
-        // Inserting single shouldn't create rules
-        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
-        final int exceptionCount = countExceptionUpdates(diff);
-        assertEquals("Unexpected exception updates", 0, exceptionCount);
-    }
-
-    public void testUpdateUpdate() {
-        final RawContactDelta updateFirst = getUpdate(mContext, CONTACT_FIRST);
-        final RawContactDelta updateSecond = getUpdate(mContext, CONTACT_SECOND);
-        final RawContactDeltaList set = buildSet(updateFirst, updateSecond);
-
-        // Updating two existing shouldn't create rules
-        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
-        final int exceptionCount = countExceptionUpdates(diff);
-        assertEquals("Unexpected exception updates", 0, exceptionCount);
-    }
-
-    public void testUpdateInsert() {
-        final RawContactDelta update = getUpdate(mContext, CONTACT_FIRST);
-        final RawContactDelta insert = getInsert();
-        final RawContactDeltaList set = buildSet(update, insert);
-
-        // New insert should only create one rule
-        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
-        final int exceptionCount = countExceptionUpdates(diff);
-        assertEquals("Unexpected exception updates", 1, exceptionCount);
-    }
-
-    public void testInsertUpdateInsert() {
-        final RawContactDelta insertFirst = getInsert();
-        final RawContactDelta update = getUpdate(mContext, CONTACT_FIRST);
-        final RawContactDelta insertSecond = getInsert();
-        final RawContactDeltaList set = buildSet(insertFirst, update, insertSecond);
-
-        // Two inserts should create two rules to bind against single existing
-        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
-        final int exceptionCount = countExceptionUpdates(diff);
-        assertEquals("Unexpected exception updates", 2, exceptionCount);
-    }
-
-    public void testInsertInsertInsert() {
-        final RawContactDelta insertFirst = getInsert();
-        final RawContactDelta insertSecond = getInsert();
-        final RawContactDelta insertThird = getInsert();
-        final RawContactDeltaList set = buildSet(insertFirst, insertSecond, insertThird);
-
-        // Three new inserts should create only two binding rules
-        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
-        final int exceptionCount = countExceptionUpdates(diff);
-        assertEquals("Unexpected exception updates", 2, exceptionCount);
-    }
-
-    public void testMergeDataRemoteInsert() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildPhone(PHONE_RED), buildPhone(PHONE_GREEN)));
-
-        // Merge in second version, verify they match
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertEquals("Unexpected change when merging", second, merged);
-    }
-
-    public void testMergeDataLocalUpdateRemoteInsert() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildPhone(PHONE_RED), buildPhone(PHONE_GREEN)));
-
-        // Change the local number to trigger update
-        final ValuesDelta phone = getPhone(first, CONTACT_BOB, PHONE_RED);
-        phone.put(Phone.NUMBER, TEST_PHONE);
-
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()),
-                buildUpdateAggregationDefault());
-
-        // Merge in the second version, verify diff matches
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged,
-                buildAssertVersion(VER_SECOND),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()),
-                buildUpdateAggregationDefault());
-    }
-
-    public void testMergeDataLocalUpdateRemoteDelete() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildPhone(PHONE_GREEN)));
-
-        // Change the local number to trigger update
-        final ValuesDelta phone = getPhone(first, CONTACT_BOB, PHONE_RED);
-        phone.put(Phone.NUMBER, TEST_PHONE);
-
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()),
-                buildUpdateAggregationDefault());
-
-        // Merge in the second version, verify that our update changed to
-        // insert, since RED was deleted on remote side
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged,
-                buildAssertVersion(VER_SECOND),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(phone, CONTACT_BOB)),
-                buildUpdateAggregationDefault());
-    }
-
-    public void testMergeDataLocalDeleteRemoteUpdate() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildPhone(PHONE_RED, TEST_PHONE)));
-
-        // Delete phone locally
-        final ValuesDelta phone = getPhone(first, CONTACT_BOB, PHONE_RED);
-        phone.markDeleted();
-
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildUpdateAggregationSuspended(),
-                buildDelete(Data.CONTENT_URI),
-                buildUpdateAggregationDefault());
-
-        // Merge in the second version, verify that our delete remains
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged,
-                buildAssertVersion(VER_SECOND),
-                buildUpdateAggregationSuspended(),
-                buildDelete(Data.CONTENT_URI),
-                buildUpdateAggregationDefault());
-    }
-
-    public void testMergeDataLocalInsertRemoteInsert() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildPhone(PHONE_RED), buildPhone(PHONE_GREEN)));
-
-        // Insert new phone locally
-        final ValuesDelta bluePhone = ValuesDelta.fromAfter(buildPhone(PHONE_BLUE));
-        first.getByRawContactId(CONTACT_BOB).addEntry(bluePhone);
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bluePhone, CONTACT_BOB)),
-                buildUpdateAggregationDefault());
-
-        // Merge in the second version, verify that our insert remains
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged,
-                buildAssertVersion(VER_SECOND),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bluePhone, CONTACT_BOB)),
-                buildUpdateAggregationDefault());
-    }
-
-    public void testMergeRawContactLocalInsertRemoteInsert() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildPhone(PHONE_RED)), buildBeforeEntity(mContext, CONTACT_MARY,
-                        VER_SECOND, buildPhone(PHONE_RED)));
-
-        // Add new contact locally, should remain insert
-        final ContentValues joePhoneInsert = buildPhone(PHONE_BLUE);
-        final RawContactDelta joeContact = buildAfterEntity(joePhoneInsert);
-        final ContentValues joeContactInsert = joeContact.getValues().getCompleteValues();
-        joeContactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
-        first.add(joeContact);
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildOper(RawContacts.CONTENT_URI, TYPE_INSERT, joeContactInsert),
-                buildOper(Data.CONTENT_URI, TYPE_INSERT, joePhoneInsert),
-                buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT),
-                buildUpdateAggregationKeepTogether(CONTACT_BOB));
-
-        // Merge in the second version, verify that our insert remains
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged,
-                buildAssertVersion(VER_SECOND),
-                buildAssertVersion(VER_SECOND),
-                buildOper(RawContacts.CONTENT_URI, TYPE_INSERT, joeContactInsert),
-                buildOper(Data.CONTENT_URI, TYPE_INSERT, joePhoneInsert),
-                buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT),
-                buildUpdateAggregationKeepTogether(CONTACT_BOB));
-    }
-
-    public void testMergeRawContactLocalDeleteRemoteDelete() {
-        final RawContactDeltaList first = buildSet(
-                buildBeforeEntity(mContext, CONTACT_BOB, VER_FIRST, buildPhone(PHONE_RED)),
-                buildBeforeEntity(mContext, CONTACT_MARY, VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(
-                buildBeforeEntity(mContext, CONTACT_BOB, VER_SECOND, buildPhone(PHONE_RED)));
-
-        // Remove contact locally
-        first.getByRawContactId(CONTACT_MARY).markDeleted();
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildAssertVersion(VER_FIRST),
-                buildDelete(RawContacts.CONTENT_URI));
-
-        // Merge in the second version, verify that our delete isn't needed
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged);
-    }
-
-    public void testMergeRawContactLocalUpdateRemoteDelete() {
-        final RawContactDeltaList first = buildSet(
-                buildBeforeEntity(mContext, CONTACT_BOB, VER_FIRST, buildPhone(PHONE_RED)),
-                buildBeforeEntity(mContext, CONTACT_MARY, VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(
-                buildBeforeEntity(mContext, CONTACT_BOB, VER_SECOND, buildPhone(PHONE_RED)));
-
-        // Perform local update
-        final ValuesDelta phone = getPhone(first, CONTACT_MARY, PHONE_RED);
-        phone.put(Phone.NUMBER, TEST_PHONE);
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildAssertVersion(VER_FIRST),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()),
-                buildUpdateAggregationDefault());
-
-        final ContentValues phoneInsert = phone.getCompleteValues();
-        final ContentValues contactInsert = first.getByRawContactId(CONTACT_MARY).getValues()
-                .getCompleteValues();
-        contactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
-
-        // Merge and verify that update turned into insert
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged,
-                buildAssertVersion(VER_SECOND),
-                buildOper(RawContacts.CONTENT_URI, TYPE_INSERT, contactInsert),
-                buildOper(Data.CONTENT_URI, TYPE_INSERT, phoneInsert),
-                buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT),
-                buildUpdateAggregationKeepTogether(CONTACT_BOB));
-    }
-
-    public void testMergeUsesNewVersion() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildPhone(PHONE_RED)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildPhone(PHONE_RED)));
-
-        assertEquals((Long)VER_FIRST, getVersion(first, CONTACT_BOB));
-        assertEquals((Long)VER_SECOND, getVersion(second, CONTACT_BOB));
-
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertEquals((Long)VER_SECOND, getVersion(merged, CONTACT_BOB));
-    }
-
-    public void testMergeAfterEnsureAndTrim() {
-        final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_FIRST, buildEmail(EMAIL_YELLOW)));
-        final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
-                VER_SECOND, buildEmail(EMAIL_YELLOW)));
-
-        // Ensure we have at least one phone
-        final AccountType source = getAccountType();
-        final RawContactDelta bobContact = first.getByRawContactId(CONTACT_BOB);
-        RawContactModifier.ensureKindExists(bobContact, source, Phone.CONTENT_ITEM_TYPE);
-        final ValuesDelta bobPhone = bobContact.getSuperPrimaryEntry(Phone.CONTENT_ITEM_TYPE, true);
-
-        // Make sure the update would insert a row
-        assertDiffPattern(first,
-                buildAssertVersion(VER_FIRST),
-                buildUpdateAggregationSuspended(),
-                buildOper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bobPhone, CONTACT_BOB)),
-                buildUpdateAggregationDefault());
-
-        // Trim values and ensure that we don't insert things
-        RawContactModifier.trimEmpty(bobContact, source);
-        assertDiffPattern(first);
-
-        // Now re-parent the change, which should remain no-op
-        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
-        assertDiffPattern(merged);
-    }
-}
diff --git a/tests/src/com/android/contacts/RawContactDeltaTests.java b/tests/src/com/android/contacts/RawContactDeltaTests.java
deleted file mode 100644
index dc4eb53..0000000
--- a/tests/src/com/android/contacts/RawContactDeltaTests.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import static android.content.ContentProviderOperation.TYPE_ASSERT;
-import static android.content.ContentProviderOperation.TYPE_DELETE;
-import static android.content.ContentProviderOperation.TYPE_INSERT;
-import static android.content.ContentProviderOperation.TYPE_UPDATE;
-
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderOperation.Builder;
-import android.content.ContentValues;
-import android.content.Context;
-import android.os.Parcel;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.RawContactDelta;
-import com.android.contacts.common.model.ValuesDelta;
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-
-/**
- * Tests for {@link RawContactDelta} and {@link ValuesDelta}. These tests
- * focus on passing changes across {@link Parcel}, and verifying that they
- * correctly build expected "diff" operations.
- */
-@LargeTest
-public class RawContactDeltaTests extends AndroidTestCase {
-    public static final String TAG = "EntityDeltaTests";
-
-    public static final long TEST_CONTACT_ID = 12;
-    public static final long TEST_PHONE_ID = 24;
-
-    public static final String TEST_PHONE_NUMBER_1 = "218-555-1111";
-    public static final String TEST_PHONE_NUMBER_2 = "218-555-2222";
-
-    public static final String TEST_ACCOUNT_NAME = "TEST";
-
-    public RawContactDeltaTests() {
-        super();
-    }
-
-    @Override
-    public void setUp() {
-        mContext = getContext();
-    }
-
-    public static RawContact getRawContact(Context context, long contactId, long phoneId) {
-        // Build an existing contact read from database
-        final ContentValues contact = new ContentValues();
-        contact.put(RawContacts.VERSION, 43);
-        contact.put(RawContacts._ID, contactId);
-
-        final ContentValues phone = new ContentValues();
-        phone.put(Data._ID, phoneId);
-        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_1);
-        phone.put(Phone.TYPE, Phone.TYPE_HOME);
-
-        final RawContact before = new RawContact(contact);
-        before.addDataItemValues(phone);
-        return before;
-    }
-
-    /**
-     * Test that {@link RawContactDelta#mergeAfter(RawContactDelta)} correctly passes
-     * any changes through the {@link Parcel} object. This enforces that
-     * {@link RawContactDelta} should be identical when serialized against the same
-     * "before" {@link RawContact}.
-     */
-    public void testParcelChangesNone() {
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-        final RawContactDelta dest = RawContactDelta.fromBefore(before);
-
-        // Merge modified values and assert they match
-        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
-        assertEquals("Unexpected change when merging", source, merged);
-    }
-
-    public void testParcelChangesInsert() {
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-        final RawContactDelta dest = RawContactDelta.fromBefore(before);
-
-        // Add a new row and pass across parcel, should be same
-        final ContentValues phone = new ContentValues();
-        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
-        phone.put(Phone.TYPE, Phone.TYPE_WORK);
-        source.addEntry(ValuesDelta.fromAfter(phone));
-
-        // Merge modified values and assert they match
-        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
-        assertEquals("Unexpected change when merging", source, merged);
-    }
-
-    public void testParcelChangesUpdate() {
-        // Update existing row and pass across parcel, should be same
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-        final RawContactDelta dest = RawContactDelta.fromBefore(before);
-
-        final ValuesDelta child = source.getEntry(TEST_PHONE_ID);
-        child.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
-
-        // Merge modified values and assert they match
-        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
-        assertEquals("Unexpected change when merging", source, merged);
-    }
-
-    public void testParcelChangesDelete() {
-        // Delete a row and pass across parcel, should be same
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-        final RawContactDelta dest = RawContactDelta.fromBefore(before);
-
-        final ValuesDelta child = source.getEntry(TEST_PHONE_ID);
-        child.markDeleted();
-
-        // Merge modified values and assert they match
-        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
-        assertEquals("Unexpected change when merging", source, merged);
-    }
-
-    public void testValuesDiffDelete() {
-        final ContentValues before = new ContentValues();
-        before.put(Data._ID, TEST_PHONE_ID);
-        before.put(Phone.NUMBER, TEST_PHONE_NUMBER_1);
-
-        final ValuesDelta values = ValuesDelta.fromBefore(before);
-        values.markDeleted();
-
-        // Should produce a delete action
-        final Builder builder = values.buildDiff(Data.CONTENT_URI);
-        final int type = builder.build().getType();
-        assertEquals("Didn't produce delete action", TYPE_DELETE, type);
-    }
-
-    /**
-     * Test that {@link RawContactDelta#buildDiff(ArrayList)} is correctly built for
-     * insert, update, and delete cases. This only tests a subset of possible
-     * {@link Data} row changes.
-     */
-    public void testEntityDiffNone() {
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-
-        // Assert that writing unchanged produces few operations
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        source.buildDiff(diff);
-
-        assertTrue("Created changes when none needed", (diff.size() == 0));
-    }
-
-    public void testEntityDiffNoneInsert() {
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-
-        // Insert a new phone number
-        final ContentValues phone = new ContentValues();
-        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
-        phone.put(Phone.TYPE, Phone.TYPE_WORK);
-        source.addEntry(ValuesDelta.fromAfter(phone));
-
-        // Assert two operations: insert Data row and enforce version
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        source.buildAssert(diff);
-        source.buildDiff(diff);
-        assertEquals("Unexpected operations", 4, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(3);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testEntityDiffUpdateInsert() {
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-
-        // Update parent contact values
-        source.getValues().put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED);
-
-        // Insert a new phone number
-        final ContentValues phone = new ContentValues();
-        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
-        phone.put(Phone.TYPE, Phone.TYPE_WORK);
-        source.addEntry(ValuesDelta.fromAfter(phone));
-
-        // Assert three operations: update Contact, insert Data row, enforce version
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        source.buildAssert(diff);
-        source.buildDiff(diff);
-        assertEquals("Unexpected operations", 5, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(3);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(4);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testEntityDiffNoneUpdate() {
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-
-        // Update existing phone number
-        final ValuesDelta child = source.getEntry(TEST_PHONE_ID);
-        child.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
-
-        // Assert that version is enforced
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        source.buildAssert(diff);
-        source.buildDiff(diff);
-        assertEquals("Unexpected operations", 4, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(3);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testEntityDiffDelete() {
-        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
-        final RawContactDelta source = RawContactDelta.fromBefore(before);
-
-        // Delete entire entity
-        source.getValues().markDeleted();
-
-        // Assert two operations: delete Contact and enforce version
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        source.buildAssert(diff);
-        source.buildDiff(diff);
-        assertEquals("Unexpected operations", 2, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testEntityDiffInsert() {
-        // Insert a RawContact
-        final ContentValues after = new ContentValues();
-        after.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
-        after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
-
-        final ValuesDelta values = ValuesDelta.fromAfter(after);
-        final RawContactDelta source = new RawContactDelta(values);
-
-        // Assert two operations: delete Contact and enforce version
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        source.buildAssert(diff);
-        source.buildDiff(diff);
-        assertEquals("Unexpected operations", 2, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testEntityDiffInsertInsert() {
-        // Insert a RawContact
-        final ContentValues after = new ContentValues();
-        after.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
-        after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
-
-        final ValuesDelta values = ValuesDelta.fromAfter(after);
-        final RawContactDelta source = new RawContactDelta(values);
-
-        // Insert a new phone number
-        final ContentValues phone = new ContentValues();
-        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
-        phone.put(Phone.TYPE, Phone.TYPE_WORK);
-        source.addEntry(ValuesDelta.fromAfter(phone));
-
-        // Assert two operations: delete Contact and enforce version
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        source.buildAssert(diff);
-        source.buildDiff(diff);
-        assertEquals("Unexpected operations", 3, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-
-        }
-    }
-}
diff --git a/tests/src/com/android/contacts/RawContactModifierTests.java b/tests/src/com/android/contacts/RawContactModifierTests.java
deleted file mode 100644
index ce69b55..0000000
--- a/tests/src/com/android/contacts/RawContactModifierTests.java
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import static android.content.ContentProviderOperation.TYPE_DELETE;
-import static android.content.ContentProviderOperation.TYPE_INSERT;
-import static android.content.ContentProviderOperation.TYPE_UPDATE;
-
-import android.content.ContentProviderOperation;
-import android.content.ContentValues;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Event;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Intents.Insert;
-import android.provider.ContactsContract.RawContacts;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.RawContactDelta;
-import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountType.EditType;
-import com.android.contacts.common.model.account.ExchangeAccountType;
-import com.android.contacts.common.model.account.GoogleAccountType;
-import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.common.test.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.common.test.mocks.MockContentProvider;
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for {@link RawContactModifier} to verify that {@link AccountType}
- * constraints are being enforced correctly.
- */
-@LargeTest
-public class RawContactModifierTests extends AndroidTestCase {
-    public static final String TAG = "EntityModifierTests";
-
-    public static final long VER_FIRST = 100;
-
-    private static final long TEST_ID = 4;
-    private static final String TEST_PHONE = "218-555-1212";
-    private static final String TEST_NAME = "Adam Young";
-    private static final String TEST_NAME2 = "Breanne Duren";
-    private static final String TEST_IM = "example@example.com";
-    private static final String TEST_POSTAL = "1600 Amphitheatre Parkway";
-
-    private static final String TEST_ACCOUNT_NAME = "unittest@example.com";
-    private static final String TEST_ACCOUNT_TYPE = "com.example.unittest";
-
-    private static final String EXCHANGE_ACCT_TYPE = "com.android.exchange";
-
-    @Override
-    public void setUp() {
-        mContext = getContext();
-    }
-
-    public static class MockContactsSource extends AccountType {
-
-        MockContactsSource() {
-            try {
-                this.accountType = TEST_ACCOUNT_TYPE;
-
-                final DataKind nameKind = new DataKind(StructuredName.CONTENT_ITEM_TYPE,
-                        R.string.nameLabelsGroup, -1, true);
-                nameKind.typeOverallMax = 1;
-                addKind(nameKind);
-
-                // Phone allows maximum 2 home, 1 work, and unlimited other, with
-                // constraint of 5 numbers maximum.
-                final DataKind phoneKind = new DataKind(
-                        Phone.CONTENT_ITEM_TYPE, -1, 10, true);
-
-                phoneKind.typeOverallMax = 5;
-                phoneKind.typeColumn = Phone.TYPE;
-                phoneKind.typeList = Lists.newArrayList();
-                phoneKind.typeList.add(new EditType(Phone.TYPE_HOME, -1).setSpecificMax(2));
-                phoneKind.typeList.add(new EditType(Phone.TYPE_WORK, -1).setSpecificMax(1));
-                phoneKind.typeList.add(new EditType(Phone.TYPE_FAX_WORK, -1).setSecondary(true));
-                phoneKind.typeList.add(new EditType(Phone.TYPE_OTHER, -1));
-
-                phoneKind.fieldList = Lists.newArrayList();
-                phoneKind.fieldList.add(new EditField(Phone.NUMBER, -1, -1));
-                phoneKind.fieldList.add(new EditField(Phone.LABEL, -1, -1));
-
-                addKind(phoneKind);
-
-                // Email is unlimited
-                final DataKind emailKind = new DataKind(Email.CONTENT_ITEM_TYPE, -1, 10, true);
-                emailKind.typeOverallMax = -1;
-                emailKind.fieldList = Lists.newArrayList();
-                emailKind.fieldList.add(new EditField(Email.DATA, -1, -1));
-                addKind(emailKind);
-
-                // IM is only one
-                final DataKind imKind = new DataKind(Im.CONTENT_ITEM_TYPE, -1, 10, true);
-                imKind.typeOverallMax = 1;
-                imKind.fieldList = Lists.newArrayList();
-                imKind.fieldList.add(new EditField(Im.DATA, -1, -1));
-                addKind(imKind);
-
-                // Organization is only one
-                final DataKind orgKind = new DataKind(Organization.CONTENT_ITEM_TYPE, -1, 10, true);
-                orgKind.typeOverallMax = 1;
-                orgKind.fieldList = Lists.newArrayList();
-                orgKind.fieldList.add(new EditField(Organization.COMPANY, -1, -1));
-                orgKind.fieldList.add(new EditField(Organization.TITLE, -1, -1));
-                addKind(orgKind);
-            } catch (DefinitionException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public boolean isGroupMembershipEditable() {
-            return false;
-        }
-
-        @Override
-        public boolean areContactsWritable() {
-            return true;
-        }
-    }
-
-    /**
-     * Build a {@link AccountType} that has various odd constraints for
-     * testing purposes.
-     */
-    protected AccountType getAccountType() {
-        return new MockContactsSource();
-    }
-
-    /**
-     * Build {@link AccountTypeManager} instance.
-     */
-    protected AccountTypeManager getAccountTypes(AccountType... types) {
-        return new MockAccountTypeManager(types, null);
-    }
-
-    /**
-     * Build an {@link RawContact} with the requested set of phone numbers.
-     */
-    protected RawContactDelta getRawContact(Long existingId, ContentValues... entries) {
-        final ContentValues contact = new ContentValues();
-        if (existingId != null) {
-            contact.put(RawContacts._ID, existingId);
-        }
-        contact.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
-        contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT_TYPE);
-
-        final RawContact before = new RawContact(contact);
-        for (ContentValues values : entries) {
-            before.addDataItemValues(values);
-        }
-        return RawContactDelta.fromBefore(before);
-    }
-
-    /**
-     * Assert this {@link List} contains the given {@link Object}.
-     */
-    protected void assertContains(List<?> list, Object object) {
-        assertTrue("Missing expected value", list.contains(object));
-    }
-
-    /**
-     * Assert this {@link List} does not contain the given {@link Object}.
-     */
-    protected void assertNotContains(List<?> list, Object object) {
-        assertFalse("Contained unexpected value", list.contains(object));
-    }
-
-    /**
-     * Insert various rows to test
-     * {@link RawContactModifier#getValidTypes(RawContactDelta, DataKind, EditType)}
-     */
-    public void testValidTypes() {
-        // Build a source and pull specific types
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-        final EditType typeWork = RawContactModifier.getType(kindPhone, Phone.TYPE_WORK);
-        final EditType typeOther = RawContactModifier.getType(kindPhone, Phone.TYPE_OTHER);
-
-        List<EditType> validTypes;
-
-        // Add first home, first work
-        final RawContactDelta state = getRawContact(TEST_ID);
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-        RawContactModifier.insertChild(state, kindPhone, typeWork);
-
-        // Expecting home, other
-        validTypes = RawContactModifier.getValidTypes(state, kindPhone, null);
-        assertContains(validTypes, typeHome);
-        assertNotContains(validTypes, typeWork);
-        assertContains(validTypes, typeOther);
-
-        // Add second home
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-
-        // Expecting other
-        validTypes = RawContactModifier.getValidTypes(state, kindPhone, null);
-        assertNotContains(validTypes, typeHome);
-        assertNotContains(validTypes, typeWork);
-        assertContains(validTypes, typeOther);
-
-        // Add third and fourth home (invalid, but possible)
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-
-        // Expecting none
-        validTypes = RawContactModifier.getValidTypes(state, kindPhone, null);
-        assertNotContains(validTypes, typeHome);
-        assertNotContains(validTypes, typeWork);
-        assertNotContains(validTypes, typeOther);
-    }
-
-    /**
-     * Test {@link RawContactModifier#canInsert(RawContactDelta, DataKind)} by
-     * inserting various rows.
-     */
-    public void testCanInsert() {
-        // Build a source and pull specific types
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-        final EditType typeWork = RawContactModifier.getType(kindPhone, Phone.TYPE_WORK);
-        final EditType typeOther = RawContactModifier.getType(kindPhone, Phone.TYPE_OTHER);
-
-        // Add first home, first work
-        final RawContactDelta state = getRawContact(TEST_ID);
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-        RawContactModifier.insertChild(state, kindPhone, typeWork);
-        assertTrue("Unable to insert", RawContactModifier.canInsert(state, kindPhone));
-
-        // Add two other, which puts us just under "5" overall limit
-        RawContactModifier.insertChild(state, kindPhone, typeOther);
-        RawContactModifier.insertChild(state, kindPhone, typeOther);
-        assertTrue("Unable to insert", RawContactModifier.canInsert(state, kindPhone));
-
-        // Add second home, which should push to snug limit
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-        assertFalse("Able to insert", RawContactModifier.canInsert(state, kindPhone));
-    }
-
-    /**
-     * Test
-     * {@link RawContactModifier#getBestValidType(RawContactDelta, DataKind, boolean, int)}
-     * by asserting expected best options in various states.
-     */
-    public void testBestValidType() {
-        // Build a source and pull specific types
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-        final EditType typeWork = RawContactModifier.getType(kindPhone, Phone.TYPE_WORK);
-        final EditType typeFaxWork = RawContactModifier.getType(kindPhone, Phone.TYPE_FAX_WORK);
-        final EditType typeOther = RawContactModifier.getType(kindPhone, Phone.TYPE_OTHER);
-
-        EditType suggested;
-
-        // Default suggestion should be home
-        final RawContactDelta state = getRawContact(TEST_ID);
-        suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
-        assertEquals("Unexpected suggestion", typeHome, suggested);
-
-        // Add first home, should now suggest work
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-        suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
-        assertEquals("Unexpected suggestion", typeWork, suggested);
-
-        // Add work fax, should still suggest work
-        RawContactModifier.insertChild(state, kindPhone, typeFaxWork);
-        suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
-        assertEquals("Unexpected suggestion", typeWork, suggested);
-
-        // Add other, should still suggest work
-        RawContactModifier.insertChild(state, kindPhone, typeOther);
-        suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
-        assertEquals("Unexpected suggestion", typeWork, suggested);
-
-        // Add work, now should suggest other
-        RawContactModifier.insertChild(state, kindPhone, typeWork);
-        suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
-        assertEquals("Unexpected suggestion", typeOther, suggested);
-    }
-
-    public void testIsEmptyEmpty() {
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-
-        // Test entirely empty row
-        final ContentValues after = new ContentValues();
-        final ValuesDelta values = ValuesDelta.fromAfter(after);
-
-        assertTrue("Expected empty", RawContactModifier.isEmpty(values, kindPhone));
-    }
-
-    public void testIsEmptyDirectFields() {
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Test row that has type values, but core fields are empty
-        final RawContactDelta state = getRawContact(TEST_ID);
-        final ValuesDelta values = RawContactModifier.insertChild(state, kindPhone, typeHome);
-
-        assertTrue("Expected empty", RawContactModifier.isEmpty(values, kindPhone));
-
-        // Insert some data to trigger non-empty state
-        values.put(Phone.NUMBER, TEST_PHONE);
-
-        assertFalse("Expected non-empty", RawContactModifier.isEmpty(values, kindPhone));
-    }
-
-    public void testTrimEmptySingle() {
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Test row that has type values, but core fields are empty
-        final RawContactDelta state = getRawContact(TEST_ID);
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-
-        // Build diff, expecting insert for data row and update enforcement
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 3, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-
-        // Trim empty rows and try again, expecting delete of overall contact
-        RawContactModifier.trimEmpty(state, source);
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 1, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testTrimEmptySpaces() {
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Test row that has type values, but values are spaces
-        final RawContactDelta state = RawContactDeltaListTests.buildBeforeEntity(mContext, TEST_ID,
-                VER_FIRST);
-        final ValuesDelta values = RawContactModifier.insertChild(state, kindPhone, typeHome);
-        values.put(Phone.NUMBER, "   ");
-
-        // Build diff, expecting insert for data row and update enforcement
-        RawContactDeltaListTests.assertDiffPattern(state,
-                RawContactDeltaListTests.buildAssertVersion(VER_FIRST),
-                RawContactDeltaListTests.buildUpdateAggregationSuspended(),
-                RawContactDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
-                        RawContactDeltaListTests.buildDataInsert(values, TEST_ID)),
-                RawContactDeltaListTests.buildUpdateAggregationDefault());
-
-        // Trim empty rows and try again, expecting delete of overall contact
-        RawContactModifier.trimEmpty(state, source);
-        RawContactDeltaListTests.assertDiffPattern(state,
-                RawContactDeltaListTests.buildAssertVersion(VER_FIRST),
-                RawContactDeltaListTests.buildDelete(RawContacts.CONTENT_URI));
-    }
-
-    public void testTrimLeaveValid() {
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Test row that has type values with valid number
-        final RawContactDelta state = RawContactDeltaListTests.buildBeforeEntity(mContext, TEST_ID,
-                VER_FIRST);
-        final ValuesDelta values = RawContactModifier.insertChild(state, kindPhone, typeHome);
-        values.put(Phone.NUMBER, TEST_PHONE);
-
-        // Build diff, expecting insert for data row and update enforcement
-        RawContactDeltaListTests.assertDiffPattern(state,
-                RawContactDeltaListTests.buildAssertVersion(VER_FIRST),
-                RawContactDeltaListTests.buildUpdateAggregationSuspended(),
-                RawContactDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
-                        RawContactDeltaListTests.buildDataInsert(values, TEST_ID)),
-                RawContactDeltaListTests.buildUpdateAggregationDefault());
-
-        // Trim empty rows and try again, expecting no differences
-        RawContactModifier.trimEmpty(state, source);
-        RawContactDeltaListTests.assertDiffPattern(state,
-                RawContactDeltaListTests.buildAssertVersion(VER_FIRST),
-                RawContactDeltaListTests.buildUpdateAggregationSuspended(),
-                RawContactDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
-                        RawContactDeltaListTests.buildDataInsert(values, TEST_ID)),
-                RawContactDeltaListTests.buildUpdateAggregationDefault());
-    }
-
-    public void testTrimEmptyUntouched() {
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Build "before" that has empty row
-        final RawContactDelta state = getRawContact(TEST_ID);
-        final ContentValues before = new ContentValues();
-        before.put(Data._ID, TEST_ID);
-        before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        state.addEntry(ValuesDelta.fromBefore(before));
-
-        // Build diff, expecting no changes
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 0, diff.size());
-
-        // Try trimming existing empty, which we shouldn't touch
-        RawContactModifier.trimEmpty(state, source);
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 0, diff.size());
-    }
-
-    public void testTrimEmptyAfterUpdate() {
-        final AccountType source = getAccountType();
-        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Build "before" that has row with some phone number
-        final ContentValues before = new ContentValues();
-        before.put(Data._ID, TEST_ID);
-        before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        before.put(kindPhone.typeColumn, typeHome.rawValue);
-        before.put(Phone.NUMBER, TEST_PHONE);
-        final RawContactDelta state = getRawContact(TEST_ID, before);
-
-        // Build diff, expecting no changes
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 0, diff.size());
-
-        // Now update row by changing number to empty string, expecting single update
-        final ValuesDelta child = state.getEntry(TEST_ID);
-        child.put(Phone.NUMBER, "");
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 3, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-
-        // Now run trim, which should turn that update into delete
-        RawContactModifier.trimEmpty(state, source);
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 1, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testTrimInsertEmpty() {
-        final AccountType accountType = getAccountType();
-        final AccountTypeManager accountTypes = getAccountTypes(accountType);
-        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Try creating a contact without any child entries
-        final RawContactDelta state = getRawContact(null);
-        final RawContactDeltaList set = new RawContactDeltaList();
-        set.add(state);
-
-
-        // Build diff, expecting single insert
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 2, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-
-        // Trim empty rows and try again, expecting no insert
-        RawContactModifier.trimEmpty(set, accountTypes);
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 0, diff.size());
-    }
-
-    public void testTrimInsertInsert() {
-        final AccountType accountType = getAccountType();
-        final AccountTypeManager accountTypes = getAccountTypes(accountType);
-        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Try creating a contact with single empty entry
-        final RawContactDelta state = getRawContact(null);
-        RawContactModifier.insertChild(state, kindPhone, typeHome);
-        final RawContactDeltaList set = new RawContactDeltaList();
-        set.add(state);
-
-        // Build diff, expecting two insert operations
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 3, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-
-        // Trim empty rows and try again, expecting silence
-        RawContactModifier.trimEmpty(set, accountTypes);
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 0, diff.size());
-    }
-
-    public void testTrimUpdateRemain() {
-        final AccountType accountType = getAccountType();
-        final AccountTypeManager accountTypes = getAccountTypes(accountType);
-        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Build "before" with two phone numbers
-        final ContentValues first = new ContentValues();
-        first.put(Data._ID, TEST_ID);
-        first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        first.put(kindPhone.typeColumn, typeHome.rawValue);
-        first.put(Phone.NUMBER, TEST_PHONE);
-
-        final ContentValues second = new ContentValues();
-        second.put(Data._ID, TEST_ID);
-        second.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        second.put(kindPhone.typeColumn, typeHome.rawValue);
-        second.put(Phone.NUMBER, TEST_PHONE);
-
-        final RawContactDelta state = getRawContact(TEST_ID, first, second);
-        final RawContactDeltaList set = new RawContactDeltaList();
-        set.add(state);
-
-        // Build diff, expecting no changes
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 0, diff.size());
-
-        // Now update row by changing number to empty string, expecting single update
-        final ValuesDelta child = state.getEntry(TEST_ID);
-        child.put(Phone.NUMBER, "");
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 3, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-
-        // Now run trim, which should turn that update into delete
-        RawContactModifier.trimEmpty(set, accountTypes);
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 3, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testTrimUpdateUpdate() {
-        final AccountType accountType = getAccountType();
-        final AccountTypeManager accountTypes = getAccountTypes(accountType);
-        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
-
-        // Build "before" with two phone numbers
-        final ContentValues first = new ContentValues();
-        first.put(Data._ID, TEST_ID);
-        first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        first.put(kindPhone.typeColumn, typeHome.rawValue);
-        first.put(Phone.NUMBER, TEST_PHONE);
-
-        final RawContactDelta state = getRawContact(TEST_ID, first);
-        final RawContactDeltaList set = new RawContactDeltaList();
-        set.add(state);
-
-        // Build diff, expecting no changes
-        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 0, diff.size());
-
-        // Now update row by changing number to empty string, expecting single update
-        final ValuesDelta child = state.getEntry(TEST_ID);
-        child.put(Phone.NUMBER, "");
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 3, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(1);
-            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
-        }
-        {
-            final ContentProviderOperation oper = diff.get(2);
-            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-
-        // Now run trim, which should turn into deleting the whole contact
-        RawContactModifier.trimEmpty(set, accountTypes);
-        diff.clear();
-        state.buildDiff(diff);
-        assertEquals("Unexpected operations", 1, diff.size());
-        {
-            final ContentProviderOperation oper = diff.get(0);
-            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
-            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
-        }
-    }
-
-    public void testParseExtrasExistingName() {
-        final AccountType accountType = getAccountType();
-
-        // Build "before" name
-        final ContentValues first = new ContentValues();
-        first.put(Data._ID, TEST_ID);
-        first.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
-        first.put(StructuredName.GIVEN_NAME, TEST_NAME);
-
-        // Parse extras, making sure we keep single name
-        final RawContactDelta state = getRawContact(TEST_ID, first);
-        final Bundle extras = new Bundle();
-        extras.putString(Insert.NAME, TEST_NAME2);
-        RawContactModifier.parseExtras(mContext, accountType, state, extras);
-
-        final int nameCount = state.getMimeEntriesCount(StructuredName.CONTENT_ITEM_TYPE, true);
-        assertEquals("Unexpected names", 1, nameCount);
-    }
-
-    public void testParseExtrasIgnoreLimit() {
-        final AccountType accountType = getAccountType();
-
-        // Build "before" IM
-        final ContentValues first = new ContentValues();
-        first.put(Data._ID, TEST_ID);
-        first.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
-        first.put(Im.DATA, TEST_IM);
-
-        final RawContactDelta state = getRawContact(TEST_ID, first);
-        final int beforeCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size();
-
-        // We should ignore data that doesn't fit account type rules, since account type
-        // only allows single Im
-        final Bundle extras = new Bundle();
-        extras.putInt(Insert.IM_PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
-        extras.putString(Insert.IM_HANDLE, TEST_IM);
-        RawContactModifier.parseExtras(mContext, accountType, state, extras);
-
-        final int afterCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size();
-        assertEquals("Broke account type rules", beforeCount, afterCount);
-    }
-
-    public void testParseExtrasIgnoreUnhandled() {
-        final AccountType accountType = getAccountType();
-        final RawContactDelta state = getRawContact(TEST_ID);
-
-        // We should silently ignore types unsupported by account type
-        final Bundle extras = new Bundle();
-        extras.putString(Insert.POSTAL, TEST_POSTAL);
-        RawContactModifier.parseExtras(mContext, accountType, state, extras);
-
-        assertNull("Broke accoun type rules",
-                state.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE));
-    }
-
-    public void testParseExtrasJobTitle() {
-        final AccountType accountType = getAccountType();
-        final RawContactDelta state = getRawContact(TEST_ID);
-
-        // Make sure that we create partial Organizations
-        final Bundle extras = new Bundle();
-        extras.putString(Insert.JOB_TITLE, TEST_NAME);
-        RawContactModifier.parseExtras(mContext, accountType, state, extras);
-
-        final int count = state.getMimeEntries(Organization.CONTENT_ITEM_TYPE).size();
-        assertEquals("Expected to create organization", 1, count);
-    }
-
-    public void testMigrateWithDisplayNameFromGoogleToExchange1() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
-
-        ContactsMockContext context = new ContactsMockContext(getContext());
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
-        mockNameValues.put(StructuredName.PREFIX, "prefix");
-        mockNameValues.put(StructuredName.GIVEN_NAME, "given");
-        mockNameValues.put(StructuredName.MIDDLE_NAME, "middle");
-        mockNameValues.put(StructuredName.FAMILY_NAME, "family");
-        mockNameValues.put(StructuredName.SUFFIX, "suffix");
-        mockNameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "PHONETIC_FAMILY");
-        mockNameValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "PHONETIC_MIDDLE");
-        mockNameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "PHONETIC_GIVEN");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateStructuredName(context, oldState, newState, kind);
-        List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
-        assertEquals(1, list.size());
-
-        ContentValues output = list.get(0).getAfter();
-        assertEquals("prefix", output.getAsString(StructuredName.PREFIX));
-        assertEquals("given", output.getAsString(StructuredName.GIVEN_NAME));
-        assertEquals("middle", output.getAsString(StructuredName.MIDDLE_NAME));
-        assertEquals("family", output.getAsString(StructuredName.FAMILY_NAME));
-        assertEquals("suffix", output.getAsString(StructuredName.SUFFIX));
-        // Phonetic middle name isn't supported by Exchange.
-        assertEquals("PHONETIC_FAMILY", output.getAsString(StructuredName.PHONETIC_FAMILY_NAME));
-        assertEquals("PHONETIC_GIVEN", output.getAsString(StructuredName.PHONETIC_GIVEN_NAME));
-    }
-
-    public void testMigrateWithDisplayNameFromGoogleToExchange2() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
-
-        ContactsMockContext context = new ContactsMockContext(getContext());
-        MockContentProvider provider = context.getContactsProvider();
-
-        String inputDisplayName = "prefix given middle family suffix";
-        // The method will ask the provider to split/join StructuredName.
-        Uri uriForBuildDisplayName =
-                ContactsContract.AUTHORITY_URI
-                        .buildUpon()
-                        .appendPath("complete_name")
-                        .appendQueryParameter(StructuredName.DISPLAY_NAME, inputDisplayName)
-                        .build();
-        provider.expectQuery(uriForBuildDisplayName)
-                .returnRow("prefix", "given", "middle", "family", "suffix")
-                .withProjection(StructuredName.PREFIX, StructuredName.GIVEN_NAME,
-                        StructuredName.MIDDLE_NAME, StructuredName.FAMILY_NAME,
-                        StructuredName.SUFFIX);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
-        mockNameValues.put(StructuredName.DISPLAY_NAME, inputDisplayName);
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateStructuredName(context, oldState, newState, kind);
-        List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
-        assertEquals(1, list.size());
-
-        ContentValues outputValues = list.get(0).getAfter();
-        assertEquals("prefix", outputValues.getAsString(StructuredName.PREFIX));
-        assertEquals("given", outputValues.getAsString(StructuredName.GIVEN_NAME));
-        assertEquals("middle", outputValues.getAsString(StructuredName.MIDDLE_NAME));
-        assertEquals("family", outputValues.getAsString(StructuredName.FAMILY_NAME));
-        assertEquals("suffix", outputValues.getAsString(StructuredName.SUFFIX));
-    }
-
-    public void testMigrateWithStructuredNameFromExchangeToGoogle() {
-        AccountType oldAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        AccountType newAccountType = new GoogleAccountType(getContext(), "");
-        DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
-
-        ContactsMockContext context = new ContactsMockContext(getContext());
-        MockContentProvider provider = context.getContactsProvider();
-
-        // The method will ask the provider to split/join StructuredName.
-        Uri uriForBuildDisplayName =
-                ContactsContract.AUTHORITY_URI
-                        .buildUpon()
-                        .appendPath("complete_name")
-                        .appendQueryParameter(StructuredName.PREFIX, "prefix")
-                        .appendQueryParameter(StructuredName.GIVEN_NAME, "given")
-                        .appendQueryParameter(StructuredName.MIDDLE_NAME, "middle")
-                        .appendQueryParameter(StructuredName.FAMILY_NAME, "family")
-                        .appendQueryParameter(StructuredName.SUFFIX, "suffix")
-                        .build();
-        provider.expectQuery(uriForBuildDisplayName)
-                .returnRow("prefix given middle family suffix")
-                .withProjection(StructuredName.DISPLAY_NAME);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
-        mockNameValues.put(StructuredName.PREFIX, "prefix");
-        mockNameValues.put(StructuredName.GIVEN_NAME, "given");
-        mockNameValues.put(StructuredName.MIDDLE_NAME, "middle");
-        mockNameValues.put(StructuredName.FAMILY_NAME, "family");
-        mockNameValues.put(StructuredName.SUFFIX, "suffix");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateStructuredName(context, oldState, newState, kind);
-
-        List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(1, list.size());
-        ContentValues outputValues = list.get(0).getAfter();
-        assertEquals("prefix given middle family suffix",
-                outputValues.getAsString(StructuredName.DISPLAY_NAME));
-    }
-
-    public void testMigratePostalFromGoogleToExchange() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
-        mockNameValues.put(StructuredPostal.FORMATTED_ADDRESS, "formatted_address");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migratePostal(oldState, newState, kind);
-
-        List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(1, list.size());
-        ContentValues outputValues = list.get(0).getAfter();
-        // FORMATTED_ADDRESS isn't supported by Exchange.
-        assertNull(outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS));
-        assertEquals("formatted_address", outputValues.getAsString(StructuredPostal.STREET));
-    }
-
-    public void testMigratePostalFromExchangeToGoogle() {
-        AccountType oldAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        AccountType newAccountType = new GoogleAccountType(getContext(), "");
-        DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
-        mockNameValues.put(StructuredPostal.COUNTRY, "country");
-        mockNameValues.put(StructuredPostal.POSTCODE, "postcode");
-        mockNameValues.put(StructuredPostal.REGION, "region");
-        mockNameValues.put(StructuredPostal.CITY, "city");
-        mockNameValues.put(StructuredPostal.STREET, "street");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migratePostal(oldState, newState, kind);
-
-        List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(1, list.size());
-        ContentValues outputValues = list.get(0).getAfter();
-
-        // Check FORMATTED_ADDRESS contains all info.
-        String formattedAddress = outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
-        assertNotNull(formattedAddress);
-        assertTrue(formattedAddress.contains("country"));
-        assertTrue(formattedAddress.contains("postcode"));
-        assertTrue(formattedAddress.contains("region"));
-        assertTrue(formattedAddress.contains("postcode"));
-        assertTrue(formattedAddress.contains("city"));
-        assertTrue(formattedAddress.contains("street"));
-    }
-
-    public void testMigrateEventFromGoogleToExchange1() {
-        testMigrateEventCommon(new GoogleAccountType(getContext(), ""),
-                new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE));
-    }
-
-    public void testMigrateEventFromExchangeToGoogle() {
-        testMigrateEventCommon(new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE),
-                new GoogleAccountType(getContext(), ""));
-    }
-
-    private void testMigrateEventCommon(AccountType oldAccountType, AccountType newAccountType) {
-        DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Event.START_DATE, "1972-02-08");
-        mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateEvent(oldState, newState, kind, 1990);
-
-        List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(1, list.size());  // Anniversary should be dropped.
-        ContentValues outputValues = list.get(0).getAfter();
-
-        assertEquals("1972-02-08", outputValues.getAsString(Event.START_DATE));
-        assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue());
-    }
-
-    public void testMigrateEventFromGoogleToExchange2() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
-        // No year format is not supported by Exchange.
-        mockNameValues.put(Event.START_DATE, "--06-01");
-        mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Event.START_DATE, "1980-08-02");
-        // Anniversary is not supported by Exchange
-        mockNameValues.put(Event.TYPE, Event.TYPE_ANNIVERSARY);
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateEvent(oldState, newState, kind, 1990);
-
-        List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(1, list.size());  // Anniversary should be dropped.
-        ContentValues outputValues = list.get(0).getAfter();
-
-        // Default year should be used.
-        assertEquals("1990-06-01", outputValues.getAsString(Event.START_DATE));
-        assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue());
-    }
-
-    public void testMigrateEmailFromGoogleToExchange() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(Email.CONTENT_ITEM_TYPE);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Email.TYPE, Email.TYPE_CUSTOM);
-        mockNameValues.put(Email.LABEL, "custom_type");
-        mockNameValues.put(Email.ADDRESS, "address1");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Email.TYPE, Email.TYPE_HOME);
-        mockNameValues.put(Email.ADDRESS, "address2");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Email.TYPE, Email.TYPE_WORK);
-        mockNameValues.put(Email.ADDRESS, "address3");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        // Exchange can have up to 3 email entries. This 4th entry should be dropped.
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Email.TYPE, Email.TYPE_OTHER);
-        mockNameValues.put(Email.ADDRESS, "address4");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
-
-        List<ValuesDelta> list = newState.getMimeEntries(Email.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(3, list.size());
-
-        ContentValues outputValues = list.get(0).getAfter();
-        assertEquals(Email.TYPE_CUSTOM, outputValues.getAsInteger(Email.TYPE).intValue());
-        assertEquals("custom_type", outputValues.getAsString(Email.LABEL));
-        assertEquals("address1", outputValues.getAsString(Email.ADDRESS));
-
-        outputValues = list.get(1).getAfter();
-        assertEquals(Email.TYPE_HOME, outputValues.getAsInteger(Email.TYPE).intValue());
-        assertEquals("address2", outputValues.getAsString(Email.ADDRESS));
-
-        outputValues = list.get(2).getAfter();
-        assertEquals(Email.TYPE_WORK, outputValues.getAsInteger(Email.TYPE).intValue());
-        assertEquals("address3", outputValues.getAsString(Email.ADDRESS));
-    }
-
-    public void testMigrateImFromGoogleToExchange() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(Im.CONTENT_ITEM_TYPE);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
-        // Exchange doesn't support TYPE_HOME
-        mockNameValues.put(Im.TYPE, Im.TYPE_HOME);
-        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_JABBER);
-        mockNameValues.put(Im.DATA, "im1");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
-        // Exchange doesn't support TYPE_WORK
-        mockNameValues.put(Im.TYPE, Im.TYPE_WORK);
-        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_YAHOO);
-        mockNameValues.put(Im.DATA, "im2");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Im.TYPE, Im.TYPE_OTHER);
-        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_CUSTOM);
-        mockNameValues.put(Im.CUSTOM_PROTOCOL, "custom_protocol");
-        mockNameValues.put(Im.DATA, "im3");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        // Exchange can have up to 3 IM entries. This 4th entry should be dropped.
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Im.TYPE, Im.TYPE_OTHER);
-        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
-        mockNameValues.put(Im.DATA, "im4");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
-
-        List<ValuesDelta> list = newState.getMimeEntries(Im.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(3, list.size());
-
-        assertNotNull(kind.defaultValues.getAsInteger(Im.TYPE));
-
-        int defaultType = kind.defaultValues.getAsInteger(Im.TYPE);
-
-        ContentValues outputValues = list.get(0).getAfter();
-        // HOME should become default type.
-        assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
-        assertEquals(Im.PROTOCOL_JABBER, outputValues.getAsInteger(Im.PROTOCOL).intValue());
-        assertEquals("im1", outputValues.getAsString(Im.DATA));
-
-        outputValues = list.get(1).getAfter();
-        assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
-        assertEquals(Im.PROTOCOL_YAHOO, outputValues.getAsInteger(Im.PROTOCOL).intValue());
-        assertEquals("im2", outputValues.getAsString(Im.DATA));
-
-        outputValues = list.get(2).getAfter();
-        assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
-        assertEquals(Im.PROTOCOL_CUSTOM, outputValues.getAsInteger(Im.PROTOCOL).intValue());
-        assertEquals("custom_protocol", outputValues.getAsString(Im.CUSTOM_PROTOCOL));
-        assertEquals("im3", outputValues.getAsString(Im.DATA));
-    }
-
-    public void testMigratePhoneFromGoogleToExchange() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-
-        // Create 5 numbers.
-        // - "1" -- HOME
-        // - "2" -- WORK
-        // - "3" -- CUSTOM
-        // - "4" -- WORK
-        // - "5" -- WORK_MOBILE
-        // Then we convert it to Exchange account type.
-        // - "1" -- HOME
-        // - "2" -- WORK
-        // - "3" -- Because CUSTOM is not supported, it'll be changed to the default, MOBILE
-        // - "4" -- WORK
-        // - "5" -- WORK_MOBILE not suppoted again, so will be MOBILE.
-        // But then, Exchange doesn't support multiple MOBILE numbers, so "5" will be removed.
-        // i.e. the result will be:
-        // - "1" -- HOME
-        // - "2" -- WORK
-        // - "3" -- MOBILE
-        // - "4" -- WORK
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Phone.TYPE, Phone.TYPE_HOME);
-        mockNameValues.put(Phone.NUMBER, "1");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK);
-        mockNameValues.put(Phone.NUMBER, "2");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        // Exchange doesn't support this type. Default to MOBILE
-        mockNameValues.put(Phone.TYPE, Phone.TYPE_CUSTOM);
-        mockNameValues.put(Phone.LABEL, "custom_type");
-        mockNameValues.put(Phone.NUMBER, "3");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK);
-        mockNameValues.put(Phone.NUMBER, "4");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-        mockNameValues = new ContentValues();
-
-        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
-        mockNameValues.put(Phone.NUMBER, "5");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
-
-        List<ValuesDelta> list = newState.getMimeEntries(Phone.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(4, list.size());
-
-        int defaultType = Phone.TYPE_MOBILE;
-
-        ContentValues outputValues = list.get(0).getAfter();
-        assertEquals(Phone.TYPE_HOME, outputValues.getAsInteger(Phone.TYPE).intValue());
-        assertEquals("1", outputValues.getAsString(Phone.NUMBER));
-        outputValues = list.get(1).getAfter();
-        assertEquals(Phone.TYPE_WORK, outputValues.getAsInteger(Phone.TYPE).intValue());
-        assertEquals("2", outputValues.getAsString(Phone.NUMBER));
-        outputValues = list.get(2).getAfter();
-        assertEquals(defaultType, outputValues.getAsInteger(Phone.TYPE).intValue());
-        assertNull(outputValues.getAsInteger(Phone.LABEL));
-        assertEquals("3", outputValues.getAsString(Phone.NUMBER));
-        outputValues = list.get(3).getAfter();
-        assertEquals(Phone.TYPE_WORK, outputValues.getAsInteger(Phone.TYPE).intValue());
-        assertEquals("4", outputValues.getAsString(Phone.NUMBER));
-    }
-
-    public void testMigrateOrganizationFromGoogleToExchange() {
-        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
-        AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE);
-        DataKind kind = newAccountType.getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
-
-        RawContactDelta oldState = new RawContactDelta();
-        ContentValues mockNameValues = new ContentValues();
-        mockNameValues.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
-        mockNameValues.put(Organization.COMPANY, "company1");
-        mockNameValues.put(Organization.DEPARTMENT, "department1");
-        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
-
-        RawContactDelta newState = new RawContactDelta();
-        RawContactModifier.migrateGenericWithoutTypeColumn(oldState, newState, kind);
-
-        List<ValuesDelta> list = newState.getMimeEntries(Organization.CONTENT_ITEM_TYPE);
-        assertNotNull(list);
-        assertEquals(1, list.size());
-
-        ContentValues outputValues = list.get(0).getAfter();
-        assertEquals("company1", outputValues.getAsString(Organization.COMPANY));
-        assertEquals("department1", outputValues.getAsString(Organization.DEPARTMENT));
-    }
-}
diff --git a/tests/src/com/android/contacts/activities/PeopleActivityTest.java b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
index 4ede006..d882da7 100644
--- a/tests/src/com/android/contacts/activities/PeopleActivityTest.java
+++ b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
@@ -45,10 +45,10 @@
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.model.account.BaseAccountType;
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContactPhotoManager;
-import com.android.contacts.tests.mocks.MockSharedPreferences;
+import com.android.contacts.common.test.InjectedServices;
+import com.android.contacts.common.test.mocks.MockAccountTypeManager;
+import com.android.contacts.common.test.mocks.MockContactPhotoManager;
+import com.android.contacts.common.test.mocks.MockSharedPreferences;
 import com.android.contacts.util.PhoneCapabilityTester;
 
 /**
diff --git a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
index 1747add..9c52161 100644
--- a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
+++ b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
@@ -25,9 +25,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.contacts.detail.ContactDetailFragment.DetailViewEntry;
-import com.android.contacts.model.dataitem.DataItem;
-import com.android.contacts.model.dataitem.EmailDataItem;
-import com.android.contacts.model.dataitem.ImDataItem;
+import com.android.contacts.common.model.dataitem.DataItem;
+import com.android.contacts.common.model.dataitem.EmailDataItem;
+import com.android.contacts.common.model.dataitem.ImDataItem;
 
 /**
  * Tests for {@link ContactDetailFragment}.
diff --git a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
index 7f1ee02..abd4680 100644
--- a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
+++ b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
@@ -22,6 +22,7 @@
 
 import com.android.contacts.util.StreamItemEntry;
 import com.android.contacts.util.StreamItemEntryBuilder;
+
 import com.google.common.collect.Lists;
 
 import java.util.ArrayList;
diff --git a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
index 0d38c95..c41c836 100644
--- a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
+++ b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
@@ -22,7 +22,7 @@
 
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.android.contacts.common.test.mocks.MockAccountTypeManager;
 import com.google.common.collect.Sets;
 
 import java.util.Collection;
diff --git a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
index 34f1e4b..bcaa398 100644
--- a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
+++ b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
@@ -34,8 +34,8 @@
 import com.android.contacts.common.model.AccountTypeManager;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.BaseAccountType;
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.android.contacts.common.test.InjectedServices;
+import com.android.contacts.common.test.mocks.MockAccountTypeManager;
 
 /**
  * Tests for {@link ContactDeletionInteraction}.
diff --git a/tests/src/com/android/contacts/model/ContactLoaderTest.java b/tests/src/com/android/contacts/model/ContactLoaderTest.java
deleted file mode 100644
index 60d6930..0000000
--- a/tests/src/com/android/contacts/model/ContactLoaderTest.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.model;
-
-import android.content.ContentUris;
-import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.DisplayNameSources;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.StatusUpdates;
-import android.test.LoaderTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.test.mocks.ContactsMockContext;
-import com.android.contacts.common.test.mocks.MockContentProvider;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.model.account.BaseAccountType;
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-
-/**
- * Runs ContactLoader tests for the the contact-detail and editor view.
- */
-@LargeTest
-public class ContactLoaderTest extends LoaderTestCase {
-    private ContactsMockContext mMockContext;
-    private MockContentProvider mContactsProvider;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mMockContext = new ContactsMockContext(getContext());
-        mContactsProvider = mMockContext.getContactsProvider();
-
-        InjectedServices services = new InjectedServices();
-        AccountType accountType = new BaseAccountType() {
-            @Override
-            public boolean areContactsWritable() {
-                return false;
-            }
-        };
-        accountType.accountType = "mockAccountType";
-
-        AccountWithDataSet account =
-                new AccountWithDataSet("mockAccountName", "mockAccountType", null);
-
-        AccountTypeManager.setInstanceForTest(
-                new MockAccountTypeManager(
-                        new AccountType[]{accountType}, new AccountWithDataSet[]{account}));
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mMockContext = null;
-        mContactsProvider = null;
-        super.tearDown();
-    }
-
-    private Contact assertLoadContact(Uri uri) {
-        final ContactLoader loader = new ContactLoader(mMockContext, uri, true);
-        return getLoaderResultSynchronously(loader);
-    }
-
-    public void testNullUri() {
-        Contact result = assertLoadContact(null);
-        assertTrue(result.isError());
-    }
-
-    public void testEmptyUri() {
-        Contact result = assertLoadContact(Uri.EMPTY);
-        assertTrue(result.isError());
-    }
-
-    public void testInvalidUri() {
-        Contact result = assertLoadContact(Uri.parse("content://wtf"));
-        assertTrue(result.isError());
-    }
-
-    public void testLoadContactWithContactIdUri() {
-        // Use content Uris that only contain the ID
-        final long contactId = 1;
-        final long rawContactId = 11;
-        final long dataId = 21;
-
-        final String lookupKey = "aa%12%@!";
-        final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
-        final Uri entityUri = Uri.withAppendedPath(baseUri, Contacts.Entity.CONTENT_DIRECTORY);
-        final Uri lookupUri = ContentUris.withAppendedId(
-                Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
-                contactId);
-
-        ContactQueries queries = new ContactQueries();
-        mContactsProvider.expectTypeQuery(baseUri, Contacts.CONTENT_ITEM_TYPE);
-        queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
-
-        Contact contact = assertLoadContact(baseUri);
-
-        assertEquals(contactId, contact.getId());
-        assertEquals(rawContactId, contact.getNameRawContactId());
-        assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
-        assertEquals(lookupKey, contact.getLookupKey());
-        assertEquals(lookupUri, contact.getLookupUri());
-        assertEquals(1, contact.getRawContacts().size());
-        assertEquals(1, contact.getStatuses().size());
-        mContactsProvider.verify();
-    }
-
-    public void testLoadContactWithOldStyleUri() {
-        // Use content Uris that only contain the ID but use the format used in Donut
-        final long contactId = 1;
-        final long rawContactId = 11;
-        final long dataId = 21;
-
-        final String lookupKey = "aa%12%@!";
-        final Uri legacyUri = ContentUris.withAppendedId(
-                Uri.parse("content://contacts"), rawContactId);
-        final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
-        final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
-        final Uri lookupUri = ContentUris.withAppendedId(
-                Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
-                contactId);
-        final Uri entityUri = Uri.withAppendedPath(lookupUri, Contacts.Entity.CONTENT_DIRECTORY);
-
-        ContactQueries queries = new ContactQueries();
-        queries.fetchContactIdAndLookupFromRawContactUri(rawContactUri, contactId, lookupKey);
-        queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
-
-        Contact contact = assertLoadContact(legacyUri);
-
-        assertEquals(contactId, contact.getId());
-        assertEquals(rawContactId, contact.getNameRawContactId());
-        assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
-        assertEquals(lookupKey, contact.getLookupKey());
-        assertEquals(lookupUri, contact.getLookupUri());
-        assertEquals(1, contact.getRawContacts().size());
-        assertEquals(1, contact.getStatuses().size());
-        mContactsProvider.verify();
-    }
-
-    public void testLoadContactWithRawContactIdUri() {
-        // Use content Uris that only contain the ID but use the format used in Donut
-        final long contactId = 1;
-        final long rawContactId = 11;
-        final long dataId = 21;
-
-        final String lookupKey = "aa%12%@!";
-        final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
-        final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
-        final Uri lookupUri = ContentUris.withAppendedId(
-                Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
-                contactId);
-        final Uri entityUri = Uri.withAppendedPath(lookupUri, Contacts.Entity.CONTENT_DIRECTORY);
-
-        ContactQueries queries = new ContactQueries();
-        mContactsProvider.expectTypeQuery(rawContactUri, RawContacts.CONTENT_ITEM_TYPE);
-        queries.fetchContactIdAndLookupFromRawContactUri(rawContactUri, contactId, lookupKey);
-        queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
-
-        Contact contact = assertLoadContact(rawContactUri);
-
-        assertEquals(contactId, contact.getId());
-        assertEquals(rawContactId, contact.getNameRawContactId());
-        assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
-        assertEquals(lookupKey, contact.getLookupKey());
-        assertEquals(lookupUri, contact.getLookupUri());
-        assertEquals(1, contact.getRawContacts().size());
-        assertEquals(1, contact.getStatuses().size());
-        mContactsProvider.verify();
-    }
-
-    public void testLoadContactWithContactLookupUri() {
-        // Use lookup-style Uris that do not contain the Contact-ID
-
-        final long contactId = 1;
-        final long rawContactId = 11;
-        final long dataId = 21;
-
-        final String lookupKey = "aa%12%@!";
-        final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
-        final Uri lookupNoIdUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);
-        final Uri lookupUri = ContentUris.withAppendedId(lookupNoIdUri, contactId);
-        final Uri entityUri = Uri.withAppendedPath(lookupNoIdUri, Contacts.Entity.CONTENT_DIRECTORY);
-
-        ContactQueries queries = new ContactQueries();
-        mContactsProvider.expectTypeQuery(lookupNoIdUri, Contacts.CONTENT_ITEM_TYPE);
-        queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
-
-        Contact contact = assertLoadContact(lookupNoIdUri);
-
-        assertEquals(contactId, contact.getId());
-        assertEquals(rawContactId, contact.getNameRawContactId());
-        assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
-        assertEquals(lookupKey, contact.getLookupKey());
-        assertEquals(lookupUri, contact.getLookupUri());
-        assertEquals(1, contact.getRawContacts().size());
-        assertEquals(1, contact.getStatuses().size());
-        mContactsProvider.verify();
-    }
-
-    public void testLoadContactWithContactLookupAndIdUri() {
-        // Use lookup-style Uris that also contain the Contact-ID
-        final long contactId = 1;
-        final long rawContactId = 11;
-        final long dataId = 21;
-
-        final String lookupKey = "aa%12%@!";
-        final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
-        final Uri lookupUri = ContentUris.withAppendedId(
-                Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
-                contactId);
-        final Uri entityUri = Uri.withAppendedPath(lookupUri, Contacts.Entity.CONTENT_DIRECTORY);
-
-        ContactQueries queries = new ContactQueries();
-        mContactsProvider.expectTypeQuery(lookupUri, Contacts.CONTENT_ITEM_TYPE);
-        queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
-
-        Contact contact = assertLoadContact(lookupUri);
-
-        assertEquals(contactId, contact.getId());
-        assertEquals(rawContactId, contact.getNameRawContactId());
-        assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
-        assertEquals(lookupKey, contact.getLookupKey());
-        assertEquals(lookupUri, contact.getLookupUri());
-        assertEquals(1, contact.getRawContacts().size());
-        assertEquals(1, contact.getStatuses().size());
-        mContactsProvider.verify();
-    }
-
-    public void testLoadContactWithContactLookupWithIncorrectIdUri() {
-        // Use lookup-style Uris that contain incorrect Contact-ID
-        // (we want to ensure that still the correct contact is chosen)
-
-        final long contactId = 1;
-        final long wrongContactId = 2;
-        final long rawContactId = 11;
-        final long wrongRawContactId = 12;
-        final long dataId = 21;
-
-        final String lookupKey = "aa%12%@!";
-        final String wrongLookupKey = "ab%12%@!";
-        final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
-        final Uri wrongBaseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, wrongContactId);
-        final Uri lookupUri = ContentUris.withAppendedId(
-                Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
-                contactId);
-        final Uri lookupWithWrongIdUri = ContentUris.withAppendedId(
-                Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
-                wrongContactId);
-        final Uri entityUri = Uri.withAppendedPath(lookupWithWrongIdUri,
-                Contacts.Entity.CONTENT_DIRECTORY);
-
-        ContactQueries queries = new ContactQueries();
-        mContactsProvider.expectTypeQuery(lookupWithWrongIdUri, Contacts.CONTENT_ITEM_TYPE);
-        queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
-
-        Contact contact = assertLoadContact(lookupWithWrongIdUri);
-
-        assertEquals(contactId, contact.getId());
-        assertEquals(rawContactId, contact.getNameRawContactId());
-        assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
-        assertEquals(lookupKey, contact.getLookupKey());
-        assertEquals(lookupUri, contact.getLookupUri());
-        assertEquals(1, contact.getRawContacts().size());
-        assertEquals(1, contact.getStatuses().size());
-
-        mContactsProvider.verify();
-    }
-
-    class ContactQueries {
-        public void fetchAllData(
-                Uri baseUri, long contactId, long rawContactId, long dataId, String encodedLookup) {
-            mContactsProvider.expectQuery(baseUri)
-                    .withProjection(new String[] {
-                        Contacts.NAME_RAW_CONTACT_ID, Contacts.DISPLAY_NAME_SOURCE,
-                        Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME,
-                        Contacts.DISPLAY_NAME_ALTERNATIVE, Contacts.PHONETIC_NAME,
-                        Contacts.PHOTO_ID, Contacts.STARRED, Contacts.CONTACT_PRESENCE,
-                        Contacts.CONTACT_STATUS, Contacts.CONTACT_STATUS_TIMESTAMP,
-                        Contacts.CONTACT_STATUS_RES_PACKAGE, Contacts.CONTACT_STATUS_LABEL,
-
-                        Contacts.Entity.CONTACT_ID,
-                        Contacts.Entity.RAW_CONTACT_ID,
-
-                        RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE,
-                        RawContacts.DATA_SET, RawContacts.ACCOUNT_TYPE_AND_DATA_SET,
-                        RawContacts.DIRTY, RawContacts.VERSION, RawContacts.SOURCE_ID,
-                        RawContacts.SYNC1, RawContacts.SYNC2, RawContacts.SYNC3, RawContacts.SYNC4,
-                        RawContacts.DELETED, RawContacts.NAME_VERIFIED,
-
-                        Contacts.Entity.DATA_ID,
-
-                        Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5,
-                        Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10,
-                        Data.DATA11, Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15,
-                        Data.SYNC1, Data.SYNC2, Data.SYNC3, Data.SYNC4,
-                        Data.DATA_VERSION, Data.IS_PRIMARY,
-                        Data.IS_SUPER_PRIMARY, Data.MIMETYPE, Data.RES_PACKAGE,
-
-                        GroupMembership.GROUP_SOURCE_ID,
-
-                        Data.PRESENCE, Data.CHAT_CAPABILITY,
-                        Data.STATUS, Data.STATUS_RES_PACKAGE, Data.STATUS_ICON,
-                        Data.STATUS_LABEL, Data.STATUS_TIMESTAMP,
-
-                        Contacts.PHOTO_URI,
-
-                        Contacts.SEND_TO_VOICEMAIL,
-                        Contacts.CUSTOM_RINGTONE,
-                        Contacts.IS_USER_PROFILE,
-                    })
-                    .withSortOrder(Contacts.Entity.RAW_CONTACT_ID)
-                    .returnRow(
-                        rawContactId, 40,
-                        "aa%12%@!", "John Doe", "Doe, John", "jdo",
-                        0, 0, StatusUpdates.AVAILABLE,
-                        "Having lunch", 0,
-                        "mockPkg1", 10,
-
-                        contactId,
-                        rawContactId,
-
-                        "mockAccountName", "mockAccountType", null, "mockAccountType",
-                        0, 1, 0,
-                        "sync1", "sync2", "sync3", "sync4",
-                        0, 0,
-
-                        dataId,
-
-                        "dat1", "dat2", "dat3", "dat4", "dat5",
-                        "dat6", "dat7", "dat8", "dat9", "dat10",
-                        "dat11", "dat12", "dat13", "dat14", "dat15",
-                        "syn1", "syn2", "syn3", "syn4",
-
-                        0, 0,
-                        0, StructuredName.CONTENT_ITEM_TYPE, "mockPkg2",
-
-                        "groupId",
-
-                        StatusUpdates.INVISIBLE, null,
-                        "Having dinner", "mockPkg3", 0,
-                        20, 0,
-
-                        "content:some.photo.uri",
-
-                        0,
-                        null,
-                        0
-                    );
-        }
-
-        void fetchLookupAndId(final Uri sourceUri, final long expectedContactId,
-                final String expectedEncodedLookup) {
-            mContactsProvider.expectQuery(sourceUri)
-                    .withProjection(Contacts.LOOKUP_KEY, Contacts._ID)
-                    .returnRow(expectedEncodedLookup, expectedContactId);
-        }
-
-        void fetchContactIdAndLookupFromRawContactUri(final Uri rawContactUri,
-                final long expectedContactId, final String expectedEncodedLookup) {
-            // TODO: use a lighter query by joining rawcontacts with contacts in provider
-            // (See ContactContracts.java)
-            final Uri dataUri = Uri.withAppendedPath(rawContactUri,
-                    RawContacts.Data.CONTENT_DIRECTORY);
-            mContactsProvider.expectQuery(dataUri)
-                    .withProjection(RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY)
-                    .returnRow(expectedContactId, expectedEncodedLookup);
-        }
-    }
-}
diff --git a/tests/src/com/android/contacts/model/RawContactTest.java b/tests/src/com/android/contacts/model/RawContactTest.java
deleted file mode 100644
index f09e64f..0000000
--- a/tests/src/com/android/contacts/model/RawContactTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.contacts.model;
-
-import android.content.ContentValues;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test for {@link RawContact}.
- */
-public class RawContactTest extends TestCase {
-
-    private RawContact buildRawContact() {
-        final ContentValues values = new ContentValues();
-        values.put("key1", "value1");
-        values.put("key2", "value2");
-
-        final ContentValues dataItem = new ContentValues();
-        dataItem.put("key3", "value3");
-        dataItem.put("key4", "value4");
-
-        final RawContact contact = new RawContact(values);
-        contact.addDataItemValues(dataItem);
-
-        return contact;
-    }
-
-    private RawContact buildRawContact2() {
-        final ContentValues values = new ContentValues();
-        values.put("key11", "value11");
-        values.put("key22", "value22");
-
-        final ContentValues dataItem = new ContentValues();
-        dataItem.put("key33", "value33");
-        dataItem.put("key44", "value44");
-
-        final RawContact contact = new RawContact(values);
-        contact.addDataItemValues(dataItem);
-
-        return contact;
-    }
-
-    public void testNotEquals() {
-        final RawContact one = buildRawContact();
-        final RawContact two = buildRawContact2();
-        assertFalse(one.equals(two));
-    }
-
-    public void testEquals() {
-        assertEquals(buildRawContact(), buildRawContact());
-    }
-
-    public void testParcelable() {
-        assertParcelableEquals(buildRawContact());
-    }
-
-    private RawContact.NamedDataItem buildNamedDataItem() {
-        final ContentValues values = new ContentValues();
-        values.put("key1", "value1");
-        values.put("key2", "value2");
-        final Uri uri = Uri.fromParts("content:", "ssp", "fragment");
-
-        return new RawContact.NamedDataItem(uri, values);
-    }
-
-    private RawContact.NamedDataItem buildNamedDataItem2() {
-        final ContentValues values = new ContentValues();
-        values.put("key11", "value11");
-        values.put("key22", "value22");
-        final Uri uri = Uri.fromParts("content:", "blah", "blah");
-
-        return new RawContact.NamedDataItem(uri, values);
-    }
-
-    public void testNamedDataItemEquals() {
-        assertEquals(buildNamedDataItem(), buildNamedDataItem());
-    }
-
-    public void testNamedDataItemNotEquals() {
-        assertFalse(buildNamedDataItem().equals(buildNamedDataItem2()));
-    }
-
-    public void testNamedDataItemParcelable() {
-        assertParcelableEquals(buildNamedDataItem());
-    }
-
-    private void assertParcelableEquals(Parcelable parcelable) {
-        final Parcel parcel = Parcel.obtain();
-        try {
-            parcel.writeParcelable(parcelable, 0);
-            parcel.setDataPosition(0);
-
-            Parcelable out = parcel.readParcelable(parcelable.getClass().getClassLoader());
-            assertEquals(parcelable, out);
-        } finally {
-            parcel.recycle();
-        }
-    }
-}
diff --git a/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java b/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
deleted file mode 100644
index 3357af3..0000000
--- a/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.contacts.tests.mocks;
-
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountTypeWithDataSet;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.google.common.base.Objects;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A mock {@link AccountTypeManager} class.
- */
-public class MockAccountTypeManager extends AccountTypeManager {
-
-    public AccountType[] mTypes;
-    public AccountWithDataSet[] mAccounts;
-
-    public MockAccountTypeManager(AccountType[] types, AccountWithDataSet[] accounts) {
-        this.mTypes = types;
-        this.mAccounts = accounts;
-    }
-
-    @Override
-    public AccountType getAccountType(AccountTypeWithDataSet accountTypeWithDataSet) {
-        for (AccountType type : mTypes) {
-            if (Objects.equal(accountTypeWithDataSet.accountType, type.accountType)
-                    && Objects.equal(accountTypeWithDataSet.dataSet, type.dataSet)) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public List<AccountWithDataSet> getAccounts(boolean writableOnly) {
-        return Arrays.asList(mAccounts);
-    }
-
-    @Override
-    public List<AccountWithDataSet> getGroupWritableAccounts() {
-        return Arrays.asList(mAccounts);
-    }
-
-    @Override
-    public Map<AccountTypeWithDataSet, AccountType> getUsableInvitableAccountTypes() {
-        return Maps.newHashMap(); // Always returns empty
-    }
-
-    @Override
-    public List<AccountType> getAccountTypes(boolean writableOnly) {
-        final List<AccountType> ret = Lists.newArrayList();
-        synchronized (this) {
-            for (AccountType type : mTypes) {
-                if (!writableOnly || type.areContactsWritable()) {
-                    ret.add(type);
-                }
-            }
-        }
-        return ret;
-    }
-}
diff --git a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
deleted file mode 100644
index f5f6084..0000000
--- a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.tests.mocks;
-
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.widget.ImageView;
-
-import com.android.contacts.common.ContactPhotoManager;
-
-/**
- * A photo preloader that always uses the "no contact" picture and never executes any real
- * db queries
- */
-public class MockContactPhotoManager extends ContactPhotoManager {
-    @Override
-    public void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
-            DefaultImageProvider defaultProvider) {
-        defaultProvider.applyDefaultImage(view, -1, darkTheme);
-    }
-
-    @Override
-    public void loadPhoto(ImageView view, Uri photoUri, int requestedExtent, boolean darkTheme,
-            DefaultImageProvider defaultProvider) {
-        defaultProvider.applyDefaultImage(view, requestedExtent, darkTheme);
-    }
-
-    @Override
-    public void removePhoto(ImageView view) {
-        view.setImageDrawable(null);
-    }
-
-    @Override
-    public void pause() {
-    }
-
-    @Override
-    public void resume() {
-    }
-
-    @Override
-    public void refreshCache() {
-    }
-
-    @Override
-    public void cacheBitmap(Uri photoUri, Bitmap bitmap, byte[] photoBytes) {
-    }
-
-    @Override
-    public void preloadPhotosInBackground() {
-    }
-}
diff --git a/tests/src/com/android/contacts/tests/mocks/MockSharedPreferences.java b/tests/src/com/android/contacts/tests/mocks/MockSharedPreferences.java
deleted file mode 100644
index 536ba7f..0000000
--- a/tests/src/com/android/contacts/tests/mocks/MockSharedPreferences.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.tests.mocks;
-
-import android.content.SharedPreferences;
-
-import com.google.common.collect.Maps;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-
-/**
- * A programmable mock content provider.
- */
-public class MockSharedPreferences implements SharedPreferences, SharedPreferences.Editor {
-
-    private HashMap<String, Object> mValues = Maps.newHashMap();
-    private HashMap<String, Object> mTempValues = Maps.newHashMap();
-
-    public Editor edit() {
-        return this;
-    }
-
-    public boolean contains(String key) {
-        return mValues.containsKey(key);
-    }
-
-    public Map<String, ?> getAll() {
-        return new HashMap<String, Object>(mValues);
-    }
-
-    public boolean getBoolean(String key, boolean defValue) {
-        if (mValues.containsKey(key)) {
-            return ((Boolean)mValues.get(key)).booleanValue();
-        }
-        return defValue;
-    }
-
-    public float getFloat(String key, float defValue) {
-        if (mValues.containsKey(key)) {
-            return ((Float)mValues.get(key)).floatValue();
-        }
-        return defValue;
-    }
-
-    public int getInt(String key, int defValue) {
-        if (mValues.containsKey(key)) {
-            return ((Integer)mValues.get(key)).intValue();
-        }
-        return defValue;
-    }
-
-    public long getLong(String key, long defValue) {
-        if (mValues.containsKey(key)) {
-            return ((Long)mValues.get(key)).longValue();
-        }
-        return defValue;
-    }
-
-    public String getString(String key, String defValue) {
-        if (mValues.containsKey(key))
-            return (String)mValues.get(key);
-        return defValue;
-    }
-
-    @SuppressWarnings("unchecked")
-    public Set<String> getStringSet(String key, Set<String> defValues) {
-        if (mValues.containsKey(key)) {
-            return (Set<String>) mValues.get(key);
-        }
-        return defValues;
-    }
-
-    public void registerOnSharedPreferenceChangeListener(
-            OnSharedPreferenceChangeListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void unregisterOnSharedPreferenceChangeListener(
-            OnSharedPreferenceChangeListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Editor putBoolean(String key, boolean value) {
-        mTempValues.put(key, Boolean.valueOf(value));
-        return this;
-    }
-
-    public Editor putFloat(String key, float value) {
-        mTempValues.put(key, value);
-        return this;
-    }
-
-    public Editor putInt(String key, int value) {
-        mTempValues.put(key, value);
-        return this;
-    }
-
-    public Editor putLong(String key, long value) {
-        mTempValues.put(key, value);
-        return this;
-    }
-
-    public Editor putString(String key, String value) {
-        mTempValues.put(key, value);
-        return this;
-    }
-
-    public Editor putStringSet(String key, Set<String> values) {
-        mTempValues.put(key, values);
-        return this;
-    }
-
-    public Editor remove(String key) {
-        mTempValues.remove(key);
-        return this;
-    }
-
-    public Editor clear() {
-        mTempValues.clear();
-        return this;
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean commit() {
-        mValues = (HashMap<String, Object>)mTempValues.clone();
-        return true;
-    }
-
-    public void apply() {
-        commit();
-    }
-}
diff --git a/tests/src/com/android/contacts/util/NameConverterTests.java b/tests/src/com/android/contacts/util/NameConverterTests.java
deleted file mode 100644
index e1773a7..0000000
--- a/tests/src/com/android/contacts/util/NameConverterTests.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.util;
-
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.TextUtils;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Tests for {@link NameConverter}.
- */
-@SmallTest
-public class NameConverterTests extends AndroidTestCase {
-
-    public void testStructuredNameToDisplayName() {
-        Map<String, String> structuredName = new HashMap<String, String>();
-        structuredName.put(StructuredName.PREFIX, "Mr.");
-        structuredName.put(StructuredName.GIVEN_NAME, "John");
-        structuredName.put(StructuredName.MIDDLE_NAME, "Quincy");
-        structuredName.put(StructuredName.FAMILY_NAME, "Adams");
-        structuredName.put(StructuredName.SUFFIX, "Esquire");
-
-        assertEquals("Mr. John Quincy Adams, Esquire",
-                NameConverter.structuredNameToDisplayName(mContext, structuredName));
-
-        structuredName.remove(StructuredName.SUFFIX);
-        assertEquals("Mr. John Quincy Adams",
-                NameConverter.structuredNameToDisplayName(mContext, structuredName));
-
-        structuredName.remove(StructuredName.MIDDLE_NAME);
-        assertEquals("Mr. John Adams",
-                NameConverter.structuredNameToDisplayName(mContext, structuredName));
-    }
-
-    public void testDisplayNameToStructuredName() {
-        assertStructuredName("Mr. John Quincy Adams, Esquire",
-                "Mr.", "John", "Quincy", "Adams", "Esquire");
-        assertStructuredName("John Doe", null, "John", null, "Doe", null);
-        assertStructuredName("Ms. Jane Eyre", "Ms.", "Jane", null, "Eyre", null);
-        assertStructuredName("Dr Leo Spaceman, PhD", "Dr", "Leo", null, "Spaceman", "PhD");
-    }
-
-    /**
-     * Helper method to check whether a given display name parses out to the other parameters.
-     * @param displayName Display name to break into a structured name.
-     * @param prefix Expected prefix (null if not expected).
-     * @param givenName Expected given name (null if not expected).
-     * @param middleName Expected middle name (null if not expected).
-     * @param familyName Expected family name (null if not expected).
-     * @param suffix Expected suffix (null if not expected).
-     */
-    private void assertStructuredName(String displayName, String prefix,
-            String givenName, String middleName, String familyName, String suffix) {
-        Map<String, String> structuredName = NameConverter.displayNameToStructuredName(mContext,
-                displayName);
-        checkNameComponent(StructuredName.PREFIX, prefix, structuredName);
-        checkNameComponent(StructuredName.GIVEN_NAME, givenName, structuredName);
-        checkNameComponent(StructuredName.MIDDLE_NAME, middleName, structuredName);
-        checkNameComponent(StructuredName.FAMILY_NAME, familyName, structuredName);
-        checkNameComponent(StructuredName.SUFFIX, suffix, structuredName);
-        assertEquals(0, structuredName.size());
-    }
-
-    /**
-     * Checks that the given field and value are present in the structured name map (or not present
-     * if the given value is null).  If the value is present and matches, the key is removed from
-     * the map - once all components of the name are checked, the map should be empty.
-     * @param field Field to check.
-     * @param value Expected value for the field (null if it is not expected to be populated).
-     * @param structuredName The map of structured field names to values.
-     */
-    private void checkNameComponent(String field, String value,
-            Map<String, String> structuredName) {
-        if (TextUtils.isEmpty(value)) {
-            assertNull(structuredName.get(field));
-        } else {
-            assertEquals(value, structuredName.get(field));
-        }
-        structuredName.remove(field);
-    }
-}