am 0cd356ea: (-s ours) am d5063654: (-s ours) Use telephony-common - DO NOT MERGE

* commit '0cd356eac4195ac28b9dd54bdbb6d642a69406dd':
  Use telephony-common - DO NOT MERGE
diff --git a/res/drawable/contacts_widget_preview.png b/res/drawable-nodpi/contacts_widget_preview.png
similarity index 100%
rename from res/drawable/contacts_widget_preview.png
rename to res/drawable-nodpi/contacts_widget_preview.png
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/divider_vertical_dark.9.png b/res/drawable-xlarge-nodpi/divider_vertical_dark.9.png
deleted file mode 100644
index 38b794b..0000000
--- a/res/drawable-xlarge-nodpi/divider_vertical_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/res/layout-w470dp/contact_detail_container.xml b/res/layout-land/contact_detail_container.xml
similarity index 100%
rename from res/layout-w470dp/contact_detail_container.xml
rename to res/layout-land/contact_detail_container.xml
diff --git a/res/layout-w470dp/contact_detail_fragment.xml b/res/layout-land/contact_detail_fragment.xml
similarity index 100%
rename from res/layout-w470dp/contact_detail_fragment.xml
rename to res/layout-land/contact_detail_fragment.xml
diff --git a/res/layout-w470dp/contact_detail_updates_fragment.xml b/res/layout-land/contact_detail_updates_fragment.xml
similarity index 100%
rename from res/layout-w470dp/contact_detail_updates_fragment.xml
rename to res/layout-land/contact_detail_updates_fragment.xml
diff --git a/res/layout-w470dp/detail_header_contact_with_updates.xml b/res/layout-land/detail_header_contact_with_updates.xml
similarity index 100%
rename from res/layout-w470dp/detail_header_contact_with_updates.xml
rename to res/layout-land/detail_header_contact_with_updates.xml
diff --git a/res/layout-w470dp/detail_header_contact_without_updates.xml b/res/layout-land/detail_header_contact_without_updates.xml
similarity index 100%
rename from res/layout-w470dp/detail_header_contact_without_updates.xml
rename to res/layout-land/detail_header_contact_without_updates.xml
diff --git a/res/layout-w470dp/group_source_button.xml b/res/layout-land/group_source_button.xml
similarity index 100%
rename from res/layout-w470dp/group_source_button.xml
rename to res/layout-land/group_source_button.xml
diff --git a/res/layout-w470dp/quickcontact_activity.xml b/res/layout-land/quickcontact_activity.xml
similarity index 100%
rename from res/layout-w470dp/quickcontact_activity.xml
rename to res/layout-land/quickcontact_activity.xml
diff --git a/res/layout-land/quickcontact_list_fragment_bottom.xml b/res/layout-land/quickcontact_list_fragment_bottom.xml
deleted file mode 100755
index 957ec53..0000000
--- a/res/layout-land/quickcontact_list_fragment_bottom.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_alignParentBottom="true"
-    style="@style/QuickContactListBottomStyle"/>
diff --git a/res/layout-w470dp/updates_header_contact.xml b/res/layout-land/updates_header_contact.xml
similarity index 100%
rename from res/layout-w470dp/updates_header_contact.xml
rename to res/layout-land/updates_header_contact.xml
diff --git a/res/layout-sw580dp-w940dp/contact_detail_container.xml b/res/layout-sw580dp-land/contact_detail_container.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/contact_detail_container.xml
rename to res/layout-sw580dp-land/contact_detail_container.xml
diff --git a/res/layout-sw580dp-w940dp/contact_detail_fragment.xml b/res/layout-sw580dp-land/contact_detail_fragment.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/contact_detail_fragment.xml
rename to res/layout-sw580dp-land/contact_detail_fragment.xml
diff --git a/res/layout-sw580dp-w940dp/contact_detail_updates_fragment.xml b/res/layout-sw580dp-land/contact_detail_updates_fragment.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/contact_detail_updates_fragment.xml
rename to res/layout-sw580dp-land/contact_detail_updates_fragment.xml
diff --git a/res/layout-sw580dp-w940dp/contact_editor_activity.xml b/res/layout-sw580dp-land/contact_editor_activity.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/contact_editor_activity.xml
rename to res/layout-sw580dp-land/contact_editor_activity.xml
diff --git a/res/layout-sw580dp-w940dp/detail_header_contact_with_updates.xml b/res/layout-sw580dp-land/detail_header_contact_with_updates.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/detail_header_contact_with_updates.xml
rename to res/layout-sw580dp-land/detail_header_contact_with_updates.xml
diff --git a/res/layout-sw580dp-w940dp/detail_header_contact_without_updates.xml b/res/layout-sw580dp-land/detail_header_contact_without_updates.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/detail_header_contact_without_updates.xml
rename to res/layout-sw580dp-land/detail_header_contact_without_updates.xml
diff --git a/res/layout-sw580dp-w940dp/group_browse_list_account_header.xml b/res/layout-sw580dp-land/group_browse_list_account_header.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/group_browse_list_account_header.xml
rename to res/layout-sw580dp-land/group_browse_list_account_header.xml
diff --git a/res/layout-sw580dp-w940dp/people_activity.xml b/res/layout-sw580dp-land/people_activity.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/people_activity.xml
rename to res/layout-sw580dp-land/people_activity.xml
diff --git a/res/layout-sw580dp-w940dp/quickcontact_activity.xml b/res/layout-sw580dp-land/quickcontact_activity.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/quickcontact_activity.xml
rename to res/layout-sw580dp-land/quickcontact_activity.xml
diff --git a/res/layout-sw580dp-w940dp/updates_header_contact.xml b/res/layout-sw580dp-land/updates_header_contact.xml
similarity index 100%
rename from res/layout-sw580dp-w940dp/updates_header_contact.xml
rename to res/layout-sw580dp-land/updates_header_contact.xml
diff --git a/res/layout-sw580dp-w940dp/quickcontact_list_fragment_bottom.xml b/res/layout-sw580dp-w940dp/quickcontact_list_fragment_bottom.xml
deleted file mode 100755
index e08b3aa..0000000
--- a/res/layout-sw580dp-w940dp/quickcontact_list_fragment_bottom.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_alignBottom="@+id/list"
-    style="@style/QuickContactListBottomStyle"/>
diff --git a/res/layout-sw580dp/favorites_star.xml b/res/layout-sw580dp/favorites_star.xml
index 22b9339..6c83866 100644
--- a/res/layout-sw580dp/favorites_star.xml
+++ b/res/layout-sw580dp/favorites_star.xml
@@ -15,11 +15,14 @@
 -->
 
 <!-- The favorite star, shown outside of the ActionBar -->
-<ImageView
+<!-- The content description is set in code -->
+<ImageButton
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/star"
     android:layout_width="48dip"
     android:layout_height="48dip"
     android:scaleType="center"
     android:background="?android:attr/selectableItemBackground"
-    android:src="@drawable/btn_star_off_normal_holo_light" />
+    android:src="@drawable/btn_star_off_normal_holo_light"
+    tools:ignore="ContentDescription" />
diff --git a/res/layout-sw680dp-w1000dp/contact_detail_container.xml b/res/layout-sw680dp-land/contact_detail_container.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/contact_detail_container.xml
rename to res/layout-sw680dp-land/contact_detail_container.xml
diff --git a/res/layout-sw680dp-w1000dp/contact_detail_empty.xml b/res/layout-sw680dp-land/contact_detail_empty.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/contact_detail_empty.xml
rename to res/layout-sw680dp-land/contact_detail_empty.xml
diff --git a/res/layout-sw680dp-w1000dp/contact_detail_fragment.xml b/res/layout-sw680dp-land/contact_detail_fragment.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/contact_detail_fragment.xml
rename to res/layout-sw680dp-land/contact_detail_fragment.xml
diff --git a/res/layout-sw680dp-w1000dp/contact_detail_list_item.xml b/res/layout-sw680dp-land/contact_detail_list_item.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/contact_detail_list_item.xml
rename to res/layout-sw680dp-land/contact_detail_list_item.xml
diff --git a/res/layout-sw680dp-w1000dp/contact_detail_updates_fragment.xml b/res/layout-sw680dp-land/contact_detail_updates_fragment.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/contact_detail_updates_fragment.xml
rename to res/layout-sw680dp-land/contact_detail_updates_fragment.xml
diff --git a/res/layout-sw680dp-w1000dp/detail_header_contact_with_updates.xml b/res/layout-sw680dp-land/detail_header_contact_with_updates.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/detail_header_contact_with_updates.xml
rename to res/layout-sw680dp-land/detail_header_contact_with_updates.xml
diff --git a/res/layout-sw680dp-w1000dp/detail_header_contact_without_updates.xml b/res/layout-sw680dp-land/detail_header_contact_without_updates.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/detail_header_contact_without_updates.xml
rename to res/layout-sw680dp-land/detail_header_contact_without_updates.xml
diff --git a/res/layout-sw680dp-w1000dp/people_activity.xml b/res/layout-sw680dp-land/people_activity.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/people_activity.xml
rename to res/layout-sw680dp-land/people_activity.xml
diff --git a/res/layout-sw680dp-w1000dp/quickcontact_activity.xml b/res/layout-sw680dp-land/quickcontact_activity.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/quickcontact_activity.xml
rename to res/layout-sw680dp-land/quickcontact_activity.xml
diff --git a/res/layout-sw680dp-w1000dp/updates_header_contact.xml b/res/layout-sw680dp-land/updates_header_contact.xml
similarity index 100%
rename from res/layout-sw680dp-w1000dp/updates_header_contact.xml
rename to res/layout-sw680dp-land/updates_header_contact.xml
diff --git a/res/layout-sw680dp/contact_detail_container.xml b/res/layout-sw680dp/contact_detail_container.xml
deleted file mode 100644
index dfbd0d0..0000000
--- a/res/layout-sw680dp/contact_detail_container.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <android.support.v4.view.ViewPager
-        android:id="@+id/pager"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <include
-        android:id="@+id/tab_carousel"
-        layout="@layout/contact_detail_tab_carousel"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:visibility="gone"/>
-
-</RelativeLayout>
diff --git a/res/layout-sw680dp/contact_detail_fragment.xml b/res/layout-sw680dp/contact_detail_fragment.xml
deleted file mode 100644
index 4c6315e..0000000
--- a/res/layout-sw680dp/contact_detail_fragment.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/contact_detail"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- Placeholder for empty list -->
-    <include
-        android:id="@android:id/empty"
-        layout="@layout/contact_detail_empty"
-        android:visibility="gone" />
-
-    <!-- Real list -->
-    <ListView android:id="@android:id/list"
-        android:layout_weight="1"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:fadingEdge="none"
-        android:cacheColorHint="#00000000"
-        android:divider="@null"
-        android:scrollbarStyle="outsideOverlay"
-        android:paddingRight="12dip" />
-
-    <!-- "QuickFix"- button (Copy to local contact, add to group) -->
-    <Button
-        android:id="@+id/contact_quick_fix"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:visibility="gone"
-        android:layout_gravity="center"
-        android:layout_marginTop="10dip"
-        android:layout_marginBottom="10dip" />
-</LinearLayout>
diff --git a/res/layout-sw680dp/contact_detail_updates_fragment.xml b/res/layout-sw680dp/contact_detail_updates_fragment.xml
deleted file mode 100644
index a2d1abb..0000000
--- a/res/layout-sw680dp/contact_detail_updates_fragment.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/contact_detail_updates_fragment"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <ListView android:id="@android:id/list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fadingEdge="none"
-        android:divider="@null"
-        android:scrollbarStyle="outsideOverlay"
-        android:paddingRight="12dip" />
-
-</FrameLayout>
diff --git a/res/layout-sw680dp/quickcontact_activity.xml b/res/layout-sw680dp/quickcontact_activity.xml
deleted file mode 100644
index 8843fc9..0000000
--- a/res/layout-sw680dp/quickcontact_activity.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<view
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
-    class="com.android.contacts.quickcontact.FloatingChildLayout"
-    android:id="@+id/floating_layout"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:focusable="true"
-    android:focusableInTouchMode="true"
-    android:descendantFocusability="afterDescendants">
-    <LinearLayout
-        android:id="@android:id/content"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="32dip"
-        android:orientation="vertical" >
-        <FrameLayout
-            android:layout_width="360dip"
-            android:layout_height="@dimen/quick_contact_photo_container_height">
-            <include layout="@layout/quickcontact_photo_container" />
-        </FrameLayout>
-        <include layout="@layout/quickcontact_track" />
-        <View
-            android:id="@+id/line_after_track"
-            android:layout_width="match_parent"
-            android:layout_height="2dip"
-            android:background="@color/quickcontact_tab_indicator" />
-        <android.support.v4.view.ViewPager
-            android:id="@+id/item_list_pager"
-            android:layout_width="match_parent"
-            android:layout_height="160dip" />
-    </LinearLayout>
-</view>
diff --git a/res/layout/quickcontact_list_fragment.xml b/res/layout/quickcontact_list_fragment.xml
index e542f7a..712f116 100755
--- a/res/layout/quickcontact_list_fragment.xml
+++ b/res/layout/quickcontact_list_fragment.xml
@@ -28,5 +28,7 @@
         android:cacheColorHint="@null"
         android:layout_alignParentTop="true"
     />
-    <include layout="@layout/quickcontact_list_fragment_bottom"/>
+    <View
+        android:layout_alignBottom="@+id/list"
+        style="@style/QuickContactListBottomStyle"/>
 </RelativeLayout>
diff --git a/res/layout/quickcontact_list_fragment_bottom.xml b/res/layout/quickcontact_list_fragment_bottom.xml
deleted file mode 100755
index e08b3aa..0000000
--- a/res/layout/quickcontact_list_fragment_bottom.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_alignBottom="@+id/list"
-    style="@style/QuickContactListBottomStyle"/>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index a43fda8..e333d20 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -286,7 +286,7 @@
     <string name="missing_name" msgid="8745511583852904385">"(بلا اسم)"</string>
     <string name="menu_accounts" msgid="8499114602017077970">"الحسابات"</string>
     <string name="menu_clear_frequents" msgid="7688250191932838833">"محو قائمة من يتصل بهم كثيرًا"</string>
-    <string name="menu_contacts_filter" msgid="2165153460860262501">"جهات الاتصال التي يتم عرضها"</string>
+    <string name="menu_contacts_filter" msgid="2165153460860262501">"جهات الاتصال المعروضة"</string>
     <string name="menu_import_export" msgid="26217871113229507">"استيراد/تصدير"</string>
     <string name="dialog_import_export" msgid="4360648034889921624">"استيراد/تصدير جهات اتصال"</string>
     <string name="dialog_import" msgid="2431698729761448759">"استيراد جهات الاتصال"</string>
@@ -455,7 +455,7 @@
     <string name="custom_list_filter" msgid="7836035257402013957">"تحديد عرض مخصص"</string>
     <string name="contact_list_loading" msgid="5488620820563977329">"جارٍ التحميل..."</string>
     <string name="activity_title_settings" msgid="5464130076132770781">"الإعدادات"</string>
-    <string name="activity_title_contacts_filter" msgid="8275542497615516969">"جهات الاتصال التي يتم عرضها"</string>
+    <string name="activity_title_contacts_filter" msgid="8275542497615516969">"جهات الاتصال المعروضة"</string>
     <string name="menu_settings" msgid="377929915873428211">"الإعدادات"</string>
     <string name="menu_help" msgid="5123887102216637725">"مساعدة"</string>
     <string name="preference_displayOptions" msgid="1341720270148252393">"خيارات العرض"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 41431bd..a31e534 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -281,7 +281,7 @@
     <string name="call_disambig_title" msgid="4392886850104795739">"Nummer auswählen"</string>
     <string name="call_settings" msgid="7666474782093693667">"Einstellungen"</string>
     <string name="sms_disambig_title" msgid="5846266399240630846">"Nummer auswählen"</string>
-    <string name="make_primary" msgid="5829291915305113983">"Diese Auswahl speichern"</string>
+    <string name="make_primary" msgid="5829291915305113983">"Auswahl speichern"</string>
     <string name="quickcontact_missing_app" msgid="358168575340921552">"Für diese Aktion wurde keine App gefunden."</string>
     <string name="missing_name" msgid="8745511583852904385">"(Kein Name)"</string>
     <string name="menu_accounts" msgid="8499114602017077970">"Konten"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 33a3b36..1eb3333 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -185,7 +185,7 @@
     <string name="type_missed" msgid="2720502601640509542">"Llamada perdida"</string>
     <string name="type_voicemail" msgid="5153139450668549908">"Buzón de voz"</string>
     <string name="actionIncomingCall" msgid="6028930669817038600">"Llamadas entrantes"</string>
-    <string name="callBack" msgid="5498224409038809224">"Volver a llamar"</string>
+    <string name="callBack" msgid="5498224409038809224">"Llamar"</string>
     <string name="callAgain" msgid="3197312117049874778">"Volver a llamar"</string>
     <string name="returnCall" msgid="8171961914203617813">"Devolver llamada"</string>
     <string name="callDetailsDurationFormat" msgid="8157706382818184268">"<xliff:g id="MINUTES">%s</xliff:g> min. y <xliff:g id="SECONDS">%s</xliff:g> seg."</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 3967d87..2a9e144 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -36,7 +36,7 @@
     <string name="editGroupDescription" msgid="6321161304201540561">"ویرایش گروه"</string>
     <string name="insertGroupDescription" msgid="5658512271662210139">"ایجاد گروه"</string>
     <string name="contactDetailAbout" msgid="5430408883907061400">"درباره"</string>
-    <string name="contactDetailUpdates" msgid="3780588624763446941">"نسخه های به روز"</string>
+    <string name="contactDetailUpdates" msgid="3780588624763446941">"نسخه‌های به روز"</string>
     <string name="searchHint" msgid="8482945356247760701">"جستجوی مخاطبین"</string>
     <string name="menu_search" msgid="9147752853603483719">"جستجو"</string>
     <string name="menu_newContact" msgid="1209922412763274638">"مخاطب جدید"</string>
@@ -47,7 +47,7 @@
     <string name="menu_editContact" msgid="9042415603857662633">"ویرایش"</string>
     <string name="menu_deleteContact" msgid="6788644058868189393">"حذف"</string>
     <string name="menu_copy" msgid="6108677035381940698">"کپی"</string>
-    <string name="menu_create_contact_shortcut" msgid="1217971915748509640">"محل بر روی صفحه اصلی"</string>
+    <string name="menu_create_contact_shortcut" msgid="1217971915748509640">"محل بر روی صفحهٔ اصلی"</string>
     <string name="menu_call" msgid="3992595586042260618">"تماس با مخاطب"</string>
     <string name="menu_sendSMS" msgid="5535886767547006515">"ارسال متن به مخاطب"</string>
     <string name="menu_splitAggregate" msgid="8368636463748691868">"تفکیک"</string>
@@ -67,18 +67,18 @@
     <string name="menu_set_ring_tone" msgid="8728345772068064946">"تنظیم آهنگ زنگ"</string>
     <string name="menu_redirect_calls_to_vm" msgid="4181789196416396656">"همه تماس‌ها به پست صوتی"</string>
     <string name="readOnlyContactWarning" msgid="7808825687289848259">"شما نمی‌توانید مخاطبین را از حساب‌های فقط خواندنی حذف کنید اما می‌توانید آن‌ها را در لیست‌های مخاطبین خود پنهان کنید."</string>
-    <string name="readOnlyContactDeleteConfirmation" msgid="2137170726670196909">"این مخاطب دارای اطلاعاتی از چند حساب است. اطلاعات حساب های فقط خواندنی در لیست های مخاطبین پنهان می شوند اما حذف نمی شوند."</string>
-    <string name="multipleContactDeleteConfirmation" msgid="938900978442960800">"حذف این مخاطب اطلاعات را از حساب های متعدد حذف می کند."</string>
-    <string name="deleteConfirmation" msgid="811706994761610640">"این مخاطب حذف می شود."</string>
+    <string name="readOnlyContactDeleteConfirmation" msgid="2137170726670196909">"این مخاطب دارای اطلاعاتی از چند حساب است. اطلاعات حساب‌های فقط خواندنی در لیست‌های مخاطبین پنهان می‌شوند اما حذف نمی‌شوند."</string>
+    <string name="multipleContactDeleteConfirmation" msgid="938900978442960800">"حذف این مخاطب اطلاعات را از حساب‌های متعدد حذف می‌کند."</string>
+    <string name="deleteConfirmation" msgid="811706994761610640">"این مخاطب حذف می‌شود."</string>
     <string name="menu_done" msgid="796017761764190697">"انجام شد"</string>
     <string name="menu_doNotSave" msgid="58593876893538465">"لغو"</string>
     <string name="menu_discard" msgid="6456087569315685632">"صرفنظر"</string>
-    <string name="label_notes" msgid="8337354953278341042">"یادداشت ها"</string>
+    <string name="label_notes" msgid="8337354953278341042">"یادداشت‌ها"</string>
     <string name="label_sip_address" msgid="124073911714324974">"تماس اینترنتی"</string>
     <string name="ghostData_company" msgid="5414421120553765775">"شرکت"</string>
     <string name="ghostData_title" msgid="7496735200318496110">"عنوان"</string>
     <string name="invalidContactMessage" msgid="8215051456181842274">"مخاطبی موجود نیست."</string>
-    <string name="createContactShortcutSuccessful" msgid="7874133287558150877">"ابزارک مخاطب به صفحه اصلی شما اضافه شد."</string>
+    <string name="createContactShortcutSuccessful" msgid="7874133287558150877">"ابزارک مخاطب به صفحهٔ اصلی شما اضافه شد."</string>
     <string name="pickerNewContactHeader" msgid="7750705279843568147">"ایجاد مخاطب جدید"</string>
     <string name="pickerNewContactText" msgid="6166997164401048211">"ایجاد مخاطب جدید"</string>
     <string name="phoneLabelsGroup" msgid="6468091477851199285">"تلفن"</string>
@@ -103,7 +103,7 @@
     <string name="emptyGroup" msgid="7502116218697177370">"هیچ فردی در این گروه نیست."</string>
     <string name="addPeopleToGroup" msgid="7879585947222263516">"برای افزودن چند عضو، گروه را ویرایش کنید."</string>
     <string name="savingContact" msgid="4075751076741924939">"در حال ذخیره مخاطب..."</string>
-    <string name="savingDisplayGroups" msgid="2133152192716475939">"در حال ذخیره گزینه های نمایش..."</string>
+    <string name="savingDisplayGroups" msgid="2133152192716475939">"در حال ذخیره گزینه‌های نمایش..."</string>
     <string name="contactSavedToast" msgid="7152589189385441091">"مخاطب ذخیره شد."</string>
     <string name="contactSavedErrorToast" msgid="3207250533172944892">"تغییرات مخاطب ذخیره نمی‌شود."</string>
     <string name="groupSavedToast" msgid="1168756874239833756">"گروه ذخیره شد."</string>
@@ -135,7 +135,7 @@
     <item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> یافت شد"</item>
   </plurals>
     <string name="contactsAllLabel" msgid="6479708629170672169">"همه مخاطبین"</string>
-    <string name="contactsGroupsLabel" msgid="2841971472518003524">"گروه ها"</string>
+    <string name="contactsGroupsLabel" msgid="2841971472518003524">"گروه‌ها"</string>
     <string name="contactsFavoritesLabel" msgid="8417039765586853670">"موارد دلخواه"</string>
     <string name="dialerIconLabel" msgid="6500826552823403796">"تلفن"</string>
     <string name="recentCallsIconLabel" msgid="1419116422359067949">"گزارش تماس"</string>
@@ -164,7 +164,7 @@
     <string name="dialerDialpadHintText" msgid="5824490365898349041">"شماره گیری برای افزودن یک تماس"</string>
     <string name="simContacts_emptyLoading" msgid="6700035985448642408">"در حال بارگیری سیم کارت..."</string>
     <string name="simContacts_title" msgid="27341688347689769">"مخاطبین سیم کارت"</string>
-    <string name="noContactsHelpTextWithSyncForCreateShortcut" msgid="801504710275614594">"شما مخاطبی برای نمایش ندارید. (در صورتی که اکنون یک حساب را اضافه کردید، همگام سازی مخاطبین چند دقیقه طول می کشد.)"</string>
+    <string name="noContactsHelpTextWithSyncForCreateShortcut" msgid="801504710275614594">"شما مخاطبی برای نمایش ندارید. (در صورتی که اکنون یک حساب را اضافه کردید، همگام سازی مخاطبین چند دقیقه طول می‌کشد.)"</string>
     <string name="noContactsHelpTextForCreateShortcut" msgid="3081286388667108335">"شما مخاطبی برای نمایش ندارید."</string>
     <string name="noContactsHelpText" product="tablet" msgid="6226271923423236696">"شما مخاطبی برای نمایش ندارید."\n\n"برای افزودن مخاطبین، "<font fgcolor="#ffffffff"><b>"منو"</b></font>" را لمس کرده و سپس این موارد را لمس کنید:"\n" "\n<li><font fgcolor="#ffffffff"><b>"حساب‌ها"</b></font>" برای افزودن یا تنظیم یک حساب با مخاطبینی که می‌توانید با رایانه لوحی همگام‌سازی کنید"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"مخاطب جدید"</b></font>" برای ایجاد یک مخاطب جدید از ابتدا"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"وارد کردن/صادر کردن"</b></font>" برای وارد کردن مخاطبین از سیم کارت یا کارت SD شما"\n</li></string>
     <string name="noContactsHelpText" product="default" msgid="4405064135698982080">"شما مخاطبی برای نمایش ندارید."\n\n"برای افزودن مخاطب، "<font fgcolor="#ffffffff"><b>"منو"</b></font>" را لمس کرده و سپس این موارد را لمس کنید:"\n" "\n<li><font fgcolor="#ffffffff"><b>"حساب‌ها"</b></font>" برای افزودن یا تنظیم یک حساب با مخاطبینی که می‌توانید با گوشی همگام‌سازی کنید"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"مخاطب جدید"</b></font>" برای ایجاد یک مخاطب جدید از ابتدا"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"وارد کردن/صادر کردن"</b></font>" برای وارد کردن مخاطبین از سیم کارت یا کارت SD شما"\n</li></string>
@@ -174,7 +174,7 @@
     <string name="noContactsNoSimHelpText" product="default" msgid="6224952277619986841">"شما مخاطبی برای نمایش ندارید."\n\n"برای افزودن مخاطبین، "<font fgcolor="#ffffffff"><b>"منو"</b></font>" را لمس کرده و سپس این موارد را لمس کنید:"\n" "\n<li><font fgcolor="#ffffffff"><b>"حساب‌ها"</b></font>" برای افزودن یا تنظیم یک حساب با مخاطبینی که می‌توانید با گوشی همگام‌سازی کنید"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"مخاطب جدید"</b></font>" برای ایجاد یک مخاطب جدید از ابتدا"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"وارد کردن/صادر کردن"</b></font>" برای وارد کردن مخاطبین از کارت SD شما"\n</li></string>
     <string name="noContactsNoSimHelpTextWithSync" product="tablet" msgid="5415762667445638265">"شما مخاطبی برای نمایش ندارید. (در صورتی که اکنون یک حساب اضافه کرده‌اید، همگام‌سازی مخاطبین چند دقیقه طول می‌کشد.)"\n\n"برای افزودن مخاطبین، "<font fgcolor="#ffffffff"><b>"منو"</b></font>" را لمس کرده و سپس این موارد را لمس کنید:"\n" "\n<li><font fgcolor="#ffffffff"><b>"حساب‌ها"</b></font>" برای افزودن یا پیکربندی یک حساب با مخاطبینی که می‌توانید در رایانه لوحی همگام‌سازی کنید"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"گزینه‌های نمایش"</b></font>" برای تغییر مخاطبینی که قابل مشاهده هستند"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"مخاطب جدید"</b></font>" برای ایجاد یک مخاطب جدید از ابتدا"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"وارد کردن/صادر کردن"</b></font>" برای وارد کردن مخاطبین از کارت SD شما"\n</li></string>
     <string name="noContactsNoSimHelpTextWithSync" product="default" msgid="7443705129830284440">"شما مخاطبی برای نمایش ندارید. (در صورتی که اکنون یک حساب اضافه کرده‌اید، همگام‌سازی مخاطبین چند دقیقه طول می‌کشد.)"\n\n"برای افزودن مخاطبین، "<font fgcolor="#ffffffff"><b>"منو"</b></font>" را لمس کرده و سپس این موارد را لمس کنید:"\n" "\n<li><font fgcolor="#ffffffff"><b>"حساب‌ها"</b></font>" برای افزودن یا تنظیم یک حساب با مخاطبینی که می‌توانید با گوشی همگام‌سازی کنید"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"گزینه‌های نمایش"</b></font>" برای تغییر مخاطبینی که قابل مشاهده هستند"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"مخاطب جدید"</b></font>" برای ایجاد یک مخاطب جدید از ابتدا"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"وارد کردن/صادر کردن"</b></font>" برای وارد کردن مخاطبین از کارت SD شما"\n</li></string>
-    <string name="noFavoritesHelpText" msgid="3744655776704833277">"شما هیچ مورد دلخواهی ندارید."\n\n"برای افزودن یک مخاطب به لیست موارد دلخواه خود: "\n\n"        "<li>"برگه "<b>"مخاطبین"</b>\n</li>" را لمس کنید"\n<li>"مخاطبی را که می خواهید به لیست موارد دلخواه خود اضافه کنید لمس کنید"\n</li>" "\n<li>"ستاره واقع در کنار نام مخاطب را لمس کنید"\n</li></string>
+    <string name="noFavoritesHelpText" msgid="3744655776704833277">"شما هیچ مورد دلخواهی ندارید."\n\n"برای افزودن یک مخاطب به لیست موارد دلخواه خود: "\n\n"        "<li>"برگه "<b>"مخاطبین"</b>\n</li>" را لمس کنید"\n<li>"مخاطبی را که می‌خواهید به لیست موارد دلخواه خود اضافه کنید لمس کنید"\n</li>" "\n<li>"ستاره واقع در کنار نام مخاطب را لمس کنید"\n</li></string>
     <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"استفاده از صفحه کلید لمسی"</string>
     <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"برگشت به تماس در حال انجام"</string>
     <string name="dialer_addAnotherCall" msgid="4205688819890074468">"افزودن تماس"</string>
@@ -184,7 +184,7 @@
     <string name="type_outgoing" msgid="343108709599392641">"تماس خروجی"</string>
     <string name="type_missed" msgid="2720502601640509542">"تماس بی پاسخ"</string>
     <string name="type_voicemail" msgid="5153139450668549908">"پست صوتی"</string>
-    <string name="actionIncomingCall" msgid="6028930669817038600">"تماس های ورودی"</string>
+    <string name="actionIncomingCall" msgid="6028930669817038600">"تماس‌های ورودی"</string>
     <string name="callBack" msgid="5498224409038809224">"بازگرداندن تماس"</string>
     <string name="callAgain" msgid="3197312117049874778">"تماس مجدد"</string>
     <string name="returnCall" msgid="8171961914203617813">"برگشت تماس"</string>
@@ -221,9 +221,9 @@
     <string name="share_visible_contacts" msgid="890150378880783797">"اشتراک گذاری مخاطبین قابل مشاهده"</string>
     <string name="import_one_vcard_string" msgid="9059163467020328433">"وارد کردن یک فایل کارت ویزیت"</string>
     <string name="import_multiple_vcard_string" msgid="3810226492811062392">"وارد کردن چند فایل کارت ویزیت"</string>
-    <string name="import_all_vcard_string" msgid="5518136113853448474">"وارد کردن همه فایل های کارت ویزیت"</string>
+    <string name="import_all_vcard_string" msgid="5518136113853448474">"وارد کردن همه فایل‌های کارت ویزیت"</string>
     <string name="searching_vcard_message" product="nosdcard" msgid="557077639409584945">"جستجوی داده کارت ویزیت در دستگاه ذخیره..."</string>
-    <string name="searching_vcard_message" product="default" msgid="3962269894118092049">"درحال جستجوی داده‌های کارت ویزیت در کارت SD..."</string>
+    <string name="searching_vcard_message" product="default" msgid="3962269894118092049">"در حال جستجوی داده‌های کارت ویزیت در کارت SD..."</string>
     <string name="scanning_sdcard_failed_message" product="nosdcard" msgid="7221682312959229201">"دستگاه ذخیره نمی‌تواند بررسی شود. (علت: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\")"</string>
     <string name="scanning_sdcard_failed_message" product="default" msgid="189023067829510792">"کارت SD نمی‌تواند بررسی شود. (علت: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\")"</string>
     <string name="fail_reason_io_error" msgid="6748358842976073255">"خطای ورودی/خروجی"</string>
@@ -245,10 +245,10 @@
     <string name="reading_vcard_canceled_title" msgid="1925216585981542019">"خواندن داده کارت ویزیت لغو شد"</string>
     <string name="importing_vcard_finished_title" msgid="3341541727268747967">"وارد کردن کارت ویزیت <xliff:g id="FILENAME">%s</xliff:g> پایان یافت"</string>
     <string name="importing_vcard_canceled_title" msgid="2147475978165599336">"واردکردن <xliff:g id="FILENAME">%s</xliff:g> لغو شد"</string>
-    <string name="vcard_import_will_start_message" msgid="2804911199145873396">"<xliff:g id="FILENAME">%s</xliff:g> به زودی وارد می شود."</string>
-    <string name="vcard_import_will_start_message_with_default_name" msgid="1022969530654129470">"فایل پس از مدت کوتاهی وارد می شود."</string>
+    <string name="vcard_import_will_start_message" msgid="2804911199145873396">"<xliff:g id="FILENAME">%s</xliff:g> به زودی وارد می‌شود."</string>
+    <string name="vcard_import_will_start_message_with_default_name" msgid="1022969530654129470">"فایل پس از مدت کوتاهی وارد می‌شود."</string>
     <string name="vcard_import_request_rejected_message" msgid="2890471184508516011">"درخواست وارد کردن کارت ویزیت رد شد. لطفاً بعداً امتحان کنید."</string>
-    <string name="vcard_export_will_start_message" msgid="2210241345252081463">"<xliff:g id="FILENAME">%s</xliff:g> به زودی صادر می شود."</string>
+    <string name="vcard_export_will_start_message" msgid="2210241345252081463">"<xliff:g id="FILENAME">%s</xliff:g> به زودی صادر می‌شود."</string>
     <string name="vcard_export_request_rejected_message" msgid="2844874826431327531">"درخواست صدور کارت ویزیت رد شد. لطفاً بعداً امتحان کنید."</string>
     <string name="vcard_unknown_filename" msgid="7171709890959915954">"مخاطب"</string>
     <string name="percentage" msgid="1044592438199055502">"<xliff:g id="PERCENTAGE">%s</xliff:g><xliff:g id="PERCENTSIGN">%%</xliff:g>"</string>
@@ -275,8 +275,8 @@
     <string name="cancel_import_confirmation_message" msgid="3929951040347726757">"وارد کردن <xliff:g id="FILENAME">%s</xliff:g> لغو شود؟"</string>
     <string name="cancel_export_confirmation_message" msgid="1995462401949262638">"صادر کردن <xliff:g id="FILENAME">%s</xliff:g> لغو شود؟"</string>
     <string name="cancel_vcard_import_or_export_failed" msgid="6139900383366166706">"نمی‌توان وارد کردن/ صادر کردن کارت ویزیت را لغو کرد"</string>
-    <string name="search_settings_description" msgid="2675223022992445813">"نام های مخاطبین شما"</string>
-    <string name="add_2sec_pause" msgid="9214012315201040129">"افزودن یک مکث 2 ثانیه ای"</string>
+    <string name="search_settings_description" msgid="2675223022992445813">"نام‌های مخاطبین شما"</string>
+    <string name="add_2sec_pause" msgid="9214012315201040129">"افزودن یک مکث ۲ ثانیه ای"</string>
     <string name="add_wait" msgid="3360818652790319634">"افزودن انتظار"</string>
     <string name="call_disambig_title" msgid="4392886850104795739">"انتخاب شماره"</string>
     <string name="call_settings" msgid="7666474782093693667">"تنظیمات"</string>
@@ -299,12 +299,12 @@
     <string name="websiteLabelsGroup" msgid="4202998982804009261">"وب سایت"</string>
     <string name="eventLabelsGroup" msgid="3695433812142818803">"رویدادها"</string>
     <string name="relationLabelsGroup" msgid="1854373894284572781">"رابطه"</string>
-    <string name="groupsLabel" msgid="8573535366319059326">"گروه ها"</string>
+    <string name="groupsLabel" msgid="8573535366319059326">"گروه‌ها"</string>
     <string name="dialog_new_contact_account" msgid="9044704073286262197">"ایجاد مخاطبین تحت حساب"</string>
     <string name="dialog_new_group_account" msgid="2318032089273496830">"ایجاد گروه تحت حساب کاربری"</string>
     <string name="menu_sync_remove" msgid="3266725887008450161">"حذف گروه همگام سازی"</string>
     <string name="dialog_sync_add" msgid="8267045393119375803">"افزودن گروه همگام سازی"</string>
-    <string name="display_more_groups" msgid="2682547080423434170">"گروه های بیشتر..."</string>
+    <string name="display_more_groups" msgid="2682547080423434170">"گروه‌های بیشتر..."</string>
     <string name="display_ungrouped" msgid="6885954210243119591">"کلیه مخاطبین دیگر"</string>
     <string name="display_all_contacts" msgid="2031647544742889505">"همه مخاطبین"</string>
     <string name="display_warn_remove_ungrouped" msgid="8872290721676651414">"حذف \"<xliff:g id="GROUP">%s</xliff:g>\" از همگام‌سازی نیز هر گونه مخاطب گروه‌بندی نشده‌ای را از همگام‌سازی حذف می‌کند."</string>
@@ -373,7 +373,7 @@
     <string name="chat_jabber" msgid="7561444230307829609">"گپ با استفاده از Jabber"</string>
     <string name="chat" msgid="9025361898797412245">"گپ"</string>
     <string name="audio_chat" msgid="2535716629358298691">"گپ صوتی"</string>
-    <string name="video_chat" msgid="1872255818640336072">"گپ ویدیویی"</string>
+    <string name="video_chat" msgid="1872255818640336072">"گپ ویدئویی"</string>
     <string name="postal_address" msgid="8765560217149624536">"آدرس"</string>
     <string name="postal_street" msgid="8133143961580058972">"خیابان"</string>
     <string name="postal_pobox" msgid="4431938829180269821">"صندوق پستی"</string>
@@ -406,17 +406,17 @@
     <string name="display_options_sort_list_by" msgid="6080091755852211076">"مرتب سازی لیست بر اساس"</string>
     <string name="display_options_sort_by_given_name" msgid="184916793466387067">"نام"</string>
     <string name="display_options_sort_by_family_name" msgid="7857986975275712622">"نام خانوادگی"</string>
-    <string name="display_options_view_names_as" msgid="18022868169627979">"مشاهده نام های مخاطب بعنوان"</string>
+    <string name="display_options_view_names_as" msgid="18022868169627979">"مشاهده نام‌های مخاطب به‌عنوان"</string>
     <string name="display_options_view_given_name_first" msgid="6968288511197363292">"ابتدا نام"</string>
     <string name="display_options_view_family_name_first" msgid="1447288164951453714">"ابتدا نام خانوادگی"</string>
     <string name="take_photo" msgid="7496128293167402354">"عکسبرداری"</string>
     <string name="take_new_photo" msgid="7341354729436576304">"گرفتن عکس جدید"</string>
     <string name="pick_photo" msgid="3746334626214970837">"انتخاب عکس از گالری"</string>
     <string name="pick_new_photo" msgid="7962368009197147617">"انتخاب عکس جدید از گالری"</string>
-    <string name="locale_change_in_progress" msgid="7583992153091537467">"لیست مخاطبین در حال به روزرسانی برای منعکس کردن تغییرات زبان است."</string>
-    <string name="upgrade_in_progress" msgid="474511436863451061">"لیست مخاطبین در حال به روزرسانی است."</string>
-    <string name="upgrade_out_of_memory" msgid="1209994418877625940">"مخاطبین در حال ارتقا هستند. "\n\n"فرآیند ارتقا به تقریباً <xliff:g id="SIZE_IN_MEGABYTES">%s</xliff:g> مگابایت از حافظه داخلی نیاز دارد. "\n\n"یکی از گزینه‌های زیر را انتخاب کنید:"</string>
-    <string name="upgrade_out_of_memory_uninstall" msgid="1721798828992091432">"حذف نصب برخی از برنامه های کاربردی"</string>
+    <string name="locale_change_in_progress" msgid="7583992153091537467">"لیست مخاطبین در حال به‌روزرسانی برای منعکس کردن تغییرات زبان است."</string>
+    <string name="upgrade_in_progress" msgid="474511436863451061">"لیست مخاطبین در حال به‌روزرسانی است."</string>
+    <string name="upgrade_out_of_memory" msgid="1209994418877625940">"مخاطبین در حال ارتقا هستند. "\n\n"فرآیند ارتقا به تقریباً <xliff:g id="SIZE_IN_MEGABYTES">%s</xliff:g> مگابایت از حافظهٔ داخلی نیاز دارد. "\n\n"یکی از گزینه‌های زیر را انتخاب کنید:"</string>
+    <string name="upgrade_out_of_memory_uninstall" msgid="1721798828992091432">"حذف نصب برخی از برنامه‌های کاربردی"</string>
     <string name="upgrade_out_of_memory_retry" msgid="8431289830472724609">"امتحان مجدد برای ارتقا"</string>
     <string name="search_results_searching" msgid="3984833028938569930">"در حال جستجو..."</string>
     <string name="menu_display_selected" msgid="6470001164297969034">"نمایش موارد انتخاب شده"</string>
@@ -439,7 +439,7 @@
   </plurals>
     <string name="local_invisible_directory" msgid="6046691709127661065">"سایر موارد"</string>
     <string name="aggregation_suggestion_join_dialog_message" msgid="3842757977671434836">"پیوستن به مخاطب فعلی با مخاطب انتخابی؟"</string>
-    <string name="aggregation_suggestion_edit_dialog_message" msgid="6549585283910518095">"به ویرایش مخاطب انتخابی می روید؟ اطلاعاتی که تا حال وارد کرده اید کپی خواهد شد."</string>
+    <string name="aggregation_suggestion_edit_dialog_message" msgid="6549585283910518095">"به ویرایش مخاطب انتخابی می‌روید؟ اطلاعاتی که تا حال وارد کرده‌اید کپی خواهد شد."</string>
     <string name="menu_copyContact" msgid="1573960845106822639">"کپی در مخاطبین من"</string>
     <string name="add_to_my_contacts" msgid="1068274916793627723">"افزودن به مخاطبین من"</string>
     <string name="contact_directory_description" msgid="683398073603909119">"دایرکتوری <xliff:g id="TYPE">%1$s</xliff:g>"</string>
@@ -453,12 +453,12 @@
     <string name="list_filter_phones" msgid="735313795643493365">"همه مخاطبین دارای شماره تلفن"</string>
     <string name="list_filter_single" msgid="5871400283515893087">"مخاطب"</string>
     <string name="custom_list_filter" msgid="7836035257402013957">"تعیین نمای سفارشی"</string>
-    <string name="contact_list_loading" msgid="5488620820563977329">"درحال بارگیری..."</string>
+    <string name="contact_list_loading" msgid="5488620820563977329">"در حال بارگیری..."</string>
     <string name="activity_title_settings" msgid="5464130076132770781">"تنظیمات"</string>
     <string name="activity_title_contacts_filter" msgid="8275542497615516969">"مخاطبین جهت نمایش"</string>
     <string name="menu_settings" msgid="377929915873428211">"تنظیمات"</string>
     <string name="menu_help" msgid="5123887102216637725">"راهنمایی"</string>
-    <string name="preference_displayOptions" msgid="1341720270148252393">"گزینه های نمایش"</string>
+    <string name="preference_displayOptions" msgid="1341720270148252393">"گزینه‌های نمایش"</string>
     <string name="organization_company_and_title" msgid="6718207751363732025">"<xliff:g id="COMPANY_0">%2$s</xliff:g>، <xliff:g id="COMPANY_1">%1$s</xliff:g>"</string>
     <string name="hint_findContacts" msgid="1808681193458772072">"پیدا کردن مخاطبین"</string>
     <string name="non_phone_caption" msgid="1541655052330027380">"شماره تلفن"</string>
@@ -468,7 +468,7 @@
     <string name="widget_name_and_phonetic" msgid="8739586586600099979">"<xliff:g id="DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="PHONETIC_NAME">%2$s</xliff:g>)"</string>
     <string name="date_year_toggle" msgid="7356532842767854606">"یک سال وارد کنید"</string>
     <string name="social_widget_label" msgid="6378905543028924592">"مخاطب"</string>
-    <string name="social_widget_loading" msgid="5327336597364074608">"درحال بارگیری..."</string>
+    <string name="social_widget_loading" msgid="5327336597364074608">"در حال بارگیری..."</string>
     <string name="contacts_unavailable_create_contact" msgid="7014525713871959208">"ایجاد مخاطب جدید"</string>
     <string name="contacts_unavailable_add_account" msgid="7911101713860139754">"وارد شدن به یک حساب"</string>
     <string name="contacts_unavailable_import_contacts" msgid="4957393255392437529">"وارد کردن مخاطبین"</string>
@@ -489,7 +489,7 @@
   </plurals>
     <string name="toast_join_with_empty_contact" msgid="2238581529864542985">"لطفاً قبل از ادغام با مخاطب دیگر، نام مخاطب را وارد کنید."</string>
     <string name="copy_text" msgid="3257145021583508761">"کپی به کلیپ بورد"</string>
-    <string name="set_default" msgid="4417505153468300351">"تنظیم پیش فرض"</string>
+    <string name="set_default" msgid="4417505153468300351">"تنظیم پیش‌فرض"</string>
     <string name="clear_default" msgid="7193185801596678067">"پاک کردن پیش فرض‌ها"</string>
     <string name="toast_text_copied" msgid="5143776250008541719">"متن کپی شده"</string>
     <string name="cancel_confirmation_dialog_message" msgid="5885724679874403115">"از تغییرات شما صرفنظر شود؟"</string>
@@ -505,7 +505,7 @@
     <string name="notification_voicemail_callers_list" msgid="1153954809339404149">"<xliff:g id="NEWER_CALLERS">%1$s</xliff:g>، <xliff:g id="OLDER_CALLER">%2$s</xliff:g>"</string>
     <string name="notification_new_voicemail_ticker" msgid="895342132049452081">"پست صوتی جدید از <xliff:g id="CALLER">%1$s</xliff:g>"</string>
     <string name="voicemail_playback_error" msgid="1811242131549854624">"پخش پست صوتی ممکن نیست."</string>
-    <string name="voicemail_buffering" msgid="738287747618697097">"درحال بافر کردن؟؟؟"</string>
+    <string name="voicemail_buffering" msgid="738287747618697097">"در حال بافر کردن؟؟؟"</string>
     <string name="voicemail_fetching_content" msgid="877911315738258780">"در حال واکشی پست صوتی؟؟؟"</string>
     <string name="voicemail_fetching_timout" msgid="6691792377574905201">"واکشی پست صوتی ممکن نیست."</string>
     <string name="call_log_new_header" msgid="846546437517724715">"جدید"</string>
@@ -550,10 +550,10 @@
     <string name="no_account_prompt" msgid="7061052512446855192">"People با یک حساب Google بهتر کار می‌کند."\n\n"• از هر مرورگر وب به آن دسترسی دارید"\n"• از رویدادهای خود به طور امن پشتیبان تهیه کنید"</string>
     <string name="generic_no_account_prompt" msgid="7218827704367325460">"مخاطبین خود را ایمن نگهدارید حتی اگر گوشی شما گم شود: با یک سرویس آنلاین همگام‌سازی کنید."</string>
     <string name="generic_no_account_prompt_title" msgid="753783911899054860">"افزودن یک حساب"</string>
-    <string name="contact_editor_prompt_zero_accounts" msgid="1785345895691886499">"از مخاطب جدید شما نسخه پشتبان تهیه نمی‌شود. حسابی را اضافه میکنید که از مخاطبین بصورت آنلاین نسخه پشتبان تهیه کند؟"</string>
+    <string name="contact_editor_prompt_zero_accounts" msgid="1785345895691886499">"از مخاطب جدید شما نسخه پشتبان تهیه نمی‌شود. حسابی را اضافه می‌کنید که از مخاطبین به‌صورت آنلاین نسخه پشتبان تهیه کند؟"</string>
     <string name="contact_editor_prompt_one_account" msgid="8669032699767375976">"مخاطب جدید شما با <xliff:g id="ACCOUNT_NAME">%1$s</xliff:g> همگام‌سازی خواهد شد."</string>
     <string name="contact_editor_prompt_multiple_accounts" msgid="611828200100438242">"شما می‌توانید مخاطب جدید خود را با یکی از حساب‌های زیر همگام‌سازی کنید. از کدام‌یک می‌خواهید استفاده کنید؟"</string>
-    <string name="keep_local" msgid="1258761699192993322">"ذخیره بصورت محلی"</string>
+    <string name="keep_local" msgid="1258761699192993322">"ذخیره به‌صورت محلی"</string>
     <string name="add_account" msgid="8201790677994503186">"افزودن حساب"</string>
     <string name="add_new_account" msgid="5748627740680940264">"اافزودن حساب جدید"</string>
     <string name="dialog_phone_call_prohibited_message" msgid="6554711866586660441">"تماس ارسال نشد"</string>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 350693a..e72a0ee 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -17,4 +17,7 @@
     <dimen name="dialpad_digits_height">66dip</dimen>
     <dimen name="dialpad_digits_text_size">28sp</dimen>
     <dimen name="dialpad_digits_margin_bottom">50dip</dimen>
+    <!-- Center vertically -->
+    <dimen name="quick_contact_top_position">-1px</dimen>
+    <dimen name="editor_type_label_width">120dip</dimen>
 </resources>
diff --git a/res/values-w470dp/donottranslate_config.xml b/res/values-land/donottranslate_config.xml
similarity index 100%
rename from res/values-w470dp/donottranslate_config.xml
rename to res/values-land/donottranslate_config.xml
diff --git a/res/values-w470dp/integers.xml b/res/values-land/integers.xml
similarity index 100%
rename from res/values-w470dp/integers.xml
rename to res/values-land/integers.xml
diff --git a/res/values-w470dp/styles.xml b/res/values-land/styles.xml
similarity index 100%
rename from res/values-w470dp/styles.xml
rename to res/values-land/styles.xml
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 68888d2..4be8bdb 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -560,6 +560,6 @@
     <string name="add_new_account" msgid="5748627740680940264">"Ongeza akaunti mpya"</string>
     <string name="dialog_phone_call_prohibited_message" msgid="6554711866586660441">"Simu haijatumwa"</string>
     <string name="dialog_voicemail_not_ready_message" msgid="4384716252789515378">"Ili kusanidi ujumbe wa sauti, nenda kwa Menyu &gt; Mipangilio."</string>
-    <string name="dialog_voicemail_airplane_mode_message" msgid="530922773669546093">"Kupigia simu ujumbe wa sauti, kwanza lemaza hali ya ndege."</string>
+    <string name="dialog_voicemail_airplane_mode_message" msgid="530922773669546093">"Kupigia simu ujumbe wa sauti, kwanza zima hali ya ndege."</string>
     <string name="action_menu_overflow_description" msgid="2303272250613084574">"Chaguo zaidi"</string>
 </resources>
diff --git a/res/values-sw580dp-w940dp/dimens.xml b/res/values-sw580dp-land/dimens.xml
similarity index 100%
rename from res/values-sw580dp-w940dp/dimens.xml
rename to res/values-sw580dp-land/dimens.xml
diff --git a/res/values-sw580dp-w940dp/donottranslate_config.xml b/res/values-sw580dp-land/donottranslate_config.xml
similarity index 100%
rename from res/values-sw580dp-w940dp/donottranslate_config.xml
rename to res/values-sw580dp-land/donottranslate_config.xml
diff --git a/res/values-sw580dp-w940dp/integers.xml b/res/values-sw580dp-land/integers.xml
similarity index 100%
rename from res/values-sw580dp-w940dp/integers.xml
rename to res/values-sw580dp-land/integers.xml
diff --git a/res/values-sw580dp-w940dp/styles.xml b/res/values-sw580dp-land/styles.xml
similarity index 97%
rename from res/values-sw580dp-w940dp/styles.xml
rename to res/values-sw580dp-land/styles.xml
index d035240..9efb20b 100644
--- a/res/values-sw580dp-w940dp/styles.xml
+++ b/res/values-sw580dp-land/styles.xml
@@ -33,7 +33,6 @@
         <item name="list_item_padding_left">0dip</item>
         <item name="list_item_gap_between_image_and_text">8dip</item>
         <item name="list_item_gap_between_label_and_data">5dip</item>
-        <item name="list_item_vertical_divider_margin">5dip</item>
         <item name="list_item_presence_icon_margin">4dip</item>
         <item name="list_item_presence_icon_size">16dip</item>
         <item name="list_item_photo_size">64dip</item>
diff --git a/res/values-sw580dp/donottranslate_config.xml b/res/values-sw580dp/donottranslate_config.xml
index 3d0dea0..406863e 100644
--- a/res/values-sw580dp/donottranslate_config.xml
+++ b/res/values-sw580dp/donottranslate_config.xml
@@ -21,7 +21,6 @@
     <bool name="config_use_two_panes">true</bool>
     <bool name="config_use_two_panes_in_favorites">false</bool>
     <bool name="show_home_icon">true</bool>
-    <bool name="config_show_group_action_in_action_bar">false</bool>
     <bool name="config_browse_list_show_images">false</bool>
     <item name="tab_width_screen_width_percentage" type="fraction">66.67%</item>
     <item name="tab_height_screen_width_percentage" type="fraction">66.67%</item>
diff --git a/res/values-sw580dp/styles.xml b/res/values-sw580dp/styles.xml
index a8d935b..1181d5d 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-sw580dp/styles.xml
@@ -33,7 +33,6 @@
         <item name="list_item_padding_left">0dip</item>
         <item name="list_item_gap_between_image_and_text">8dip</item>
         <item name="list_item_gap_between_label_and_data">5dip</item>
-        <item name="list_item_vertical_divider_margin">5dip</item>
         <item name="list_item_presence_icon_margin">4dip</item>
         <item name="list_item_presence_icon_size">16dip</item>
         <item name="list_item_photo_size">64dip</item>
@@ -69,7 +68,6 @@
         <item name="list_item_padding_left">0dip</item>
         <item name="list_item_gap_between_image_and_text">8dip</item>
         <item name="list_item_gap_between_label_and_data">5dip</item>
-        <item name="list_item_vertical_divider_margin">5dip</item>
         <item name="list_item_presence_icon_margin">18dip</item>
         <item name="list_item_photo_size">64dip</item>
         <item name="list_item_profile_photo_size">80dip</item>
diff --git a/res/values-sw680dp-w1000dp/dimens.xml b/res/values-sw680dp-land/dimens.xml
similarity index 100%
rename from res/values-sw680dp-w1000dp/dimens.xml
rename to res/values-sw680dp-land/dimens.xml
diff --git a/res/values-sw680dp-w1000dp/integers.xml b/res/values-sw680dp-land/integers.xml
similarity index 100%
rename from res/values-sw680dp-w1000dp/integers.xml
rename to res/values-sw680dp-land/integers.xml
diff --git a/res/values-sw680dp-w1000dp/styles.xml b/res/values-sw680dp-land/styles.xml
similarity index 100%
rename from res/values-sw680dp-w1000dp/styles.xml
rename to res/values-sw680dp-land/styles.xml
diff --git a/res/values-sw680dp/styles.xml b/res/values-sw680dp/styles.xml
index fb242d9..d84c76a 100644
--- a/res/values-sw680dp/styles.xml
+++ b/res/values-sw680dp/styles.xml
@@ -33,7 +33,6 @@
         <item name="list_item_padding_left">0dip</item>
         <item name="list_item_gap_between_image_and_text">16dip</item>
         <item name="list_item_gap_between_label_and_data">5dip</item>
-        <item name="list_item_vertical_divider_margin">5dip</item>
         <item name="list_item_presence_icon_margin">4dip</item>
         <item name="list_item_presence_icon_size">16dip</item>
         <item name="list_item_photo_size">64dip</item>
diff --git a/res/values-w470dp/dimens.xml b/res/values-w470dp/dimens.xml
deleted file mode 100644
index c457147..0000000
--- a/res/values-w470dp/dimens.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<resources>
-    <!-- Center vertically -->
-    <dimen name="quick_contact_top_position">-1px</dimen>
-    <dimen name="editor_type_label_width">120dip</dimen>
-</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index e8798e4..6b09f78 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -74,7 +74,7 @@
     <string name="menu_doNotSave" msgid="58593876893538465">"取消"</string>
     <string name="menu_discard" msgid="6456087569315685632">"舍弃"</string>
     <string name="label_notes" msgid="8337354953278341042">"备注"</string>
-    <string name="label_sip_address" msgid="124073911714324974">"互联网通话"</string>
+    <string name="label_sip_address" msgid="124073911714324974">"互联网电话"</string>
     <string name="ghostData_company" msgid="5414421120553765775">"公司"</string>
     <string name="ghostData_title" msgid="7496735200318496110">"职位"</string>
     <string name="invalidContactMessage" msgid="8215051456181842274">"该联系人不存在。"</string>
@@ -82,8 +82,8 @@
     <string name="pickerNewContactHeader" msgid="7750705279843568147">"新建联系人"</string>
     <string name="pickerNewContactText" msgid="6166997164401048211">"创建新联系人"</string>
     <string name="phoneLabelsGroup" msgid="6468091477851199285">"电话"</string>
-    <string name="emailLabelsGroup" msgid="8389931313045344406">"发送电子邮件"</string>
-    <string name="imLabelsGroup" msgid="3898238486262614027">"即时消息"</string>
+    <string name="emailLabelsGroup" msgid="8389931313045344406">"电子邮件"</string>
+    <string name="imLabelsGroup" msgid="3898238486262614027">"即时聊天工具"</string>
     <string name="postalLabelsGroup" msgid="3487738141112589324">"地址"</string>
   <string-array name="otherLabels">
     <item msgid="8287841928119937597">"组织"</item>
@@ -297,7 +297,7 @@
     <string name="nicknameLabelsGroup" msgid="2891682101053358010">"昵称"</string>
     <string name="organizationLabelsGroup" msgid="2478611760751832035">"组织"</string>
     <string name="websiteLabelsGroup" msgid="4202998982804009261">"网站"</string>
-    <string name="eventLabelsGroup" msgid="3695433812142818803">"活动"</string>
+    <string name="eventLabelsGroup" msgid="3695433812142818803">"重要日子"</string>
     <string name="relationLabelsGroup" msgid="1854373894284572781">"关系"</string>
     <string name="groupsLabel" msgid="8573535366319059326">"群组"</string>
     <string name="dialog_new_contact_account" msgid="9044704073286262197">"在帐户下创建联系人"</string>
@@ -385,15 +385,15 @@
     <string name="full_name" msgid="6602579550613988977">"姓名"</string>
     <string name="name_given" msgid="1687286314106019813">"名字"</string>
     <string name="name_family" msgid="3416695586119999058">"姓氏"</string>
-    <string name="name_prefix" msgid="59756378548779822">"名称前缀"</string>
+    <string name="name_prefix" msgid="59756378548779822">"姓名前缀"</string>
     <string name="name_middle" msgid="8467433655992690326">"中间名"</string>
-    <string name="name_suffix" msgid="3855278445375651441">"名称后缀"</string>
+    <string name="name_suffix" msgid="3855278445375651441">"姓名后缀"</string>
     <string name="name_phonetic_given" msgid="6853570431394449191">"名字拼音"</string>
     <string name="name_phonetic_middle" msgid="8643721493320405200">"中间名拼音"</string>
     <string name="name_phonetic_family" msgid="462095502140180305">"姓氏拼音"</string>
     <string name="name_phonetic" msgid="4259595234312430484">"姓名拼音"</string>
-    <string name="connections" msgid="8098440723172028350">"联系"</string>
-    <string name="add_connection_button" msgid="4861308615789601727">"加强联系"</string>
+    <string name="connections" msgid="8098440723172028350">"社交网络"</string>
+    <string name="add_connection_button" msgid="4861308615789601727">"添加社交网络"</string>
     <string name="recent" msgid="2659189233141493004">"最新"</string>
     <string name="recent_updates" msgid="4267258535615860710">"最新动态"</string>
     <string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> 联系人"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index f49b0bf..5a5016e 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -74,7 +74,6 @@
         <attr name="list_item_padding_left" format="dimension"/>
         <attr name="list_item_gap_between_image_and_text" format="dimension"/>
         <attr name="list_item_gap_between_label_and_data" format="dimension"/>
-        <attr name="list_item_vertical_divider_margin" format="dimension"/>
         <attr name="list_item_presence_icon_margin" format="dimension"/>
         <attr name="list_item_presence_icon_size" format="dimension"/>
         <attr name="list_item_photo_size" format="dimension"/>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 829b207..6a7bd6f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -32,7 +32,6 @@
         <item name="list_item_padding_left">0dip</item>
         <item name="list_item_gap_between_image_and_text">8dip</item>
         <item name="list_item_gap_between_label_and_data">5dip</item>
-        <item name="list_item_vertical_divider_margin">5dip</item>
         <item name="list_item_presence_icon_margin">4dip</item>
         <item name="list_item_presence_icon_size">16dip</item>
         <item name="list_item_photo_size">@dimen/contact_browser_list_item_photo_size</item>
@@ -145,7 +144,6 @@
         <item name="list_item_padding_left">0dip</item>
         <item name="list_item_gap_between_image_and_text">8dip</item>
         <item name="list_item_gap_between_label_and_data">5dip</item>
-        <item name="list_item_vertical_divider_margin">5dip</item>
         <item name="list_item_presence_icon_margin">4dip</item>
         <item name="list_item_presence_icon_size">16dip</item>
         <item name="list_item_photo_size">@dimen/contact_browser_list_item_photo_size</item>
diff --git a/src/com/android/contacts/CallContactActivity.java b/src/com/android/contacts/CallContactActivity.java
index 793770b..c4b4dc7 100644
--- a/src/com/android/contacts/CallContactActivity.java
+++ b/src/com/android/contacts/CallContactActivity.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts;
 
-import com.android.contacts.interactions.PhoneNumberInteraction;
-
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnDismissListener;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.ContactsContract.Contacts;
 
+import com.android.contacts.interactions.PhoneNumberInteraction;
+
 /**
  * An interstitial activity used when the user selects a QSB search suggestion using
  * a call button.
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 47441ce..7bb2157 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -16,22 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.BackScrollManager.ScrollableHeader;
-import com.android.contacts.calllog.CallDetailHistoryAdapter;
-import com.android.contacts.calllog.CallTypeHelper;
-import com.android.contacts.calllog.ContactInfo;
-import com.android.contacts.calllog.ContactInfoHelper;
-import com.android.contacts.calllog.PhoneNumberHelper;
-import com.android.contacts.format.FormatUtils;
-import com.android.contacts.util.AsyncTaskExecutor;
-import com.android.contacts.util.AsyncTaskExecutors;
-import com.android.contacts.util.ClipboardUtils;
-import com.android.contacts.util.Constants;
-import com.android.contacts.voicemail.VoicemailPlaybackFragment;
-import com.android.contacts.voicemail.VoicemailStatusHelper;
-import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
-import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
-
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.ContentResolver;
@@ -67,6 +51,22 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.contacts.BackScrollManager.ScrollableHeader;
+import com.android.contacts.calllog.CallDetailHistoryAdapter;
+import com.android.contacts.calllog.CallTypeHelper;
+import com.android.contacts.calllog.ContactInfo;
+import com.android.contacts.calllog.ContactInfoHelper;
+import com.android.contacts.calllog.PhoneNumberHelper;
+import com.android.contacts.format.FormatUtils;
+import com.android.contacts.util.AsyncTaskExecutor;
+import com.android.contacts.util.AsyncTaskExecutors;
+import com.android.contacts.util.ClipboardUtils;
+import com.android.contacts.util.Constants;
+import com.android.contacts.voicemail.VoicemailPlaybackFragment;
+import com.android.contacts.voicemail.VoicemailStatusHelper;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/CallDetailActivityQueryHandler.java b/src/com/android/contacts/CallDetailActivityQueryHandler.java
index df5b4f7..41cf937 100644
--- a/src/com/android/contacts/CallDetailActivityQueryHandler.java
+++ b/src/com/android/contacts/CallDetailActivityQueryHandler.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.common.io.MoreCloseables;
-import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
-
 import android.content.AsyncQueryHandler;
 import android.database.Cursor;
 import android.net.Uri;
@@ -26,6 +23,9 @@
 import android.provider.VoicemailContract.Voicemails;
 import android.util.Log;
 
+import com.android.common.io.MoreCloseables;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+
 /**
  * Class used by {@link CallDetailActivity} to fire async content resolver queries.
  */
diff --git a/src/com/android/contacts/ContactPhotoManager.java b/src/com/android/contacts/ContactPhotoManager.java
index 5b6a1ca..5c866d0 100644
--- a/src/com/android/contacts/ContactPhotoManager.java
+++ b/src/com/android/contacts/ContactPhotoManager.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.util.BitmapUtil;
-import com.android.contacts.util.MemoryUtils;
-import com.android.contacts.util.UriUtils;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-
 import android.content.ComponentCallbacks2;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -55,6 +48,13 @@
 import android.util.TypedValue;
 import android.widget.ImageView;
 
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.util.BitmapUtil;
+import com.android.contacts.util.MemoryUtils;
+import com.android.contacts.util.UriUtils;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.lang.ref.Reference;
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index b8bf45f..4333aa4 100644
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -16,15 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.util.CallerInfoCacheUtils;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-
 import android.app.Activity;
 import android.app.IntentService;
 import android.content.ContentProviderOperation;
@@ -55,6 +46,15 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.util.CallerInfoCacheUtils;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -289,7 +289,7 @@
      * @param rawContactId identifies a writable raw-contact whose photo is to be updated.
      * @param updatedPhotoPath denotes a temporary file containing the contact's new photo.
      */
-    public static Intent createSaveContactIntent(Context context, EntityDeltaList state,
+    public static Intent createSaveContactIntent(Context context, RawContactDeltaList state,
             String saveModeExtraKey, int saveMode, boolean isProfile,
             Class<? extends Activity> callbackActivity, String callbackAction, long rawContactId,
             String updatedPhotoPath) {
@@ -306,7 +306,7 @@
      * Contact Editor.
      * @param updatedPhotos maps each raw-contact's ID to the file-path of the new photo.
      */
-    public static Intent createSaveContactIntent(Context context, EntityDeltaList state,
+    public static Intent createSaveContactIntent(Context context, RawContactDeltaList state,
             String saveModeExtraKey, int saveMode, boolean isProfile,
             Class<? extends Activity> callbackActivity, String callbackAction,
             Bundle updatedPhotos) {
@@ -332,13 +332,13 @@
     }
 
     private void saveContact(Intent intent) {
-        EntityDeltaList state = intent.getParcelableExtra(EXTRA_CONTACT_STATE);
+        RawContactDeltaList state = intent.getParcelableExtra(EXTRA_CONTACT_STATE);
         boolean isProfile = intent.getBooleanExtra(EXTRA_SAVE_IS_PROFILE, false);
         Bundle updatedPhotos = intent.getParcelableExtra(EXTRA_UPDATED_PHOTOS);
 
         // Trim any empty fields, and RawContacts, before persisting
         final AccountTypeManager accountTypes = AccountTypeManager.getInstance(this);
-        EntityModifier.trimEmpty(state, accountTypes);
+        RawContactModifier.trimEmpty(state, accountTypes);
 
         Uri lookupUri = null;
 
@@ -427,16 +427,16 @@
                     throw new IllegalStateException("Version consistency failed for a new contact");
                 }
 
-                final EntityDeltaList newState = EntityDeltaList.fromQuery(
+                final RawContactDeltaList newState = RawContactDeltaList.fromQuery(
                         isProfile
                                 ? RawContactsEntity.PROFILE_CONTENT_URI
                                 : RawContactsEntity.CONTENT_URI,
                         resolver, sb.toString(), null, null);
-                state = EntityDeltaList.mergeAfter(newState, state);
+                state = RawContactDeltaList.mergeAfter(newState, state);
 
                 // Update the new state to use profile URIs if appropriate.
                 if (isProfile) {
-                    for (EntityDelta delta : state) {
+                    for (RawContactDelta delta : state) {
                         delta.setProfileQueryUri();
                     }
                 }
@@ -518,7 +518,7 @@
     /**
      * Find the ID of an existing or newly-inserted raw-contact.  If none exists, return -1.
      */
-    private long getRawContactId(EntityDeltaList state,
+    private long getRawContactId(RawContactDeltaList state,
             final ArrayList<ContentProviderOperation> diff,
             final ContentProviderResult[] results) {
         long existingRawContactId = state.findRawContactId();
diff --git a/src/com/android/contacts/ContactTileLoaderFactory.java b/src/com/android/contacts/ContactTileLoaderFactory.java
index 28f2164..3a23400 100644
--- a/src/com/android/contacts/ContactTileLoaderFactory.java
+++ b/src/com/android/contacts/ContactTileLoaderFactory.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts;
 
-import com.android.contacts.list.ContactTileView;
-
 import android.content.Context;
 import android.content.CursorLoader;
 import android.net.Uri;
@@ -24,6 +22,8 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.Contacts;
 
+import com.android.contacts.list.ContactTileView;
+
 /**
  * Used to create {@link CursorLoader}s to load different groups of {@link ContactTileView}s
  */
diff --git a/src/com/android/contacts/ContactsActivity.java b/src/com/android/contacts/ContactsActivity.java
index 371b0b7..90900ce 100644
--- a/src/com/android/contacts/ContactsActivity.java
+++ b/src/com/android/contacts/ContactsActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.activities.TransactionSafeActivity;
-
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
@@ -28,6 +25,9 @@
 import android.os.Bundle;
 import android.view.View;
 
+import com.android.contacts.activities.TransactionSafeActivity;
+import com.android.contacts.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 956ce65..3380553 100644
--- a/src/com/android/contacts/ContactsApplication.java
+++ b/src/com/android/contacts/ContactsApplication.java
@@ -16,12 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.list.ContactListFilterController;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.util.Constants;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.app.Application;
 import android.app.FragmentManager;
 import android.app.LoaderManager;
@@ -35,6 +29,12 @@
 import android.provider.ContactsContract.Contacts;
 import android.util.Log;
 
+import com.android.contacts.list.ContactListFilterController;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.test.InjectedServices;
+import com.android.contacts.util.Constants;
+import com.google.common.annotations.VisibleForTesting;
+
 public final class ContactsApplication extends Application {
     private static final boolean ENABLE_LOADER_LOG = false; // Don't submit with true
     private static final boolean ENABLE_FRAGMENT_LOG = false; // Don't submit with true
diff --git a/src/com/android/contacts/ContactsSearchManager.java b/src/com/android/contacts/ContactsSearchManager.java
index edb2016..20d7c5c 100644
--- a/src/com/android/contacts/ContactsSearchManager.java
+++ b/src/com/android/contacts/ContactsSearchManager.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts;
 
-import com.android.contacts.list.ContactsRequest;
-
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Intents.UI;
 
+import com.android.contacts.list.ContactsRequest;
+
 /**
  * A convenience class that helps launch contact search from within the app.
  */
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index ca32ff8..e8aa1ae 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.activities.DialtactsActivity;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.test.NeededForTesting;
-import com.android.contacts.util.Constants;
-
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
@@ -39,6 +32,13 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.contacts.activities.DialtactsActivity;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.test.NeededForTesting;
+import com.android.contacts.util.Constants;
+
 import java.util.List;
 
 public class ContactsUtils {
diff --git a/src/com/android/contacts/GroupMemberLoader.java b/src/com/android/contacts/GroupMemberLoader.java
index 1cef4d4..12e82ce 100644
--- a/src/com/android/contacts/GroupMemberLoader.java
+++ b/src/com/android/contacts/GroupMemberLoader.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts;
 
-import com.android.contacts.preference.ContactsPreferences;
-
 import android.content.Context;
 import android.content.CursorLoader;
 import android.net.Uri;
@@ -26,6 +24,8 @@
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Directory;
 
+import com.android.contacts.preference.ContactsPreferences;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/NfcHandler.java b/src/com/android/contacts/NfcHandler.java
index 1ae72be..3cd4b08 100644
--- a/src/com/android/contacts/NfcHandler.java
+++ b/src/com/android/contacts/NfcHandler.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.detail.ContactDetailFragment;
-
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.net.Uri;
@@ -27,9 +25,10 @@
 import android.nfc.NfcEvent;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Profile;
-
 import android.util.Log;
 
+import com.android.contacts.detail.ContactDetailFragment;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/src/com/android/contacts/PhoneCallDetailsHelper.java b/src/com/android/contacts/PhoneCallDetailsHelper.java
index fd950fe..8192975 100644
--- a/src/com/android/contacts/PhoneCallDetailsHelper.java
+++ b/src/com/android/contacts/PhoneCallDetailsHelper.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.calllog.CallTypeHelper;
-import com.android.contacts.calllog.PhoneNumberHelper;
-import com.android.contacts.test.NeededForTesting;
-
 import android.content.res.Resources;
 import android.graphics.Typeface;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -33,6 +29,10 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.contacts.calllog.CallTypeHelper;
+import com.android.contacts.calllog.PhoneNumberHelper;
+import com.android.contacts.test.NeededForTesting;
+
 /**
  * Helper class to fill in the views in {@link PhoneCallDetailsViews}.
  */
diff --git a/src/com/android/contacts/PhoneCallDetailsViews.java b/src/com/android/contacts/PhoneCallDetailsViews.java
index ea5a461..8be7f0c 100644
--- a/src/com/android/contacts/PhoneCallDetailsViews.java
+++ b/src/com/android/contacts/PhoneCallDetailsViews.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts;
 
-import com.android.contacts.calllog.CallTypeIconsView;
-
 import android.content.Context;
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.contacts.calllog.CallTypeIconsView;
+
 /**
  * Encapsulates the views that are used to display the details of a phone call in the call log.
  */
diff --git a/src/com/android/contacts/SplitAggregateView.java b/src/com/android/contacts/SplitAggregateView.java
index 091cd56..1b42ca3 100644
--- a/src/com/android/contacts/SplitAggregateView.java
+++ b/src/com/android/contacts/SplitAggregateView.java
@@ -16,22 +16,16 @@
 
 package com.android.contacts;
 
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.database.Cursor;
-import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Nickname;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts.Data;
-import android.util.Log;
+import android.provider.ContactsContract.RawContacts;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -41,6 +35,9 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/src/com/android/contacts/TypePrecedence.java b/src/com/android/contacts/TypePrecedence.java
index 92f3a6e..b2d8a8f 100644
--- a/src/com/android/contacts/TypePrecedence.java
+++ b/src/com/android/contacts/TypePrecedence.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.util.Constants;
-
 import android.accounts.Account;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Im;
@@ -26,11 +23,14 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.util.Constants;
+
 /**
  * This class contains utility functions for determining the precedence of
  * different types associated with contact data items.
  *
- * @deprecated use {@link EntityModifier#getTypePrecedence} instead, since this
+ * @deprecated use {@link RawContactModifier#getTypePrecedence} instead, since this
  *             list isn't {@link Account} based.
  */
 @Deprecated
diff --git a/src/com/android/contacts/ViewNotificationService.java b/src/com/android/contacts/ViewNotificationService.java
index a85c780..3bc5ed2 100644
--- a/src/com/android/contacts/ViewNotificationService.java
+++ b/src/com/android/contacts/ViewNotificationService.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.ContactLoader.Result;
-
 import android.app.Service;
 import android.content.Intent;
 import android.content.Loader;
@@ -25,6 +23,10 @@
 import android.os.IBinder;
 import android.util.Log;
 
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.ContactLoader;
+
+
 /**
  * Service that sends out a view notification for a contact. At the moment, this is only
  * supposed to be used by the Phone app
@@ -41,9 +43,9 @@
         // We simply need to start a Loader here. When its done, it will send out the
         // View-Notification automatically.
         final ContactLoader contactLoader = new ContactLoader(this, intent.getData(), true);
-        contactLoader.registerListener(0, new OnLoadCompleteListener<ContactLoader.Result>() {
+        contactLoader.registerListener(0, new OnLoadCompleteListener<Contact>() {
             @Override
-            public void onLoadComplete(Loader<Result> loader, Result data) {
+            public void onLoadComplete(Loader<Contact> loader, Contact data) {
                 try {
                     loader.reset();
                 } catch (RuntimeException e) {
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index 4fc9866..d50c240 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -16,17 +16,12 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.R;
-import com.android.contacts.activities.ActionBarAdapter.Listener.Action;
-import com.android.contacts.list.ContactsRequest;
-
 import android.app.ActionBar;
 import android.app.ActionBar.LayoutParams;
 import android.app.ActionBar.Tab;
 import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.graphics.Color;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.text.TextUtils;
@@ -40,6 +35,10 @@
 import android.widget.SearchView.OnQueryTextListener;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.activities.ActionBarAdapter.Listener.Action;
+import com.android.contacts.list.ContactsRequest;
+
 /**
  * Adapter for the action bar at the top of the Contacts activity.
  */
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index 9ca9cfd..2f7651f 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -30,15 +30,15 @@
 import android.provider.ContactsContract.DisplayPhoto;
 import android.util.Log;
 
-import com.android.contacts.ContactLoader;
-import com.android.contacts.ContactLoader.Result;
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.ContactsActivity;
 import com.android.contacts.ContactsUtils;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityModifier;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.ContactLoader;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.account.AccountType;
 import com.android.contacts.util.ContactPhotoUtils;
 
 import java.io.File;
@@ -131,7 +131,7 @@
         } else if (requestCode == REQUEST_CROP_PHOTO) {
             loadContact(mContactUri, new Listener() {
                 @Override
-                public void onContactLoaded(ContactLoader.Result contact) {
+                public void onContactLoaded(Contact contact) {
                     saveContact(contact);
                 }
             });
@@ -144,10 +144,10 @@
     // instance, the loader doesn't persist across Activity restarts.
     private void loadContact(Uri contactUri, final Listener listener) {
         final ContactLoader loader = new ContactLoader(this, contactUri, true);
-        loader.registerListener(0, new OnLoadCompleteListener<ContactLoader.Result>() {
+        loader.registerListener(0, new OnLoadCompleteListener<Contact>() {
             @Override
             public void onLoadComplete(
-                    Loader<ContactLoader.Result> loader, ContactLoader.Result contact) {
+                    Loader<Contact> loader, Contact contact) {
                 try {
                     loader.reset();
                 }
@@ -161,7 +161,7 @@
     }
 
     private interface Listener {
-        public void onContactLoaded(Result contact);
+        public void onContactLoaded(Contact contact);
     }
 
     /**
@@ -170,11 +170,11 @@
      * - photo has been cropped
      * - contact has been loaded
      */
-    private void saveContact(ContactLoader.Result contact) {
+    private void saveContact(Contact contact) {
 
         // Obtain the raw-contact that we will save to.
-        EntityDeltaList deltaList = contact.createEntityDeltaList();
-        EntityDelta raw = deltaList.getFirstWritableRawContact(this);
+        RawContactDeltaList deltaList = contact.createRawContactDeltaList();
+        RawContactDelta raw = deltaList.getFirstWritableRawContact(this);
         if (raw == null) {
             Log.w(TAG, "no writable raw-contact found");
             return;
@@ -195,13 +195,13 @@
         // the ContactSaveService would not create the new contact, and the
         // full-res photo would fail to be saved to the non-existent contact.
         AccountType account = raw.getRawContactAccountType(this);
-        EntityDelta.ValuesDelta values =
-                EntityModifier.ensureKindExists(raw, account, Photo.CONTENT_ITEM_TYPE);
+        RawContactDelta.ValuesDelta values =
+                RawContactModifier.ensureKindExists(raw, account, Photo.CONTENT_ITEM_TYPE);
         if (values == null) {
             Log.w(TAG, "cannot attach photo to this account type");
             return;
         }
-        values.put(Photo.PHOTO, compressed);
+        values.setPhoto(compressed);
 
         // Finally, invoke the ContactSaveService.
         Log.v(TAG, "all prerequisites met, about to save photo to contact");
diff --git a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
index becbf5c..c8adf95 100644
--- a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
+++ b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
@@ -16,20 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.R;
-import com.android.contacts.editor.Editor;
-import com.android.contacts.editor.ViewIdGenerator;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.util.DialogManager;
-import com.android.contacts.util.EmptyService;
-
 import android.app.Activity;
 import android.app.Dialog;
 import android.app.ProgressDialog;
@@ -38,7 +24,6 @@
 import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.OperationApplicationException;
@@ -73,6 +58,21 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.contacts.R;
+import com.android.contacts.editor.Editor;
+import com.android.contacts.editor.ViewIdGenerator;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.RawContact;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.DialogManager;
+import com.android.contacts.util.EmptyService;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -124,11 +124,11 @@
 
     private QueryHandler mQueryHandler;
 
-    /** {@link EntityDeltaList} for the entire selected contact. */
-    private EntityDeltaList mEntityDeltaList;
+    /** {@link RawContactDeltaList} for the entire selected contact. */
+    private RawContactDeltaList mEntityDeltaList;
 
-    /** {@link EntityDeltaList} for the editable account */
-    private EntityDelta mEntityDelta;
+    /** {@link RawContactDeltaList} for the editable account */
+    private RawContactDelta mRawContactDelta;
 
     private String mMimetype = Phone.CONTENT_ITEM_TYPE;
 
@@ -357,7 +357,7 @@
                 new String[] { String.valueOf(mContactId) }, null);
     }
 
-    private static class QueryEntitiesTask extends AsyncTask<Intent, Void, EntityDeltaList> {
+    private static class QueryEntitiesTask extends AsyncTask<Intent, Void, RawContactDeltaList> {
 
         private ConfirmAddDetailActivity activityTarget;
         private String mSelection;
@@ -367,7 +367,7 @@
         }
 
         @Override
-        protected EntityDeltaList doInBackground(Intent... params) {
+        protected RawContactDeltaList doInBackground(Intent... params) {
 
             final Intent intent = params[0];
 
@@ -400,7 +400,7 @@
 
             // Note that this query does not need to concern itself with whether the contact is
             // the user's profile, since the profile does not show up in the picker.
-            return EntityDeltaList.fromQuery(RawContactsEntity.CONTENT_URI,
+            return RawContactDeltaList.fromQuery(RawContactsEntity.CONTENT_URI,
                     activityTarget.getContentResolver(), mSelection,
                     new String[] { selectionArg }, null);
         }
@@ -425,7 +425,7 @@
         }
 
         @Override
-        protected void onPostExecute(EntityDeltaList entityList) {
+        protected void onPostExecute(RawContactDeltaList entityList) {
             if (activityTarget.isFinishing()) {
                 return;
             }
@@ -567,7 +567,7 @@
         }
     }
 
-    private void setEntityDeltaList(EntityDeltaList entityList) {
+    private void setEntityDeltaList(RawContactDeltaList entityList) {
         if (entityList == null) {
             throw new IllegalStateException();
         }
@@ -578,31 +578,33 @@
         mEntityDeltaList = entityList;
 
         // Find the editable raw_contact.
-        mEntityDelta = mEntityDeltaList.getFirstWritableRawContact(this);
+        mRawContactDelta = mEntityDeltaList.getFirstWritableRawContact(this);
 
         // If no editable raw_contacts are found, create one.
-        if (mEntityDelta == null) {
-            mEntityDelta = addEditableRawContact(this, mEntityDeltaList);
+        if (mRawContactDelta == null) {
+            mRawContactDelta = addEditableRawContact(this, mEntityDeltaList);
 
-            if ((mEntityDelta != null) && VERBOSE_LOGGING) {
+            if ((mRawContactDelta != null) && VERBOSE_LOGGING) {
                 Log.v(TAG, "setEntityDeltaList: created editable raw_contact " + entityList);
             }
         }
 
-        if (mEntityDelta == null) {
+        if (mRawContactDelta == null) {
             // Selected contact is read-only, and there's no editable account.
             mIsReadOnly = true;
             mEditableAccountType = null;
         } else {
             mIsReadOnly = false;
 
-            mEditableAccountType = mEntityDelta.getRawContactAccountType(this);
+            mEditableAccountType = mRawContactDelta.getRawContactAccountType(this);
 
             // Handle any incoming values that should be inserted
             final Bundle extras = getIntent().getExtras();
             if (extras != null && extras.size() > 0) {
-                // If there are any intent extras, add them as additional fields in the EntityDelta.
-                EntityModifier.parseExtras(this, mEditableAccountType, mEntityDelta, extras);
+                // If there are any intent extras, add them as additional fields in the
+                // RawContactDelta.
+                RawContactModifier.parseExtras(this, mEditableAccountType, mRawContactDelta,
+                        extras);
             }
         }
 
@@ -610,12 +612,12 @@
     }
 
     /**
-     * Create an {@link EntityDelta} for a raw_contact on the first editable account found, and add
+     * Create an {@link RawContactDelta} for a raw_contact on the first editable account found, and add
      * to the list.  Also copy the structured name from an existing (read-only) raw_contact to the
      * new one, if any of the read-only contacts has a name.
      */
-    private static EntityDelta addEditableRawContact(Context context,
-            EntityDeltaList entityDeltaList) {
+    private static RawContactDelta addEditableRawContact(Context context,
+            RawContactDeltaList entityDeltaList) {
         // First, see if there's an editable account.
         final AccountTypeManager accounts = AccountTypeManager.getInstance(context);
         final List<AccountWithDataSet> editableAccounts = accounts.getAccounts(true);
@@ -627,44 +629,29 @@
         final AccountType accountType = accounts.getAccountType(
                 editableAccount.type, editableAccount.dataSet);
 
-        // Create a new EntityDelta for the new raw_contact.
-        final ContentValues values = new ContentValues();
-        values.put(RawContacts.ACCOUNT_NAME, editableAccount.name);
-        values.put(RawContacts.ACCOUNT_TYPE, editableAccount.type);
-        values.put(RawContacts.DATA_SET, editableAccount.dataSet);
+        // Create a new RawContactDelta for the new raw_contact.
+        final RawContact rawContact = new RawContact(context);
+        rawContact.setAccount(editableAccount);
 
-        final EntityDelta entityDelta = new EntityDelta(ValuesDelta.fromAfter(values));
+        final RawContactDelta entityDelta = new RawContactDelta(ValuesDelta.fromAfter(
+                rawContact.getValues()));
 
         // Then, copy the structure name from an existing (read-only) raw_contact.
-        for (EntityDelta entity : entityDeltaList) {
+        for (RawContactDelta entity : entityDeltaList) {
             final ArrayList<ValuesDelta> readOnlyNames =
                     entity.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
             if ((readOnlyNames != null) && (readOnlyNames.size() > 0)) {
                 final ValuesDelta readOnlyName = readOnlyNames.get(0);
-
-                final ValuesDelta newName = EntityModifier.ensureKindExists(entityDelta,
+                final ValuesDelta newName = RawContactModifier.ensureKindExists(entityDelta,
                         accountType, StructuredName.CONTENT_ITEM_TYPE);
 
                 // Copy all the data fields.
-                newName.copyStringFrom(readOnlyName, StructuredName.DISPLAY_NAME);
-
-                newName.copyStringFrom(readOnlyName, StructuredName.GIVEN_NAME);
-                newName.copyStringFrom(readOnlyName, StructuredName.FAMILY_NAME);
-                newName.copyStringFrom(readOnlyName, StructuredName.PREFIX);
-                newName.copyStringFrom(readOnlyName, StructuredName.MIDDLE_NAME);
-                newName.copyStringFrom(readOnlyName, StructuredName.SUFFIX);
-
-                newName.copyStringFrom(readOnlyName, StructuredName.PHONETIC_GIVEN_NAME);
-                newName.copyStringFrom(readOnlyName, StructuredName.PHONETIC_MIDDLE_NAME);
-                newName.copyStringFrom(readOnlyName, StructuredName.PHONETIC_FAMILY_NAME);
-
-                newName.copyStringFrom(readOnlyName, StructuredName.FULL_NAME_STYLE);
-                newName.copyStringFrom(readOnlyName, StructuredName.PHONETIC_NAME_STYLE);
+                newName.copyStructuredNameFieldsFrom(readOnlyName);
                 break;
             }
         }
 
-        // Add the new EntityDelta to the list.
+        // Add the new RawContactDelta to the list.
         entityDeltaList.add(entityDelta);
 
         return entityDelta;
@@ -695,11 +682,11 @@
             // Skip kind that are not editable
             if (!kind.editable) continue;
             if (mMimetype.equals(kind.mimeType)) {
-                for (ValuesDelta valuesDelta : mEntityDelta.getMimeEntries(mMimetype)) {
+                for (ValuesDelta valuesDelta : mRawContactDelta.getMimeEntries(mMimetype)) {
                     // Skip entries that aren't visible
                     if (!valuesDelta.isVisible()) continue;
                     if (valuesDelta.isInsert()) {
-                        inflateEditorView(kind, valuesDelta, mEntityDelta);
+                        inflateEditorView(kind, valuesDelta, mRawContactDelta);
                         return;
                     }
                 }
@@ -712,7 +699,7 @@
      * the views corresponding to the the object-model. The resulting EditorView is also added
      * to the end of mEditors
      */
-    private void inflateEditorView(DataKind dataKind, ValuesDelta valuesDelta, EntityDelta state) {
+    private void inflateEditorView(DataKind dataKind, ValuesDelta valuesDelta, RawContactDelta state) {
         final View view = mInflater.inflate(dataKind.editorLayoutResourceId, mEditorContainerView,
                 false);
 
@@ -765,11 +752,11 @@
 
     /**
      * Background task for persisting edited contact data, using the changes
-     * defined by a set of {@link EntityDelta}. This task starts
+     * defined by a set of {@link RawContactDelta}. This task starts
      * {@link EmptyService} to make sure the background thread can finish
      * persisting in cases where the system wants to reclaim our process.
      */
-    private static class PersistTask extends AsyncTask<EntityDeltaList, Void, Integer> {
+    private static class PersistTask extends AsyncTask<RawContactDeltaList, Void, Integer> {
         // In the future, use ContactSaver instead of WeakAsyncTask because of
         // the danger of the activity being null during a save action
         private static final int PERSIST_TRIES = 3;
@@ -799,18 +786,18 @@
         }
 
         @Override
-        protected Integer doInBackground(EntityDeltaList... params) {
+        protected Integer doInBackground(RawContactDeltaList... params) {
             final Context context = activityTarget;
             final ContentResolver resolver = context.getContentResolver();
 
-            EntityDeltaList state = params[0];
+            RawContactDeltaList state = params[0];
 
             if (state == null) {
                 return RESULT_FAILURE;
             }
 
             // Trim any empty fields, and RawContacts, before persisting
-            EntityModifier.trimEmpty(state, mAccountTypeManager);
+            RawContactModifier.trimEmpty(state, mAccountTypeManager);
 
             // Attempt to persist changes
             int tries = 0;
@@ -898,4 +885,4 @@
         }
         finish();
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index d656fdb..b03a976 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -16,23 +16,11 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactLoader;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.detail.ContactDetailDisplayUtils;
-import com.android.contacts.detail.ContactDetailFragment;
-import com.android.contacts.detail.ContactDetailLayoutController;
-import com.android.contacts.detail.ContactLoaderFragment;
-import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
-import com.android.contacts.interactions.ContactDeletionInteraction;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.util.PhoneCapabilityTester;
-
 import android.app.ActionBar;
 import android.app.Fragment;
 import android.content.ActivityNotFoundException;
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -49,6 +37,19 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.detail.ContactDetailDisplayUtils;
+import com.android.contacts.detail.ContactDetailFragment;
+import com.android.contacts.detail.ContactDetailLayoutController;
+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.model.account.AccountWithDataSet;
+import com.android.contacts.util.PhoneCapabilityTester;
+
 import java.util.ArrayList;
 
 public class ContactDetailActivity extends ContactsActivity {
@@ -57,7 +58,7 @@
     /** Shows a toogle button for hiding/showing updates. Don't submit with true */
     private static final boolean DEBUG_TRANSITIONS = false;
 
-    private ContactLoader.Result mContactData;
+    private Contact mContactData;
     private Uri mLookupUri;
 
     private ContactDetailLayoutController mContactDetailLayoutController;
@@ -208,7 +209,7 @@
         }
 
         @Override
-        public void onDetailsLoaded(final ContactLoader.Result result) {
+        public void onDetailsLoaded(final Contact result) {
             if (result == null) {
                 return;
             }
@@ -259,11 +260,14 @@
         actionBar.setTitle(displayName);
         actionBar.setSubtitle(company);
 
-        if (!TextUtils.isEmpty(displayName) &&
-                AccessibilityManager.getInstance(this).isEnabled()) {
-            View decorView = getWindow().getDecorView();
-            decorView.setContentDescription(displayName);
-            decorView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        if (!TextUtils.isEmpty(displayName)) {
+            AccessibilityManager accessibilityManager =
+                    (AccessibilityManager) this.getSystemService(Context.ACCESSIBILITY_SERVICE);
+            if (accessibilityManager.isEnabled()) {
+                View decorView = getWindow().getDecorView();
+                decorView.setContentDescription(displayName);
+                decorView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+            }
         }
     }
 
diff --git a/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java b/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
index 3e2a893..f5852e5 100644
--- a/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
@@ -31,7 +31,7 @@
 import com.android.contacts.R;
 import com.android.contacts.editor.ContactEditorUtils;
 import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
+import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.util.AccountsListAdapter;
 import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
 
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 9dde2dd..77ed857 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -16,16 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.editor.ContactEditorFragment;
-import com.android.contacts.editor.ContactEditorFragment.SaveMode;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.util.DialogManager;
-
 import android.app.ActionBar;
 import android.app.Dialog;
 import android.content.ContentValues;
@@ -41,6 +31,16 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.editor.ContactEditorFragment;
+import com.android.contacts.editor.ContactEditorFragment.SaveMode;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.util.DialogManager;
+
 import java.util.ArrayList;
 
 public class ContactEditorActivity extends ContactsActivity
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index 0db3a0c..c60a228 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -16,23 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.list.ContactEntryListFragment;
-import com.android.contacts.list.ContactPickerFragment;
-import com.android.contacts.list.ContactsIntentResolver;
-import com.android.contacts.list.ContactsRequest;
-import com.android.contacts.list.DirectoryListLoader;
-import com.android.contacts.list.EmailAddressPickerFragment;
-import com.android.contacts.list.OnContactPickerActionListener;
-import com.android.contacts.list.OnEmailAddressPickerActionListener;
-import com.android.contacts.list.OnPhoneNumberPickerActionListener;
-import com.android.contacts.list.OnPostalAddressPickerActionListener;
-import com.android.contacts.list.PhoneNumberPickerFragment;
-import com.android.contacts.list.PostalAddressPickerFragment;
-import com.android.contacts.widget.ContextMenuAdapter;
-import com.google.android.collect.Sets;
-
 import android.app.ActionBar;
 import android.app.ActionBar.LayoutParams;
 import android.app.Activity;
@@ -53,11 +36,27 @@
 import android.view.View.OnClickListener;
 import android.view.View.OnFocusChangeListener;
 import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
 import android.widget.SearchView;
 import android.widget.SearchView.OnCloseListener;
 import android.widget.SearchView.OnQueryTextListener;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.list.ContactEntryListFragment;
+import com.android.contacts.list.ContactPickerFragment;
+import com.android.contacts.list.ContactsIntentResolver;
+import com.android.contacts.list.ContactsRequest;
+import com.android.contacts.list.DirectoryListLoader;
+import com.android.contacts.list.EmailAddressPickerFragment;
+import com.android.contacts.list.OnContactPickerActionListener;
+import com.android.contacts.list.OnEmailAddressPickerActionListener;
+import com.android.contacts.list.OnPhoneNumberPickerActionListener;
+import com.android.contacts.list.OnPostalAddressPickerActionListener;
+import com.android.contacts.list.PhoneNumberPickerFragment;
+import com.android.contacts.list.PostalAddressPickerFragment;
+import com.android.contacts.widget.ContextMenuAdapter;
+import com.google.common.collect.Sets;
+
 import java.util.Set;
 
 /**
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index b5b0a63..175189a 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -16,21 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.calllog.CallLogFragment;
-import com.android.contacts.dialpad.DialpadFragment;
-import com.android.contacts.interactions.PhoneNumberInteraction;
-import com.android.contacts.list.ContactListFilterController;
-import com.android.contacts.list.ContactListFilterController.ContactListFilterListener;
-import com.android.contacts.list.ContactListItemView;
-import com.android.contacts.list.OnPhoneNumberPickerActionListener;
-import com.android.contacts.list.PhoneFavoriteFragment;
-import com.android.contacts.list.PhoneNumberPickerFragment;
-import com.android.contacts.util.AccountFilterUtil;
-import com.android.contacts.util.Constants;
-import com.android.internal.telephony.ITelephony;
-
 import android.app.ActionBar;
 import android.app.ActionBar.LayoutParams;
 import android.app.ActionBar.Tab;
@@ -71,6 +56,21 @@
 import android.widget.SearchView.OnCloseListener;
 import android.widget.SearchView.OnQueryTextListener;
 
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.calllog.CallLogFragment;
+import com.android.contacts.dialpad.DialpadFragment;
+import com.android.contacts.interactions.PhoneNumberInteraction;
+import com.android.contacts.list.ContactListFilterController;
+import com.android.contacts.list.ContactListFilterController.ContactListFilterListener;
+import com.android.contacts.list.ContactListItemView;
+import com.android.contacts.list.OnPhoneNumberPickerActionListener;
+import com.android.contacts.list.PhoneFavoriteFragment;
+import com.android.contacts.list.PhoneNumberPickerFragment;
+import com.android.contacts.util.AccountFilterUtil;
+import com.android.contacts.util.Constants;
+import com.android.internal.telephony.ITelephony;
+
 /**
  * The dialer activity that has one tab with the virtual 12key
  * dialer, a tab with recent calls in it, a tab with the contacts and
diff --git a/src/com/android/contacts/activities/GroupBrowserActivity.java b/src/com/android/contacts/activities/GroupBrowserActivity.java
index e8b3ad8..3d3af3f 100644
--- a/src/com/android/contacts/activities/GroupBrowserActivity.java
+++ b/src/com/android/contacts/activities/GroupBrowserActivity.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-
 import android.content.Intent;
 import android.os.Bundle;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+
 /**
  * Displays a list to browse groups.
  */
diff --git a/src/com/android/contacts/activities/GroupDetailActivity.java b/src/com/android/contacts/activities/GroupDetailActivity.java
index e49789e..492a2ff 100644
--- a/src/com/android/contacts/activities/GroupDetailActivity.java
+++ b/src/com/android/contacts/activities/GroupDetailActivity.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.group.GroupDetailDisplayUtils;
-import com.android.contacts.group.GroupDetailFragment;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-
 import android.app.ActionBar;
 import android.content.ContentUris;
 import android.content.Intent;
@@ -36,6 +29,13 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.group.GroupDetailDisplayUtils;
+import com.android.contacts.group.GroupDetailFragment;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+
 public class GroupDetailActivity extends ContactsActivity {
 
     private static final String TAG = "GroupDetailActivity";
diff --git a/src/com/android/contacts/activities/GroupEditorActivity.java b/src/com/android/contacts/activities/GroupEditorActivity.java
index f3255bf..ff9301b 100644
--- a/src/com/android/contacts/activities/GroupEditorActivity.java
+++ b/src/com/android/contacts/activities/GroupEditorActivity.java
@@ -16,12 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.group.GroupEditorFragment;
-import com.android.contacts.util.DialogManager;
-import com.android.contacts.util.PhoneCapabilityTester;
-
 import android.app.ActionBar;
 import android.app.Dialog;
 import android.content.Context;
@@ -33,6 +27,12 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.group.GroupEditorFragment;
+import com.android.contacts.util.DialogManager;
+import com.android.contacts.util.PhoneCapabilityTester;
+
 public class GroupEditorActivity extends ContactsActivity
         implements DialogManager.DialogShowingViewActivity {
 
diff --git a/src/com/android/contacts/activities/JoinContactActivity.java b/src/com/android/contacts/activities/JoinContactActivity.java
index 4a277cb..a580165 100644
--- a/src/com/android/contacts/activities/JoinContactActivity.java
+++ b/src/com/android/contacts/activities/JoinContactActivity.java
@@ -17,12 +17,6 @@
 package com.android.contacts.activities;
 
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.list.ContactEntryListFragment;
-import com.android.contacts.list.JoinContactListFragment;
-import com.android.contacts.list.OnContactPickerActionListener;
-
 import android.app.ActionBar;
 import android.app.ActionBar.LayoutParams;
 import android.app.Fragment;
@@ -42,6 +36,12 @@
 import android.widget.SearchView.OnCloseListener;
 import android.widget.SearchView.OnQueryTextListener;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.list.ContactEntryListFragment;
+import com.android.contacts.list.JoinContactListFragment;
+import com.android.contacts.list.OnContactPickerActionListener;
+
 /**
  * An activity that shows a list of contacts that can be joined with the target contact.
  */
diff --git a/src/com/android/contacts/activities/NonPhoneActivity.java b/src/com/android/contacts/activities/NonPhoneActivity.java
index 47ae020..fc22146 100644
--- a/src/com/android/contacts/activities/NonPhoneActivity.java
+++ b/src/com/android/contacts/activities/NonPhoneActivity.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.util.Constants;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -33,11 +29,18 @@
 import android.provider.ContactsContract.Intents.Insert;
 import android.text.TextUtils;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.util.Constants;
+
 /**
  * Activity that intercepts DIAL and VIEW intents for phone numbers for devices that can not
  * be used as a phone. This allows the user to see the phone number
  */
 public class NonPhoneActivity extends ContactsActivity {
+
+    private static final String PHONE_NUMBER_KEY = "PHONE_NUMBER";
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -48,7 +51,9 @@
         }
 
         final NonPhoneDialogFragment fragment = new NonPhoneDialogFragment();
-        fragment.setArguments(Bundle.forPair("PHONE_NUMBER", phoneNumber));
+        Bundle bundle = new Bundle();
+        bundle.putString(PHONE_NUMBER_KEY, phoneNumber);
+        fragment.setArguments(bundle);
         getFragmentManager().beginTransaction().add(fragment, "Fragment").commitAllowingStateLoss();
     }
 
@@ -89,7 +94,7 @@
         }
 
         private String getArgumentPhoneNumber() {
-            return getArguments().getPairValue();
+            return getArguments().getString(PHONE_NUMBER_KEY);
         }
 
         @Override
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index d1b493f..a99ac45 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -16,7 +16,37 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactLoader;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.ActivityNotFoundException;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcelable;
+import android.preference.PreferenceActivity;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.ProviderStatus;
+import android.provider.ContactsContract.QuickContact;
+import android.provider.Settings;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.Log;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.ContactsActivity;
 import com.android.contacts.ContactsUtils;
@@ -50,7 +80,8 @@
 import com.android.contacts.list.OnContactsUnavailableActionListener;
 import com.android.contacts.list.ProviderStatusWatcher;
 import com.android.contacts.list.ProviderStatusWatcher.ProviderStatusListener;
-import com.android.contacts.model.AccountWithDataSet;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.preference.ContactsPreferenceActivity;
 import com.android.contacts.preference.DisplayOptionsPreferenceFragment;
 import com.android.contacts.util.AccountFilterUtil;
@@ -62,37 +93,6 @@
 import com.android.contacts.util.UriUtils;
 import com.android.contacts.widget.TransitionAnimationView;
 
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.ActivityNotFoundException;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcelable;
-import android.preference.PreferenceActivity;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.ProviderStatus;
-import android.provider.ContactsContract.QuickContact;
-import android.provider.Settings;
-import android.support.v13.app.FragmentPagerAdapter;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.Log;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MenuItem.OnMenuItemClickListener;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Toast;
-
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -1162,7 +1162,7 @@
         }
 
         @Override
-        public void onDetailsLoaded(final ContactLoader.Result result) {
+        public void onDetailsLoaded(final Contact result) {
             if (result == null) {
                 // Nothing is loaded. Show empty state.
                 mContactDetailLayoutController.showEmptyState();
diff --git a/src/com/android/contacts/activities/PhotoSelectionActivity.java b/src/com/android/contacts/activities/PhotoSelectionActivity.java
index 21cf192..6f3da00 100644
--- a/src/com/android/contacts/activities/PhotoSelectionActivity.java
+++ b/src/com/android/contacts/activities/PhotoSelectionActivity.java
@@ -15,15 +15,6 @@
  */
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.detail.PhotoSelectionHandler;
-import com.android.contacts.editor.PhotoActionPopup;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.util.ContactPhotoUtils;
-import com.android.contacts.util.SchedulingUtils;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -42,6 +33,15 @@
 import android.widget.FrameLayout.LayoutParams;
 import android.widget.ImageView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.ContactSaveService;
+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.util.ContactPhotoUtils;
+import com.android.contacts.util.SchedulingUtils;
+
 
 /**
  * Popup activity for choosing a contact photo within the Contacts app.
@@ -93,7 +93,7 @@
     private Uri mPhotoUri;
 
     /** Entity delta list of the contact. */
-    private EntityDeltaList mState;
+    private RawContactDeltaList mState;
 
     /** Whether the contact is the user's profile. */
     private boolean mIsProfile;
@@ -167,7 +167,7 @@
         // Pull data out of the intent.
         final Intent intent = getIntent();
         mPhotoUri = intent.getParcelableExtra(PHOTO_URI);
-        mState = (EntityDeltaList) intent.getParcelableExtra(ENTITY_DELTA_LIST);
+        mState = (RawContactDeltaList) intent.getParcelableExtra(ENTITY_DELTA_LIST);
         mIsProfile = intent.getBooleanExtra(IS_PROFILE, false);
         mIsDirectoryContact = intent.getBooleanExtra(IS_DIRECTORY_CONTACT, false);
         mExpandPhoto = intent.getBooleanExtra(EXPAND_PHOTO, false);
@@ -268,7 +268,7 @@
      * @return An intent that can be used to invoke the photo selection activity.
      */
     public static Intent buildIntent(Context context, Uri photoUri, Bitmap photoBitmap,
-            byte[] photoBytes, Rect photoBounds, EntityDeltaList delta, boolean isProfile,
+            byte[] photoBytes, Rect photoBounds, RawContactDeltaList delta, boolean isProfile,
             boolean isDirectoryContact, boolean expandPhotoOnClick) {
         Intent intent = new Intent(context, PhotoSelectionActivity.class);
         if (photoUri != null && photoBitmap != null && photoBytes != null) {
@@ -515,7 +515,7 @@
         private final PhotoActionListener mListener;
 
         private PhotoHandler(
-                Context context, View photoView, int photoMode, EntityDeltaList state) {
+                Context context, View photoView, int photoMode, RawContactDeltaList state) {
             super(context, photoView, photoMode, PhotoSelectionActivity.this.mIsDirectoryContact,
                     state);
             mListener = new PhotoListener();
@@ -536,7 +536,7 @@
         private final class PhotoListener extends PhotoActionListener {
             @Override
             public void onPhotoSelected(Bitmap bitmap) {
-                EntityDeltaList delta = getDeltaForAttachingPhotoToContact();
+                RawContactDeltaList delta = getDeltaForAttachingPhotoToContact();
                 long rawContactId = getWritableEntityId();
                 final String croppedPath = ContactPhotoUtils.pathForCroppedPhoto(
                         PhotoSelectionActivity.this, mCurrentPhotoFile);
diff --git a/src/com/android/contacts/activities/ShowOrCreateActivity.java b/src/com/android/contacts/activities/ShowOrCreateActivity.java
index 2efd6ba..1dc0197 100755
--- a/src/com/android/contacts/activities/ShowOrCreateActivity.java
+++ b/src/com/android/contacts/activities/ShowOrCreateActivity.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.util.Constants;
-import com.android.contacts.util.NotifyingAsyncQueryHandler;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -37,6 +32,11 @@
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.util.Constants;
+import com.android.contacts.util.NotifyingAsyncQueryHandler;
+
 /**
  * Handle several edge cases around showing or possibly creating contacts in
  * connected with a specific E-mail address or phone number. Will search based
diff --git a/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java b/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
index 7b6ae63..9183208 100644
--- a/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
+++ b/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.PhoneCallDetails;
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.provider.CallLog.Calls;
 import android.text.format.DateUtils;
@@ -28,6 +25,9 @@
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import com.android.contacts.PhoneCallDetails;
+import com.android.contacts.R;
+
 /**
  * Adapter for a ListView containing history items from the details of a call.
  */
diff --git a/src/com/android/contacts/calllog/CallLogAdapter.java b/src/com/android/contacts/calllog/CallLogAdapter.java
index 2275a3d..3688dca 100644
--- a/src/com/android/contacts/calllog/CallLogAdapter.java
+++ b/src/com/android/contacts/calllog/CallLogAdapter.java
@@ -16,15 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.common.widget.GroupingListAdapter;
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.PhoneCallDetails;
-import com.android.contacts.PhoneCallDetailsHelper;
-import com.android.contacts.R;
-import com.android.contacts.util.ExpirableCache;
-import com.android.contacts.util.UriUtils;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.res.Resources;
@@ -40,9 +31,17 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
-import java.util.LinkedList;
+import com.android.common.widget.GroupingListAdapter;
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.PhoneCallDetails;
+import com.android.contacts.PhoneCallDetailsHelper;
+import com.android.contacts.R;
+import com.android.contacts.util.ExpirableCache;
+import com.android.contacts.util.UriUtils;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Objects;
 
-import libcore.util.Objects;
+import java.util.LinkedList;
 
 /**
  * Adapter class to fill in data for the Call Log.
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index fcd1780..f04a2f3 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -16,18 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.common.io.MoreCloseables;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.util.Constants;
-import com.android.contacts.util.EmptyLoader;
-import com.android.contacts.voicemail.VoicemailStatusHelper;
-import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
-import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
-import com.android.internal.telephony.CallerInfo;
-import com.android.internal.telephony.ITelephony;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.app.Activity;
 import android.app.KeyguardManager;
 import android.app.ListFragment;
@@ -41,8 +29,8 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.CallLog;
-import android.provider.ContactsContract;
 import android.provider.CallLog.Calls;
+import android.provider.ContactsContract;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.util.Log;
@@ -55,6 +43,18 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.common.io.MoreCloseables;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.util.Constants;
+import com.android.contacts.util.EmptyLoader;
+import com.android.contacts.voicemail.VoicemailStatusHelper;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.ITelephony;
+import com.google.common.annotations.VisibleForTesting;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/calllog/CallLogGroupBuilder.java b/src/com/android/contacts/calllog/CallLogGroupBuilder.java
index 9829d4a..3d7dd2c 100644
--- a/src/com/android/contacts/calllog/CallLogGroupBuilder.java
+++ b/src/com/android/contacts/calllog/CallLogGroupBuilder.java
@@ -16,13 +16,13 @@
 
 package com.android.contacts.calllog;
 
-import com.android.common.widget.GroupingListAdapter;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.database.Cursor;
 import android.provider.CallLog.Calls;
 import android.telephony.PhoneNumberUtils;
 
+import com.android.common.widget.GroupingListAdapter;
+import com.google.common.annotations.VisibleForTesting;
+
 /**
  * Groups together calls in the call log.
  * <p>
diff --git a/src/com/android/contacts/calllog/CallLogListItemHelper.java b/src/com/android/contacts/calllog/CallLogListItemHelper.java
index 9485b54..eb30c81 100644
--- a/src/com/android/contacts/calllog/CallLogListItemHelper.java
+++ b/src/com/android/contacts/calllog/CallLogListItemHelper.java
@@ -16,15 +16,15 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.PhoneCallDetails;
-import com.android.contacts.PhoneCallDetailsHelper;
-import com.android.contacts.R;
-
 import android.content.res.Resources;
 import android.provider.CallLog.Calls;
 import android.text.TextUtils;
 import android.view.View;
 
+import com.android.contacts.PhoneCallDetails;
+import com.android.contacts.PhoneCallDetailsHelper;
+import com.android.contacts.R;
+
 /**
  * Helper class to fill in the views of a call log entry.
  */
diff --git a/src/com/android/contacts/calllog/CallLogListItemViews.java b/src/com/android/contacts/calllog/CallLogListItemViews.java
index 503de43..348cd2f 100644
--- a/src/com/android/contacts/calllog/CallLogListItemViews.java
+++ b/src/com/android/contacts/calllog/CallLogListItemViews.java
@@ -16,16 +16,16 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.PhoneCallDetailsViews;
-import com.android.contacts.R;
-import com.android.contacts.test.NeededForTesting;
-
 import android.content.Context;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
 
+import com.android.contacts.PhoneCallDetailsViews;
+import com.android.contacts.R;
+import com.android.contacts.test.NeededForTesting;
+
 /**
  * Simple value object containing the various views within a call log entry.
  */
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index edc631f..ba604cd 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.common.io.MoreCloseables;
-import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
-import com.google.android.collect.Lists;
-
 import android.content.AsyncQueryHandler;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -37,6 +33,10 @@
 import android.provider.VoicemailContract.Status;
 import android.util.Log;
 
+import com.android.common.io.MoreCloseables;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+import com.google.common.collect.Lists;
+
 import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
diff --git a/src/com/android/contacts/calllog/CallTypeHelper.java b/src/com/android/contacts/calllog/CallTypeHelper.java
index d5d1068..2ca0db0 100644
--- a/src/com/android/contacts/calllog/CallTypeHelper.java
+++ b/src/com/android/contacts/calllog/CallTypeHelper.java
@@ -16,11 +16,11 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.R;
-
 import android.content.res.Resources;
 import android.provider.CallLog.Calls;
 
+import com.android.contacts.R;
+
 /**
  * Helper class to perform operations related to call types.
  */
diff --git a/src/com/android/contacts/calllog/CallTypeIconsView.java b/src/com/android/contacts/calllog/CallTypeIconsView.java
index e0242c8..384b597 100644
--- a/src/com/android/contacts/calllog/CallTypeIconsView.java
+++ b/src/com/android/contacts/calllog/CallTypeIconsView.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.R;
-import com.android.contacts.test.NeededForTesting;
-import com.google.common.collect.Lists;
-
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
@@ -27,6 +23,10 @@
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.contacts.R;
+import com.android.contacts.test.NeededForTesting;
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/calllog/ClearCallLogDialog.java b/src/com/android/contacts/calllog/ClearCallLogDialog.java
index 426732a..c4dbb7e 100644
--- a/src/com/android/contacts/calllog/ClearCallLogDialog.java
+++ b/src/com/android/contacts/calllog/ClearCallLogDialog.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.R;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -30,6 +28,8 @@
 import android.os.Bundle;
 import android.provider.CallLog.Calls;
 
+import com.android.contacts.R;
+
 /**
  * Dialog that clears the call log after confirming with the user
  */
diff --git a/src/com/android/contacts/calllog/ContactInfo.java b/src/com/android/contacts/calllog/ContactInfo.java
index a02b457..30e7e71 100644
--- a/src/com/android/contacts/calllog/ContactInfo.java
+++ b/src/com/android/contacts/calllog/ContactInfo.java
@@ -16,11 +16,11 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.util.UriUtils;
-
 import android.net.Uri;
 import android.text.TextUtils;
 
+import com.android.contacts.util.UriUtils;
+
 /**
  * Information for a contact as needed by the Call Log.
  */
diff --git a/src/com/android/contacts/calllog/ContactInfoHelper.java b/src/com/android/contacts/calllog/ContactInfoHelper.java
index 90d5e8b..edca00c 100644
--- a/src/com/android/contacts/calllog/ContactInfoHelper.java
+++ b/src/com/android/contacts/calllog/ContactInfoHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.util.UriUtils;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
@@ -26,6 +24,8 @@
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 
+import com.android.contacts.util.UriUtils;
+
 /**
  * Utility class to look up the contact information for a given number.
  */
diff --git a/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java b/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
index 1c2a595..cfac1de 100644
--- a/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
+++ b/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.common.io.MoreCloseables;
-import com.android.contacts.CallDetailActivity;
-import com.android.contacts.R;
-import com.google.common.collect.Maps;
-
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -36,6 +31,11 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.common.io.MoreCloseables;
+import com.android.contacts.CallDetailActivity;
+import com.android.contacts.R;
+import com.google.common.collect.Maps;
+
 import java.util.Map;
 
 /**
diff --git a/src/com/android/contacts/calllog/ExtendedCursor.java b/src/com/android/contacts/calllog/ExtendedCursor.java
index 499a350..3894192 100644
--- a/src/com/android/contacts/calllog/ExtendedCursor.java
+++ b/src/com/android/contacts/calllog/ExtendedCursor.java
@@ -16,13 +16,13 @@
 
 package com.android.contacts.calllog;
 
-import com.android.common.io.MoreCloseables;
-
 import android.database.AbstractCursor;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.DataSetObserver;
 
+import com.android.common.io.MoreCloseables;
+
 /**
  * Wraps a cursor to add an additional column with the same value for all rows.
  * <p>
diff --git a/src/com/android/contacts/calllog/IntentProvider.java b/src/com/android/contacts/calllog/IntentProvider.java
index 7ddfecc..487799c 100644
--- a/src/com/android/contacts/calllog/IntentProvider.java
+++ b/src/com/android/contacts/calllog/IntentProvider.java
@@ -16,16 +16,15 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.CallDetailActivity;
-import com.android.contacts.ContactsUtils;
-
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.CallLog.Calls;
-import android.telephony.PhoneNumberUtils;
+
+import com.android.contacts.CallDetailActivity;
+import com.android.contacts.ContactsUtils;
 
 /**
  * Used to create an intent to attach to an action in the call log.
diff --git a/src/com/android/contacts/calllog/PhoneNumberHelper.java b/src/com/android/contacts/calllog/PhoneNumberHelper.java
index af7c2f6..e24d0ae 100644
--- a/src/com/android/contacts/calllog/PhoneNumberHelper.java
+++ b/src/com/android/contacts/calllog/PhoneNumberHelper.java
@@ -16,15 +16,13 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.internal.telephony.CallerInfo;
-
 import android.content.res.Resources;
-import android.net.Uri;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 
+import com.android.contacts.R;
+import com.android.internal.telephony.CallerInfo;
+
 /**
  * Helper for formatting and managing phone numbers.
  */
diff --git a/src/com/android/contacts/datepicker/DatePicker.java b/src/com/android/contacts/datepicker/DatePicker.java
index 629fd9c..ef91c95 100644
--- a/src/com/android/contacts/datepicker/DatePicker.java
+++ b/src/com/android/contacts/datepicker/DatePicker.java
@@ -19,8 +19,6 @@
 // This is a fork of the standard Android DatePicker that additionally allows toggling the year
 // on/off. It uses some private API so that not everything has to be copied.
 
-import com.android.contacts.R;
-
 import android.animation.LayoutTransition;
 import android.annotation.Widget;
 import android.content.Context;
@@ -40,6 +38,8 @@
 import android.widget.NumberPicker;
 import android.widget.NumberPicker.OnValueChangeListener;
 
+import com.android.contacts.R;
+
 import java.text.DateFormatSymbols;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
diff --git a/src/com/android/contacts/datepicker/DatePickerDialog.java b/src/com/android/contacts/datepicker/DatePickerDialog.java
index b0c4ed6..9c7cee6 100644
--- a/src/com/android/contacts/datepicker/DatePickerDialog.java
+++ b/src/com/android/contacts/datepicker/DatePickerDialog.java
@@ -19,10 +19,6 @@
 // This is a fork of the standard Android DatePicker that additionally allows toggling the year
 // on/off. It uses some private API so that not everything has to be copied.
 
-import com.android.contacts.R;
-import com.android.contacts.datepicker.DatePicker.OnDateChangedListener;
-import com.android.contacts.util.DateUtils;
-
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -34,6 +30,10 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.datepicker.DatePicker.OnDateChangedListener;
+import com.android.contacts.util.DateUtils;
+
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
diff --git a/src/com/android/contacts/detail/CarouselTab.java b/src/com/android/contacts/detail/CarouselTab.java
index 0b430b6..09e097a 100644
--- a/src/com/android/contacts/detail/CarouselTab.java
+++ b/src/com/android/contacts/detail/CarouselTab.java
@@ -16,15 +16,15 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.R;
-import com.android.contacts.widget.FrameLayoutWithOverlay;
-
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewPropertyAnimator;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.widget.FrameLayoutWithOverlay;
+
 /**
  * This is a tab in the {@link ContactDetailTabCarousel}.
  */
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index 404148d..1908e96 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -16,23 +16,8 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.ContactLoader;
-import com.android.contacts.ContactLoader.Result;
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.R;
-import com.android.contacts.preference.ContactsPreferences;
-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 android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
-import android.content.Entity;
-import android.content.Entity.NamedContentValues;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
@@ -40,8 +25,6 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.DisplayNameSources;
 import android.provider.ContactsContract.StreamItems;
 import android.text.Html;
@@ -56,12 +39,27 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.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.preference.ContactsPreferences;
+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;
+
 import java.util.List;
 
 /**
  * This class contains utility methods to bind high-level contact details
  * (meaning name, phonetic name, job, and attribution) from a
- * {@link ContactLoader.Result} data object to appropriate {@link View}s.
+ * {@link Contact} data object to appropriate {@link View}s.
  */
 public class ContactDetailDisplayUtils {
     private static final String TAG = "ContactDetailDisplayUtils";
@@ -95,7 +93,7 @@
      * Returns the display name of the contact, using the current display order setting.
      * Returns res/string/missing_name if there is no display name.
      */
-    public static CharSequence getDisplayName(Context context, Result contactData) {
+    public static CharSequence getDisplayName(Context context, Contact contactData) {
         CharSequence displayName = contactData.getDisplayName();
         CharSequence altDisplayName = contactData.getAltDisplayName();
         ContactsPreferences prefs = new ContactsPreferences(context);
@@ -115,7 +113,7 @@
     /**
      * Returns the phonetic name of the contact or null if there isn't one.
      */
-    public static String getPhoneticName(Context context, Result contactData) {
+    public static String getPhoneticName(Context context, Contact contactData) {
         String phoneticName = contactData.getPhoneticName();
         if (!TextUtils.isEmpty(phoneticName)) {
             return phoneticName;
@@ -127,7 +125,7 @@
      * Returns the attribution string for the contact, which may specify the contact directory that
      * the contact came from. Returns null if there is none applicable.
      */
-    public static String getAttribution(Context context, Result contactData) {
+    public static String getAttribution(Context context, Contact contactData) {
         if (contactData.isDirectoryEntry()) {
             String directoryDisplayName = contactData.getDirectoryDisplayName();
             String directoryType = contactData.getDirectoryType();
@@ -143,40 +141,37 @@
      * Returns the organization of the contact. If several organizations are given,
      * the first one is used. Returns null if not applicable.
      */
-    public static String getCompany(Context context, Result contactData) {
+    public static String getCompany(Context context, Contact contactData) {
         final boolean displayNameIsOrganization = contactData.getDisplayNameSource()
                 == DisplayNameSources.ORGANIZATION;
-        for (Entity entity : contactData.getEntities()) {
-            for (NamedContentValues subValue : entity.getSubValues()) {
-                final ContentValues entryValues = subValue.values;
-                final String mimeType = entryValues.getAsString(Data.MIMETYPE);
-
-                if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    final String company = entryValues.getAsString(Organization.COMPANY);
-                    final String title = entryValues.getAsString(Organization.TITLE);
-                    final String combined;
-                    // We need to show company and title in a combined string. However, if the
-                    // DisplayName is already the organization, it mirrors company or (if company
-                    // is empty title). Make sure we don't show what's already shown as DisplayName
-                    if (TextUtils.isEmpty(company)) {
-                        combined = displayNameIsOrganization ? null : title;
+        for (RawContact rawContact : contactData.getRawContacts()) {
+            for (DataItem dataItem : Iterables.filter(
+                    rawContact.getDataItems(), OrganizationDataItem.class)) {
+                OrganizationDataItem organization = (OrganizationDataItem) dataItem;
+                final String company = organization.getCompany();
+                final String title = organization.getTitle();
+                final String combined;
+                // We need to show company and title in a combined string. However, if the
+                // DisplayName is already the organization, it mirrors company or (if company
+                // is empty title). Make sure we don't show what's already shown as DisplayName
+                if (TextUtils.isEmpty(company)) {
+                    combined = displayNameIsOrganization ? null : title;
+                } else {
+                    if (TextUtils.isEmpty(title)) {
+                        combined = displayNameIsOrganization ? null : company;
                     } else {
-                        if (TextUtils.isEmpty(title)) {
-                            combined = displayNameIsOrganization ? null : company;
+                        if (displayNameIsOrganization) {
+                            combined = title;
                         } else {
-                            if (displayNameIsOrganization) {
-                                combined = title;
-                            } else {
-                                combined = context.getString(
-                                        R.string.organization_company_and_title,
-                                        company, title);
-                            }
+                            combined = context.getString(
+                                    R.string.organization_company_and_title,
+                                    company, title);
                         }
                     }
+                }
 
-                    if (!TextUtils.isEmpty(combined)) {
-                        return combined;
-                    }
+                if (!TextUtils.isEmpty(combined)) {
+                    return combined;
                 }
             }
         }
@@ -225,7 +220,7 @@
     /**
      * Set the social snippet text. If there isn't one, then set the view to gone.
      */
-    public static void setSocialSnippet(Context context, Result contactData, TextView statusView,
+    public static void setSocialSnippet(Context context, Contact contactData, TextView statusView,
             ImageView statusPhotoView) {
         if (statusView == null) {
             return;
@@ -378,7 +373,7 @@
      * Sets the display name of this contact to the given {@link TextView}. If
      * there is none, then set the view to gone.
      */
-    public static void setDisplayName(Context context, Result contactData, TextView textView) {
+    public static void setDisplayName(Context context, Contact contactData, TextView textView) {
         if (textView == null) {
             return;
         }
@@ -389,7 +384,7 @@
      * Sets the company and job title of this contact to the given {@link TextView}. If
      * there is none, then set the view to gone.
      */
-    public static void setCompanyName(Context context, Result contactData, TextView textView) {
+    public static void setCompanyName(Context context, Contact contactData, TextView textView) {
         if (textView == null) {
             return;
         }
@@ -400,7 +395,7 @@
      * Sets the phonetic name of this contact to the given {@link TextView}. If
      * there is none, then set the view to gone.
      */
-    public static void setPhoneticName(Context context, Result contactData, TextView textView) {
+    public static void setPhoneticName(Context context, Contact contactData, TextView textView) {
         if (textView == null) {
             return;
         }
@@ -411,7 +406,7 @@
      * Sets the attribution contact to the given {@link TextView}. If
      * there is none, then set the view to gone.
      */
-    public static void setAttribution(Context context, Result contactData, TextView textView) {
+    public static void setAttribution(Context context, Contact contactData, TextView textView) {
         if (textView == null) {
             return;
         }
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 5c68dcb..f66466d 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -16,45 +16,12 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.Collapser;
-import com.android.contacts.Collapser.Collapsible;
-import com.android.contacts.ContactLoader;
-import com.android.contacts.ContactPresenceIconUtil;
-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.detail.ContactDetailPhotoSetter;
-import com.android.contacts.editor.SelectAccountDialogFragment;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
-import com.android.contacts.util.ClipboardUtils;
-import com.android.contacts.util.Constants;
-import com.android.contacts.util.DataStatus;
-import com.android.contacts.util.DateUtils;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.android.contacts.util.StructuredPostalUtils;
-import com.android.internal.telephony.ITelephony;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.SearchManager;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.Entity;
-import android.content.Entity.NamedContentValues;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
@@ -67,23 +34,13 @@
 import android.os.ServiceManager;
 import android.provider.ContactsContract;
 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.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;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.DisplayNameSources;
-import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.StatusUpdates;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
@@ -112,6 +69,52 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.Collapser;
+import com.android.contacts.Collapser.Collapsible;
+import com.android.contacts.ContactPresenceIconUtil;
+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.editor.SelectAccountDialogFragment;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.RawContact;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountType.EditType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.model.dataitem.DataKind;
+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.AccountsListAdapter.AccountListFilter;
+import com.android.contacts.util.ClipboardUtils;
+import com.android.contacts.util.Constants;
+import com.android.contacts.util.DataStatus;
+import com.android.contacts.util.DateUtils;
+import com.android.contacts.util.PhoneCapabilityTester;
+import com.android.contacts.util.StructuredPostalUtils;
+import com.android.internal.telephony.ITelephony;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Iterables;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -138,7 +141,7 @@
     private Uri mLookupUri;
     private Listener mListener;
 
-    private ContactLoader.Result mContactData;
+    private Contact mContactData;
     private ViewGroup mStaticPhotoContainer;
     private View mPhotoTouchOverlay;
     private ListView mListView;
@@ -188,9 +191,8 @@
     private Parcelable mListState;
 
     /**
-     * A list of distinct contact IDs included in the current contact.
+     * Lists of specific types of entries to be shown in contact details.
      */
-    private ArrayList<Long> mRawContactIds = new ArrayList<Long>();
     private ArrayList<DetailViewEntry> mPhoneEntries = new ArrayList<DetailViewEntry>();
     private ArrayList<DetailViewEntry> mSmsEntries = new ArrayList<DetailViewEntry>();
     private ArrayList<DetailViewEntry> mEmailEntries = new ArrayList<DetailViewEntry>();
@@ -336,7 +338,7 @@
         return mListener;
     }
 
-    protected ContactLoader.Result getContactData() {
+    protected Contact getContactData() {
         return mContactData;
     }
 
@@ -363,7 +365,7 @@
         setData(null, null);
     }
 
-    public void setData(Uri lookupUri, ContactLoader.Result result) {
+    public void setData(Uri lookupUri, Contact result) {
         mLookupUri = lookupUri;
         mContactData = result;
         bindData();
@@ -531,65 +533,47 @@
         // Clear out the old entries
         mAllEntries.clear();
 
-        mRawContactIds.clear();
-
         mPrimaryPhoneUri = null;
 
-        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-
         // Build up method entries
         if (mContactData == null) {
             return;
         }
 
         ArrayList<String> groups = new ArrayList<String>();
-        for (Entity entity: mContactData.getEntities()) {
-            final ContentValues entValues = entity.getEntityValues();
-            final String accountType = entValues.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = entValues.getAsString(RawContacts.DATA_SET);
-            final long rawContactId = entValues.getAsLong(RawContacts._ID);
+        for (RawContact rawContact: mContactData.getRawContacts()) {
+            final long rawContactId = rawContact.getId();
+            for (DataItem dataItem : rawContact.getDataItems()) {
+                dataItem.setRawContactId(rawContactId);
 
-            if (!mRawContactIds.contains(rawContactId)) {
-                mRawContactIds.add(rawContactId);
-            }
+                if (dataItem.getMimeType() == null) continue;
 
-            AccountType type = accountTypes.getAccountType(accountType, dataSet);
-
-            for (NamedContentValues subValue : entity.getSubValues()) {
-                final ContentValues entryValues = subValue.values;
-                entryValues.put(Data.RAW_CONTACT_ID, rawContactId);
-
-                final long dataId = entryValues.getAsLong(Data._ID);
-                final String mimeType = entryValues.getAsString(Data.MIMETYPE);
-                if (mimeType == null) continue;
-
-                if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    Long groupId = entryValues.getAsLong(GroupMembership.GROUP_ROW_ID);
+                if (dataItem instanceof GroupMembershipDataItem) {
+                    GroupMembershipDataItem groupMembership =
+                            (GroupMembershipDataItem) dataItem;
+                    Long groupId = groupMembership.getGroupRowId();
                     if (groupId != null) {
                         handleGroupMembership(groups, mContactData.getGroupMetaData(), groupId);
                     }
                     continue;
                 }
 
-                final DataKind kind = accountTypes.getKindOrFallback(
-                        accountType, dataSet, mimeType);
+                final DataKind kind = dataItem.getDataKind();
                 if (kind == null) continue;
 
-                final DetailViewEntry entry = DetailViewEntry.fromValues(mContext, mimeType, kind,
-                        dataId, entryValues, mContactData.isDirectoryEntry(),
-                        mContactData.getDirectoryId());
+                final DetailViewEntry entry = DetailViewEntry.fromValues(mContext, dataItem,
+                        mContactData.isDirectoryEntry(), mContactData.getDirectoryId());
                 entry.maxLines = kind.maxLinesForDisplay;
 
                 final boolean hasData = !TextUtils.isEmpty(entry.data);
-                Integer superPrimary = entryValues.getAsInteger(Data.IS_SUPER_PRIMARY);
-                final boolean isSuperPrimary = superPrimary != null && superPrimary != 0;
+                final boolean isSuperPrimary = dataItem.isSuperPrimary();
 
-                if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
+                if (dataItem instanceof StructuredNameDataItem) {
                     // Always ignore the name. It is shown in the header if set
-                } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof PhoneDataItem && hasData) {
+                    PhoneDataItem phone = (PhoneDataItem) dataItem;
                     // Build phone entries
-                    String phoneNumberE164 =
-                            entryValues.getAsString(Phone.NORMALIZED_NUMBER);
+                    String phoneNumberE164 = phone.getNormalizedNumber();
                     entry.data = PhoneNumberUtils.formatNumber(
                             entry.data, phoneNumberE164, mDefaultCountryIso);
                     final Intent phoneIntent = mHasPhone ?
@@ -624,7 +608,7 @@
                         // add to end of list
                         mPhoneEntries.add(entry);
                     }
-                } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof EmailDataItem && hasData) {
                     // Build email entries
                     entry.intent = new Intent(Intent.ACTION_SENDTO,
                             Uri.fromParts(Constants.SCHEME_MAILTO, entry.data, null));
@@ -639,24 +623,23 @@
                     // When Email rows have status, create additional Im row
                     final DataStatus status = mContactData.getStatuses().get(entry.id);
                     if (status != null) {
-                        final String imMime = Im.CONTENT_ITEM_TYPE;
-                        final DataKind imKind = accountTypes.getKindOrFallback(accountType, dataSet,
-                                imMime);
-                        final DetailViewEntry imEntry = DetailViewEntry.fromValues(mContext, imMime,
-                                imKind, dataId, entryValues, mContactData.isDirectoryEntry(),
-                                mContactData.getDirectoryId());
-                        buildImActions(mContext, imEntry, entryValues);
+                        EmailDataItem email = (EmailDataItem) dataItem;
+                        ImDataItem im = ImDataItem.createFromEmail(email);
+
+                        final DetailViewEntry imEntry = DetailViewEntry.fromValues(mContext, im,
+                                mContactData.isDirectoryEntry(), mContactData.getDirectoryId());
+                        buildImActions(mContext, imEntry, im);
                         imEntry.setPresence(status.getPresence());
-                        imEntry.maxLines = imKind.maxLinesForDisplay;
+                        imEntry.maxLines = kind.maxLinesForDisplay;
                         mImEntries.add(imEntry);
                     }
-                } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof StructuredPostalDataItem && hasData) {
                     // Build postal entries
                     entry.intent = StructuredPostalUtils.getViewPostalAddressIntent(entry.data);
                     mPostalEntries.add(entry);
-                } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof ImDataItem && hasData) {
                     // Build IM entries
-                    buildImActions(mContext, entry, entryValues);
+                    buildImActions(mContext, entry, (ImDataItem) dataItem);
 
                     // Apply presence when available
                     final DataStatus status = mContactData.getStatuses().get(entry.id);
@@ -664,10 +647,10 @@
                         entry.setPresence(status.getPresence());
                     }
                     mImEntries.add(entry);
-                } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
+                } else if (dataItem instanceof OrganizationDataItem) {
                     // Organizations are not shown. The first one is shown in the header
                     // and subsequent ones are not supported anymore
-                } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof NicknameDataItem && hasData) {
                     // Build nickname entries
                     final boolean isNameRawContact =
                         (mContactData.getNameRawContactId() == rawContactId);
@@ -680,11 +663,11 @@
                         entry.uri = null;
                         mNicknameEntries.add(entry);
                     }
-                } else if (Note.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof NoteDataItem && hasData) {
                     // Build note entries
                     entry.uri = null;
                     mNoteEntries.add(entry);
-                } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof WebsiteDataItem && hasData) {
                     // Build Website entries
                     entry.uri = null;
                     try {
@@ -695,7 +678,7 @@
                         Log.e(TAG, "Couldn't parse website: " + entry.data);
                     }
                     mWebsiteEntries.add(entry);
-                } else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof SipAddressDataItem && hasData) {
                     // Build SipAddress entries
                     entry.uri = null;
                     if (mHasSip) {
@@ -711,11 +694,11 @@
                     // (Then, we'd also update FallbackAccountType.java to set
                     // secondary=false for this field, and tweak the weight
                     // of its DataKind.)
-                } else if (Event.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof EventDataItem && hasData) {
                     entry.data = DateUtils.formatDate(mContext, entry.data);
                     entry.uri = null;
                     mEventEntries.add(entry);
-                } else if (Relation.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                } else if (dataItem instanceof RelationDataItem && hasData) {
                     entry.intent = new Intent(Intent.ACTION_SEARCH);
                     entry.intent.putExtra(SearchManager.QUERY, entry.data);
                     entry.intent.setType(Contacts.CONTENT_TYPE);
@@ -725,14 +708,12 @@
                     entry.intent = new Intent(Intent.ACTION_VIEW);
                     entry.intent.setDataAndType(entry.uri, entry.mimetype);
 
-                    if (kind.actionBody != null) {
-                         CharSequence body = kind.actionBody.inflateUsing(mContext, entryValues);
-                         entry.data = (body == null) ? null : body.toString();
-                    }
+                    entry.data = dataItem.buildDataString();
 
                     if (!TextUtils.isEmpty(entry.data)) {
                         // If the account type exists in the hash map, add it as another entry for
                         // that account type
+                        AccountType type = dataItem.getAccountType();
                         if (mOtherEntriesMap.containsKey(type)) {
                             List<DetailViewEntry> listEntries = mOtherEntriesMap.get(type);
                             listEntries.add(entry);
@@ -961,37 +942,27 @@
         }
     }
 
-    private static String buildDataString(DataKind kind, ContentValues values,
-            Context context) {
-        if (kind.actionBody == null) {
-            return null;
-        }
-        CharSequence actionBody = kind.actionBody.inflateUsing(context, values);
-        return actionBody == null ? null : actionBody.toString();
-    }
-
     /**
      * Writes the Instant Messaging action into the given entry value.
      */
     @VisibleForTesting
     public static void buildImActions(Context context, DetailViewEntry entry,
-            ContentValues values) {
-        final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(values.getAsString(Data.MIMETYPE));
+            ImDataItem im) {
+        final boolean isEmail = im.isCreatedFromEmail();
 
-        if (!isEmail && !isProtocolValid(values)) {
+        if (!isEmail && !im.isProtocolValid()) {
             return;
         }
 
-        final String data = values.getAsString(isEmail ? Email.DATA : Im.DATA);
+        final String data = im.getData();
         if (TextUtils.isEmpty(data)) {
             return;
         }
 
-        final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : values.getAsInteger(Im.PROTOCOL);
+        final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();
 
         if (protocol == Im.PROTOCOL_GOOGLE_TALK) {
-            final Integer chatCapabilityObj = values.getAsInteger(Im.CHAT_CAPABILITY);
-            final int chatCapability = chatCapabilityObj == null ? 0 : chatCapabilityObj;
+            final int chatCapability = im.getChatCapability();
             entry.chatCapability = chatCapability;
             entry.typeString = Im.getProtocolLabel(context.getResources(), Im.PROTOCOL_GOOGLE_TALK,
                     null).toString();
@@ -1012,7 +983,7 @@
             }
         } else {
             // Build an IM Intent
-            String host = values.getAsString(Im.CUSTOM_PROTOCOL);
+            String host = im.getCustomProtocol();
 
             if (protocol != Im.PROTOCOL_CUSTOM) {
                 // Try bringing in a well-known host for specific protocols
@@ -1028,19 +999,6 @@
         }
     }
 
-    private static boolean isProtocolValid(ContentValues values) {
-        String protocolString = values.getAsString(Im.PROTOCOL);
-        if (protocolString == null) {
-            return false;
-        }
-        try {
-            Integer.valueOf(protocolString);
-        } catch (NumberFormatException e) {
-            return false;
-        }
-        return true;
-    }
-
     /**
      * Show a list popup.  Used for "popup-able" entry, such as "More networks".
      */
@@ -1247,6 +1205,38 @@
 
         private boolean mIsInSubSection = false;
 
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("== DetailViewEntry ==\n");
+            sb.append("  type: " + type + "\n");
+            sb.append("  kind: " + kind + "\n");
+            sb.append("  typeString: " + typeString + "\n");
+            sb.append("  data: " + data + "\n");
+            sb.append("  uri: " + uri.toString() + "\n");
+            sb.append("  maxLines: " + maxLines + "\n");
+            sb.append("  mimetype: " + mimetype + "\n");
+            sb.append("  isPrimary: " + (isPrimary ? "true" : "false") + "\n");
+            sb.append("  secondaryActionIcon: " + secondaryActionIcon + "\n");
+            sb.append("  secondaryActionDescription: " + secondaryActionDescription + "\n");
+            if (intent == null) {
+                sb.append("  intent: " + intent.toString() + "\n");
+            } else {
+                sb.append("  intent: " + intent.toString() + "\n");
+            }
+            if (secondaryIntent == null) {
+                sb.append("  secondaryIntent: (null)\n");
+            } else {
+                sb.append("  secondaryIntent: " + secondaryIntent.toString() + "\n");
+            }
+            sb.append("  ids: " + Iterables.toString(ids) + "\n");
+            sb.append("  collapseCount: " + collapseCount + "\n");
+            sb.append("  presence: " + presence + "\n");
+            sb.append("  chatCapability: " + chatCapability + "\n");
+            sb.append("  mIsInSubsection: " + (mIsInSubSection ? "true" : "false") + "\n");
+            return sb.toString();
+        }
+
         DetailViewEntry() {
             super(ViewAdapter.VIEW_TYPE_DETAIL_ENTRY);
             isEnabled = true;
@@ -1255,34 +1245,34 @@
         /**
          * Build new {@link DetailViewEntry} and populate from the given values.
          */
-        public static DetailViewEntry fromValues(Context context, String mimeType, DataKind kind,
-                long dataId, ContentValues values, boolean isDirectoryEntry, long directoryId) {
+        public static DetailViewEntry fromValues(Context context, DataItem item,
+                boolean isDirectoryEntry, long directoryId) {
             final DetailViewEntry entry = new DetailViewEntry();
-            entry.id = dataId;
+            entry.id = item.getId();
             entry.context = context;
             entry.uri = ContentUris.withAppendedId(Data.CONTENT_URI, entry.id);
             if (isDirectoryEntry) {
                 entry.uri = entry.uri.buildUpon().appendQueryParameter(
                         ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build();
             }
-            entry.mimetype = mimeType;
-            entry.kind = (kind.titleRes == -1 || kind.titleRes == 0) ? ""
-                    : context.getString(kind.titleRes);
-            entry.data = buildDataString(kind, values, context);
+            entry.mimetype = item.getMimeType();
+            entry.kind = item.getKindString();
+            entry.data = item.buildDataString();
 
-            if (kind.typeColumn != null && values.containsKey(kind.typeColumn)) {
-                entry.type = values.getAsInteger(kind.typeColumn);
+            if (item.hasKindTypeColumn()) {
+                entry.type = item.getKindTypeColumn();
 
                 // get type string
                 entry.typeString = "";
-                for (EditType type : kind.typeList) {
+                for (EditType type : item.getDataKind().typeList) {
                     if (type.rawValue == entry.type) {
                         if (type.customColumn == null) {
                             // Non-custom type. Get its description from the resource
                             entry.typeString = context.getString(type.labelRes);
                         } else {
                             // Custom type. Read it from the database
-                            entry.typeString = values.getAsString(type.customColumn);
+                            entry.typeString =
+                                    item.getContentValues().getAsString(type.customColumn);
                         }
                         break;
                     }
@@ -1997,7 +1987,7 @@
             if (mContactData.isUserProfile()) return false;
 
             // Only if exactly one raw contact
-            if (mContactData.getEntities().size() != 1) return false;
+            if (mContactData.getRawContacts().size() != 1) return false;
 
             // test if the default group is assigned
             final List<GroupMetaData> groups = mContactData.getGroupMetaData();
@@ -2009,28 +1999,20 @@
             final long defaultGroupId = getDefaultGroupId(groups);
             if (defaultGroupId == -1) return false;
 
-            final Entity rawContactEntity = mContactData.getEntities().get(0);
-            ContentValues rawValues = rawContactEntity.getEntityValues();
-            final String accountType = rawValues.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = rawValues.getAsString(RawContacts.DATA_SET);
-            final AccountTypeManager accountTypes =
-                    AccountTypeManager.getInstance(mContext);
-            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
+            final RawContact rawContact = (RawContact) mContactData.getRawContacts().get(0);
+            final AccountType type = rawContact.getAccountType();
             // Offline or non-writeable account? Nothing to fix
             if (type == null || !type.areContactsWritable()) return false;
 
             // Check whether the contact is in the default group
             boolean isInDefaultGroup = false;
-            for (NamedContentValues subValue : rawContactEntity.getSubValues()) {
-                final String mimeType = subValue.values.getAsString(Data.MIMETYPE);
-
-                if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    final Long groupId =
-                            subValue.values.getAsLong(GroupMembership.GROUP_ROW_ID);
-                    if (groupId == defaultGroupId) {
-                        isInDefaultGroup = true;
-                        break;
-                    }
+            for (DataItem dataItem : Iterables.filter(
+                    rawContact.getDataItems(), GroupMembershipDataItem.class)) {
+                GroupMembershipDataItem groupMembership = (GroupMembershipDataItem) dataItem;
+                final Long groupId = groupMembership.getGroupRowId();
+                if (groupId == defaultGroupId) {
+                    isInDefaultGroup = true;
+                    break;
                 }
             }
 
@@ -2050,19 +2032,16 @@
             if (defaultGroupId == -1) return;
 
             // add the group membership to the current state
-            final EntityDeltaList contactDeltaList = mContactData.createEntityDeltaList();
-            final EntityDelta rawContactEntityDelta = contactDeltaList.get(0);
+            final RawContactDeltaList contactDeltaList = mContactData.createRawContactDeltaList();
+            final RawContactDelta rawContactEntityDelta = contactDeltaList.get(0);
 
             final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-            final ValuesDelta values = rawContactEntityDelta.getValues();
-            final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = values.getAsString(RawContacts.DATA_SET);
-            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
+            final AccountType type = rawContactEntityDelta.getAccountType(accountTypes);
             final DataKind groupMembershipKind = type.getKindForMimetype(
                     GroupMembership.CONTENT_ITEM_TYPE);
-            final ValuesDelta entry = EntityModifier.insertChild(rawContactEntityDelta,
+            final ValuesDelta entry = RawContactModifier.insertChild(rawContactEntityDelta,
                     groupMembershipKind);
-            entry.put(GroupMembership.GROUP_ROW_ID, defaultGroupId);
+            entry.setGroupRowId(defaultGroupId);
 
             // and fire off the intent. we don't need a callback, as the database listener
             // should update the ui
@@ -2199,7 +2178,7 @@
         private final LayoutInflater mInflater;
         private final ArrayList<AccountType> mAccountTypes;
 
-        public InvitableAccountTypesAdapter(Context context, ContactLoader.Result contactData) {
+        public InvitableAccountTypesAdapter(Context context, Contact contactData) {
             mContext = context;
             mInflater = LayoutInflater.from(context);
             final List<AccountType> types = contactData.getInvitableAccountTypes();
diff --git a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
index 08ed87b..a66baa5 100644
--- a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
@@ -16,18 +16,18 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.R;
-import com.android.contacts.widget.FrameLayoutWithOverlay;
-
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewPropertyAnimator;
 import android.view.View.OnTouchListener;
+import android.view.ViewPropertyAnimator;
 import android.widget.HorizontalScrollView;
 
+import com.android.contacts.R;
+import com.android.contacts.widget.FrameLayoutWithOverlay;
+
 /**
  * This is a horizontally scrolling carousel with 2 fragments: one to see info about the contact and
  * one to see updates from the contact. Depending on the scroll position and user selection of which
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index 2c18d4f..fca426c 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -16,16 +16,6 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.ContactLoader;
-
-import com.android.contacts.NfcHandler;
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.android.contacts.util.UriUtils;
-import com.android.contacts.widget.FrameLayoutWithOverlay;
-import com.android.contacts.widget.TransitionAnimationView;
-
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.ObjectAnimator;
@@ -44,6 +34,15 @@
 import android.widget.AbsListView;
 import android.widget.AbsListView.OnScrollListener;
 
+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.util.PhoneCapabilityTester;
+import com.android.contacts.util.UriUtils;
+import com.android.contacts.widget.FrameLayoutWithOverlay;
+import com.android.contacts.widget.TransitionAnimationView;
+
 /**
  * Determines the layout of the contact card.
  */
@@ -103,7 +102,7 @@
 
     private final ContactDetailFragment.Listener mContactDetailFragmentListener;
 
-    private ContactLoader.Result mContactData;
+    private Contact mContactData;
     private Uri mContactUri;
 
     private boolean mTabCarouselIsAnimating;
@@ -271,7 +270,7 @@
         }
     }
 
-    public void setContactData(ContactLoader.Result data) {
+    public void setContactData(Contact data) {
         final boolean contactWasLoaded;
         final boolean contactHadUpdates;
         final boolean isDifferentContact;
diff --git a/src/com/android/contacts/detail/ContactDetailPhotoSetter.java b/src/com/android/contacts/detail/ContactDetailPhotoSetter.java
index dffb37b..eb832e9 100644
--- a/src/com/android/contacts/detail/ContactDetailPhotoSetter.java
+++ b/src/com/android/contacts/detail/ContactDetailPhotoSetter.java
@@ -26,9 +26,9 @@
 import android.widget.ImageView;
 
 import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactLoader.Result;
 import com.android.contacts.activities.PhotoSelectionActivity;
-import com.android.contacts.model.EntityDeltaList;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.RawContactDeltaList;
 import com.android.contacts.util.ImageViewDrawableSetter;
 
 /**
@@ -36,7 +36,7 @@
  * photo.
  */
 public class ContactDetailPhotoSetter extends ImageViewDrawableSetter {
-    public OnClickListener setupContactPhotoForClick(Context context, Result contactData,
+    public OnClickListener setupContactPhotoForClick(Context context, Contact contactData,
             ImageView photoView, boolean expandPhotoOnClick) {
         setTarget(photoView);
         Bitmap bitmap = setCompressedImage(contactData.getPhotoBinaryData());
@@ -46,12 +46,12 @@
     private static final class PhotoClickListener implements OnClickListener {
 
         private final Context mContext;
-        private final Result mContactData;
+        private final Contact mContactData;
         private final Bitmap mPhotoBitmap;
         private final byte[] mPhotoBytes;
         private final boolean mExpandPhotoOnClick;
 
-        public PhotoClickListener(Context context, Result contactData, Bitmap photoBitmap,
+        public PhotoClickListener(Context context, Contact contactData, Bitmap photoBitmap,
                 byte[] photoBytes, boolean expandPhotoOnClick) {
             mContext = context;
             mContactData = contactData;
@@ -63,7 +63,7 @@
         @Override
         public void onClick(View v) {
             // Assemble the intent.
-            EntityDeltaList delta = mContactData.createEntityDeltaList();
+            RawContactDeltaList delta = mContactData.createRawContactDeltaList();
 
             // Find location and bounds of target view, adjusting based on the
             // assumed local density.
@@ -96,7 +96,7 @@
         }
     }
 
-    private OnClickListener setupClickListener(Context context, Result contactData, Bitmap bitmap,
+    private OnClickListener setupClickListener(Context context, Contact contactData, Bitmap bitmap,
             boolean expandPhotoOnClick) {
         final ImageView target = getTarget();
         if (target == null) return null;
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
index 3929281..540f001 100644
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
@@ -16,16 +16,10 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.R;
-import com.android.contacts.ContactLoader;
-import com.android.contacts.detail.ContactDetailPhotoSetter;
-import com.android.contacts.util.MoreMath;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.android.contacts.util.SchedulingUtils;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.TypedValue;
 import android.view.MotionEvent;
 import android.view.View;
@@ -35,7 +29,10 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import android.util.Log;
+import com.android.contacts.R;
+import com.android.contacts.model.Contact;
+import com.android.contacts.util.MoreMath;
+import com.android.contacts.util.SchedulingUtils;
 
 /**
  * This is a horizontally scrolling carousel with 2 tabs: one to see info about the contact and
@@ -467,7 +464,7 @@
      * Loads the data from the Loader-Result. This is the only function that has to be called
      * from the outside to fully setup the View
      */
-    public void loadData(ContactLoader.Result contactData) {
+    public void loadData(Contact contactData) {
         if (contactData == null) return;
 
         // TODO: Move this into the {@link CarouselTab} class when the updates
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
index e8ce622..88c30c2 100644
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
@@ -16,14 +16,6 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.ContactLoader;
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.detail.ContactDetailDisplayUtils.StreamPhotoTag;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.util.StreamItemEntry;
-
 import android.app.ListFragment;
 import android.content.ContentUris;
 import android.content.Intent;
@@ -32,16 +24,23 @@
 import android.provider.ContactsContract.StreamItems;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.AbsListView.OnScrollListener;
 import android.widget.ListView;
 
+import com.android.contacts.R;
+import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
+import com.android.contacts.detail.ContactDetailDisplayUtils.StreamPhotoTag;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.util.StreamItemEntry;
+
 public class ContactDetailUpdatesFragment extends ListFragment implements FragmentKeyListener {
 
     private static final String TAG = "ContactDetailUpdatesFragment";
 
-    private ContactLoader.Result mContactData;
+    private Contact mContactData;
     private Uri mLookupUri;
 
     private LayoutInflater mInflater;
@@ -122,7 +121,7 @@
         }
     }
 
-    public void setData(Uri lookupUri, ContactLoader.Result result) {
+    public void setData(Uri lookupUri, Contact result) {
         if (result == null) {
             return;
         }
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
index c56f659..6a69744 100644
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ b/src/com/android/contacts/detail/ContactLoaderFragment.java
@@ -16,15 +16,6 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.ContactLoader;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.list.ShortcutIntentBuilder;
-import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.android.internal.util.Objects;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -48,6 +39,16 @@
 import android.view.ViewGroup;
 import android.widget.Toast;
 
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.R;
+import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
+import com.android.contacts.list.ShortcutIntentBuilder;
+import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.ContactLoader;
+import com.android.contacts.util.PhoneCapabilityTester;
+import com.android.internal.util.Objects;
+
 /**
  * This is an invisible worker {@link Fragment} that loads the contact details for the contact card.
  * The data is then passed to the listener, who can then pass the data to other {@link View}s.
@@ -84,7 +85,7 @@
         /**
          * Contact details have finished loading.
          */
-        public void onDetailsLoaded(ContactLoader.Result result);
+        public void onDetailsLoaded(Contact result);
 
         /**
          * User decided to go to Edit-Mode
@@ -107,7 +108,7 @@
     private Uri mLookupUri;
     private ContactLoaderFragmentListener mListener;
 
-    private ContactLoader.Result mContactData;
+    private Contact mContactData;
 
     public ContactLoaderFragment() {
     }
@@ -179,10 +180,10 @@
     /**
      * The listener for the detail loader
      */
-    private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDetailLoaderListener =
-            new LoaderCallbacks<ContactLoader.Result>() {
+    private final LoaderManager.LoaderCallbacks<Contact> mDetailLoaderListener =
+            new LoaderCallbacks<Contact>() {
         @Override
-        public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
+        public Loader<Contact> onCreateLoader(int id, Bundle args) {
             Uri lookupUri = args.getParcelable(LOADER_ARG_CONTACT_URI);
             return new ContactLoader(mContext, lookupUri, true /* loadGroupMetaData */,
                     true /* loadStreamItems */, true /* load invitable account types */,
@@ -190,7 +191,7 @@
         }
 
         @Override
-        public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
+        public void onLoadFinished(Loader<Contact> loader, Contact data) {
             if (!mLookupUri.equals(data.getRequestedUri())) {
                 Log.e(TAG, "Different URI: requested=" + mLookupUri + "  actual=" + data);
                 return;
@@ -219,7 +220,7 @@
         }
 
         @Override
-        public void onLoaderReset(Loader<ContactLoader.Result> loader) {}
+        public void onLoaderReset(Loader<Contact> loader) {}
     };
 
     @Override
@@ -461,14 +462,14 @@
 
     /** Toggles whether to load stream items. Just for debugging */
     public void toggleLoadStreamItems() {
-        Loader<ContactLoader.Result> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS);
+        Loader<Contact> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS);
         ContactLoader loader = (ContactLoader) loaderObj;
         loader.setLoadStreamItems(!loader.getLoadStreamItems());
     }
 
     /** Returns whether to load stream items. Just for debugging */
     public boolean getLoadStreamItems() {
-        Loader<ContactLoader.Result> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS);
+        Loader<Contact> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS);
         ContactLoader loader = (ContactLoader) loaderObj;
         return loader != null && loader.getLoadStreamItems();
     }
diff --git a/src/com/android/contacts/detail/PhotoSelectionHandler.java b/src/com/android/contacts/detail/PhotoSelectionHandler.java
index 569012e..b5e406a 100644
--- a/src/com/android/contacts/detail/PhotoSelectionHandler.java
+++ b/src/com/android/contacts/detail/PhotoSelectionHandler.java
@@ -39,12 +39,12 @@
 
 import com.android.contacts.R;
 import com.android.contacts.editor.PhotoActionPopup;
-import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityModifier;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.RawContactDeltaList;
 import com.android.contacts.util.ContactPhotoUtils;
 
 import java.io.File;
@@ -64,12 +64,12 @@
     private final View mPhotoView;
     private final int mPhotoMode;
     private final int mPhotoPickSize;
-    private final EntityDeltaList mState;
+    private final RawContactDeltaList mState;
     private final boolean mIsDirectoryContact;
     private ListPopupWindow mPopup;
 
     public PhotoSelectionHandler(Context context, View photoView, int photoMode,
-            boolean isDirectoryContact, EntityDeltaList state) {
+            boolean isDirectoryContact, RawContactDeltaList state) {
         mContext = context;
         mPhotoView = photoView;
         mPhotoMode = photoMode;
@@ -162,12 +162,12 @@
      *     or null if the photo could not be parsed or none of the accounts associated with the
      *     contact are writable.
      */
-    public EntityDeltaList getDeltaForAttachingPhotoToContact() {
+    public RawContactDeltaList getDeltaForAttachingPhotoToContact() {
         // Find the first writable entity.
         int writableEntityIndex = getWritableEntityIndex();
         if (writableEntityIndex != -1) {
             // We are guaranteed to have contact data if we have a writable entity index.
-            final EntityDelta delta = mState.get(writableEntityIndex);
+            final RawContactDelta delta = mState.get(writableEntityIndex);
 
             // Need to find the right account so that EntityModifier knows which fields to add
             final ContentValues entityValues = delta.getValues().getCompleteValues();
@@ -176,10 +176,10 @@
             final AccountType accountType = AccountTypeManager.getInstance(mContext).getAccountType(
                         type, dataSet);
 
-            final ValuesDelta child = EntityModifier.ensureKindExists(
+            final ValuesDelta child = RawContactModifier.ensureKindExists(
                     delta, accountType, Photo.CONTENT_ITEM_TYPE);
             child.setFromTemplate(false);
-            child.put(Photo.IS_SUPER_PRIMARY, 1);
+            child.setSuperPrimary(true);
 
             return mState;
         }
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
index 089cb07..15219cd 100644
--- a/src/com/android/contacts/detail/StreamItemAdapter.java
+++ b/src/com/android/contacts/detail/StreamItemAdapter.java
@@ -16,18 +16,18 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.util.StreamItemEntry;
-import com.google.android.collect.Lists;
-
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.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/dialog/ClearFrequentsDialog.java b/src/com/android/contacts/dialog/ClearFrequentsDialog.java
index 4aeaf1c..800ba9d 100644
--- a/src/com/android/contacts/dialog/ClearFrequentsDialog.java
+++ b/src/com/android/contacts/dialog/ClearFrequentsDialog.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.dialog;
 
-import com.android.contacts.R;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -29,6 +27,8 @@
 import android.os.Bundle;
 import android.provider.ContactsContract;
 
+import com.android.contacts.R;
+
 /**
  * Dialog that clears the frequently contacted list after confirming with the user.
  */
diff --git a/src/com/android/contacts/editor/AggregationSuggestionEngine.java b/src/com/android/contacts/editor/AggregationSuggestionEngine.java
index c340f96..0da05e8 100644
--- a/src/com/android/contacts/editor/AggregationSuggestionEngine.java
+++ b/src/com/android/contacts/editor/AggregationSuggestionEngine.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.google.android.collect.Lists;
-
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -40,6 +37,9 @@
 import android.provider.ContactsContract.RawContacts;
 import android.text.TextUtils;
 
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
diff --git a/src/com/android/contacts/editor/AggregationSuggestionView.java b/src/com/android/contacts/editor/AggregationSuggestionView.java
index 9d7e16a..7327a4c 100644
--- a/src/com/android/contacts/editor/AggregationSuggestionView.java
+++ b/src/com/android/contacts/editor/AggregationSuggestionView.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.R;
-import com.android.contacts.editor.AggregationSuggestionEngine.RawContact;
-import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.google.android.collect.Lists;
-
 import android.content.Context;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
@@ -32,6 +25,13 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.editor.AggregationSuggestionEngine.RawContact;
+import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/editor/BaseRawContactEditorView.java b/src/com/android/contacts/editor/BaseRawContactEditorView.java
index b2d7186..66fc864 100644
--- a/src/com/android/contacts/editor/BaseRawContactEditorView.java
+++ b/src/com/android/contacts/editor/BaseRawContactEditorView.java
@@ -16,15 +16,7 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityModifier;
-
 import android.content.Context;
-import android.content.Entity;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
@@ -35,14 +27,21 @@
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
+import com.android.contacts.R;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountType.EditType;
+
 /**
  * Base view that provides common code for the editor interaction for a specific
- * RawContact represented through an {@link EntityDelta}.
+ * RawContact represented through an {@link RawContactDelta}.
  * <p>
  * Internal updates are performed against {@link ValuesDelta} so that the
- * source {@link Entity} can be swapped out. Any state-based changes, such as
+ * source {@link RawContact} can be swapped out. Any state-based changes, such as
  * adding {@link Data} rows or changing {@link EditType}, are performed through
- * {@link EntityModifier} to ensure that {@link AccountType} are enforced.
+ * {@link RawContactModifier} to ensure that {@link AccountType} are enforced.
  */
 public abstract class BaseRawContactEditorView extends LinearLayout {
 
@@ -78,7 +77,7 @@
 
     /**
      * Assign the given {@link Bitmap} to the internal {@link PhotoEditorView}
-     * for the {@link EntityDelta} currently being edited.
+     * for the {@link RawContactDelta} currently being edited.
      */
     public void setPhotoBitmap(Bitmap bitmap) {
         mPhoto.setPhotoBitmap(bitmap);
@@ -115,10 +114,10 @@
 
     /**
      * Set the internal state for this view, given a current
-     * {@link EntityDelta} state and the {@link AccountType} that
+     * {@link RawContactDelta} state and the {@link AccountType} that
      * apply to that state.
      */
-    public abstract void setState(EntityDelta state, AccountType source, ViewIdGenerator vig,
+    public abstract void setState(RawContactDelta state, AccountType source, ViewIdGenerator vig,
             boolean isProfile);
 
     /* package */ void setExpanded(boolean value) {
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index a4e4db4..780279e 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -16,29 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.ContactLoader;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.GroupMetaDataLoader;
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
-import com.android.contacts.activities.ContactEditorActivity;
-import com.android.contacts.activities.JoinContactActivity;
-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.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.GoogleAccountType;
-import com.android.contacts.util.AccountsListAdapter;
-import com.android.contacts.util.ContactPhotoUtils;
-import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
-import com.android.contacts.util.HelpUtils;
-
 import android.accounts.Account;
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -52,7 +29,6 @@
 import android.content.Context;
 import android.content.CursorLoader;
 import android.content.DialogInterface;
-import android.content.Entity;
 import android.content.Intent;
 import android.content.Loader;
 import android.database.Cursor;
@@ -85,6 +61,32 @@
 import android.widget.ListPopupWindow;
 import android.widget.Toast;
 
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
+import com.android.contacts.activities.ContactEditorActivity;
+import com.android.contacts.activities.JoinContactActivity;
+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.AccountTypeManager;
+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.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.account.GoogleAccountType;
+import com.android.contacts.util.AccountsListAdapter;
+import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
+import com.android.contacts.util.ContactPhotoUtils;
+import com.android.contacts.util.HelpUtils;
+import com.google.common.collect.ImmutableList;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -224,7 +226,7 @@
     private ContactEditorUtils mEditorUtils;
 
     private LinearLayout mContent;
-    private EntityDeltaList mState;
+    private RawContactDeltaList mState;
 
     private ViewIdGenerator mViewIdGenerator;
 
@@ -420,7 +422,7 @@
             mViewIdGenerator = new ViewIdGenerator();
         } else {
             // Read state from savedState. No loading involved here
-            mState = savedState.<EntityDeltaList> getParcelable(KEY_EDIT_STATE);
+            mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE);
             mRawContactIdRequestingPhoto = savedState.getLong(
                     KEY_RAW_CONTACT_ID_REQUESTING_PHOTO);
             mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR);
@@ -436,7 +438,7 @@
         }
     }
 
-    public void setData(ContactLoader.Result data) {
+    public void setData(Contact data) {
         // If we have already loaded data, we do not want to change it here to not confuse the user
         if (mState != null) {
             Log.v(TAG, "Ignoring background change. This will have to be rebased later");
@@ -444,19 +446,17 @@
         }
 
         // See if this edit operation needs to be redirected to a custom editor
-        ArrayList<Entity> entities = data.getEntities();
-        if (entities.size() == 1) {
-            Entity entity = entities.get(0);
-            ContentValues entityValues = entity.getEntityValues();
-            String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
-            String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
-            AccountType accountType = AccountTypeManager.getInstance(mContext).getAccountType(
-                    type, dataSet);
+        ImmutableList<RawContact> rawContacts = data.getRawContacts();
+        if (rawContacts.size() == 1) {
+            RawContact rawContact = rawContacts.get(0);
+            String type = rawContact.getAccountTypeString();
+            String dataSet = rawContact.getDataSet();
+            AccountType accountType = rawContact.getAccountType();
             if (accountType.getEditContactActivityClassName() != null &&
                     !accountType.areContactsWritable()) {
                 if (mListener != null) {
-                    String name = entityValues.getAsString(RawContacts.ACCOUNT_NAME);
-                    long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID);
+                    String name = rawContact.getAccountName();
+                    long rawContactId = rawContact.getId();
                     mListener.onCustomEditContactActivityRequested(
                             new AccountWithDataSet(name, type, dataSet),
                             ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
@@ -474,10 +474,10 @@
         mListener.onCustomEditContactActivityRequested(account, uri, null, false);
     }
 
-    private void bindEditorsForExistingContact(ContactLoader.Result contact) {
+    private void bindEditorsForExistingContact(Contact contact) {
         setEnabled(true);
 
-        mState = contact.createEntityDeltaList();
+        mState = contact.createRawContactDeltaList();
         setIntentExtras(mIntentExtras);
         mIntentExtras = null;
 
@@ -486,7 +486,7 @@
         boolean localProfileExists = false;
 
         if (mIsUserProfile) {
-            for (EntityDelta state : mState) {
+            for (RawContactDelta state : mState) {
                 // For profile contacts, we need a different query URI
                 state.setProfileQueryUri();
                 // Try to find a local profile contact
@@ -496,11 +496,11 @@
             }
             // Editor should always present a local profile for editing
             if (!localProfileExists) {
-                final ContentValues values = new ContentValues();
-                values.putNull(RawContacts.ACCOUNT_NAME);
-                values.putNull(RawContacts.ACCOUNT_TYPE);
-                values.putNull(RawContacts.DATA_SET);
-                EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values));
+                final RawContact rawContact = new RawContact(mContext);
+                rawContact.setAccountToLocal();
+
+                RawContactDelta insert = new RawContactDelta(ValuesDelta.fromAfter(
+                        rawContact.getValues()));
                 insert.setProfileQueryUri();
                 mState.add(insert);
             }
@@ -519,13 +519,11 @@
         }
 
         final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-        for (EntityDelta state : mState) {
-            final String accountType = state.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = state.getValues().getAsString(RawContacts.DATA_SET);
-            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
+        for (RawContactDelta state : mState) {
+            final AccountType type = state.getAccountType(accountTypes);
             if (type.areContactsWritable()) {
                 // Apply extras to the first writable raw contact only
-                EntityModifier.parseExtras(mContext, type, state, extras);
+                RawContactModifier.parseExtras(mContext, type, state, extras);
                 break;
             }
         }
@@ -604,7 +602,8 @@
      * @param newAccount New account to be used.
      */
     private void rebindEditorsForNewContact(
-            EntityDelta oldState, AccountWithDataSet oldAccount, AccountWithDataSet newAccount) {
+            RawContactDelta oldState, AccountWithDataSet oldAccount,
+            AccountWithDataSet newAccount) {
         AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
         AccountType oldAccountType = accountTypes.getAccountType(
                 oldAccount.type, oldAccount.dataSet);
@@ -628,36 +627,34 @@
     }
 
     private void bindEditorsForNewContact(AccountWithDataSet newAccount,
-            final AccountType newAccountType, EntityDelta oldState, AccountType oldAccountType) {
+            final AccountType newAccountType, RawContactDelta oldState,
+            AccountType oldAccountType) {
         mStatus = Status.EDITING;
 
-        final ContentValues values = new ContentValues();
+        final RawContact rawContact = new RawContact(mContext);
         if (newAccount != null) {
-            values.put(RawContacts.ACCOUNT_NAME, newAccount.name);
-            values.put(RawContacts.ACCOUNT_TYPE, newAccount.type);
-            values.put(RawContacts.DATA_SET, newAccount.dataSet);
+            rawContact.setAccount(newAccount);
         } else {
-            values.putNull(RawContacts.ACCOUNT_NAME);
-            values.putNull(RawContacts.ACCOUNT_TYPE);
-            values.putNull(RawContacts.DATA_SET);
+            rawContact.setAccountToLocal();
         }
 
-        EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values));
+        RawContactDelta insert = new RawContactDelta(ValuesDelta.fromAfter(rawContact.getValues()));
         if (oldState == null) {
             // Parse any values from incoming intent
-            EntityModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras);
+            RawContactModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras);
         } else {
-            EntityModifier.migrateStateForNewContact(mContext, oldState, insert,
+            RawContactModifier.migrateStateForNewContact(mContext, oldState, insert,
                     oldAccountType, newAccountType);
         }
 
         // Ensure we have some default fields (if the account type does not support a field,
         // ensureKind will not add it, so it is safe to add e.g. Event)
-        EntityModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE);
-        EntityModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE);
-        EntityModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE);
-        EntityModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE);
-        EntityModifier.ensureKindExists(insert, newAccountType, StructuredPostal.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(insert, newAccountType,
+                StructuredPostal.CONTENT_ITEM_TYPE);
 
         // Set the correct URI for saving the contact as a profile
         if (mNewLocalProfile) {
@@ -666,7 +663,7 @@
 
         if (mState == null) {
             // Create state if none exists yet
-            mState = EntityDeltaList.fromSingle(insert);
+            mState = RawContactDeltaList.fromSingle(insert);
         } else {
             // Add contact onto end of existing state
             mState.add(insert);
@@ -690,14 +687,11 @@
         int numRawContacts = mState.size();
         for (int i = 0; i < numRawContacts; i++) {
             // TODO ensure proper ordering of entities in the list
-            final EntityDelta entity = mState.get(i);
-            final ValuesDelta values = entity.getValues();
-            if (!values.isVisible()) continue;
+            final RawContactDelta rawContactDelta = mState.get(i);
+            if (!rawContactDelta.isVisible()) continue;
 
-            final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = values.getAsString(RawContacts.DATA_SET);
-            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
-            final long rawContactId = values.getAsLong(RawContacts._ID);
+            final AccountType type = rawContactDelta.getAccountType(accountTypes);
+            final long rawContactId = rawContactDelta.getRawContactId();
 
             final BaseRawContactEditorView editor;
             if (!type.areContactsWritable()) {
@@ -724,7 +718,7 @@
 
             mContent.addView(editor);
 
-            editor.setState(entity, type, mViewIdGenerator, isEditingUserProfile());
+            editor.setState(rawContactDelta, type, mViewIdGenerator, isEditingUserProfile());
 
             // Set up the photo handler.
             bindPhotoHandler(editor, type, mState);
@@ -797,7 +791,7 @@
     }
 
     private void bindPhotoHandler(BaseRawContactEditorView editor, AccountType type,
-            EntityDeltaList state) {
+            RawContactDeltaList state) {
         final int mode;
         if (type.areContactsWritable()) {
             if (editor.hasSetPhoto()) {
@@ -852,11 +846,10 @@
         // Find the associated account for this contact (retrieve it here because there are
         // multiple paths to creating a contact and this ensures we always have the correct
         // account).
-        final EntityDelta entity = mState.get(0);
-        final ValuesDelta values = entity.getValues();
-        String name = values.getAsString(RawContacts.ACCOUNT_NAME);
-        String type = values.getAsString(RawContacts.ACCOUNT_TYPE);
-        String dataSet = values.getAsString(RawContacts.DATA_SET);
+        final RawContactDelta rawContactDelta = mState.get(0);
+        String name = rawContactDelta.getAccountName();
+        String type = rawContactDelta.getAccountType();
+        String dataSet = rawContactDelta.getDataSet();
 
         AccountWithDataSet account = (name == null || type == null) ? null :
                 new AccountWithDataSet(name, type, dataSet);
@@ -864,12 +857,11 @@
     }
 
     private void addAccountSwitcher(
-            final EntityDelta currentState, BaseRawContactEditorView editor) {
-        ValuesDelta values = currentState.getValues();
+            final RawContactDelta currentState, BaseRawContactEditorView editor) {
         final AccountWithDataSet currentAccount = new AccountWithDataSet(
-                values.getAsString(RawContacts.ACCOUNT_NAME),
-                values.getAsString(RawContacts.ACCOUNT_TYPE),
-                values.getAsString(RawContacts.DATA_SET));
+                currentState.getAccountName(),
+                currentState.getAccountType(),
+                currentState.getDataSet());
         final View accountView = editor.findViewById(R.id.account);
         final View anchorView = editor.findViewById(R.id.account_container);
         accountView.setOnClickListener(new View.OnClickListener() {
@@ -1005,7 +997,7 @@
      */
     private boolean hasPendingChanges() {
         final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-        return EntityModifier.hasChanges(mState, accountTypes);
+        return RawContactModifier.hasChanges(mState, accountTypes);
     }
 
     /**
@@ -1209,10 +1201,8 @@
         final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
         int size = mState.size();
         for (int i = 0; i < size; i++) {
-            ValuesDelta values = mState.get(i).getValues();
-            final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = values.getAsString(RawContacts.DATA_SET);
-            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
+            RawContactDelta entity = mState.get(i);
+            final AccountType type = entity.getAccountType(accountTypes);
             if (type.areContactsWritable()) {
                 return true;
             }
@@ -1273,12 +1263,12 @@
                 Bundle intentExtras, boolean redirect);
     }
 
-    private class EntityDeltaComparator implements Comparator<EntityDelta> {
+    private class EntityDeltaComparator implements Comparator<RawContactDelta> {
         /**
          * Compare EntityDeltas for sorting the stack of editors.
          */
         @Override
-        public int compare(EntityDelta one, EntityDelta two) {
+        public int compare(RawContactDelta one, RawContactDelta two) {
             // Check direct equality
             if (one.equals(two)) {
                 return 0;
@@ -1333,11 +1323,9 @@
             }
 
             // Check account name
-            ValuesDelta oneValues = one.getValues();
-            String oneAccount = oneValues.getAsString(RawContacts.ACCOUNT_NAME);
+            String oneAccount = one.getAccountName();
             if (oneAccount == null) oneAccount = "";
-            ValuesDelta twoValues = two.getValues();
-            String twoAccount = twoValues.getAsString(RawContacts.ACCOUNT_NAME);
+            String twoAccount = two.getAccountName();
             if (twoAccount == null) twoAccount = "";
             value = oneAccount.compareTo(twoAccount);
             if (value != 0) {
@@ -1345,8 +1333,8 @@
             }
 
             // Both are in the same account, fall back to contact ID
-            Long oneId = oneValues.getAsLong(RawContacts._ID);
-            Long twoId = twoValues.getAsLong(RawContacts._ID);
+            Long oneId = one.getRawContactId();
+            Long twoId = two.getRawContactId();
             if (oneId == null) {
                 return -1;
             } else if (twoId == null) {
@@ -1362,7 +1350,7 @@
      */
     protected long getContactId() {
         if (mState != null) {
-            for (EntityDelta rawContact : mState) {
+            for (RawContactDelta rawContact : mState) {
                 Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID);
                 if (contactId != null) {
                     return contactId;
@@ -1662,14 +1650,13 @@
         int countWithPicture = 0;
         final int numEntities = mState.size();
         for (int i = 0; i < numEntities; i++) {
-            final EntityDelta entity = mState.get(i);
-            final ValuesDelta values = entity.getValues();
-            if (values.isVisible()) {
+            final RawContactDelta entity = mState.get(i);
+            if (entity.isVisible()) {
                 final ValuesDelta primary = entity.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE);
-                if (primary != null && primary.getAsByteArray(Photo.PHOTO) != null) {
+                if (primary != null && primary.getPhoto() != null) {
                     countWithPicture++;
                 } else {
-                    final long rawContactId = values.getAsLong(RawContacts._ID);
+                    final long rawContactId = entity.getRawContactId();
                     final String path = mUpdatedPhotos.getString(String.valueOf(rawContactId));
                     if (path != null) {
                         final File file = new File(path);
@@ -1690,16 +1677,16 @@
     /**
      * The listener for the data loader
      */
-    private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDataLoaderListener =
-            new LoaderCallbacks<ContactLoader.Result>() {
+    private final LoaderManager.LoaderCallbacks<Contact> mDataLoaderListener =
+            new LoaderCallbacks<Contact>() {
         @Override
-        public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
+        public Loader<Contact> onCreateLoader(int id, Bundle args) {
             mLoaderStartTime = SystemClock.elapsedRealtime();
             return new ContactLoader(mContext, mLookupUri, true);
         }
 
         @Override
-        public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
+        public void onLoadFinished(Loader<Contact> loader, Contact data) {
             final long loaderCurrentTime = SystemClock.elapsedRealtime();
             Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
             if (!data.isLoaded()) {
@@ -1719,7 +1706,7 @@
         }
 
         @Override
-        public void onLoaderReset(Loader<ContactLoader.Result> loader) {
+        public void onLoaderReset(Loader<Contact> loader) {
         }
     };
 
@@ -1772,7 +1759,7 @@
         private final PhotoActionListener mPhotoEditorListener;
 
         public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode,
-                EntityDeltaList state) {
+                RawContactDeltaList state) {
             super(context, editor.getPhotoEditor(), photoMode, false, state);
             mEditor = editor;
             mRawContactId = editor.getRawContactId();
diff --git a/src/com/android/contacts/editor/ContactEditorUtils.java b/src/com/android/contacts/editor/ContactEditorUtils.java
index 46006a0..2791c2d 100644
--- a/src/com/android/contacts/editor/ContactEditorUtils.java
+++ b/src/com/android/contacts/editor/ContactEditorUtils.java
@@ -16,14 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.test.NeededForTesting;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Sets;
-
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.app.Activity;
@@ -34,6 +26,14 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.test.NeededForTesting;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
diff --git a/src/com/android/contacts/editor/Editor.java b/src/com/android/contacts/editor/Editor.java
index 1151afd..05336f2 100644
--- a/src/com/android/contacts/editor/Editor.java
+++ b/src/com/android/contacts/editor/Editor.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-
 import android.provider.ContactsContract.Data;
 
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.dataitem.DataKind;
+
 /**
  * Generic definition of something that edits a {@link Data} row through an
  * {@link ValuesDelta} object.
@@ -60,7 +60,7 @@
      * builds any needed views. Any changes performed by the user will be
      * written back to that same object.
      */
-    public void setValues(DataKind kind, ValuesDelta values, EntityDelta state, boolean readOnly,
+    public void setValues(DataKind kind, ValuesDelta values, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig);
 
     public void setDeletable(boolean deletable);
diff --git a/src/com/android/contacts/editor/EditorAnimator.java b/src/com/android/contacts/editor/EditorAnimator.java
index a16b425..5196f3f 100644
--- a/src/com/android/contacts/editor/EditorAnimator.java
+++ b/src/com/android/contacts/editor/EditorAnimator.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.util.SchedulingUtils;
-
-import com.google.common.collect.Lists;
-
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
@@ -30,6 +26,9 @@
 import android.view.ViewParent;
 import android.widget.LinearLayout;
 
+import com.android.contacts.util.SchedulingUtils;
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index 538d4dc..ca1bf64 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -16,17 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.R;
-import com.android.contacts.datepicker.DatePicker;
-import com.android.contacts.datepicker.DatePickerDialog;
-import com.android.contacts.datepicker.DatePickerDialog.OnDateSetListener;
-import com.android.contacts.model.AccountType.EditField;
-import com.android.contacts.model.AccountType.EventEditType;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.util.DateUtils;
-
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Resources;
@@ -36,6 +25,17 @@
 import android.view.View;
 import android.widget.Button;
 
+import com.android.contacts.R;
+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.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.account.AccountType.EditField;
+import com.android.contacts.model.account.AccountType.EventEditType;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.DateUtils;
+
 import java.text.ParsePosition;
 import java.util.Calendar;
 import java.util.Date;
@@ -108,7 +108,7 @@
     }
 
     @Override
-    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
+    public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig) {
         if (kind.fieldList.size() != 1) throw new IllegalStateException("kind must have 1 field");
         super.setValues(kind, entry, state, readOnly, vig);
diff --git a/src/com/android/contacts/editor/GroupMembershipView.java b/src/com/android/contacts/editor/GroupMembershipView.java
index a8e8d03..b84e22b 100644
--- a/src/com/android/contacts/editor/GroupMembershipView.java
+++ b/src/com/android/contacts/editor/GroupMembershipView.java
@@ -16,22 +16,11 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.GroupMetaDataLoader;
-import com.android.contacts.R;
-import com.android.contacts.interactions.GroupCreationDialogFragment;
-import com.android.contacts.interactions.GroupCreationDialogFragment.OnGroupCreatedListener;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.internal.util.Objects;
-
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.RawContacts;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
@@ -46,6 +35,16 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.interactions.GroupCreationDialogFragment;
+import com.android.contacts.interactions.GroupCreationDialogFragment.OnGroupCreatedListener;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.internal.util.Objects;
+
 import java.util.ArrayList;
 
 /**
@@ -127,7 +126,7 @@
         }
     }
 
-    private EntityDelta mState;
+    private RawContactDelta mState;
     private Cursor mGroupMetaData;
     private String mAccountName;
     private String mAccountType;
@@ -197,12 +196,11 @@
         }
     }
 
-    public void setState(EntityDelta state) {
+    public void setState(RawContactDelta state) {
         mState = state;
-        ValuesDelta values = state.getValues();
-        mAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-        mAccountName = values.getAsString(RawContacts.ACCOUNT_NAME);
-        mDataSet = values.getAsString(RawContacts.DATA_SET);
+        mAccountType = mState.getAccountType();
+        mAccountName = mState.getAccountName();
+        mDataSet = mState.getDataSet();
         mDefaultGroupVisibilityKnown = false;
         mCreatedNewGroup = false;
         updateView();
@@ -357,7 +355,7 @@
         if (entries != null) {
             for (ValuesDelta entry : entries) {
                 if (!entry.isDelete()) {
-                    Long groupId = entry.getAsLong(GroupMembership.GROUP_ROW_ID);
+                    Long groupId = entry.getGroupRowId();
                     if (groupId != null && groupId != mFavoritesGroupId
                             && (groupId != mDefaultGroupId || mDefaultGroupVisible)
                             && !isGroupChecked(groupId)) {
@@ -372,8 +370,8 @@
             GroupSelectionItem item = mAdapter.getItem(i);
             long groupId = item.getGroupId();
             if (item.isChecked() && !hasMembership(groupId)) {
-                ValuesDelta entry = EntityModifier.insertChild(mState, mKind);
-                entry.put(GroupMembership.GROUP_ROW_ID, groupId);
+                ValuesDelta entry = RawContactModifier.insertChild(mState, mKind);
+                entry.setGroupRowId(groupId);
             }
         }
 
@@ -400,7 +398,7 @@
         if (entries != null) {
             for (ValuesDelta values : entries) {
                 if (!values.isDelete()) {
-                    Long id = values.getAsLong(GroupMembership.GROUP_ROW_ID);
+                    Long id = values.getGroupRowId();
                     if (id != null && id == groupId) {
                         return true;
                     }
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index b474956..2d4263b 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.R;
-import com.android.contacts.editor.Editor.EditorListener;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityModifier;
-
 import android.content.Context;
 import android.provider.ContactsContract.Data;
 import android.text.TextUtils;
@@ -33,6 +26,13 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+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.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.dataitem.DataKind;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -50,7 +50,7 @@
     private String mTitleString;
 
     private DataKind mKind;
-    private EntityDelta mState;
+    private RawContactDelta mState;
     private boolean mReadOnly;
 
     private ViewIdGenerator mViewIdGenerator;
@@ -136,7 +136,7 @@
         }
     }
 
-    public void setState(DataKind kind, EntityDelta state, boolean readOnly, ViewIdGenerator vig) {
+    public void setState(DataKind kind, RawContactDelta state, boolean readOnly, ViewIdGenerator vig) {
         mKind = kind;
         mState = state;
         mReadOnly = readOnly;
@@ -237,7 +237,7 @@
             updateEmptyEditors();
             // If there are no existing empty editors and it's possible to add
             // another field, then make the "add footer" field visible.
-            if (!hasEmptyEditor() && EntityModifier.canInsert(mState, mKind)) {
+            if (!hasEmptyEditor() && RawContactModifier.canInsert(mState, mKind)) {
                 if (animate) {
                     EditorAnimator.getInstance().showAddFieldFooter(mAddFieldFooter);
                 } else {
@@ -364,7 +364,7 @@
 
         // Insert a new child, create its view and set its focus
         if (values == null) {
-            values = EntityModifier.insertChild(mState, mKind);
+            values = RawContactModifier.insertChild(mState, mKind);
         }
 
         final View newField = createEditorView(values);
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index 6f10fa2..789f425 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -16,28 +16,17 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.util.DialogManager;
-import com.android.contacts.util.DialogManager.DialogShowingView;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.content.Entity;
 import android.content.DialogInterface.OnShowListener;
 import android.os.Bundle;
 import android.os.Handler;
 import android.text.Editable;
 import android.text.TextUtils;
-import android.text.TextWatcher;
 import android.text.TextUtils.TruncateAt;
+import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -55,11 +44,21 @@
 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.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType.EditType;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.DialogManager;
+import com.android.contacts.util.DialogManager.DialogShowingView;
+
 import java.util.List;
 
 /**
  * Base class for editors that handles labels and values. Uses
- * {@link ValuesDelta} to read any existing {@link Entity} values, and to
+ * {@link ValuesDelta} to read any existing {@link RawContact} values, and to
  * correctly write any changes values.
  */
 public abstract class LabeledEditorView extends LinearLayout implements Editor, DialogShowingView {
@@ -76,7 +75,7 @@
 
     private DataKind mKind;
     private ValuesDelta mEntry;
-    private EntityDelta mState;
+    private RawContactDelta mState;
     private boolean mReadOnly;
     private boolean mWasEmpty = true;
     private boolean mIsDeletable = true;
@@ -342,7 +341,7 @@
      * structure and {@link ValuesDelta} describing the content to edit.
      */
     @Override
-    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
+    public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig) {
         mKind = kind;
         mEntry = entry;
@@ -359,11 +358,11 @@
         setVisibility(View.VISIBLE);
 
         // Display label selector if multiple types available
-        final boolean hasTypes = EntityModifier.hasEditTypes(kind);
+        final boolean hasTypes = RawContactModifier.hasEditTypes(kind);
         setupLabelButton(hasTypes);
         mLabel.setEnabled(!readOnly && isEnabled());
         if (hasTypes) {
-            mType = EntityModifier.getCurrentType(entry, kind);
+            mType = RawContactModifier.getCurrentType(entry, kind);
             rebuildLabel();
         }
     }
@@ -398,7 +397,7 @@
                 final String customText = editText.getText().toString().trim();
                 if (ContactsUtils.isGraphic(customText)) {
                     final List<EditType> allTypes =
-                            EntityModifier.getValidTypes(mState, mKind, null);
+                            RawContactModifier.getValidTypes(mState, mKind, null);
                     mType = null;
                     for (EditType editType : allTypes) {
                         if (editType.customColumn != null) {
@@ -534,7 +533,7 @@
                 }
             }
 
-            addAll(EntityModifier.getValidTypes(mState, mKind, mType));
+            addAll(RawContactModifier.getValidTypes(mState, mKind, mType));
         }
 
         public boolean hasCustomSelection() {
diff --git a/src/com/android/contacts/editor/PhoneticNameEditorView.java b/src/com/android/contacts/editor/PhoneticNameEditorView.java
index 5e47d89..8cbb921 100644
--- a/src/com/android/contacts/editor/PhoneticNameEditorView.java
+++ b/src/com/android/contacts/editor/PhoneticNameEditorView.java
@@ -16,16 +16,16 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-
-import android.content.ContentValues;
 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.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.model.dataitem.StructuredNameDataItem;
+
 /**
  * A dedicated editor for phonetic name. It is similar to {@link StructuredNameEditorView}.
  */
@@ -61,19 +61,16 @@
         }
 
         private void parsePhoneticName(String value) {
-            ContentValues values = PhoneticNameEditorView.parsePhoneticName(value, null);
-            mValues.put(StructuredName.PHONETIC_FAMILY_NAME,
-                    values.getAsString(StructuredName.PHONETIC_FAMILY_NAME));
-            mValues.put(StructuredName.PHONETIC_MIDDLE_NAME,
-                    values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME));
-            mValues.put(StructuredName.PHONETIC_GIVEN_NAME,
-                    values.getAsString(StructuredName.PHONETIC_GIVEN_NAME));
+            StructuredNameDataItem dataItem = PhoneticNameEditorView.parsePhoneticName(value, null);
+            mValues.setPhoneticFamilyName(dataItem.getPhoneticFamilyName());
+            mValues.setPhoneticMiddleName(dataItem.getPhoneticMiddleName());
+            mValues.setPhoneticGivenName(dataItem.getPhoneticGivenName());
         }
 
         private void buildPhoneticName() {
-            String family = mValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
-            String middle = mValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
-            String given = mValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
+            String family = mValues.getPhoneticFamilyName();
+            String middle = mValues.getPhoneticMiddleName();
+            String given = mValues.getPhoneticGivenName();
             mPhoneticName = PhoneticNameEditorView.buildPhoneticName(family, middle, given);
         }
 
@@ -100,7 +97,8 @@
      * created.
      * @return ContentValues with parsed data. Those data can be null.
      */
-    public static ContentValues parsePhoneticName(String phoneticName, ContentValues values) {
+    public static StructuredNameDataItem parsePhoneticName(String phoneticName,
+            StructuredNameDataItem item) {
         String family = null;
         String middle = null;
         String given = null;
@@ -123,13 +121,13 @@
             }
         }
 
-        if (values == null) {
-            values = new ContentValues();
+        if (item == null) {
+            item = new StructuredNameDataItem();
         }
-        values.put(StructuredName.PHONETIC_FAMILY_NAME, family);
-        values.put(StructuredName.PHONETIC_MIDDLE_NAME, middle);
-        values.put(StructuredName.PHONETIC_GIVEN_NAME, given);
-        return values;
+        item.setPhoneticFamilyName(family);
+        item.setPhoneticMiddleName(middle);
+        item.setPhoneticGivenName(given);
+        return item;
     }
 
     /**
@@ -172,7 +170,7 @@
     }
 
     @Override
-    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
+    public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig) {
         if (!(entry instanceof PhoneticValuesDelta)) {
             entry = new PhoneticValuesDelta(entry);
@@ -213,9 +211,9 @@
     public boolean hasData() {
         ValuesDelta entry = getEntry();
 
-        String family = entry.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
-        String middle = entry.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
-        String given = entry.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
+        String family = entry.getPhoneticFamilyName();
+        String middle = entry.getPhoneticMiddleName();
+        String given = entry.getPhoneticGivenName();
 
         return !TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
                 || !TextUtils.isEmpty(given);
diff --git a/src/com/android/contacts/editor/PhotoActionPopup.java b/src/com/android/contacts/editor/PhotoActionPopup.java
index a27dd8a..36a1340 100644
--- a/src/com/android/contacts/editor/PhotoActionPopup.java
+++ b/src/com/android/contacts/editor/PhotoActionPopup.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.view.View;
 import android.widget.AdapterView;
@@ -26,6 +24,8 @@
 import android.widget.ListAdapter;
 import android.widget.ListPopupWindow;
 
+import com.android.contacts.R;
+
 import java.util.ArrayList;
 
 /**
diff --git a/src/com/android/contacts/editor/PhotoEditorView.java b/src/com/android/contacts/editor/PhotoEditorView.java
index 955554c..30c3bb4 100644
--- a/src/com/android/contacts/editor/PhotoEditorView.java
+++ b/src/com/android/contacts/editor/PhotoEditorView.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.util.ContactPhotoUtils;
-
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -32,6 +25,13 @@
 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.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.ContactPhotoUtils;
+
 /**
  * Simple editor for {@link Photo}.
  */
@@ -92,7 +92,7 @@
 
     /** {@inheritDoc} */
     @Override
-    public void setValues(DataKind kind, ValuesDelta values, EntityDelta state, boolean readOnly,
+    public void setValues(DataKind kind, ValuesDelta values, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig) {
         mEntry = values;
         mReadOnly = readOnly;
@@ -143,7 +143,7 @@
         mEntry.setFromTemplate(false);
 
         // When the user chooses a new photo mark it as super primary
-        mEntry.put(Photo.IS_SUPER_PRIMARY, 1);
+        mEntry.setSuperPrimary(true);
 
         // Even though high-res photos cannot be saved by passing them via
         // an EntityDeltaList (since they cause the Bundle size limit to be
@@ -154,7 +154,7 @@
         final int size = ContactsUtils.getThumbnailSize(getContext());
         final Bitmap scaled = Bitmap.createScaledBitmap(photo, size, size, false);
         final byte[] compressed = ContactPhotoUtils.compressBitmap(scaled);
-        if (compressed != null) mEntry.put(Photo.PHOTO, compressed);
+        if (compressed != null) mEntry.setPhoto(compressed);
     }
 
     /**
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index cb5e838..daccdd8 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -16,18 +16,7 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.GroupMetaDataLoader;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.internal.util.Objects;
-
 import android.content.Context;
-import android.content.Entity;
 import android.database.Cursor;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
 import android.provider.ContactsContract.CommonDataKinds.Organization;
@@ -35,7 +24,6 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -48,18 +36,28 @@
 import android.widget.PopupMenu;
 import android.widget.TextView;
 
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountType.EditType;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.internal.util.Objects;
+
 import java.util.ArrayList;
 
 /**
  * Custom view that provides all the editor interaction for a specific
- * {@link Contacts} represented through an {@link EntityDelta}. Callers can
+ * {@link Contacts} represented through an {@link RawContactDelta}. Callers can
  * reuse this view and quickly rebuild its contents through
- * {@link #setState(EntityDelta, AccountType, ViewIdGenerator)}.
+ * {@link #setState(RawContactDelta, AccountType, ViewIdGenerator)}.
  * <p>
  * Internal updates are performed against {@link ValuesDelta} so that the
- * source {@link Entity} can be swapped out. Any state-based changes, such as
+ * source {@link RawContact} can be swapped out. Any state-based changes, such as
  * adding {@link Data} rows or changing {@link EditType}, are performed through
- * {@link EntityModifier} to ensure that {@link AccountType} are enforced.
+ * {@link RawContactModifier} to ensure that {@link AccountType} are enforced.
  */
 public class RawContactEditorView extends BaseRawContactEditorView {
     private LayoutInflater mInflater;
@@ -80,7 +78,7 @@
     private boolean mAutoAddToDefaultGroup = true;
     private Cursor mGroupMetaData;
     private DataKind mGroupMembershipKind;
-    private EntityDelta mState;
+    private RawContactDelta mState;
 
     private boolean mPhoneticNameAdded;
 
@@ -152,11 +150,11 @@
 
     /**
      * Set the internal state for this view, given a current
-     * {@link EntityDelta} state and the {@link AccountType} that
+     * {@link RawContactDelta} state and the {@link AccountType} that
      * apply to that state.
      */
     @Override
-    public void setState(EntityDelta state, AccountType type, ViewIdGenerator vig,
+    public void setState(RawContactDelta state, AccountType type, ViewIdGenerator vig,
             boolean isProfile) {
 
         mState = state;
@@ -170,15 +168,14 @@
         setId(vig.getId(state, null, null, ViewIdGenerator.NO_VIEW_INDEX));
 
         // Make sure we have a StructuredName and Organization
-        EntityModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE);
-        EntityModifier.ensureKindExists(state, type, Organization.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(state, type, Organization.CONTENT_ITEM_TYPE);
 
-        ValuesDelta values = state.getValues();
-        mRawContactId = values.getAsLong(RawContacts._ID);
+        mRawContactId = state.getRawContactId();
 
         // Fill in the account info
         if (isProfile) {
-            String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
+            String accountName = state.getAccountName();
             if (TextUtils.isEmpty(accountName)) {
                 mAccountNameTextView.setVisibility(View.GONE);
                 mAccountTypeTextView.setText(R.string.local_profile_title);
@@ -189,7 +186,7 @@
                 mAccountNameTextView.setText(accountName);
             }
         } else {
-            String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
+            String accountName = state.getAccountName();
             CharSequence accountType = type.getDisplayLabel(mContext);
             if (TextUtils.isEmpty(accountType)) {
                 accountType = mContext.getString(R.string.account_phone);
@@ -208,7 +205,7 @@
         mAccountIcon.setImageDrawable(type.getDisplayIcon(mContext));
 
         // Show photo editor when supported
-        EntityModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE);
         setHasPhotoEditor((type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null));
         getPhotoEditor().setEnabled(isEnabled());
         mName.setEnabled(isEnabled());
@@ -341,7 +338,7 @@
         ArrayList<ValuesDelta> entries = mState.getMimeEntries(GroupMembership.CONTENT_ITEM_TYPE);
         if (entries != null) {
             for (ValuesDelta values : entries) {
-                Long id = values.getAsLong(GroupMembership.GROUP_ROW_ID);
+                Long id = values.getGroupRowId();
                 if (id != null && id.longValue() != 0) {
                     hasGroupMembership = true;
                     break;
@@ -352,8 +349,8 @@
         if (!hasGroupMembership) {
             long defaultGroupId = getDefaultGroupId();
             if (defaultGroupId != -1) {
-                ValuesDelta entry = EntityModifier.insertChild(mState, mGroupMembershipKind);
-                entry.put(GroupMembership.GROUP_ROW_ID, defaultGroupId);
+                ValuesDelta entry = RawContactModifier.insertChild(mState, mGroupMembershipKind);
+                entry.setGroupRowId(defaultGroupId);
             }
         }
     }
@@ -363,9 +360,9 @@
      * account.  Returns -1 if there is no such group.
      */
     private long getDefaultGroupId() {
-        String accountType = mState.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
-        String accountName = mState.getValues().getAsString(RawContacts.ACCOUNT_NAME);
-        String accountDataSet = mState.getValues().getAsString(RawContacts.DATA_SET);
+        String accountType = mState.getAccountType();
+        String accountName = mState.getAccountName();
+        String accountDataSet = mState.getDataSet();
         mGroupMetaData.moveToPosition(-1);
         while (mGroupMetaData.moveToNext()) {
             String name = mGroupMetaData.getString(GroupMetaDataLoader.ACCOUNT_NAME);
diff --git a/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java b/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
index 58474ef..8e51d18 100644
--- a/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
+++ b/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
@@ -16,15 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityModifier;
-
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.res.Resources;
@@ -46,6 +37,15 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.dataitem.DataKind;
+
 import java.util.ArrayList;
 
 /**
@@ -108,11 +108,11 @@
 
     /**
      * Set the internal state for this view, given a current
-     * {@link EntityDelta} state and the {@link AccountType} that
+     * {@link RawContactDelta} state and the {@link AccountType} that
      * apply to that state.
      */
     @Override
-    public void setState(EntityDelta state, AccountType type, ViewIdGenerator vig,
+    public void setState(RawContactDelta state, AccountType type, ViewIdGenerator vig,
             boolean isProfile) {
         // Remove any existing sections
         mGeneral.removeAllViews();
@@ -121,13 +121,12 @@
         if (state == null || type == null) return;
 
         // Make sure we have StructuredName
-        EntityModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE);
 
         // Fill in the header info
-        ValuesDelta values = state.getValues();
-        mAccountName = values.getAsString(RawContacts.ACCOUNT_NAME);
-        mAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-        mDataSet = values.getAsString(RawContacts.DATA_SET);
+        mAccountName = state.getAccountName();
+        mAccountType = state.getAccountType();
+        mDataSet = state.getDataSet();
 
         if (isProfile) {
             if (TextUtils.isEmpty(mAccountName)) {
@@ -162,14 +161,14 @@
 
         mAccountIcon.setImageDrawable(type.getDisplayIcon(mContext));
 
-        mRawContactId = values.getAsLong(RawContacts._ID);
+        mRawContactId = state.getRawContactId();
 
         ValuesDelta primary;
 
         // Photo
         DataKind kind = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE);
         if (kind != null) {
-            EntityModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE);
+            RawContactModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE);
             boolean hasPhotoEditor = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null;
             setHasPhotoEditor(hasPhotoEditor);
             primary = state.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE);
@@ -203,13 +202,13 @@
             for (int i = 0; i < phones.size(); i++) {
                 ValuesDelta phone = phones.get(i);
                 final String phoneNumber = PhoneNumberUtils.formatNumber(
-                        phone.getAsString(Phone.NUMBER),
-                        phone.getAsString(Phone.NORMALIZED_NUMBER),
+                        phone.getPhoneNumber(),
+                        phone.getPhoneNormalizedNumber(),
                         ContactsUtils.getCurrentCountryIso(getContext()));
                 final CharSequence phoneType;
-                if (phone.containsKey(Phone.TYPE)) {
+                if (phone.phoneHasType()) {
                     phoneType = Phone.getTypeLabel(
-                            res, phone.getAsInteger(Phone.TYPE), phone.getAsString(Phone.LABEL));
+                            res, phone.getPhoneType(), phone.getPhoneLabel());
                 } else {
                     phoneType = null;
                 }
@@ -223,11 +222,11 @@
         if (emails != null) {
             for (int i = 0; i < emails.size(); i++) {
                 ValuesDelta email = emails.get(i);
-                final String emailAddress = email.getAsString(Email.DATA);
+                final String emailAddress = email.getEmailData();
                 final CharSequence emailType;
-                if (email.containsKey(Email.TYPE)) {
+                if (email.emailHasType()) {
                     emailType = Email.getTypeLabel(
-                            res, email.getAsInteger(Email.TYPE), email.getAsString(Email.LABEL));
+                            res, email.getEmailType(), email.getEmailLabel());
                 } else {
                     emailType = null;
                 }
diff --git a/src/com/android/contacts/editor/SelectAccountDialogFragment.java b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
index 42ac170..3e7ad0e 100644
--- a/src/com/android/contacts/editor/SelectAccountDialogFragment.java
+++ b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.util.AccountsListAdapter;
-import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -28,6 +24,10 @@
 import android.content.DialogInterface;
 import android.os.Bundle;
 
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.util.AccountsListAdapter;
+import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
+
 /**
  * Shows a dialog asking the user which account to chose.
  *
diff --git a/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java b/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
index 3259fd4..c790e0b 100644
--- a/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
+++ b/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.R;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -25,6 +23,8 @@
 import android.content.DialogInterface;
 import android.os.Bundle;
 
+import com.android.contacts.R;
+
 /**
  * Shows a dialog asking the user whether to split the contact. The result is passed back
  * to the Fragment that is configured by {@link Fragment#setTargetFragment(Fragment, int)}, which
diff --git a/src/com/android/contacts/editor/StructuredNameEditorView.java b/src/com/android/contacts/editor/StructuredNameEditorView.java
index af1b3cf..3c4476d 100644
--- a/src/com/android/contacts/editor/StructuredNameEditorView.java
+++ b/src/com/android/contacts/editor/StructuredNameEditorView.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.util.NameConverter;
-
 import android.content.ContentValues;
 import android.content.Context;
 import android.net.Uri;
@@ -30,6 +25,13 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.model.dataitem.StructuredNameDataItem;
+import com.android.contacts.util.NameConverter;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -45,7 +47,7 @@
  */
 public class StructuredNameEditorView extends TextFieldsEditorView {
 
-    private ContentValues mSnapshot;
+    private StructuredNameDataItem mSnapshot;
     private boolean mChanged;
 
     public StructuredNameEditorView(Context context) {
@@ -61,11 +63,12 @@
     }
 
     @Override
-    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
+    public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig) {
         super.setValues(kind, entry, state, readOnly, vig);
         if (mSnapshot == null) {
-            mSnapshot = new ContentValues(getValues().getCompleteValues());
+            mSnapshot = (StructuredNameDataItem) DataItem.createFrom(null,
+                    new ContentValues(getValues().getCompleteValues()));
             mChanged = entry.isInsert();
         } else {
             mChanged = false;
@@ -114,12 +117,12 @@
 
         if (!mChanged) {
             for (String field : NameConverter.STRUCTURED_NAME_FIELDS) {
-                values.put(field, mSnapshot.getAsString(field));
+                values.put(field, mSnapshot.getContentValues().getAsString(field));
             }
             return;
         }
 
-        String displayName = values.getAsString(StructuredName.DISPLAY_NAME);
+        String displayName = values.getDisplayName();
         Map<String, String> structuredNameMap = NameConverter.displayNameToStructuredName(
                 getContext(), displayName);
         if (!structuredNameMap.isEmpty()) {
@@ -129,17 +132,16 @@
             }
         }
 
-        mSnapshot.clear();
-        mSnapshot.putAll(values.getCompleteValues());
-        mSnapshot.put(StructuredName.DISPLAY_NAME, displayName);
+        mSnapshot.getContentValues().clear();
+        mSnapshot.getContentValues().putAll(values.getCompleteValues());
+        mSnapshot.setDisplayName(displayName);
     }
 
     private void switchFromStructuredNameToFullName() {
         ValuesDelta values = getValues();
 
         if (!mChanged) {
-            values.put(StructuredName.DISPLAY_NAME,
-                    mSnapshot.getAsString(StructuredName.DISPLAY_NAME));
+            values.setDisplayName(mSnapshot.getDisplayName());
             return;
         }
 
@@ -151,10 +153,10 @@
             values.put(StructuredName.DISPLAY_NAME, displayName);
         }
 
-        mSnapshot.clear();
-        mSnapshot.put(StructuredName.DISPLAY_NAME, values.getAsString(StructuredName.DISPLAY_NAME));
+        mSnapshot.getContentValues().clear();
+        mSnapshot.setDisplayName(values.getDisplayName());
         for (String field : structuredNameMap.keySet()) {
-            mSnapshot.put(field, structuredNameMap.get(field));
+            mSnapshot.getContentValues().put(field, structuredNameMap.get(field));
         }
     }
 
@@ -167,14 +169,14 @@
     }
 
     private void eraseFullName(ValuesDelta values) {
-        values.putNull(StructuredName.DISPLAY_NAME);
+        values.setDisplayName(null);
     }
 
     private void rebuildFullName(ValuesDelta values) {
         Map<String, String> structuredNameMap = valuesToStructuredNameMap(values);
         String displayName = NameConverter.structuredNameToDisplayName(getContext(),
                 structuredNameMap);
-        values.put(StructuredName.DISPLAY_NAME, displayName);
+        values.setDisplayName(displayName);
     }
 
     private void eraseStructuredName(ValuesDelta values) {
@@ -184,7 +186,7 @@
     }
 
     private void rebuildStructuredName(ValuesDelta values) {
-        String displayName = values.getAsString(StructuredName.DISPLAY_NAME);
+        String displayName = values.getDisplayName();
         Map<String, String> structuredNameMap = NameConverter.displayNameToStructuredName(
                 getContext(), displayName);
         for (String field : structuredNameMap.keySet()) {
@@ -202,7 +204,7 @@
     protected Parcelable onSaveInstanceState() {
         SavedState state = new SavedState(super.onSaveInstanceState());
         state.mChanged = mChanged;
-        state.mSnapshot = mSnapshot;
+        state.mSnapshot = mSnapshot.getContentValues();
         return state;
     }
 
@@ -212,7 +214,7 @@
         super.onRestoreInstanceState(ss.mSuperState);
 
         mChanged = ss.mChanged;
-        mSnapshot = ss.mSnapshot;
+        mSnapshot = (StructuredNameDataItem) DataItem.createFrom(null, ss.mSnapshot);
     }
 
     private static class SavedState implements Parcelable {
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index a1f67a8..8558b11 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -16,16 +16,7 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType.EditField;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.util.PhoneNumberFormatter;
-
 import android.content.Context;
-import android.content.Entity;
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -44,9 +35,17 @@
 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.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.account.AccountType.EditField;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.PhoneNumberFormatter;
+
 /**
  * Simple editor that handles labels and any {@link EditField} defined for the
- * entry. Uses {@link ValuesDelta} to read any existing {@link Entity} values,
+ * entry. Uses {@link ValuesDelta} to read any existing {@link RawContact} values,
  * and to correctly write any changes values.
  */
 public class TextFieldsEditorView extends LabeledEditorView {
@@ -171,7 +170,7 @@
     }
 
     @Override
-    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
+    public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig) {
         super.setValues(kind, entry, state, readOnly, vig);
         // Remove edit texts that we currently have
diff --git a/src/com/android/contacts/editor/ViewIdGenerator.java b/src/com/android/contacts/editor/ViewIdGenerator.java
index c3cd08b..55a42a7 100644
--- a/src/com/android/contacts/editor/ViewIdGenerator.java
+++ b/src/com/android/contacts/editor/ViewIdGenerator.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.dataitem.DataKind;
+
 /**
  * A class that provides unique view ids for {@link ContentEditorView}, {@link KindSectionView},
  * {@link LabeledEditorView} and {@link EditView} on {@link EditContactActivity}.
@@ -62,13 +62,13 @@
     /**
      * Returns an id for a view associated with specified contact field.
      *
-     * @param entity {@link EntityDelta} associated with the view
+     * @param entity {@link RawContactDelta} associated with the view
      * @param kind {@link DataKind} associated with the view, or null if none exists.
      * @param values {@link ValuesDelta} associated with the view, or null if none exists.
      * @param viewIndex index of the view in the parent {@link Editor}, if it's a leave view.
      *     Otherwise, pass {@link #NO_VIEW_INDEX}.
      */
-    public int getId(EntityDelta entity, DataKind kind, ValuesDelta values,
+    public int getId(RawContactDelta entity, DataKind kind, ValuesDelta values,
             int viewIndex) {
         final String k = getMapKey(entity, kind, values, viewIndex);
 
@@ -81,7 +81,7 @@
         return id;
     }
 
-    private static String getMapKey(EntityDelta entity, DataKind kind, ValuesDelta values,
+    private static String getMapKey(RawContactDelta entity, DataKind kind, ValuesDelta values,
             int viewIndex) {
         sWorkStringBuilder.setLength(0);
         if (entity != null) {
diff --git a/src/com/android/contacts/format/FormatUtils.java b/src/com/android/contacts/format/FormatUtils.java
index 82bf78d..dd25c8d 100644
--- a/src/com/android/contacts/format/FormatUtils.java
+++ b/src/com/android/contacts/format/FormatUtils.java
@@ -15,13 +15,13 @@
  */
 package com.android.contacts.format;
 
-import com.android.contacts.test.NeededForTesting;
-
 import android.database.CharArrayBuffer;
 import android.graphics.Typeface;
 import android.text.SpannableString;
 import android.text.style.StyleSpan;
 
+import com.android.contacts.test.NeededForTesting;
+
 import java.util.Arrays;
 
 /**
diff --git a/src/com/android/contacts/group/GroupBrowseListAdapter.java b/src/com/android/contacts/group/GroupBrowseListAdapter.java
index 8affab3..acea625 100644
--- a/src/com/android/contacts/group/GroupBrowseListAdapter.java
+++ b/src/com/android/contacts/group/GroupBrowseListAdapter.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.group;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.GroupListLoader;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.internal.util.Objects;
-
 import android.content.ContentUris;
 import android.content.Context;
 import android.database.Cursor;
@@ -34,6 +27,12 @@
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import com.android.contacts.GroupListLoader;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.internal.util.Objects;
+
 /**
  * Adapter to populate the list of groups.
  */
@@ -238,4 +237,4 @@
             return mUri;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java
index 79bdd09..625615f 100644
--- a/src/com/android/contacts/group/GroupBrowseListFragment.java
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -16,12 +16,6 @@
 
 package com.android.contacts.group;
 
-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.widget.AutoScrollListView;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -33,10 +27,8 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Parcelable;
 import android.provider.ContactsContract;
 import android.provider.Settings;
-import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -50,6 +42,12 @@
 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.widget.AutoScrollListView;
+
 /**
  * Fragment to display the list of groups.
  */
diff --git a/src/com/android/contacts/group/GroupDetailDisplayUtils.java b/src/com/android/contacts/group/GroupDetailDisplayUtils.java
index da5e0e9..d4e43a0 100644
--- a/src/com/android/contacts/group/GroupDetailDisplayUtils.java
+++ b/src/com/android/contacts/group/GroupDetailDisplayUtils.java
@@ -16,16 +16,16 @@
 
 package com.android.contacts.group;
 
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+
 public class GroupDetailDisplayUtils {
 
     private GroupDetailDisplayUtils() {
@@ -57,4 +57,4 @@
         }
         accountIcon.setImageDrawable(accountType.getDisplayIcon(context));
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java
index 9e19735..6294b40 100644
--- a/src/com/android/contacts/group/GroupDetailFragment.java
+++ b/src/com/android/contacts/group/GroupDetailFragment.java
@@ -16,17 +16,6 @@
 
 package com.android.contacts.group;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.GroupMemberLoader;
-import com.android.contacts.GroupMetaDataLoader;
-import com.android.contacts.R;
-import com.android.contacts.interactions.GroupDeletionDialogFragment;
-import com.android.contacts.list.ContactTileAdapter;
-import com.android.contacts.list.ContactTileAdapter.DisplayType;
-import com.android.contacts.list.ContactTileView;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -56,6 +45,17 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.GroupMemberLoader;
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.interactions.GroupDeletionDialogFragment;
+import com.android.contacts.list.ContactTileAdapter;
+import com.android.contacts.list.ContactTileAdapter.DisplayType;
+import com.android.contacts.list.ContactTileView;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+
 /**
  * Displays the details of a group and shows a list of actions possible for the group.
  */
diff --git a/src/com/android/contacts/group/GroupEditorFragment.java b/src/com/android/contacts/group/GroupEditorFragment.java
index 6940efb..762867c 100644
--- a/src/com/android/contacts/group/GroupEditorFragment.java
+++ b/src/com/android/contacts/group/GroupEditorFragment.java
@@ -16,22 +16,6 @@
 
 package com.android.contacts.group;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.GroupMemberLoader;
-import com.android.contacts.GroupMemberLoader.GroupEditorQuery;
-import com.android.contacts.GroupMetaDataLoader;
-import com.android.contacts.R;
-import com.android.contacts.activities.GroupEditorActivity;
-import com.android.contacts.editor.SelectAccountDialogFragment;
-import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
-import com.android.contacts.util.ViewUtil;
-import com.android.internal.util.Objects;
-
 import android.accounts.Account;
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -73,6 +57,22 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.GroupMemberLoader;
+import com.android.contacts.GroupMemberLoader.GroupEditorQuery;
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.activities.GroupEditorActivity;
+import com.android.contacts.editor.SelectAccountDialogFragment;
+import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
+import com.android.contacts.util.ViewUtil;
+import com.android.internal.util.Objects;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/group/SuggestedMemberListAdapter.java b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
index 30718de..067c052 100644
--- a/src/com/android/contacts/group/SuggestedMemberListAdapter.java
+++ b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
@@ -15,9 +15,6 @@
  */
 package com.android.contacts.group;
 
-import com.android.contacts.R;
-import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
-
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
@@ -39,6 +36,9 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
diff --git a/src/com/android/contacts/interactions/ContactDeletionInteraction.java b/src/com/android/contacts/interactions/ContactDeletionInteraction.java
index 4aa4030..ea6e6dc 100644
--- a/src/com/android/contacts/interactions/ContactDeletionInteraction.java
+++ b/src/com/android/contacts/interactions/ContactDeletionInteraction.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.interactions;
 
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.google.android.collect.Sets;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Fragment;
@@ -39,7 +32,13 @@
 import android.os.Bundle;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Contacts.Entity;
-import android.util.Log;
+
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Sets;
 
 import java.util.HashSet;
 
diff --git a/src/com/android/contacts/interactions/GroupCreationDialogFragment.java b/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
index 051dc13..5731bc1 100644
--- a/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
+++ b/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
@@ -15,16 +15,16 @@
  */
 package com.android.contacts.interactions;
 
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountWithDataSet;
-
 import android.app.Activity;
 import android.app.FragmentManager;
 import android.content.Intent;
 import android.os.Bundle;
 import android.widget.EditText;
 
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.R;
+import com.android.contacts.model.account.AccountWithDataSet;
+
 /**
  * A dialog for creating a new group.
  */
diff --git a/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java b/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java
index 09306f2..2df7fe2 100644
--- a/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java
+++ b/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java
@@ -15,9 +15,6 @@
  */
 package com.android.contacts.interactions;
 
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -25,6 +22,9 @@
 import android.content.DialogInterface;
 import android.os.Bundle;
 
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.R;
+
 /**
  * A dialog for deleting a group.
  */
diff --git a/src/com/android/contacts/interactions/GroupNameDialogFragment.java b/src/com/android/contacts/interactions/GroupNameDialogFragment.java
index 8798c59..b0ad9c9 100644
--- a/src/com/android/contacts/interactions/GroupNameDialogFragment.java
+++ b/src/com/android/contacts/interactions/GroupNameDialogFragment.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.interactions;
 
-import com.android.contacts.R;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -32,6 +30,8 @@
 import android.widget.Button;
 import android.widget.EditText;
 
+import com.android.contacts.R;
+
 /**
  * A common superclass for creating and renaming groups.
  */
diff --git a/src/com/android/contacts/interactions/ImportExportDialogFragment.java b/src/com/android/contacts/interactions/ImportExportDialogFragment.java
index 521d2f0..f63f84c 100644
--- a/src/com/android/contacts/interactions/ImportExportDialogFragment.java
+++ b/src/com/android/contacts/interactions/ImportExportDialogFragment.java
@@ -16,14 +16,6 @@
 
 package com.android.contacts.interactions;
 
-import com.android.contacts.R;
-import com.android.contacts.editor.SelectAccountDialogFragment;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.util.AccountSelectionUtil;
-import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
-import com.android.contacts.vcard.ExportVCardActivity;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -45,6 +37,14 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.contacts.R;
+import com.android.contacts.editor.SelectAccountDialogFragment;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.util.AccountSelectionUtil;
+import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
+import com.android.contacts.vcard.ExportVCardActivity;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/interactions/PhoneNumberInteraction.java b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
index 3c3c347..207ceea 100644
--- a/src/com/android/contacts/interactions/PhoneNumberInteraction.java
+++ b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
@@ -15,19 +15,6 @@
  */
 package com.android.contacts.interactions;
 
-import com.android.contacts.Collapser;
-import com.android.contacts.Collapser.Collapsible;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.activities.DialtactsActivity;
-import com.android.contacts.activities.TransactionSafeActivity;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.StringInflater;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.DataKind;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -59,6 +46,19 @@
 import android.widget.ListAdapter;
 import android.widget.TextView;
 
+import com.android.contacts.Collapser;
+import com.android.contacts.Collapser.Collapsible;
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.activities.DialtactsActivity;
+import com.android.contacts.activities.TransactionSafeActivity;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountType.StringInflater;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.model.AccountTypeManager;
+import com.google.common.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/interactions/TestLoaderManager.java b/src/com/android/contacts/interactions/TestLoaderManager.java
index 6c2d9e8..fb6a49b 100644
--- a/src/com/android/contacts/interactions/TestLoaderManager.java
+++ b/src/com/android/contacts/interactions/TestLoaderManager.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.interactions;
 
-import com.google.common.annotations.VisibleForTesting;
-
 import android.app.Activity;
 import android.app.LoaderManager;
 import android.content.AsyncTaskLoader;
@@ -25,14 +23,16 @@
 import android.os.Bundle;
 import android.util.Log;
 
+import com.google.common.annotations.VisibleForTesting;
+
+import junit.framework.Assert;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 
-import junit.framework.Assert;
-
 /**
  * A {@link LoaderManager} that records which loaders have been completed.
  * <p>
diff --git a/src/com/android/contacts/list/AccountFilterActivity.java b/src/com/android/contacts/list/AccountFilterActivity.java
index 2624e5d..af727a5 100644
--- a/src/com/android/contacts/list/AccountFilterActivity.java
+++ b/src/com/android/contacts/list/AccountFilterActivity.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.google.android.collect.Lists;
-
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.LoaderManager.LoaderCallbacks;
@@ -41,6 +34,13 @@
 import android.widget.BaseAdapter;
 import android.widget.ListView;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -69,7 +69,7 @@
         super.onCreate(icicle);
         setContentView(R.layout.contact_list_filter);
 
-        mListView = (ListView) findViewById(com.android.internal.R.id.list);
+        mListView = (ListView) findViewById(android.R.id.list);
         mListView.setOnItemClickListener(this);
 
         ActionBar actionBar = getActionBar();
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index a2b61c7..3e8e4a3 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -15,11 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.common.widget.CompositeCursorAdapter.Partition;
-import com.android.contacts.R;
-import com.android.contacts.util.ContactLoaderUtils;
-import com.android.contacts.widget.AutoScrollListView;
-
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -39,6 +34,11 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.common.widget.CompositeCursorAdapter.Partition;
+import com.android.contacts.R;
+import com.android.contacts.util.ContactLoaderUtils;
+import com.android.contacts.widget.AutoScrollListView;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index 78bf628..00c26ff 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -15,10 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.R;
-import com.android.contacts.widget.IndexerListAdapter;
-
 import android.content.Context;
 import android.content.CursorLoader;
 import android.database.Cursor;
@@ -37,6 +33,10 @@
 import android.widget.SectionIndexer;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.R;
+import com.android.contacts.widget.IndexerListAdapter;
+
 import java.util.HashSet;
 
 /**
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index 27fdada..e422d1b 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -16,13 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.common.widget.CompositeCursorAdapter.Partition;
-import com.android.contacts.ContactListEmptyView;
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.R;
-import com.android.contacts.preference.ContactsPreferences;
-import com.android.contacts.widget.ContextMenuAdapter;
-
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.app.Activity;
@@ -60,6 +53,13 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.common.widget.CompositeCursorAdapter.Partition;
+import com.android.contacts.ContactListEmptyView;
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.R;
+import com.android.contacts.preference.ContactsPreferences;
+import com.android.contacts.widget.ContextMenuAdapter;
+
 /**
  * Common base class for various contact-related list fragments.
  */
@@ -744,7 +744,7 @@
                     "'android.R.id.list'");
         }
 
-        View emptyView = mView.findViewById(com.android.internal.R.id.empty);
+        View emptyView = mView.findViewById(android.R.id.empty);
         if (emptyView != null) {
             mListView.setEmptyView(emptyView);
             if (emptyView instanceof ContactListEmptyView) {
diff --git a/src/com/android/contacts/list/ContactListAdapter.java b/src/com/android/contacts/list/ContactListAdapter.java
index 18f7e04..1eb2dae 100644
--- a/src/com/android/contacts/list/ContactListAdapter.java
+++ b/src/com/android/contacts/list/ContactListAdapter.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
@@ -30,6 +28,8 @@
 import android.view.ViewGroup;
 import android.widget.ListView;
 
+import com.android.contacts.R;
+
 /**
  * A cursor adapter for the {@link ContactsContract.Contacts#CONTENT_TYPE} content type.
  * Also includes support for including the {@link ContactsContract.Profile} record in the
diff --git a/src/com/android/contacts/list/ContactListFilterController.java b/src/com/android/contacts/list/ContactListFilterController.java
index 9f483f1..ddcb1ae 100644
--- a/src/com/android/contacts/list/ContactListFilterController.java
+++ b/src/com/android/contacts/list/ContactListFilterController.java
@@ -15,13 +15,13 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
 
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountWithDataSet;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/list/ContactListFilterView.java b/src/com/android/contacts/list/ContactListFilterView.java
index 020952d..d0ecfe4 100644
--- a/src/com/android/contacts/list/ContactListFilterView.java
+++ b/src/com/android/contacts/list/ContactListFilterView.java
@@ -16,12 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-import com.android.contacts.editor.ContactEditorFragment;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.util.ThemeUtils;
-
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -31,6 +25,10 @@
 import android.widget.RadioButton;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+
 /**
  * Contact list filter parameters.
  */
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index 191212b..bfe06b0 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.contacts.ContactPresenceIconUtil;
-import com.android.contacts.ContactStatusUtil;
-import com.android.contacts.R;
-import com.android.contacts.format.PrefixHighlighter;
-
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
@@ -49,6 +44,11 @@
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPresenceIconUtil;
+import com.android.contacts.ContactStatusUtil;
+import com.android.contacts.R;
+import com.android.contacts.format.PrefixHighlighter;
+
 /**
  * A custom view for an item in the contact list.
  * The view contains the contact's photo, a set of text views (for name, status, etc...) and
@@ -67,12 +67,8 @@
 public class ContactListItemView extends ViewGroup
         implements SelectionBoundsAdjuster {
 
-    private static final int QUICK_CONTACT_BADGE_STYLE =
-            com.android.internal.R.attr.quickContactBadgeStyleWindowMedium;
-
     // Style values for layout and appearance
     private final int mPreferredHeight;
-    private final int mVerticalDividerMargin;
     private final int mGapBetweenImageAndText;
     private final int mGapBetweenLabelAndData;
     private final int mPresenceIconMargin;
@@ -115,11 +111,6 @@
     public static final PhotoPosition DEFAULT_PHOTO_POSITION = PhotoPosition.RIGHT;
     private PhotoPosition mPhotoPosition = DEFAULT_PHOTO_POSITION;
 
-    // Vertical divider between the call icon and the text.
-    private boolean mVerticalDividerVisible;
-    private Drawable mVerticalDividerDrawable;
-    private int mVerticalDividerWidth;
-
     // Header layout data
     private boolean mHeaderVisible;
     private View mHeaderDivider;
@@ -132,7 +123,6 @@
     private ImageView mPhotoView;
     private TextView mNameTextView;
     private TextView mPhoneticNameTextView;
-    private DontPressWithParentImageView mCallButton;
     private TextView mLabelView;
     private TextView mDataView;
     private TextView mSnippetView;
@@ -200,27 +190,6 @@
     private PrefixHighlighter mPrefixHighlighter;
     private CharSequence mUnknownNameText;
 
-    /**
-     * Special class to allow the parent to be pressed without being pressed itself.
-     * This way the line of a tab can be pressed, but the image itself is not.
-     */
-    // TODO: understand this
-    private static class DontPressWithParentImageView extends ImageView {
-
-        public DontPressWithParentImageView(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-
-        @Override
-        public void setPressed(boolean pressed) {
-            // If the parent is pressed, do not set to pressed.
-            if (pressed && ((View) getParent()).isPressed()) {
-                return;
-            }
-            super.setPressed(pressed);
-        }
-    }
-
     public ContactListItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
@@ -233,8 +202,6 @@
                 R.styleable.ContactListItemView_activated_background);
         mHorizontalDividerDrawable = a.getDrawable(
                 R.styleable.ContactListItemView_list_item_divider);
-        mVerticalDividerMargin = a.getDimensionPixelOffset(
-                R.styleable.ContactListItemView_list_item_vertical_divider_margin, 0);
 
         mGapBetweenImageAndText = a.getDimensionPixelOffset(
                 R.styleable.ContactListItemView_list_item_gap_between_image_and_text, 0);
@@ -428,11 +395,6 @@
                 mLabelAndDataViewMaxHeight +
                 mSnippetTextViewHeight + mStatusTextViewHeight);
 
-        if (isVisible(mCallButton)) {
-            mCallButton.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
-                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-        }
-
         // Make sure the height is at least as high as the photo
         height = Math.max(height, mPhotoViewHeight + getPaddingBottom() + getPaddingTop());
 
@@ -541,9 +503,6 @@
             leftBound += mTextIndent;
         }
 
-        // Layout the call button.
-        rightBound = layoutRightSide(height, topBound, bottomBound, rightBound);
-
         // Center text vertically
         final int totalTextHeight = mNameTextViewHeight + mPhoneticNameTextViewHeight +
                 mLabelAndDataViewMaxHeight + mSnippetTextViewHeight + mStatusTextViewHeight;
@@ -630,36 +589,6 @@
         }
     }
 
-    /**
-     * Performs layout of the right side of the view
-     *
-     * @return new right boundary
-     */
-    protected int layoutRightSide(int height, int topBound, int bottomBound, int rightBound) {
-        // Put call button and vertical divider
-        if (isVisible(mCallButton)) {
-            int buttonWidth = mCallButton.getMeasuredWidth();
-            rightBound -= buttonWidth;
-            mCallButton.layout(
-                    rightBound,
-                    topBound,
-                    rightBound + buttonWidth,
-                    height - mHorizontalDividerHeight);
-            mVerticalDividerVisible = true;
-            ensureVerticalDivider();
-            rightBound -= mVerticalDividerWidth;
-            mVerticalDividerDrawable.setBounds(
-                    rightBound,
-                    topBound + mVerticalDividerMargin,
-                    rightBound + mVerticalDividerWidth,
-                    height - mVerticalDividerMargin);
-        } else {
-            mVerticalDividerVisible = false;
-        }
-
-        return rightBound;
-    }
-
     @Override
     public void adjustListItemSelectionBounds(Rect bounds) {
         bounds.top += mBoundsWithoutHeader.top;
@@ -673,38 +602,18 @@
     }
 
     /**
-     * Loads the drawable for the vertical divider if it has not yet been loaded.
-     */
-    private void ensureVerticalDivider() {
-        if (mVerticalDividerDrawable == null) {
-            mVerticalDividerDrawable = mContext.getResources().getDrawable(
-                    R.drawable.divider_vertical_dark);
-            mVerticalDividerWidth = mVerticalDividerDrawable.getIntrinsicWidth();
-        }
-    }
-
-    /**
      * Extracts width and height from the style
      */
     private void ensurePhotoViewSize() {
         if (!mPhotoViewWidthAndHeightAreReady) {
-            if (mQuickContactEnabled) {
-                TypedArray a = mContext.obtainStyledAttributes(null,
-                        com.android.internal.R.styleable.ViewGroup_Layout,
-                        QUICK_CONTACT_BADGE_STYLE, 0);
-                mPhotoViewWidth = a.getLayoutDimension(
-                        android.R.styleable.ViewGroup_Layout_layout_width,
-                        ViewGroup.LayoutParams.WRAP_CONTENT);
-                mPhotoViewHeight = a.getLayoutDimension(
-                        android.R.styleable.ViewGroup_Layout_layout_height,
-                        ViewGroup.LayoutParams.WRAP_CONTENT);
-                a.recycle();
-            } else if (mPhotoView != null) {
-                mPhotoViewWidth = mPhotoViewHeight = getDefaultPhotoViewSize();
-            } else {
-                final int defaultPhotoViewSize = getDefaultPhotoViewSize();
-                mPhotoViewWidth = mKeepHorizontalPaddingForPhotoView ? defaultPhotoViewSize : 0;
-                mPhotoViewHeight = mKeepVerticalPaddingForPhotoView ? defaultPhotoViewSize : 0;
+            mPhotoViewWidth = mPhotoViewHeight = getDefaultPhotoViewSize();
+            if (!mQuickContactEnabled && mPhotoView == null) {
+                if (!mKeepHorizontalPaddingForPhotoView) {
+                    mPhotoViewWidth = 0;
+                }
+                if (!mKeepVerticalPaddingForPhotoView) {
+                    mPhotoViewHeight = 0;
+                }
             }
 
             mPhotoViewWidthAndHeightAreReady = true;
@@ -719,6 +628,18 @@
         return mDefaultPhotoViewSize;
     }
 
+    /**
+     * Gets a LayoutParam that corresponds to the default photo size.
+     *
+     * @return A new LayoutParam.
+     */
+    private LayoutParams getDefaultPhotoLayoutParams() {
+        LayoutParams params = generateDefaultLayoutParams();
+        params.width = getDefaultPhotoViewSize();
+        params.height = params.width;
+        return params;
+    }
+
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
@@ -748,9 +669,6 @@
         if (mHorizontalDividerVisible) {
             mHorizontalDividerDrawable.draw(canvas);
         }
-        if (mVerticalDividerVisible) {
-            mVerticalDividerDrawable.draw(canvas);
-        }
 
         super.dispatchDraw(canvas);
     }
@@ -805,7 +723,8 @@
             throw new IllegalStateException("QuickContact is disabled for this view");
         }
         if (mQuickContact == null) {
-            mQuickContact = new QuickContactBadge(mContext, null, QUICK_CONTACT_BADGE_STYLE);
+            mQuickContact = new QuickContactBadge(mContext);
+            mQuickContact.setLayoutParams(getDefaultPhotoLayoutParams());
             if (mNameTextView != null) {
                 mQuickContact.setContentDescription(mContext.getString(
                         R.string.description_quick_contact_for, mNameTextView.getText()));
@@ -822,11 +741,8 @@
      */
     public ImageView getPhotoView() {
         if (mPhotoView == null) {
-            if (mQuickContactEnabled) {
-                mPhotoView = new ImageView(mContext, null, QUICK_CONTACT_BADGE_STYLE);
-            } else {
-                mPhotoView = new ImageView(mContext);
-            }
+            mPhotoView = new ImageView(mContext);
+            mPhotoView.setLayoutParams(getDefaultPhotoLayoutParams());
             // Quick contact style used above will set a background - remove it
             mPhotoView.setBackground(null);
             addView(mPhotoView);
diff --git a/src/com/android/contacts/list/ContactListPinnedHeaderView.java b/src/com/android/contacts/list/ContactListPinnedHeaderView.java
index aee77e1..34a56d6 100644
--- a/src/com/android/contacts/list/ContactListPinnedHeaderView.java
+++ b/src/com/android/contacts/list/ContactListPinnedHeaderView.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Color;
@@ -30,6 +28,8 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+
 /**
  * A custom view for the pinned section header shown at the top of the contact list.
  */
diff --git a/src/com/android/contacts/list/ContactNameHighlightingAnimation.java b/src/com/android/contacts/list/ContactNameHighlightingAnimation.java
index 05881ce..ddea603 100644
--- a/src/com/android/contacts/list/ContactNameHighlightingAnimation.java
+++ b/src/com/android/contacts/list/ContactNameHighlightingAnimation.java
@@ -15,11 +15,11 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.widget.TextHighlightingAnimation;
-
 import android.view.View;
 import android.widget.ListView;
 
+import com.android.contacts.widget.TextHighlightingAnimation;
+
 /**
  * A {@link TextHighlightingAnimation} that redraws just the contact display name in a
  * list item.
diff --git a/src/com/android/contacts/list/ContactPickerFragment.java b/src/com/android/contacts/list/ContactPickerFragment.java
index ef51732..bda62f3 100644
--- a/src/com/android/contacts/list/ContactPickerFragment.java
+++ b/src/com/android/contacts/list/ContactPickerFragment.java
@@ -15,10 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactsSearchManager;
-import com.android.contacts.R;
-import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
-
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -27,6 +23,9 @@
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 
+import com.android.contacts.R;
+import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+
 /**
  * Fragment for the contact list used for browsing contacts (as compared to
  * picking a contact with one of the PICK or SHORTCUT intents).
diff --git a/src/com/android/contacts/list/ContactTileAdapter.java b/src/com/android/contacts/list/ContactTileAdapter.java
index ddf88b0..75e3149 100644
--- a/src/com/android/contacts/list/ContactTileAdapter.java
+++ b/src/com/android/contacts/list/ContactTileAdapter.java
@@ -15,15 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactPresenceIconUtil;
-import com.android.contacts.ContactStatusUtil;
-import com.android.contacts.ContactTileLoaderFactory;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.GroupMemberLoader;
-import com.android.contacts.GroupMemberLoader.GroupDetailQuery;
-import com.android.contacts.R;
-
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.res.Resources;
@@ -37,6 +28,15 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.ContactPresenceIconUtil;
+import com.android.contacts.ContactStatusUtil;
+import com.android.contacts.ContactTileLoaderFactory;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.GroupMemberLoader;
+import com.android.contacts.GroupMemberLoader.GroupDetailQuery;
+import com.android.contacts.R;
+
 import java.util.ArrayList;
 
 /**
diff --git a/src/com/android/contacts/list/ContactTileFrequentFragment.java b/src/com/android/contacts/list/ContactTileFrequentFragment.java
index 73ff6cc..88ef1e8 100644
--- a/src/com/android/contacts/list/ContactTileFrequentFragment.java
+++ b/src/com/android/contacts/list/ContactTileFrequentFragment.java
@@ -15,14 +15,14 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+
 /**
  * Fragment containing a list of frequently contacted people.
  */
diff --git a/src/com/android/contacts/list/ContactTileFrequentView.java b/src/com/android/contacts/list/ContactTileFrequentView.java
index 0bd6729..ba240af 100644
--- a/src/com/android/contacts/list/ContactTileFrequentView.java
+++ b/src/com/android/contacts/list/ContactTileFrequentView.java
@@ -15,11 +15,11 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.util.ViewUtil;
-
 import android.content.Context;
 import android.util.AttributeSet;
 
+import com.android.contacts.util.ViewUtil;
+
 /**
  * A {@link ContactTileView} that is used for most frequently contacted in the People app
  */
diff --git a/src/com/android/contacts/list/ContactTileListFragment.java b/src/com/android/contacts/list/ContactTileListFragment.java
index 4ee20f5..f5de15f 100644
--- a/src/com/android/contacts/list/ContactTileListFragment.java
+++ b/src/com/android/contacts/list/ContactTileListFragment.java
@@ -15,12 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactTileLoaderFactory;
-import com.android.contacts.R;
-import com.android.contacts.list.ContactTileAdapter.DisplayType;
-import com.android.contacts.util.PhoneCapabilityTester;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -32,13 +26,17 @@
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.ContactTileLoaderFactory;
+import com.android.contacts.R;
+import com.android.contacts.list.ContactTileAdapter.DisplayType;
+
 /**
  * Fragment containing a list of starred contacts followed by a list of frequently contacted.
  *
diff --git a/src/com/android/contacts/list/ContactTilePhoneFrequentView.java b/src/com/android/contacts/list/ContactTilePhoneFrequentView.java
index 88796ba..7c3aef3 100644
--- a/src/com/android/contacts/list/ContactTilePhoneFrequentView.java
+++ b/src/com/android/contacts/list/ContactTilePhoneFrequentView.java
@@ -15,15 +15,15 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.list.ContactTileAdapter.ContactEntry;
-import com.android.contacts.util.ViewUtil;
-
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.list.ContactTileAdapter.ContactEntry;
+import com.android.contacts.util.ViewUtil;
+
 /**
  * A dark version of the {@link ContactTileView} that is used in Dialtacts
  * for frequently called contacts. Slightly different behavior from superclass...
diff --git a/src/com/android/contacts/list/ContactTilePhoneStarredView.java b/src/com/android/contacts/list/ContactTilePhoneStarredView.java
index fc53782..dc68688 100644
--- a/src/com/android/contacts/list/ContactTilePhoneStarredView.java
+++ b/src/com/android/contacts/list/ContactTilePhoneStarredView.java
@@ -15,14 +15,14 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.Intent;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.ImageButton;
 
+import com.android.contacts.R;
+
 /**
  * Displays the contact's picture overlayed with their name
  * in a perfect square. It also has an additional touch target for a secondary action.
diff --git a/src/com/android/contacts/list/ContactTileView.java b/src/com/android/contacts/list/ContactTileView.java
index 528e7a3..c108827 100644
--- a/src/com/android/contacts/list/ContactTileView.java
+++ b/src/com/android/contacts/list/ContactTileView.java
@@ -15,11 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.list.ContactTileAdapter.ContactEntry;
-
 import android.content.Context;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -31,6 +26,11 @@
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.list.ContactTileAdapter.ContactEntry;
+
 /**
  * A ContactTile displays a contact's picture and name
  */
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index 9199766..8daf39d 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.contacts.CallContactActivity;
-import com.android.contacts.ContactsSearchManager;
-import com.android.contacts.ContactsUtils;
-
 import android.app.Activity;
 import android.app.SearchManager;
 import android.content.Intent;
@@ -39,6 +35,10 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.contacts.CallContactActivity;
+import com.android.contacts.ContactsSearchManager;
+import com.android.contacts.ContactsUtils;
+
 /**
  * Parses a Contacts intent, extracting all relevant parts and packaging them
  * as a {@link ContactsRequest} object.
diff --git a/src/com/android/contacts/list/ContactsUnavailableFragment.java b/src/com/android/contacts/list/ContactsUnavailableFragment.java
index b645425..43a2d8e 100644
--- a/src/com/android/contacts/list/ContactsUnavailableFragment.java
+++ b/src/com/android/contacts/list/ContactsUnavailableFragment.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.app.Fragment;
 import android.content.Context;
 import android.os.Bundle;
@@ -30,6 +28,8 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+
 /**
  * Fragment shown when contacts are unavailable. It contains provider status
  * messaging as well as instructions for the user.
diff --git a/src/com/android/contacts/list/CustomContactListFilterActivity.java b/src/com/android/contacts/list/CustomContactListFilterActivity.java
index d5395bd..c62b389 100644
--- a/src/com/android/contacts/list/CustomContactListFilterActivity.java
+++ b/src/com/android/contacts/list/CustomContactListFilterActivity.java
@@ -16,18 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.GoogleAccountType;
-import com.android.contacts.util.EmptyService;
-import com.android.contacts.util.LocalizedNameResolver;
-import com.android.contacts.util.WeakAsyncTask;
-import com.google.android.collect.Lists;
-
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -39,7 +27,6 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.content.EntityIterator;
 import android.content.Intent;
 import android.content.Loader;
 import android.content.OperationApplicationException;
@@ -66,6 +53,18 @@
 import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
 import android.widget.TextView;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.account.GoogleAccountType;
+import com.android.contacts.util.EmptyService;
+import com.android.contacts.util.LocalizedNameResolver;
+import com.android.contacts.util.WeakAsyncTask;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -93,7 +92,7 @@
         super.onCreate(icicle);
         setContentView(R.layout.contact_list_filter_custom);
 
-        mList = (ExpandableListView) findViewById(com.android.internal.R.id.list);
+        mList = (ExpandableListView) findViewById(android.R.id.list);
         mList.setOnChildClickListener(this);
         mList.setHeaderDividersEnabled(true);
         mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
@@ -146,7 +145,8 @@
                 if (account.dataSet != null) {
                     groupsUri.appendQueryParameter(Groups.DATA_SET, account.dataSet).build();
                 }
-                EntityIterator iterator = ContactsContract.Groups.newEntityIterator(resolver.query(
+                android.content.EntityIterator iterator =
+                        ContactsContract.Groups.newEntityIterator(resolver.query(
                         groupsUri.build(), null, null, null, null));
                 try {
                     boolean hasGroups = false;
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index e358f6f..8f38045 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -15,10 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-import com.android.contacts.editor.ContactEditorFragment;
-import com.android.contacts.util.AccountFilterUtil;
-
 import android.content.CursorLoader;
 import android.content.Intent;
 import android.database.Cursor;
@@ -28,7 +24,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.View.OnLayoutChangeListener;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.Button;
@@ -36,6 +31,10 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.editor.ContactEditorFragment;
+import com.android.contacts.util.AccountFilterUtil;
+
 /**
  * Fragment containing a contact list used for browsing (as compared to
  * picking a contact with one of the PICK intents).
diff --git a/src/com/android/contacts/list/DefaultContactListAdapter.java b/src/com/android/contacts/list/DefaultContactListAdapter.java
index a53914d..88c1db0 100644
--- a/src/com/android/contacts/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/list/DefaultContactListAdapter.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.preference.ContactsPreferences;
-
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.CursorLoader;
@@ -28,11 +26,12 @@
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Directory;
-import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.SearchSnippetColumns;
 import android.text.TextUtils;
 import android.view.View;
 
+import com.android.contacts.preference.ContactsPreferences;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/list/DirectoryListLoader.java b/src/com/android/contacts/list/DirectoryListLoader.java
index 0bb250a..f85cc5e 100644
--- a/src/com/android/contacts/list/DirectoryListLoader.java
+++ b/src/com/android/contacts/list/DirectoryListLoader.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.content.AsyncTaskLoader;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -29,6 +27,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.contacts.R;
+
 /**
  * A specialized loader for the list of directories, see {@link Directory}.
  */
diff --git a/src/com/android/contacts/list/DirectoryPartition.java b/src/com/android/contacts/list/DirectoryPartition.java
index 47a1037..c1fd533 100644
--- a/src/com/android/contacts/list/DirectoryPartition.java
+++ b/src/com/android/contacts/list/DirectoryPartition.java
@@ -15,10 +15,10 @@
  */
 package com.android.contacts.list;
 
-import com.android.common.widget.CompositeCursorAdapter;
-
 import android.provider.ContactsContract.Directory;
 
+import com.android.common.widget.CompositeCursorAdapter;
+
 /**
  * Model object for a {@link Directory} row.
  */
diff --git a/src/com/android/contacts/list/EmailAddressPickerFragment.java b/src/com/android/contacts/list/EmailAddressPickerFragment.java
index 13fe541..41f470f 100644
--- a/src/com/android/contacts/list/EmailAddressPickerFragment.java
+++ b/src/com/android/contacts/list/EmailAddressPickerFragment.java
@@ -15,13 +15,13 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.net.Uri;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.contacts.R;
+
 /**
  * Fragment containing an email list for picking.
  */
diff --git a/src/com/android/contacts/list/JoinContactListAdapter.java b/src/com/android/contacts/list/JoinContactListAdapter.java
index 80ddc83..6e1a6b2 100644
--- a/src/com/android/contacts/list/JoinContactListAdapter.java
+++ b/src/com/android/contacts/list/JoinContactListAdapter.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.CursorLoader;
 import android.database.Cursor;
@@ -32,6 +30,8 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+
 public class JoinContactListAdapter extends ContactListAdapter {
 
     /** Maximum number of suggestions shown for joining aggregates */
diff --git a/src/com/android/contacts/list/JoinContactListFragment.java b/src/com/android/contacts/list/JoinContactListFragment.java
index 1c526a5..9cfa4ae 100644
--- a/src/com/android/contacts/list/JoinContactListFragment.java
+++ b/src/com/android/contacts/list/JoinContactListFragment.java
@@ -15,9 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-import com.android.contacts.list.JoinContactLoader.JoinContactLoaderResult;
-
 import android.app.Activity;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ContentUris;
@@ -34,6 +31,9 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.list.JoinContactLoader.JoinContactLoaderResult;
+
 /**
  * Fragment for the Join Contact list.
  */
diff --git a/src/com/android/contacts/list/PhoneFavoriteFragment.java b/src/com/android/contacts/list/PhoneFavoriteFragment.java
index 170790f..5ef19ff 100644
--- a/src/com/android/contacts/list/PhoneFavoriteFragment.java
+++ b/src/com/android/contacts/list/PhoneFavoriteFragment.java
@@ -15,14 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactTileLoaderFactory;
-import com.android.contacts.R;
-import com.android.contacts.dialog.ClearFrequentsDialog;
-import com.android.contacts.interactions.ImportExportDialogFragment;
-import com.android.contacts.preference.ContactsPreferences;
-import com.android.contacts.util.AccountFilterUtil;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -53,6 +45,14 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.ContactTileLoaderFactory;
+import com.android.contacts.R;
+import com.android.contacts.dialog.ClearFrequentsDialog;
+import com.android.contacts.interactions.ImportExportDialogFragment;
+import com.android.contacts.preference.ContactsPreferences;
+import com.android.contacts.util.AccountFilterUtil;
+
 /**
  * Fragment for Phone UI's favorite screen.
  *
diff --git a/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java b/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
index d5b62e5..3aa9fe5 100644
--- a/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
+++ b/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
@@ -16,8 +16,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.DataSetObserver;
@@ -27,6 +25,8 @@
 import android.widget.FrameLayout;
 import android.widget.SectionIndexer;
 
+import com.android.contacts.R;
+
 /**
  * An adapter that combines items from {@link ContactTileAdapter} and
  * {@link ContactEntryListAdapter} into a single list. In between those two results,
@@ -295,4 +295,4 @@
         final int contactTileAdapterCount = mContactTileAdapter.getCount();
         return firstVisibleItem > contactTileAdapterCount;
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index 3785fa6..17b5500 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -15,10 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
-import com.android.contacts.util.AccountFilterUtil;
-
 import android.content.Intent;
 import android.content.Loader;
 import android.database.Cursor;
@@ -30,7 +26,10 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.widget.TextView;
+
+import com.android.contacts.R;
+import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+import com.android.contacts.util.AccountFilterUtil;
 
 /**
  * Fragment containing a phone number list for picking.
diff --git a/src/com/android/contacts/list/PostalAddressPickerFragment.java b/src/com/android/contacts/list/PostalAddressPickerFragment.java
index ddb8e9a..9bd4fc3 100644
--- a/src/com/android/contacts/list/PostalAddressPickerFragment.java
+++ b/src/com/android/contacts/list/PostalAddressPickerFragment.java
@@ -15,13 +15,13 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-
 import android.net.Uri;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.contacts.R;
+
 /**
  * Fragment containing a postal address list for picking.
  */
diff --git a/src/com/android/contacts/list/ProfileAndContactsLoader.java b/src/com/android/contacts/list/ProfileAndContactsLoader.java
index 7f85ea6..4291a40 100644
--- a/src/com/android/contacts/list/ProfileAndContactsLoader.java
+++ b/src/com/android/contacts/list/ProfileAndContactsLoader.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.google.android.collect.Lists;
-
 import android.content.Context;
 import android.content.CursorLoader;
 import android.database.Cursor;
@@ -25,6 +23,8 @@
 import android.os.Bundle;
 import android.provider.ContactsContract.Profile;
 
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/list/ProviderStatusWatcher.java b/src/com/android/contacts/list/ProviderStatusWatcher.java
index ae0b779..3e8d3f5 100644
--- a/src/com/android/contacts/list/ProviderStatusWatcher.java
+++ b/src/com/android/contacts/list/ProviderStatusWatcher.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.google.common.collect.Lists;
-
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -27,6 +25,8 @@
 import android.provider.ContactsContract.ProviderStatus;
 import android.util.Log;
 
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 
 /**
diff --git a/src/com/android/contacts/list/ShortcutIntentBuilder.java b/src/com/android/contacts/list/ShortcutIntentBuilder.java
index d71a0f5..1578524 100644
--- a/src/com/android/contacts/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/list/ShortcutIntentBuilder.java
@@ -15,9 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.R;
-import com.android.contacts.util.Constants;
-
 import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -43,6 +40,9 @@
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 
+import com.android.contacts.R;
+import com.android.contacts.util.Constants;
+
 /**
  * Constructs shortcut intents.
  */
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index d6f140e..64f3a91 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -16,16 +16,6 @@
 
 package com.android.contacts.model;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.list.ContactListFilterController;
-import com.android.contacts.util.Constants;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
-import com.android.internal.util.Objects;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.AuthenticatorDescription;
@@ -53,12 +43,28 @@
 import android.util.Log;
 import android.util.TimingLogger;
 
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.list.ContactListFilterController;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountTypeWithDataSet;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.account.ExchangeAccountType;
+import com.android.contacts.model.account.ExternalAccountType;
+import com.android.contacts.model.account.FallbackAccountType;
+import com.android.contacts.model.account.GoogleAccountType;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.Constants;
+import com.android.internal.util.Objects;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
diff --git a/src/com/android/contacts/model/Contact.java b/src/com/android/contacts/model/Contact.java
new file mode 100644
index 0000000..ede2101
--- /dev/null
+++ b/src/com/android/contacts/model/Contact.java
@@ -0,0 +1,495 @@
+/*
+ * 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.model.account.AccountType;
+import com.android.contacts.model.dataitem.DataItem;
+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;
+
+/**
+ * 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 ImmutableList<StreamItemEntry> mStreamItems;
+    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;
+        mStreamItems = 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;
+        mStreamItems = 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;
+        mStreamItems = from.mStreamItems;
+        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 mStreamItems;
+    }
+
+    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();
+            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 = new ArrayList<ContentValues>();
+        for (DataItem dataItem : rawContact.getDataItems()) {
+            result.add(dataItem.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;
+    }
+
+    /* package */ void setStreamItems(ImmutableList<StreamItemEntry> streamItems) {
+        mStreamItems = streamItems;
+    }
+}
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/model/ContactLoader.java
similarity index 63%
rename from src/com/android/contacts/ContactLoader.java
rename to src/com/android/contacts/model/ContactLoader.java
index 10579f3..6db997e 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/model/ContactLoader.java
@@ -14,29 +14,13 @@
  * limitations under the License
  */
 
-package com.android.contacts;
-
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountTypeWithDataSet;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.util.ContactLoaderUtils;
-import com.android.contacts.util.DataStatus;
-import com.android.contacts.util.StreamItemEntry;
-import com.android.contacts.util.StreamItemPhotoEntry;
-import com.android.contacts.util.UriUtils;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+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.Entity;
-import android.content.Entity.NamedContentValues;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -46,11 +30,9 @@
 import android.net.Uri;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Directory;
-import android.provider.ContactsContract.DisplayNameSources;
 import android.provider.ContactsContract.Groups;
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.StreamItemPhotos;
@@ -59,25 +41,39 @@
 import android.util.Log;
 import android.util.LongSparseArray;
 
+import com.android.contacts.GroupMetaData;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountTypeWithDataSet;
+import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.model.dataitem.PhotoDataItem;
+import com.android.contacts.util.ContactLoaderUtils;
+import com.android.contacts.util.DataStatus;
+import com.android.contacts.util.StreamItemEntry;
+import com.android.contacts.util.StreamItemPhotoEntry;
+import com.android.contacts.util.UriUtils;
+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 java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
-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<ContactLoader.Result> {
+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 Result sCachedResult = null;
+    private static Contact sCachedResult = null;
 
     private final Uri mRequestedUri;
     private Uri mLookupUri;
@@ -85,7 +81,7 @@
     private boolean mLoadStreamItems;
     private boolean mLoadInvitableAccountTypes;
     private boolean mPostViewNotification;
-    private Result mContact;
+    private Contact mContact;
     private ForceLoadContentObserver mObserver;
     private final Set<Long> mNotifiedRawContactIds = Sets.newHashSet();
 
@@ -106,433 +102,6 @@
     }
 
     /**
-     * The result of a load operation. Contains all data necessary to display the contact.
-     */
-    public static final class Result {
-        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 final ArrayList<Entity> mEntities;
-        private ArrayList<StreamItemEntry> mStreamItems;
-        private final LongSparseArray<DataStatus> mStatuses;
-        private ArrayList<AccountType> mInvitableAccountTypes;
-
-        private String mDirectoryDisplayName;
-        private String mDirectoryType;
-        private String mDirectoryAccountType;
-        private String mDirectoryAccountName;
-        private int mDirectoryExportSupport;
-
-        private ArrayList<GroupMetaData> mGroups;
-
-        private byte[] mPhotoBinaryData;
-        private final boolean mSendToVoicemail;
-        private final String mCustomRingtone;
-        private final boolean mIsUserProfile;
-
-        private final Status mStatus;
-        private final Exception mException;
-
-        /**
-         * Constructor for special results, namely "no contact found" and "error".
-         */
-        private Result(Uri requestedUri, 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;
-            mEntities = null;
-            mStreamItems = 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;
-        }
-
-        private static Result forError(Uri requestedUri, Exception exception) {
-            return new Result(requestedUri, Status.ERROR, exception);
-        }
-
-        private static Result forNotFound(Uri requestedUri) {
-            return new Result(requestedUri, Status.NOT_FOUND, null);
-        }
-
-        /**
-         * Constructor to call when contact was found
-         */
-        private Result(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;
-            mEntities = new ArrayList<Entity>();
-            mStreamItems = null;
-            mStatuses = new LongSparseArray<DataStatus>();
-            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;
-        }
-
-        private Result(Uri requestedUri, Result 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;
-            mEntities = from.mEntities;
-            mStreamItems = from.mStreamItems;
-            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}.
-         */
-        private void setDirectoryMetaData(String displayName, String directoryType,
-                String accountType, String accountName, int exportSupport) {
-            mDirectoryDisplayName = displayName;
-            mDirectoryType = directoryType;
-            mDirectoryAccountType = accountType;
-            mDirectoryAccountName = accountName;
-            mDirectoryExportSupport = exportSupport;
-        }
-
-        private 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 EntityDeltaList for this contact.
-         */
-        public EntityDeltaList createEntityDeltaList() {
-            return EntityDeltaList.fromIterator(getEntities().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;
-        }
-
-        public ArrayList<AccountType> getInvitableAccountTypes() {
-            return mInvitableAccountTypes;
-        }
-
-        public ArrayList<Entity> getEntities() {
-            return mEntities;
-        }
-
-        public ArrayList<StreamItemEntry> getStreamItems() {
-            return mStreamItems;
-        }
-
-        public LongSparseArray<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.
-            final AccountTypeManager accountTypes = AccountTypeManager.getInstance(context);
-            for (Entity entity : getEntities()) {
-                ContentValues values = entity.getEntityValues();
-                String type = values.getAsString(RawContacts.ACCOUNT_TYPE);
-                String dataSet = values.getAsString(RawContacts.DATA_SET);
-
-                AccountType accountType = accountTypes.getAccountType(type, dataSet);
-                if (accountType != null && accountType.areContactsWritable()) {
-                    return values.getAsLong(RawContacts._ID);
-                }
-            }
-            // 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 (mEntities.size() != 1) {
-                throw new IllegalStateException(
-                        "Cannot extract content values from an aggregated contact");
-            }
-
-            Entity entity = mEntities.get(0);
-            ArrayList<ContentValues> result = new ArrayList<ContentValues>();
-            ArrayList<NamedContentValues> subValues = entity.getSubValues();
-            if (subValues != null) {
-                int size = subValues.size();
-                for (int i = 0; i < size; i++) {
-                    NamedContentValues pair = subValues.get(i);
-                    if (Data.CONTENT_URI.equals(pair.uri)) {
-                        result.add(pair.values);
-                    }
-                }
-            }
-
-            // 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;
-        }
-
-        public List<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 + "}";
-        }
-    }
-
-    /**
      * Projection used for the query that loads all data for the entire contact (except for
      * social stream items).
      */
@@ -726,21 +295,21 @@
     }
 
     @Override
-    public Result loadInBackground() {
+    public Contact loadInBackground() {
         try {
             final ContentResolver resolver = getContext().getContentResolver();
             final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(
                     resolver, mLookupUri);
-            final Result cachedResult = sCachedResult;
+            final Contact cachedResult = sCachedResult;
             sCachedResult = null;
             // Is this the same Uri as what we had before already? In that case, reuse that result
-            final Result 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 Result(mRequestedUri, cachedResult);
+                result = new Contact(mRequestedUri, cachedResult);
                 resultIsCached = true;
             } else {
                 result = loadContactEntity(resolver, uriCurrentFormat);
@@ -769,57 +338,62 @@
             return result;
         } catch (Exception e) {
             Log.e(TAG, "Error loading the contact: " + mLookupUri, e);
-            return Result.forError(mRequestedUri, e);
+            return Contact.forError(mRequestedUri, e);
         }
     }
 
-    private Result loadContactEntity(ContentResolver resolver, Uri contactUri) {
+    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 Result.forNotFound(mRequestedUri);
+            return Contact.forNotFound(mRequestedUri);
         }
 
         try {
             if (!cursor.moveToFirst()) {
                 cursor.close();
-                return Result.forNotFound(mRequestedUri);
+                return Contact.forNotFound(mRequestedUri);
             }
 
-            // Create the loaded result starting with the Contact data.
-            Result result = loadContactHeaderData(cursor, contactUri);
+            // 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;
-            Entity entity = null;
-            ArrayList<Entity> entities = result.getEntities();
-            LongSparseArray<DataStatus> statuses = result.getStatuses();
-            for (; !cursor.isAfterLast(); cursor.moveToNext()) {
+            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;
-                    entity = new android.content.Entity(loadRawContact(cursor));
-                    entities.add(entity);
+                    rawContact = new RawContact(getContext(), loadRawContactValues(cursor));
+                    rawContactsBuilder.add(rawContact);
                 }
                 if (!cursor.isNull(ContactQuery.DATA_ID)) {
-                    ContentValues data = loadData(cursor);
-                    entity.addSubValue(ContactsContract.Data.CONTENT_URI, data);
+                    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);
-                        statuses.put(dataId, status);
+                        statusesBuilder.put(dataId, status);
                     }
                 }
-            }
+            } while (cursor.moveToNext());
 
-            return result;
+            contact.setRawContacts(rawContactsBuilder.build());
+            contact.setStatuses(statusesBuilder.build());
+
+            return contact;
         } finally {
             cursor.close();
         }
@@ -829,7 +403,7 @@
      * Looks for the photo data item in entities. If found, creates a new Bitmap instance. If
      * not found, returns null
      */
-    private void loadPhotoBinaryData(Result contactData) {
+    private void loadPhotoBinaryData(Contact contactData) {
 
         // If we have a photo URI, try loading that first.
         String photoUri = contactData.getPhotoUri();
@@ -863,17 +437,15 @@
             return;
         }
 
-        for (Entity entity : contactData.getEntities()) {
-            for (NamedContentValues subValue : entity.getSubValues()) {
-                final ContentValues entryValues = subValue.values;
-                final long dataId = entryValues.getAsLong(Data._ID);
-                if (dataId == photoId) {
-                    final String mimeType = entryValues.getAsString(Data.MIMETYPE);
-                    // Correct Data Id but incorrect MimeType? Don't load
-                    if (!Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                        return;
+        for (RawContact rawContact : contactData.getRawContacts()) {
+            for (DataItem dataItem : rawContact.getDataItems()) {
+                if (dataItem.getId() == photoId) {
+                    if (!(dataItem instanceof PhotoDataItem)) {
+                        break;
                     }
-                    contactData.setPhotoBinaryData(entryValues.getAsByteArray(Photo.PHOTO));
+
+                    final PhotoDataItem photo = (PhotoDataItem) dataItem;
+                    contactData.setPhotoBinaryData(photo.getPhoto());
                     break;
                 }
             }
@@ -881,10 +453,11 @@
     }
 
     /**
-     * Sets the "invitable" account types to {@link Result#mInvitableAccountTypes}.
+     * Sets the "invitable" account types to {@link Contact#mInvitableAccountTypes}.
      */
-    private void loadInvitableAccountTypes(Result contactData) {
-        final ArrayList<AccountType> resultList = Lists.newArrayList();
+    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();
@@ -893,26 +466,25 @@
                         Maps.newHashMap(invitables);
 
                 // Remove the ones that already have a raw contact in the current contact
-                for (Entity entity : contactData.getEntities()) {
-                    final ContentValues values = entity.getEntityValues();
+                for (RawContact rawContact : contactData.getRawContacts()) {
                     final AccountTypeWithDataSet type = AccountTypeWithDataSet.get(
-                            values.getAsString(RawContacts.ACCOUNT_TYPE),
-                            values.getAsString(RawContacts.DATA_SET));
+                            rawContact.getAccountTypeString(),
+                            rawContact.getDataSet());
                     resultMap.remove(type);
                 }
 
-                resultList.addAll(resultMap.values());
+                resultListBuilder.addAll(resultMap.values());
             }
         }
 
         // Set to mInvitableAccountTypes
-        contactData.mInvitableAccountTypes = resultList;
+        contactData.setInvitableAccountTypes(resultListBuilder.build());
     }
 
     /**
      * Extracts Contact level columns from the cursor.
      */
-    private Result loadContactHeaderData(final Cursor cursor, Uri contactUri) {
+    private Contact loadContactHeaderData(final Cursor cursor, Uri contactUri) {
         final String directoryParameter =
                 contactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
         final long directoryId = directoryParameter == null
@@ -943,7 +515,7 @@
             lookupUri = contactUri;
         }
 
-        return new Result(mRequestedUri, contactUri, lookupUri, directoryId, lookupKey,
+        return new Contact(mRequestedUri, contactUri, lookupUri, directoryId, lookupKey,
                 contactId, nameRawContactId, displayNameSource, photoId, photoUri, displayName,
                 altDisplayName, phoneticName, starred, presence, sendToVoicemail,
                 customRingtone, isUserProfile);
@@ -952,7 +524,7 @@
     /**
      * Extracts RawContact level columns from the cursor.
      */
-    private ContentValues loadRawContact(Cursor cursor) {
+    private ContentValues loadRawContactValues(Cursor cursor) {
         ContentValues cv = new ContentValues();
 
         cv.put(RawContacts._ID, cursor.getLong(ContactQuery.RAW_CONTACT_ID));
@@ -979,7 +551,7 @@
     /**
      * Extracts Data level columns from the cursor.
      */
-    private ContentValues loadData(Cursor cursor) {
+    private ContentValues loadDataValues(Cursor cursor) {
         ContentValues cv = new ContentValues();
 
         cv.put(Data._ID, cursor.getLong(ContactQuery.DATA_ID));
@@ -1034,7 +606,7 @@
         }
     }
 
-    private void loadDirectoryMetaData(Result result) {
+    private void loadDirectoryMetaData(Contact result) {
         long directoryId = result.getDirectoryId();
 
         Cursor cursor = getContext().getContentResolver().query(
@@ -1075,14 +647,13 @@
      * Loads groups meta-data for all groups associated with all constituent raw contacts'
      * accounts.
      */
-    private void loadGroupMetaData(Result result) {
+    private void loadGroupMetaData(Contact result) {
         StringBuilder selection = new StringBuilder();
         ArrayList<String> selectionArgs = new ArrayList<String>();
-        for (Entity entity : result.mEntities) {
-            ContentValues values = entity.getEntityValues();
-            String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
-            String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
-            String dataSet = values.getAsString(RawContacts.DATA_SET);
+        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 ");
@@ -1101,7 +672,8 @@
                 selection.append(")");
             }
         }
-        final ArrayList<GroupMetaData> groupList = new ArrayList<GroupMetaData>();
+        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);
@@ -1119,28 +691,28 @@
                         ? false
                         : cursor.getInt(GroupQuery.FAVORITES) != 0;
 
-                groupList.add(new GroupMetaData(
+                groupListBuilder.add(new GroupMetaData(
                         accountName, accountType, dataSet, groupId, title, defaultGroup,
                         favorites));
             }
         } finally {
             cursor.close();
         }
-        result.mGroups = groupList;
+        result.setGroupMetaData(groupListBuilder.build());
     }
 
     /**
      * Loads all stream items and stream item photos belonging to this contact.
      */
-    private void loadStreamItems(Result result) {
-        Cursor cursor = getContext().getContentResolver().query(
+    private void loadStreamItems(Contact result) {
+        final Cursor cursor = getContext().getContentResolver().query(
                 Contacts.CONTENT_LOOKUP_URI.buildUpon()
                         .appendPath(result.getLookupKey())
                         .appendPath(Contacts.StreamItems.CONTENT_DIRECTORY).build(),
                 null, null, null, null);
-        LongSparseArray<StreamItemEntry> streamItemsById =
+        final LongSparseArray<StreamItemEntry> streamItemsById =
                 new LongSparseArray<StreamItemEntry>();
-        ArrayList<StreamItemEntry> streamItems = new ArrayList<StreamItemEntry>();
+        final ArrayList<StreamItemEntry> streamItems = new ArrayList<StreamItemEntry>();
         try {
             while (cursor.moveToNext()) {
                 StreamItemEntry streamItem = new StreamItemEntry(cursor);
@@ -1213,11 +785,13 @@
 
         // Set the sorted stream items on the result.
         Collections.sort(streamItems);
-        result.mStreamItems = streamItems;
+        result.setStreamItems(new ImmutableList.Builder<StreamItemEntry>()
+                .addAll(streamItems.iterator())
+                .build());
     }
 
     @Override
-    public void deliverResult(Result result) {
+    public void deliverResult(Contact result) {
         unregisterObserver();
 
         // The creator isn't interested in any further updates
@@ -1254,17 +828,13 @@
      */
     private void postViewNotificationToSyncAdapter() {
         Context context = getContext();
-        for (Entity entity : mContact.getEntities()) {
-            final ContentValues entityValues = entity.getEntityValues();
-            final long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID);
+        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 String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
-            final AccountType accountType = AccountTypeManager.getInstance(context).getAccountType(
-                    type, dataSet);
+            final AccountType accountType = rawContact.getAccountType();
             final String serviceName = accountType.getViewContactNotifyServiceClassName();
             final String servicePackageName = accountType.getViewContactNotifyServicePackageName();
             if (!TextUtils.isEmpty(serviceName) && !TextUtils.isEmpty(servicePackageName)) {
diff --git a/src/com/android/contacts/model/RawContact.java b/src/com/android/contacts/model/RawContact.java
new file mode 100644
index 0000000..d884198
--- /dev/null
+++ b/src/com/android/contacts/model/RawContact.java
@@ -0,0 +1,262 @@
+/*
+ * 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.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.RawContacts;
+
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.dataitem.DataItem;
+
+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.).
+ */
+public class RawContact {
+
+    private final Context mContext;
+    private AccountTypeManager mAccountTypeManager;
+    private final ContentValues mValues;
+    private final ArrayList<NamedDataItem> mDataItems;
+
+    public static class NamedDataItem {
+        public final Uri uri;
+        public final DataItem dataItem;
+
+        public NamedDataItem(Uri uri, DataItem dataItem) {
+            this.uri = uri;
+            this.dataItem = dataItem;
+        }
+    }
+
+    public static RawContact createFrom(Entity entity) {
+        final ContentValues values = entity.getEntityValues();
+        final ArrayList<Entity.NamedContentValues> subValues = entity.getSubValues();
+
+        RawContact rawContact = new RawContact(null, 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.
+     *
+     * The context is used for the buildString() member function in DataItem objects,
+     * specifically for retrieving an instance of AccountTypeManager.  It is okay to
+     * pass in null for the context in which case, you will not be able to call buildString(),
+     * getDataKind(), or getAccountType() from a DataItem object.
+     */
+    public RawContact(Context context) {
+        this(context, new ContentValues());
+    }
+
+    public RawContact(Context context, ContentValues values) {
+        mContext = context;
+        mValues = values;
+        mDataItems = new ArrayList<NamedDataItem>();
+    }
+
+    public AccountTypeManager getAccountTypeManager() {
+        if (mAccountTypeManager == null) {
+            mAccountTypeManager = AccountTypeManager.getInstance(mContext);
+        }
+        return mAccountTypeManager;
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
+    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 long getVersion() {
+        return getValues().getAsLong(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() {
+        return getAccountTypeManager().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);
+    }
+
+    public void addDataItemValues(ContentValues values) {
+        addNamedDataItemValues(Data.CONTENT_URI, values);
+    }
+
+    public void addNamedDataItemValues(Uri uri, ContentValues values) {
+        mDataItems.add(new NamedDataItem(uri, DataItem.createFrom(this, values)));
+    }
+
+    public List<DataItem> getDataItems() {
+        final ArrayList<DataItem> list = new ArrayList<DataItem>();
+        for (NamedDataItem dataItem : mDataItems) {
+            if (Data.CONTENT_URI.equals(dataItem.uri)) {
+                list.add(dataItem.dataItem);
+            }
+        }
+        return list;
+    }
+
+    public List<NamedDataItem> getNamedDataItems() {
+        return mDataItems;
+    }
+
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("RawContact: ").append(mValues);
+        for (RawContact.NamedDataItem namedDataItem : mDataItems) {
+            sb.append("\n  ").append(namedDataItem.uri);
+            sb.append("\n  -> ").append(namedDataItem.dataItem.getContentValues());
+        }
+        return sb.toString();
+    }
+}
diff --git a/src/com/android/contacts/model/EntityDelta.java b/src/com/android/contacts/model/RawContactDelta.java
similarity index 83%
rename from src/com/android/contacts/model/EntityDelta.java
rename to src/com/android/contacts/model/RawContactDelta.java
index 0f45a4b..2ee9d5c 100644
--- a/src/com/android/contacts/model/EntityDelta.java
+++ b/src/com/android/contacts/model/RawContactDelta.java
@@ -16,48 +16,50 @@
 
 package com.android.contacts.model;
 
-import com.android.contacts.test.NeededForTesting;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
-
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderOperation.Builder;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.Entity;
-import android.content.Entity.NamedContentValues;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.BaseColumns;
+import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Profile;
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
 
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.test.NeededForTesting;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 /**
- * Contains an {@link Entity} and records any modifications separately so the
- * original {@link Entity} can be swapped out with a newer version and the
+ * 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 Entity}, which then becomes an insert {@link RawContacts} case.
+ * empty {@link RawContact}, which then becomes an insert {@link RawContacts} case.
  * <p>
- * When applying modifications over an {@link Entity}, we try finding the
+ * 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 Entity}, we know the original data must
+ * 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 EntityDelta implements Parcelable {
+public class RawContactDelta implements Parcelable {
     // TODO: optimize by using contentvalues pool, since we allocate so many of them
 
     private static final String TAG = "EntityDelta";
@@ -80,40 +82,40 @@
      */
     private final HashMap<String, ArrayList<ValuesDelta>> mEntries = Maps.newHashMap();
 
-    public EntityDelta() {
+    public RawContactDelta() {
     }
 
-    public EntityDelta(ValuesDelta values) {
+    public RawContactDelta(ValuesDelta values) {
         mValues = values;
     }
 
     /**
-     * Build an {@link EntityDelta} using the given {@link Entity} as a
+     * Build an {@link RawContactDelta} using the given {@link RawContact} as a
      * starting point; the "before" snapshot.
      */
-    public static EntityDelta fromBefore(Entity before) {
-        final EntityDelta entity = new EntityDelta();
-        entity.mValues = ValuesDelta.fromBefore(before.getEntityValues());
-        entity.mValues.setIdColumn(RawContacts._ID);
-        for (NamedContentValues namedValues : before.getSubValues()) {
-            entity.addEntry(ValuesDelta.fromBefore(namedValues.values));
+    public static RawContactDelta fromBefore(RawContact before) {
+        final RawContactDelta rawContactDelta = new RawContactDelta();
+        rawContactDelta.mValues = ValuesDelta.fromBefore(before.getValues());
+        rawContactDelta.mValues.setIdColumn(RawContacts._ID);
+        for (DataItem dataItem : before.getDataItems()) {
+            rawContactDelta.addEntry(ValuesDelta.fromBefore(dataItem.getContentValues()));
         }
-        return entity;
+        return rawContactDelta;
     }
 
     /**
-     * Merge the "after" values from the given {@link EntityDelta} onto the
-     * "before" state represented by this {@link EntityDelta}, discarding any
+     * 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 EntityDelta mergeAfter(EntityDelta local, EntityDelta remote) {
+    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 EntityDelta();
+        if (local == null) local = new RawContactDelta();
 
         if (LOGV) {
             final Long localVersion = (local.mValues == null) ? null : local.mValues
@@ -224,6 +226,26 @@
         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.
@@ -309,8 +331,8 @@
 
     @Override
     public boolean equals(Object object) {
-        if (object instanceof EntityDelta) {
-            final EntityDelta other = (EntityDelta)object;
+        if (object instanceof RawContactDelta) {
+            final RawContactDelta other = (RawContactDelta)object;
 
             // Equality failed if parent values different
             if (!other.mValues.equals(mValues)) return false;
@@ -404,7 +426,7 @@
     /**
      * Build a list of {@link ContentProviderOperation} that will transform the
      * current "before" {@link Entity} state into the modified state which this
-     * {@link EntityDelta} represents.
+     * {@link RawContactDelta} represents.
      */
     public void buildDiff(ArrayList<ContentProviderOperation> buildInto) {
         final int firstIndex = buildInto.size();
@@ -525,15 +547,16 @@
         mContactsQueryUri = Profile.CONTENT_RAW_CONTACTS_URI;
     }
 
-    public static final Parcelable.Creator<EntityDelta> CREATOR = new Parcelable.Creator<EntityDelta>() {
-        public EntityDelta createFromParcel(Parcel in) {
-            final EntityDelta state = new EntityDelta();
+    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 EntityDelta[] newArray(int size) {
-            return new EntityDelta[size];
+        public RawContactDelta[] newArray(int size) {
+            return new RawContactDelta[size];
         }
     };
 
@@ -963,5 +986,118 @@
                 return new ValuesDelta[size];
             }
         };
+
+        public void setGroupRowId(long groupId) {
+            put(GroupMembership.GROUP_ROW_ID, groupId);
+        }
+
+        public Long getGroupRowId() {
+            return getAsLong(GroupMembership.GROUP_ROW_ID);
+        }
+
+        public void setPhoto(byte[] value) {
+            put(Photo.PHOTO, value);
+        }
+
+        public byte[] getPhoto() {
+            return getAsByteArray(Photo.PHOTO);
+        }
+
+        public void setSuperPrimary(boolean val) {
+            if (val) {
+                put(Data.IS_SUPER_PRIMARY, 1);
+            } else {
+                put(Data.IS_SUPER_PRIMARY, 0);
+            }
+        }
+
+        public void setPhoneticFamilyName(String value) {
+            put(StructuredName.PHONETIC_FAMILY_NAME, value);
+        }
+
+        public void setPhoneticMiddleName(String value) {
+            put(StructuredName.PHONETIC_MIDDLE_NAME, value);
+        }
+
+        public void setPhoneticGivenName(String value) {
+            put(StructuredName.PHONETIC_GIVEN_NAME, value);
+        }
+
+        public String getPhoneticFamilyName() {
+            return getAsString(StructuredName.PHONETIC_FAMILY_NAME);
+        }
+
+        public String getPhoneticMiddleName() {
+            return getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
+        }
+
+        public String getPhoneticGivenName() {
+            return getAsString(StructuredName.PHONETIC_GIVEN_NAME);
+        }
+
+        public String getDisplayName() {
+            return getAsString(StructuredName.DISPLAY_NAME);
+        }
+
+        public void setDisplayName(String name) {
+            if (name == null) {
+                putNull(StructuredName.DISPLAY_NAME);
+            } else {
+                put(StructuredName.DISPLAY_NAME, name);
+            }
+        }
+
+        public void copyStructuredNameFieldsFrom(ValuesDelta name) {
+            copyStringFrom(name, StructuredName.DISPLAY_NAME);
+
+            copyStringFrom(name, StructuredName.GIVEN_NAME);
+            copyStringFrom(name, StructuredName.FAMILY_NAME);
+            copyStringFrom(name, StructuredName.PREFIX);
+            copyStringFrom(name, StructuredName.MIDDLE_NAME);
+            copyStringFrom(name, StructuredName.SUFFIX);
+
+            copyStringFrom(name, StructuredName.PHONETIC_GIVEN_NAME);
+            copyStringFrom(name, StructuredName.PHONETIC_MIDDLE_NAME);
+            copyStringFrom(name, StructuredName.PHONETIC_FAMILY_NAME);
+
+            copyStringFrom(name, StructuredName.FULL_NAME_STYLE);
+            copyStringFrom(name, StructuredName.PHONETIC_NAME_STYLE);
+        }
+
+        public String getPhoneNumber() {
+            return getAsString(Phone.NUMBER);
+        }
+
+        public String getPhoneNormalizedNumber() {
+            return getAsString(Phone.NORMALIZED_NUMBER);
+        }
+
+        public boolean phoneHasType() {
+            return containsKey(Phone.TYPE);
+        }
+
+        public int getPhoneType() {
+            return getAsInteger(Phone.TYPE);
+        }
+
+        public String getPhoneLabel() {
+            return getAsString(Phone.LABEL);
+        }
+
+        public String getEmailData() {
+            return getAsString(Email.DATA);
+        }
+
+        public boolean emailHasType() {
+            return containsKey(Email.TYPE);
+        }
+
+        public int getEmailType() {
+            return getAsInteger(Email.TYPE);
+        }
+
+        public String getEmailLabel() {
+            return getAsString(Email.LABEL);
+        }
     }
 }
diff --git a/src/com/android/contacts/model/EntityDeltaList.java b/src/com/android/contacts/model/RawContactDeltaList.java
similarity index 78%
rename from src/com/android/contacts/model/EntityDeltaList.java
rename to src/com/android/contacts/model/RawContactDeltaList.java
index 47fd9c6..82dd494 100644
--- a/src/com/android/contacts/model/EntityDeltaList.java
+++ b/src/com/android/contacts/model/RawContactDeltaList.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.model;
 
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.google.android.collect.Lists;
-
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderOperation.Builder;
 import android.content.ContentResolver;
@@ -33,45 +30,47 @@
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
 
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 
 /**
- * Container for multiple {@link EntityDelta} objects, usually when editing
+ * Container for multiple {@link RawContactDelta} objects, usually when editing
  * together as an entire aggregate. Provides convenience methods for parceling
- * and applying another {@link EntityDeltaList} over it.
+ * and applying another {@link RawContactDeltaList} over it.
  */
-public class EntityDeltaList extends ArrayList<EntityDelta> implements Parcelable {
-    private static final String TAG = "EntityDeltaList";
+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;
 
-    private EntityDeltaList() {
+    private RawContactDeltaList() {
     }
 
     /**
-     * Create an {@link EntityDeltaList} that contains the given {@link EntityDelta},
+     * Create an {@link RawContactDeltaList} that contains the given {@link RawContactDelta},
      * usually when inserting a new {@link Contacts} entry.
      */
-    public static EntityDeltaList fromSingle(EntityDelta delta) {
-        final EntityDeltaList state = new EntityDeltaList();
+    public static RawContactDeltaList fromSingle(RawContactDelta delta) {
+        final RawContactDeltaList state = new RawContactDeltaList();
         state.add(delta);
         return state;
     }
 
     /**
-     * Create an {@link EntityDeltaList} based on {@link Contacts} specified by the
+     * 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 EntityDeltaList fromQuery(Uri entityUri, ContentResolver resolver,
+    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));
+        final EntityIterator iterator = RawContacts.newEntityIterator(
+                resolver.query(entityUri, null, selection, selectionArgs, sortOrder));
         try {
             return fromIterator(iterator);
         } finally {
@@ -80,36 +79,41 @@
     }
 
     /**
-     * Create an {@link EntityDeltaList} that contains the entities of the Iterator as before
-     * values.
+     * 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 EntityDeltaList fromIterator(Iterator<Entity> iterator) {
-        final EntityDeltaList state = new EntityDeltaList();
+    public static RawContactDeltaList fromIterator(Iterator<?> iterator) {
+        final RawContactDeltaList state = new RawContactDeltaList();
         // Perform background query to pull contact details
         while (iterator.hasNext()) {
             // Read all contacts into local deltas to prepare for edits
-            final Entity before = iterator.next();
-            final EntityDelta entity = EntityDelta.fromBefore(before);
-            state.add(entity);
+            Object nextObject = iterator.next();
+            final RawContact before = nextObject instanceof Entity
+                    ? RawContact.createFrom((Entity) nextObject)
+                    : (RawContact) nextObject;
+            final RawContactDelta rawContactDelta = RawContactDelta.fromBefore(before);
+            state.add(rawContactDelta);
         }
         return state;
     }
 
     /**
-     * Merge the "after" values from the given {@link EntityDeltaList}, discarding any
+     * 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 EntityDeltaList}.
+     * edits onto an updated {@link RawContactDeltaList}.
      */
-    public static EntityDeltaList mergeAfter(EntityDeltaList local, EntityDeltaList remote) {
-        if (local == null) local = new EntityDeltaList();
+    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 (EntityDelta remoteEntity : remote) {
+        for (RawContactDelta remoteEntity : remote) {
             final Long rawContactId = remoteEntity.getValues().getId();
 
             // Find or create local match and merge
-            final EntityDelta localEntity = local.getByRawContactId(rawContactId);
-            final EntityDelta merged = EntityDelta.mergeAfter(localEntity, remoteEntity);
+            final RawContactDelta localEntity = local.getByRawContactId(rawContactId);
+            final RawContactDelta merged = RawContactDelta.mergeAfter(localEntity, remoteEntity);
 
             if (localEntity == null && merged != null) {
                 // No local entry before, so insert
@@ -123,7 +127,7 @@
     /**
      * Build a list of {@link ContentProviderOperation} that will transform all
      * the "before" {@link Entity} states into the modified state which all
-     * {@link EntityDelta} objects represent. This method specifically creates
+     * {@link RawContactDelta} objects represent. This method specifically creates
      * any {@link AggregationExceptions} rules needed to groups edits together.
      */
     public ArrayList<ContentProviderOperation> buildDiff() {
@@ -136,7 +140,7 @@
         int firstInsertRow = -1;
 
         // First pass enforces versions remain consistent
-        for (EntityDelta delta : this) {
+        for (RawContactDelta delta : this) {
             delta.buildAssert(diff);
         }
 
@@ -146,7 +150,7 @@
         int rawContactIndex = 0;
 
         // Second pass builds actual operations
-        for (EntityDelta delta : this) {
+        for (RawContactDelta delta : this) {
             final int firstBatch = diff.size();
             final boolean isInsert = delta.isContactInsert();
             backRefs[rawContactIndex++] = isInsert ? firstBatch : -1;
@@ -281,12 +285,12 @@
     }
 
     /**
-     * Search all contained {@link EntityDelta} for the first one with an
+     * 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 (EntityDelta delta : this) {
+        for (RawContactDelta delta : this) {
             final Long rawContactId = delta.getValues().getAsLong(RawContacts._ID);
             if (rawContactId != null && rawContactId >= 0) {
                 return rawContactId;
@@ -296,11 +300,11 @@
     }
 
     /**
-     * Find {@link RawContacts#_ID} of the requested {@link EntityDelta}.
+     * Find {@link RawContacts#_ID} of the requested {@link RawContactDelta}.
      */
     public Long getRawContactId(int index) {
         if (index >= 0 && index < this.size()) {
-            final EntityDelta delta = this.get(index);
+            final RawContactDelta delta = this.get(index);
             final ValuesDelta values = delta.getValues();
             if (values.isVisible()) {
                 return values.getAsLong(RawContacts._ID);
@@ -310,9 +314,9 @@
     }
 
     /**
-     * Find the raw-contact (an {@link EntityDelta}) with the specified ID.
+     * Find the raw-contact (an {@link RawContactDelta}) with the specified ID.
      */
-    public EntityDelta getByRawContactId(Long rawContactId) {
+    public RawContactDelta getByRawContactId(Long rawContactId) {
         final int index = this.indexOfRawContactId(rawContactId);
         return (index == -1) ? null : this.get(index);
     }
@@ -332,19 +336,21 @@
         return -1;
     }
 
-    /** Return the index of the first EntityDelta corresponding to a writable raw-contact, or -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 (EntityDelta delta : this) {
+        for (RawContactDelta delta : this) {
             if (delta.getRawContactAccountType(context).areContactsWritable()) return entityIndex;
             entityIndex++;
         }
         return -1;
     }
 
-    /**  Return the first EntityDelta corresponding to a writable raw-contact, or null. */
-    public EntityDelta getFirstWritableRawContact(Context context) {
+    /**  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);
     }
@@ -352,7 +358,7 @@
     public ValuesDelta getSuperPrimaryEntry(final String mimeType) {
         ValuesDelta primary = null;
         ValuesDelta randomEntry = null;
-        for (EntityDelta delta : this) {
+        for (RawContactDelta delta : this) {
             final ArrayList<ValuesDelta> mimeEntries = delta.getMimeEntries(mimeType);
             if (mimeEntries == null) return null;
 
@@ -404,7 +410,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         final int size = this.size();
         dest.writeInt(size);
-        for (EntityDelta delta : this) {
+        for (RawContactDelta delta : this) {
             dest.writeParcelable(delta, flags);
         }
         dest.writeLongArray(mJoinWithRawContactIds);
@@ -416,24 +422,24 @@
         final ClassLoader loader = getClass().getClassLoader();
         final int size = source.readInt();
         for (int i = 0; i < size; i++) {
-            this.add(source.<EntityDelta> readParcelable(loader));
+            this.add(source.<RawContactDelta> readParcelable(loader));
         }
         mJoinWithRawContactIds = source.createLongArray();
         mSplitRawContacts = source.readInt() != 0;
     }
 
-    public static final Parcelable.Creator<EntityDeltaList> CREATOR =
-            new Parcelable.Creator<EntityDeltaList>() {
+    public static final Parcelable.Creator<RawContactDeltaList> CREATOR =
+            new Parcelable.Creator<RawContactDeltaList>() {
         @Override
-        public EntityDeltaList createFromParcel(Parcel in) {
-            final EntityDeltaList state = new EntityDeltaList();
+        public RawContactDeltaList createFromParcel(Parcel in) {
+            final RawContactDeltaList state = new RawContactDeltaList();
             state.readFromParcel(in);
             return state;
         }
 
         @Override
-        public EntityDeltaList[] newArray(int size) {
-            return new EntityDeltaList[size];
+        public RawContactDeltaList[] newArray(int size) {
+            return new RawContactDeltaList[size];
         }
     };
 
diff --git a/src/com/android/contacts/model/EntityModifier.java b/src/com/android/contacts/model/RawContactModifier.java
similarity index 91%
rename from src/com/android/contacts/model/EntityModifier.java
rename to src/com/android/contacts/model/RawContactModifier.java
index 2d87ff0..c397e5f 100644
--- a/src/com/android/contacts/model/EntityModifier.java
+++ b/src/com/android/contacts/model/RawContactModifier.java
@@ -16,16 +16,6 @@
 
 package com.android.contacts.model;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.editor.EventFieldEditorView;
-import com.android.contacts.util.NameConverter;
-import com.android.contacts.editor.PhoneticNameEditorView;
-import com.android.contacts.model.AccountType.EditField;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.AccountType.EventEditType;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.util.DateUtils;
-
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
@@ -56,6 +46,20 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.editor.EventFieldEditorView;
+import com.android.contacts.editor.PhoneticNameEditorView;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountType.EditField;
+import com.android.contacts.model.account.AccountType.EditType;
+import com.android.contacts.model.account.AccountType.EventEditType;
+import com.android.contacts.model.account.GoogleAccountType;
+import com.android.contacts.model.dataitem.DataKind;
+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;
@@ -68,21 +72,21 @@
 import java.util.Set;
 
 /**
- * Helper methods for modifying an {@link EntityDelta}, such as inserting
+ * Helper methods for modifying an {@link RawContactDelta}, such as inserting
  * new rows, or enforcing {@link AccountType}.
  */
-public class EntityModifier {
-    private static final String TAG = "EntityModifier";
+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 EntityDelta}, determine if the given
+     * For the given {@link RawContactDelta}, determine if the given
      * {@link DataKind} could be inserted under specific
      * {@link AccountType}.
      */
-    public static boolean canInsert(EntityDelta state, DataKind kind) {
+    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);
@@ -91,8 +95,8 @@
         return (validTypes && validOverall);
     }
 
-    public static boolean hasValidTypes(EntityDelta state, DataKind kind) {
-        if (EntityModifier.hasEditTypes(kind)) {
+    public static boolean hasValidTypes(RawContactDelta state, DataKind kind) {
+        if (RawContactModifier.hasEditTypes(kind)) {
             return (getValidTypes(state, kind).size() > 0);
         } else {
             return true;
@@ -101,12 +105,12 @@
 
     /**
      * Ensure that at least one of the given {@link DataKind} exists in the
-     * given {@link EntityDelta} state, and try creating one if none exist.
+     * 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(
-            EntityDelta state, AccountType accountType, String mimeType) {
+            RawContactDelta state, AccountType accountType, String mimeType) {
         final DataKind kind = accountType.getKindForMimetype(mimeType);
         final boolean hasChild = state.getMimeEntriesCount(mimeType, true) > 0;
 
@@ -127,16 +131,16 @@
     }
 
     /**
-     * For the given {@link EntityDelta} and {@link DataKind}, return the
+     * 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(EntityDelta state, DataKind kind) {
+    public static ArrayList<EditType> getValidTypes(RawContactDelta state, DataKind kind) {
         return getValidTypes(state, kind, null, true, null);
     }
 
     /**
-     * For the given {@link EntityDelta} and {@link DataKind}, return the
+     * For the given {@link RawContactDelta} and {@link DataKind}, return the
      * list possible {@link EditType} options available based on
      * {@link AccountType}.
      *
@@ -144,13 +148,13 @@
      *            list, even when an otherwise-invalid choice. This is useful
      *            when showing a dialog that includes the current type.
      */
-    public static ArrayList<EditType> getValidTypes(EntityDelta state, DataKind kind,
+    public static ArrayList<EditType> getValidTypes(RawContactDelta state, DataKind kind,
             EditType forceInclude) {
         return getValidTypes(state, kind, forceInclude, true, null);
     }
 
     /**
-     * For the given {@link EntityDelta} and {@link DataKind}, return the
+     * For the given {@link RawContactDelta} and {@link DataKind}, return the
      * list possible {@link EditType} options available based on
      * {@link AccountType}.
      *
@@ -161,9 +165,9 @@
      *            {@link EditType#secondary}.
      * @param typeCount When provided, will be used for the frequency count of
      *            each {@link EditType}, otherwise built using
-     *            {@link #getTypeFrequencies(EntityDelta, DataKind)}.
+     *            {@link #getTypeFrequencies(RawContactDelta, DataKind)}.
      */
-    private static ArrayList<EditType> getValidTypes(EntityDelta state, DataKind kind,
+    private static ArrayList<EditType> getValidTypes(RawContactDelta state, DataKind kind,
             EditType forceInclude, boolean includeSecondary, SparseIntArray typeCount) {
         final ArrayList<EditType> validTypes = new ArrayList<EditType>();
 
@@ -197,11 +201,11 @@
 
     /**
      * Count up the frequency that each {@link EditType} appears in the given
-     * {@link EntityDelta}. The returned {@link SparseIntArray} maps from
+     * {@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(EntityDelta state, DataKind kind) {
+    private static SparseIntArray getTypeFrequencies(RawContactDelta state, DataKind kind) {
         final SparseIntArray typeCount = new SparseIntArray();
 
         // Find all entries for this kind, bailing early if none found
@@ -297,7 +301,7 @@
      * first primary type that doesn't already exist. When all valid types
      * exist, we pick the last valid option.
      */
-    public static EditType getBestValidType(EntityDelta state, DataKind kind,
+    public static EditType getBestValidType(RawContactDelta state, DataKind kind,
             boolean includeSecondary, int exactValue) {
         // Shortcut when no types
         if (kind.typeColumn == null) return null;
@@ -338,10 +342,10 @@
 
     /**
      * Insert a new child of kind {@link DataKind} into the given
-     * {@link EntityDelta}. Tries using the best {@link EditType} found using
-     * {@link #getBestValidType(EntityDelta, DataKind, boolean, int)}.
+     * {@link RawContactDelta}. Tries using the best {@link EditType} found using
+     * {@link #getBestValidType(RawContactDelta, DataKind, boolean, int)}.
      */
-    public static ValuesDelta insertChild(EntityDelta state, DataKind kind) {
+    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) {
@@ -353,9 +357,9 @@
 
     /**
      * Insert a new child of kind {@link DataKind} into the given
-     * {@link EntityDelta}, marked with the given {@link EditType}.
+     * {@link RawContactDelta}, marked with the given {@link EditType}.
      */
-    public static ValuesDelta insertChild(EntityDelta state, DataKind kind, EditType type) {
+    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();
@@ -379,13 +383,13 @@
     }
 
     /**
-     * Processing to trim any empty {@link ValuesDelta} and {@link EntityDelta}
-     * from the given {@link EntityDeltaList}, assuming the given {@link AccountTypeManager}
+     * 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(EntityDeltaList set, AccountTypeManager accountTypes) {
-        for (EntityDelta state : set) {
+    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);
@@ -394,12 +398,12 @@
         }
     }
 
-    public static boolean hasChanges(EntityDeltaList set, AccountTypeManager accountTypes) {
+    public static boolean hasChanges(RawContactDeltaList set, AccountTypeManager accountTypes) {
         if (set.isMarkedForSplitting() || set.isMarkedForJoining()) {
             return true;
         }
 
-        for (EntityDelta state : set) {
+        for (RawContactDelta state : set) {
             ValuesDelta values = state.getValues();
             final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
             final String dataSet = values.getAsString(RawContacts.DATA_SET);
@@ -413,11 +417,11 @@
 
     /**
      * Processing to trim any empty {@link ValuesDelta} rows from the given
-     * {@link EntityDelta}, assuming the given {@link AccountType} dictates
+     * {@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(EntityDelta state, AccountType accountType) {
+    public static void trimEmpty(RawContactDelta state, AccountType accountType) {
         boolean hasValues = false;
 
         // Walk through entries for each well-known kind
@@ -440,7 +444,7 @@
                 final boolean isPhoto = TextUtils.equals(Photo.CONTENT_ITEM_TYPE, kind.mimeType);
                 final boolean isGooglePhoto = isPhoto && isGoogleAccount;
 
-                if (EntityModifier.isEmpty(entry, kind) && !isGooglePhoto) {
+                if (RawContactModifier.isEmpty(entry, kind) && !isGooglePhoto) {
                     if (DEBUG) {
                         Log.v(TAG, "Trimming: " + entry.toString());
                     }
@@ -456,7 +460,7 @@
         }
     }
 
-    private static boolean hasChanges(EntityDelta state, AccountType accountType) {
+    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);
@@ -516,10 +520,10 @@
     }
 
     /**
-     * Parse the given {@link Bundle} into the given {@link EntityDelta} state,
+     * 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, EntityDelta state,
+    public static void parseExtras(Context context, AccountType accountType, RawContactDelta state,
             Bundle extras) {
         if (extras == null || extras.size() == 0) {
             // Bail early if no useful data
@@ -560,8 +564,8 @@
         final boolean hasOrg = extras.containsKey(Insert.COMPANY)
                 || extras.containsKey(Insert.JOB_TITLE);
         final DataKind kindOrg = accountType.getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
-        if (hasOrg && EntityModifier.canInsert(state, kindOrg)) {
-            final ValuesDelta child = EntityModifier.insertChild(state, kindOrg);
+        if (hasOrg && RawContactModifier.canInsert(state, kindOrg)) {
+            final ValuesDelta child = RawContactModifier.insertChild(state, kindOrg);
 
             final String company = extras.getString(Insert.COMPANY);
             if (ContactsUtils.isGraphic(company)) {
@@ -577,8 +581,8 @@
         // Notes
         final boolean hasNotes = extras.containsKey(Insert.NOTES);
         final DataKind kindNotes = accountType.getKindForMimetype(Note.CONTENT_ITEM_TYPE);
-        if (hasNotes && EntityModifier.canInsert(state, kindNotes)) {
-            final ValuesDelta child = EntityModifier.insertChild(state, kindNotes);
+        if (hasNotes && RawContactModifier.canInsert(state, kindNotes)) {
+            final ValuesDelta child = RawContactModifier.insertChild(state, kindNotes);
 
             final String notes = extras.getString(Insert.NOTES);
             if (ContactsUtils.isGraphic(notes)) {
@@ -594,9 +598,9 @@
     }
 
     private static void parseStructuredNameExtra(
-            Context context, AccountType accountType, EntityDelta state, Bundle extras) {
+            Context context, AccountType accountType, RawContactDelta state, Bundle extras) {
         // StructuredName
-        EntityModifier.ensureKindExists(state, accountType, StructuredName.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(state, accountType, StructuredName.CONTENT_ITEM_TYPE);
         final ValuesDelta child = state.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
 
         final String name = extras.getString(Insert.NAME);
@@ -649,7 +653,7 @@
     }
 
     private static void parseStructuredPostalExtra(
-            AccountType accountType, EntityDelta state, Bundle extras) {
+            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,
@@ -675,7 +679,8 @@
     }
 
     private static void parseValues(
-            EntityDelta state, AccountType accountType, ArrayList<ContentValues> dataValueList) {
+            RawContactDelta state, AccountType accountType,
+            ArrayList<ContentValues> dataValueList) {
         for (ContentValues values : dataValueList) {
             String mimeType = values.getAsString(Data.MIMETYPE);
             if (TextUtils.isEmpty(mimeType)) {
@@ -873,7 +878,7 @@
 
     /**
      * Parse a specific entry from the given {@link Bundle} and insert into the
-     * given {@link EntityDelta}. Silently skips the insert when missing value
+     * 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
@@ -881,7 +886,7 @@
      * @param valueExtra {@link Bundle} key that holds the incoming value.
      * @param valueColumn Column to write value into {@link ValuesDelta}.
      */
-    public static ValuesDelta parseExtras(EntityDelta state, DataKind kind, Bundle extras,
+    public static ValuesDelta parseExtras(RawContactDelta state, DataKind kind, Bundle extras,
             String typeExtra, String valueExtra, String valueColumn) {
         final CharSequence value = extras.getCharSequence(valueExtra);
 
@@ -889,7 +894,7 @@
         if (kind == null) return null;
 
         // Bail when can't insert type, or value missing
-        final boolean canInsert = EntityModifier.canInsert(state, kind);
+        final boolean canInsert = RawContactModifier.canInsert(state, kind);
         final boolean validValue = (value != null && TextUtils.isGraphic(value));
         if (!validValue || !canInsert) return null;
 
@@ -897,10 +902,10 @@
         final boolean hasType = extras.containsKey(typeExtra);
         final int typeValue = extras.getInt(typeExtra, hasType ? BaseTypes.TYPE_CUSTOM
                 : Integer.MIN_VALUE);
-        final EditType editType = EntityModifier.getBestValidType(state, kind, true, typeValue);
+        final EditType editType = RawContactModifier.getBestValidType(state, kind, true, typeValue);
 
         // Create data row and fill with value
-        final ValuesDelta child = EntityModifier.insertChild(state, kind, editType);
+        final ValuesDelta child = RawContactModifier.insertChild(state, kind, editType);
         child.put(valueColumn, value.toString());
 
         if (editType != null && editType.customColumn != null) {
@@ -937,13 +942,13 @@
     private static final int TYPE_CUSTOM = Phone.TYPE_CUSTOM;
 
     /**
-     * Migrates old EntityDelta to newly created one with a new restriction supplied from
+     * 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,
-            EntityDelta oldState, EntityDelta newState,
+            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
@@ -996,8 +1001,8 @@
      * Checks {@link DataKind#isList} and {@link DataKind#typeOverallMax}, and restricts
      * the number of entries (ValuesDelta) inside newState.
      */
-    private static ArrayList<ValuesDelta> ensureEntryMaxSize(EntityDelta newState, DataKind kind,
-            ArrayList<ValuesDelta> mimeEntries) {
+    private static ArrayList<ValuesDelta> ensureEntryMaxSize(RawContactDelta newState,
+            DataKind kind, ArrayList<ValuesDelta> mimeEntries) {
         if (mimeEntries == null) {
             return null;
         }
@@ -1015,7 +1020,8 @@
 
     /** @hide Public only for testing. */
     public static void migrateStructuredName(
-            Context context, EntityDelta oldState, EntityDelta newState, DataKind newDataKind) {
+            Context context, RawContactDelta oldState, RawContactDelta newState,
+            DataKind newDataKind) {
         final ContentValues values =
                 oldState.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE).getAfter();
         if (values == null) {
@@ -1071,24 +1077,24 @@
         if (!TextUtils.isEmpty(phoneticFullName)) {
             if (!supportPhoneticFullName) {
                 // Old data has a phonetic (full) name, while the new account doesn't allow it.
-                final ContentValues tmpValues =
+                final StructuredNameDataItem tmpItem =
                         PhoneticNameEditorView.parsePhoneticName(phoneticFullName, null);
                 values.remove(DataKind.PSEUDO_COLUMN_PHONETIC_NAME);
                 if (supportPhoneticFamilyName) {
                     values.put(StructuredName.PHONETIC_FAMILY_NAME,
-                            tmpValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME));
+                            tmpItem.getPhoneticFamilyName());
                 } else {
                     values.remove(StructuredName.PHONETIC_FAMILY_NAME);
                 }
                 if (supportPhoneticMiddleName) {
                     values.put(StructuredName.PHONETIC_MIDDLE_NAME,
-                            tmpValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME));
+                            tmpItem.getPhoneticMiddleName());
                 } else {
                     values.remove(StructuredName.PHONETIC_MIDDLE_NAME);
                 }
                 if (supportPhoneticGivenName) {
                     values.put(StructuredName.PHONETIC_GIVEN_NAME,
-                            tmpValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME));
+                            tmpItem.getPhoneticGivenName());
                 } else {
                     values.remove(StructuredName.PHONETIC_GIVEN_NAME);
                 }
@@ -1117,7 +1123,7 @@
     }
 
     /** @hide Public only for testing. */
-    public static void migratePostal(EntityDelta oldState, EntityDelta newState,
+    public static void migratePostal(RawContactDelta oldState, RawContactDelta newState,
             DataKind newDataKind) {
         final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
                 oldState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE));
@@ -1228,7 +1234,7 @@
     }
 
     /** @hide Public only for testing. */
-    public static void migrateEvent(EntityDelta oldState, EntityDelta newState,
+    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));
@@ -1285,7 +1291,7 @@
 
     /** @hide Public only for testing. */
     public static void migrateGenericWithoutTypeColumn(
-            EntityDelta oldState, EntityDelta newState, DataKind newDataKind) {
+            RawContactDelta oldState, RawContactDelta newState, DataKind newDataKind) {
         final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
                 oldState.getMimeEntries(newDataKind.mimeType));
         if (mimeEntries == null || mimeEntries.isEmpty()) {
@@ -1302,7 +1308,7 @@
 
     /** @hide Public only for testing. */
     public static void migrateGenericWithTypeColumn(
-            EntityDelta oldState, EntityDelta newState, DataKind newDataKind) {
+            RawContactDelta oldState, RawContactDelta newState, DataKind newDataKind) {
         final ArrayList<ValuesDelta> mimeEntries = oldState.getMimeEntries(newDataKind.mimeType);
         if (mimeEntries == null || mimeEntries.isEmpty()) {
             return;
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/account/AccountType.java
similarity index 98%
rename from src/com/android/contacts/model/AccountType.java
rename to src/com/android/contacts/model/account/AccountType.java
index 7e48d83..edd17a0 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/account/AccountType.java
@@ -14,12 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.R;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import com.google.common.annotations.VisibleForTesting;
+package com.android.contacts.model.account;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -32,6 +27,13 @@
 import android.view.inputmethod.EditorInfo;
 import android.widget.EditText;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.dataitem.DataKind;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/src/com/android/contacts/model/AccountTypeWithDataSet.java b/src/com/android/contacts/model/account/AccountTypeWithDataSet.java
similarity index 98%
rename from src/com/android/contacts/model/AccountTypeWithDataSet.java
rename to src/com/android/contacts/model/account/AccountTypeWithDataSet.java
index b103755..ab0a891 100644
--- a/src/com/android/contacts/model/AccountTypeWithDataSet.java
+++ b/src/com/android/contacts/model/account/AccountTypeWithDataSet.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.google.common.base.Objects;
+package com.android.contacts.model.account;
 
 import android.content.Context;
 import android.database.Cursor;
@@ -26,6 +24,8 @@
 import android.provider.ContactsContract.RawContacts;
 import android.text.TextUtils;
 
+import com.google.common.base.Objects;
+
 
 /**
  * Encapsulates an "account type" string and a "data set" string.
diff --git a/src/com/android/contacts/model/AccountWithDataSet.java b/src/com/android/contacts/model/account/AccountWithDataSet.java
similarity index 98%
rename from src/com/android/contacts/model/AccountWithDataSet.java
rename to src/com/android/contacts/model/account/AccountWithDataSet.java
index 784e870..03fcc02 100644
--- a/src/com/android/contacts/model/AccountWithDataSet.java
+++ b/src/com/android/contacts/model/account/AccountWithDataSet.java
@@ -14,22 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.internal.util.Objects;
-import com.google.common.collect.Lists;
+package com.android.contacts.model.account;
 
 import android.accounts.Account;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Parcel;
-import android.os.Parcelable.Creator;
 import android.provider.BaseColumns;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.RawContacts;
 import android.text.TextUtils;
 
+import com.android.internal.util.Objects;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Pattern;
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/account/BaseAccountType.java
similarity index 99%
rename from src/com/android/contacts/model/BaseAccountType.java
rename to src/com/android/contacts/model/account/BaseAccountType.java
index 1e830e2..7f9e1ef 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/account/BaseAccountType.java
@@ -14,13 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.R;
-import com.android.contacts.test.NeededForTesting;
-import com.android.contacts.util.DateUtils;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
+package com.android.contacts.model.account;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -44,6 +38,13 @@
 import android.util.Log;
 import android.view.inputmethod.EditorInfo;
 
+import com.android.contacts.R;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.test.NeededForTesting;
+import com.android.contacts.util.DateUtils;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
diff --git a/src/com/android/contacts/model/ExchangeAccountType.java b/src/com/android/contacts/model/account/ExchangeAccountType.java
similarity index 98%
rename from src/com/android/contacts/model/ExchangeAccountType.java
rename to src/com/android/contacts/model/account/ExchangeAccountType.java
index 1e3f6ee..5ca3308 100644
--- a/src/com/android/contacts/model/ExchangeAccountType.java
+++ b/src/com/android/contacts/model/account/ExchangeAccountType.java
@@ -14,12 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType.DefinitionException;
-import com.android.contacts.util.DateUtils;
-import com.google.android.collect.Lists;
+package com.android.contacts.model.account;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -36,6 +31,11 @@
 import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.util.Log;
 
+import com.android.contacts.R;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.DateUtils;
+import com.google.common.collect.Lists;
+
 import java.util.Locale;
 
 public class ExchangeAccountType extends BaseAccountType {
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/account/ExternalAccountType.java
similarity index 99%
rename from src/com/android/contacts/model/ExternalAccountType.java
rename to src/com/android/contacts/model/account/ExternalAccountType.java
index d7420af..71dbebf 100644
--- a/src/com/android/contacts/model/ExternalAccountType.java
+++ b/src/com/android/contacts/model/account/ExternalAccountType.java
@@ -14,12 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
+package com.android.contacts.model.account;
 
 import android.content.Context;
 import android.content.pm.PackageInfo;
@@ -36,6 +31,12 @@
 import android.util.Log;
 import android.util.Xml;
 
+import com.android.contacts.model.dataitem.DataKind;
+import com.google.common.annotations.VisibleForTesting;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/com/android/contacts/model/FallbackAccountType.java b/src/com/android/contacts/model/account/FallbackAccountType.java
similarity index 96%
rename from src/com/android/contacts/model/FallbackAccountType.java
rename to src/com/android/contacts/model/account/FallbackAccountType.java
index 892c049..dae288d 100644
--- a/src/com/android/contacts/model/FallbackAccountType.java
+++ b/src/com/android/contacts/model/account/FallbackAccountType.java
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.R;
-import com.android.contacts.test.NeededForTesting;
+package com.android.contacts.model.account;
 
 import android.content.Context;
 import android.util.Log;
 
+import com.android.contacts.R;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.test.NeededForTesting;
+
 public class FallbackAccountType extends BaseAccountType {
     private static final String TAG = "FallbackAccountType";
 
diff --git a/src/com/android/contacts/model/GoogleAccountType.java b/src/com/android/contacts/model/account/GoogleAccountType.java
similarity index 97%
rename from src/com/android/contacts/model/GoogleAccountType.java
rename to src/com/android/contacts/model/account/GoogleAccountType.java
index a8a4069..192c3d0 100644
--- a/src/com/android/contacts/model/GoogleAccountType.java
+++ b/src/com/android/contacts/model/account/GoogleAccountType.java
@@ -14,12 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType.DefinitionException;
-import com.android.contacts.util.DateUtils;
-import com.google.android.collect.Lists;
+package com.android.contacts.model.account;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -29,6 +24,11 @@
 import android.provider.ContactsContract.CommonDataKinds.Relation;
 import android.util.Log;
 
+import com.android.contacts.R;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.DateUtils;
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
 public class GoogleAccountType extends BaseAccountType {
diff --git a/src/com/android/contacts/model/dataitem/DataItem.java b/src/com/android/contacts/model/dataitem/DataItem.java
new file mode 100644
index 0000000..25c44cb
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/DataItem.java
@@ -0,0 +1,214 @@
+/*
+ * 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.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.model.AccountTypeManager;
+import com.android.contacts.model.RawContact;
+import com.android.contacts.model.account.AccountType;
+
+/**
+ * This is the base class for data items, which represents a row from the Data table.
+ */
+public class DataItem {
+
+    private final ContentValues mContentValues;
+
+    /**
+     * The raw contact that this data item is associated with.  This can be null.
+     */
+    private final RawContact mRawContact;
+    private DataKind mDataKind;
+
+    protected DataItem(RawContact rawContact, ContentValues values) {
+        mContentValues = values;
+        mRawContact = rawContact;
+    }
+
+    /**
+     * 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(RawContact rawContact, ContentValues values) {
+        final String mimeType = values.getAsString(Data.MIMETYPE);
+        if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new GroupMembershipDataItem(rawContact, values);
+        } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new StructuredNameDataItem(rawContact, values);
+        } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new PhoneDataItem(rawContact, values);
+        } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new EmailDataItem(rawContact, values);
+        } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new StructuredPostalDataItem(rawContact, values);
+        } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new ImDataItem(rawContact, values);
+        } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new OrganizationDataItem(rawContact, values);
+        } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new NicknameDataItem(rawContact, values);
+        } else if (Note.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new NoteDataItem(rawContact, values);
+        } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new WebsiteDataItem(rawContact, values);
+        } else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new SipAddressDataItem(rawContact, values);
+        } else if (Event.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new EventDataItem(rawContact, values);
+        } else if (Relation.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new RelationDataItem(rawContact, values);
+        } else if (Identity.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new IdentityDataItem(rawContact, values);
+        } else if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            return new PhotoDataItem(rawContact, values);
+        }
+
+        // generic
+        return new DataItem(rawContact, values);
+    }
+
+    public ContentValues getContentValues() {
+        return mContentValues;
+    }
+
+    protected RawContact getRawContact() {
+        return mRawContact;
+    }
+
+    public void setRawContactId(long rawContactId) {
+        mContentValues.put(Data.RAW_CONTACT_ID, rawContactId);
+    }
+
+    /**
+     * Returns the data id.
+     */
+    public long getId() {
+        return mContentValues.getAsLong(Data._ID);
+    }
+
+    public long getRawContactId() {
+        return mContentValues.getAsLong(Data.RAW_CONTACT_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 int getDataVersion() {
+        return mContentValues.getAsInteger(Data.DATA_VERSION);
+    }
+
+    public AccountTypeManager getAccountTypeManager() {
+        if (mRawContact == null) {
+            return null;
+        } else {
+            return mRawContact.getAccountTypeManager();
+        }
+    }
+
+    public AccountType getAccountType() {
+        if (mRawContact == null) {
+            return null;
+        } else {
+            return mRawContact.getAccountType();
+        }
+    }
+
+    /**
+     * This method can only be invoked if the raw contact is non-null.
+     */
+    public DataKind getDataKind() {
+        if (mRawContact == null) {
+            throw new IllegalStateException("mRawContact must be non-null to call getDataKind()");
+        }
+
+        if (mDataKind == null) {
+            mDataKind = getAccountTypeManager().getKindOrFallback(
+                    mRawContact.getAccountTypeString(), mRawContact.getDataSet(), getMimeType());
+        }
+
+        return mDataKind;
+    }
+
+    public boolean hasKindTypeColumn() {
+        final String key = getDataKind().typeColumn;
+        return key != null && mContentValues.containsKey(key);
+    }
+
+    public int getKindTypeColumn() {
+        final String key = getDataKind().typeColumn;
+        return mContentValues.getAsInteger(key);
+    }
+
+    /**
+     * This builds the data string depending on the type of data item by using the generic
+     * DataKind object underneath.  This DataItem object must be associated with a raw contact
+     * for this function to work.
+     */
+    public String buildDataString() {
+        if (mRawContact == null) {
+            throw new IllegalStateException("mRawContact must be non-null to call getDataKind()");
+        }
+        final DataKind kind = getDataKind();
+
+        if (kind.actionBody == null) {
+            return null;
+        }
+        CharSequence actionBody = kind.actionBody.inflateUsing(mRawContact.getContext(),
+                mContentValues);
+        return actionBody == null ? null : actionBody.toString();
+    }
+
+    public String getKindString() {
+        final DataKind kind = getDataKind();
+        return (kind.titleRes == -1 || kind.titleRes == 0) ? ""
+                : mRawContact.getContext().getString(kind.titleRes);
+    }
+}
diff --git a/src/com/android/contacts/model/DataKind.java b/src/com/android/contacts/model/dataitem/DataKind.java
similarity index 95%
rename from src/com/android/contacts/model/DataKind.java
rename to src/com/android/contacts/model/dataitem/DataKind.java
index 0d60317..8707012 100644
--- a/src/com/android/contacts/model/DataKind.java
+++ b/src/com/android/contacts/model/dataitem/DataKind.java
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType.EditField;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.AccountType.StringInflater;
-import com.google.common.collect.Iterators;
+package com.android.contacts.model.dataitem;
 
 import android.content.ContentValues;
 import android.provider.ContactsContract.Data;
 
+import com.android.contacts.R;
+import com.android.contacts.model.account.AccountType.EditField;
+import com.android.contacts.model.account.AccountType.EditType;
+import com.android.contacts.model.account.AccountType.StringInflater;
+import com.google.common.collect.Iterators;
+
 import java.text.SimpleDateFormat;
 import java.util.List;
 
@@ -144,4 +144,4 @@
             return Iterators.toString(list.iterator());
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/model/dataitem/EmailDataItem.java b/src/com/android/contacts/model/dataitem/EmailDataItem.java
new file mode 100644
index 0000000..a535c73
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/EmailDataItem.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.contacts.model.RawContact;
+
+/**
+ * Represents an email data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Email}.
+ */
+public class EmailDataItem extends DataItem {
+
+    /* package */ EmailDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, 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);
+    }
+
+    /**
+     * Values is one of Email.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Email.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..2114279
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/EventDataItem.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents an event data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Event}.
+ */
+public class EventDataItem extends DataItem {
+
+    /* package */ EventDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+    }
+
+    public String getStartDate() {
+        return getContentValues().getAsString(Event.START_DATE);
+    }
+
+    /**
+     * Values are one of Event.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Event.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..aea9bca
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/GroupMembershipDataItem.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a group memebership data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.GroupMembership}.
+ */
+public class GroupMembershipDataItem extends DataItem {
+
+    /* package */ GroupMembershipDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, 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
new file mode 100644
index 0000000..fd4b836
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/IdentityDataItem.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents an identity data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Identity}.
+ */
+public class IdentityDataItem extends DataItem {
+
+    /* package */ IdentityDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, 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
new file mode 100644
index 0000000..3a08325
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/ImDataItem.java
@@ -0,0 +1,94 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents an IM data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Im}.
+ */
+public class ImDataItem extends DataItem {
+
+    private final boolean mCreatedFromEmail;
+
+    /* package */ ImDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+        mCreatedFromEmail = false;
+    }
+
+    private ImDataItem(RawContact rawContact, ContentValues values,
+            boolean createdFromEmail) {
+        super(rawContact, values);
+        mCreatedFromEmail = createdFromEmail;
+    }
+
+    public static ImDataItem createFromEmail(EmailDataItem item) {
+        ImDataItem im = new ImDataItem(item.getRawContact(),
+                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);
+        }
+    }
+
+    /**
+     * Values are one of Im.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Im.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..7b52510
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/NicknameDataItem.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a nickname data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Nickname}.
+ */
+public class NicknameDataItem extends DataItem {
+
+    public NicknameDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+    }
+
+    public String getName() {
+        return getContentValues().getAsString(Nickname.NAME);
+    }
+
+    /**
+     * Types are defined as Nickname.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Nickname.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..0d0fa24
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/NoteDataItem.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a note data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Note}.
+ */
+public class NoteDataItem extends DataItem {
+
+    /* package */ NoteDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, 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
new file mode 100644
index 0000000..1326bdb
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/OrganizationDataItem.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents an organization data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Organization}.
+ */
+public class OrganizationDataItem extends DataItem {
+
+    /* package */ OrganizationDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+    }
+
+    public String getCompany() {
+        return getContentValues().getAsString(Organization.COMPANY);
+    }
+
+    /**
+     * Values are one of Organization.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Organization.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..94a0054
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/PhoneDataItem.java
@@ -0,0 +1,57 @@
+/*
+ * 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.Phone;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a phone data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Phone}.
+ */
+public class PhoneDataItem extends DataItem {
+
+    /* package */ PhoneDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, 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);
+    }
+
+    /**
+     * Values are Phone.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Phone.TYPE);
+    }
+
+    public String getLabel() {
+        return getContentValues().getAsString(Phone.LABEL);
+    }
+
+}
diff --git a/src/com/android/contacts/model/dataitem/PhotoDataItem.java b/src/com/android/contacts/model/dataitem/PhotoDataItem.java
new file mode 100644
index 0000000..5e355fa
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/PhotoDataItem.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a photo data item, wrapping the columns in
+ * {@link ContactsContract.Contacts.Photo}.
+ */
+public class PhotoDataItem extends DataItem {
+
+    /* package */ PhotoDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, 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
new file mode 100644
index 0000000..7c22cf5
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/RelationDataItem.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a relation data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Relation}.
+ */
+public class RelationDataItem extends DataItem {
+
+    /* package */ RelationDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+    }
+
+    public String getName() {
+        return getContentValues().getAsString(Relation.NAME);
+    }
+
+    /**
+     * Values are one of Relation.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Relation.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..6b8e93d
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/SipAddressDataItem.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a sip address data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.SipAddress}.
+ */
+public class SipAddressDataItem extends DataItem {
+
+    /* package */ SipAddressDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+    }
+
+    public String getSipAddress() {
+        return getContentValues().getAsString(SipAddress.SIP_ADDRESS);
+    }
+
+    /**
+     * Value is one of SipAddress.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(SipAddress.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..4654a6f
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/StructuredNameDataItem.java
@@ -0,0 +1,100 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a structured name data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.StructuredName}.
+ */
+public class StructuredNameDataItem extends DataItem {
+
+    public StructuredNameDataItem() {
+        super(null, new ContentValues());
+        getContentValues().put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+    }
+
+    /* package */ StructuredNameDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, 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
new file mode 100644
index 0000000..cc2cf56
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/StructuredPostalDataItem.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a structured postal data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.StructuredPostal}.
+ */
+public class StructuredPostalDataItem extends DataItem {
+
+    /* package */ StructuredPostalDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+    }
+
+    public String getFormattedAddress() {
+        return getContentValues().getAsString(StructuredPostal.FORMATTED_ADDRESS);
+    }
+
+    /**
+     * Values are one of StructuredPostal.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(StructuredPostal.TYPE);
+    }
+
+    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
new file mode 100644
index 0000000..c3aadf3
--- /dev/null
+++ b/src/com/android/contacts/model/dataitem/WebsiteDataItem.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import com.android.contacts.model.RawContact;
+
+/**
+ * Represents a website data item, wrapping the columns in
+ * {@link ContactsContract.CommonDataKinds.Website}.
+ */
+public class WebsiteDataItem extends DataItem {
+
+    /* package */ WebsiteDataItem(RawContact rawContact, ContentValues values) {
+        super(rawContact, values);
+    }
+
+    public String getUrl() {
+        return getContentValues().getAsString(Website.URL);
+    }
+
+    /**
+     * Value is one of Website.TYPE_*
+     */
+    public int getType() {
+        return getContentValues().getAsInteger(Website.TYPE);
+    }
+
+    public String getLabel() {
+        return getContentValues().getAsString(Website.LABEL);
+    }
+}
diff --git a/src/com/android/contacts/preference/ContactsPreferenceActivity.java b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
index 0b1970e..79557ba 100644
--- a/src/com/android/contacts/preference/ContactsPreferenceActivity.java
+++ b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.preference;
 
-import com.android.contacts.R;
-import com.android.contacts.activities.PeopleActivity;
-
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.Intent;
@@ -26,6 +23,9 @@
 import android.preference.PreferenceActivity;
 import android.view.MenuItem;
 
+import com.android.contacts.R;
+import com.android.contacts.activities.PeopleActivity;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/preference/ContactsPreferences.java b/src/com/android/contacts/preference/ContactsPreferences.java
index 540158d..e88417f 100644
--- a/src/com/android/contacts/preference/ContactsPreferences.java
+++ b/src/com/android/contacts/preference/ContactsPreferences.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.preference;
 
-import com.android.contacts.R;
-
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -26,6 +24,8 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 
+import com.android.contacts.R;
+
 /**
  * Manages user preferences for contacts.
  */
diff --git a/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java b/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
index db4a94e..02177d2 100644
--- a/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
+++ b/src/com/android/contacts/preference/DisplayOptionsPreferenceFragment.java
@@ -16,11 +16,11 @@
 
 package com.android.contacts.preference;
 
-import com.android.contacts.R;
-
 import android.os.Bundle;
 import android.preference.PreferenceFragment;
 
+import com.android.contacts.R;
+
 /**
  * This fragment shows the preferences for the first header.
  */
diff --git a/src/com/android/contacts/preference/DisplayOrderPreference.java b/src/com/android/contacts/preference/DisplayOrderPreference.java
index bedce48..8629384 100644
--- a/src/com/android/contacts/preference/DisplayOrderPreference.java
+++ b/src/com/android/contacts/preference/DisplayOrderPreference.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.preference;
 
-import com.android.contacts.R;
-
 import android.app.AlertDialog.Builder;
 import android.content.Context;
 import android.preference.ListPreference;
 import android.provider.ContactsContract;
 import android.util.AttributeSet;
 
+import com.android.contacts.R;
+
 /**
  * Custom preference: view-name-as (first name first or last name first).
  */
diff --git a/src/com/android/contacts/preference/SortOrderPreference.java b/src/com/android/contacts/preference/SortOrderPreference.java
index 2ac9557..6ad4aad 100644
--- a/src/com/android/contacts/preference/SortOrderPreference.java
+++ b/src/com/android/contacts/preference/SortOrderPreference.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.preference;
 
-import com.android.contacts.R;
-
 import android.app.AlertDialog.Builder;
 import android.content.Context;
 import android.preference.ListPreference;
 import android.provider.ContactsContract;
 import android.util.AttributeSet;
 
+import com.android.contacts.R;
+
 /**
  * Custom preference: sort-by.
  */
diff --git a/src/com/android/contacts/quickcontact/Action.java b/src/com/android/contacts/quickcontact/Action.java
index 3a283fb..08fbce4 100644
--- a/src/com/android/contacts/quickcontact/Action.java
+++ b/src/com/android/contacts/quickcontact/Action.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.quickcontact;
 
-import com.android.contacts.Collapser;
-
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 
+import com.android.contacts.Collapser;
+
 /**
  * Abstract definition of an action that could be performed, along with
  * string description and icon.
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index ddec799..c10c338 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -16,32 +16,33 @@
 
 package com.android.contacts.quickcontact;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.util.Constants;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.android.contacts.util.StructuredPostalUtils;
-
 import android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.net.WebAddress;
-import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.provider.ContactsContract.Data;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.model.account.AccountType.EditType;
+import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.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.util.Constants;
+import com.android.contacts.util.PhoneCapabilityTester;
+import com.android.contacts.util.StructuredPostalUtils;
+
 /**
  * Description of a specific {@link Data#_ID} item, with style information
  * defined by a {@link DataKind}.
@@ -68,51 +69,45 @@
     /**
      * Create an action from common {@link Data} elements.
      */
-    public DataAction(Context context, String mimeType, DataKind kind, long dataId,
-            ContentValues entryValues) {
+    public DataAction(Context context, DataItem item) {
         mContext = context;
-        mKind = kind;
-        mMimeType = mimeType;
+        mKind = item.getDataKind();
+        mMimeType = item.getMimeType();
 
         // Determine type for subtitle
         mSubtitle = "";
-        if (kind.typeColumn != null) {
-            if (entryValues.containsKey(kind.typeColumn)) {
-                final int typeValue = entryValues.getAsInteger(kind.typeColumn);
+        if (item.hasKindTypeColumn()) {
+            final int typeValue = item.getKindTypeColumn();
 
-                // get type string
-                for (EditType type : kind.typeList) {
-                    if (type.rawValue == typeValue) {
-                        if (type.customColumn == null) {
-                            // Non-custom type. Get its description from the resource
-                            mSubtitle = context.getString(type.labelRes);
-                        } else {
-                            // Custom type. Read it from the database
-                            mSubtitle = entryValues.getAsString(type.customColumn);
-                        }
-                        break;
+            // get type string
+            for (EditType type : item.getDataKind().typeList) {
+                if (type.rawValue == typeValue) {
+                    if (type.customColumn == null) {
+                        // Non-custom type. Get its description from the resource
+                        mSubtitle = context.getString(type.labelRes);
+                    } else {
+                        // Custom type. Read it from the database
+                        mSubtitle = item.getContentValues().getAsString(type.customColumn);
                     }
+                    break;
                 }
             }
         }
 
-        final Integer superPrimary = entryValues.getAsInteger(Data.IS_SUPER_PRIMARY);
-        mIsPrimary = superPrimary != null && superPrimary != 0;
+        mIsPrimary = item.isSuperPrimary();
+        mBody = item.buildDataString();
 
-        if (mKind.actionBody != null) {
-            mBody = mKind.actionBody.inflateUsing(context, entryValues);
-        }
-
-        mDataId = dataId;
-        mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId);
+        mDataId = item.getId();
+        mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, mDataId);
 
         final boolean hasPhone = PhoneCapabilityTester.isPhone(mContext);
         final boolean hasSms = PhoneCapabilityTester.isSmsIntentRegistered(mContext);
 
         // Handle well-known MIME-types with special care
-        if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
+        if (item instanceof PhoneDataItem) {
             if (PhoneCapabilityTester.isPhone(mContext)) {
-                final String number = entryValues.getAsString(Phone.NUMBER);
+                PhoneDataItem phone = (PhoneDataItem) item;
+                final String number = phone.getNumber();
                 if (!TextUtils.isEmpty(number)) {
 
                     final Intent phoneIntent = hasPhone ? ContactsUtils.getCallIntent(number)
@@ -124,8 +119,8 @@
                     if (hasPhone && hasSms) {
                         mIntent = phoneIntent;
                         mAlternateIntent = smsIntent;
-                        mAlternateIconRes = kind.iconAltRes;
-                        mAlternateIconDescriptionRes = kind.iconAltDescriptionRes;
+                        mAlternateIconRes = phone.getDataKind().iconAltRes;
+                        mAlternateIconDescriptionRes = phone.getDataKind().iconAltDescriptionRes;
                     } else if (hasPhone) {
                         mIntent = phoneIntent;
                     } else if (hasSms) {
@@ -133,9 +128,10 @@
                     }
                 }
             }
-        } else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType)) {
+        } else if (item instanceof SipAddressDataItem) {
             if (PhoneCapabilityTester.isSipPhone(mContext)) {
-                final String address = entryValues.getAsString(SipAddress.SIP_ADDRESS);
+                final SipAddressDataItem sip = (SipAddressDataItem) item;
+                final String address = sip.getSipAddress();
                 if (!TextUtils.isEmpty(address)) {
                     final Uri callUri = Uri.fromParts(Constants.SCHEME_SIP, address, null);
                     mIntent = ContactsUtils.getCallIntent(callUri);
@@ -147,26 +143,27 @@
                     // for the SIP-related intent-filters in its manifest.
                 }
             }
-        } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            final String address = entryValues.getAsString(Email.DATA);
+        } else if (item instanceof EmailDataItem) {
+            final EmailDataItem email = (EmailDataItem) item;
+            final String address = email.getData();
             if (!TextUtils.isEmpty(address)) {
                 final Uri mailUri = Uri.fromParts(Constants.SCHEME_MAILTO, address, null);
                 mIntent = new Intent(Intent.ACTION_SENDTO, mailUri);
             }
 
-        } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            final String url = entryValues.getAsString(Website.URL);
+        } else if (item instanceof WebsiteDataItem) {
+            final WebsiteDataItem website = (WebsiteDataItem) item;
+            final String url = website.getUrl();
             if (!TextUtils.isEmpty(url)) {
                 WebAddress webAddress = new WebAddress(url);
                 mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
             }
 
-        } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(
-                    entryValues.getAsString(Data.MIMETYPE));
-            if (isEmail || isProtocolValid(entryValues)) {
-                final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK :
-                        entryValues.getAsInteger(Im.PROTOCOL);
+        } else if (item instanceof ImDataItem) {
+            ImDataItem im = (ImDataItem) item;
+            final boolean isEmail = im.isCreatedFromEmail();
+            if (isEmail || im.isProtocolValid()) {
+                final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();
 
                 if (isEmail) {
                     // Use Google Talk string when using Email, and clear data
@@ -176,8 +173,8 @@
                     mDataUri = null;
                 }
 
-                String host = entryValues.getAsString(Im.CUSTOM_PROTOCOL);
-                String data = entryValues.getAsString(isEmail ? Email.DATA : Im.DATA);
+                String host = im.getCustomProtocol();
+                String data = im.getData();
                 if (protocol != Im.PROTOCOL_CUSTOM) {
                     // Try bringing in a well-known host for specific protocols
                     host = ContactsUtils.lookupProviderNameFromId(protocol);
@@ -191,8 +188,7 @@
 
                     // If the address is also available for a video chat, we'll show the capability
                     // as a secondary action.
-                    final Integer chatCapabilityObj = entryValues.getAsInteger(Im.CHAT_CAPABILITY);
-                    final int chatCapability = chatCapabilityObj == null ? 0 : chatCapabilityObj;
+                    final int chatCapability = im.getChatCapability();
                     final boolean isVideoChatCapable =
                             (chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0;
                     final boolean isAudioChatCapable =
@@ -210,9 +206,9 @@
                     }
                 }
             }
-        } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            final String postalAddress =
-                    entryValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
+        } else if (item instanceof StructuredPostalDataItem) {
+            StructuredPostalDataItem postal = (StructuredPostalDataItem) item;
+            final String postalAddress = postal.getFormattedAddress();
             if (!TextUtils.isEmpty(postalAddress)) {
                 mIntent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
             }
@@ -221,7 +217,7 @@
         if (mIntent == null) {
             // Otherwise fall back to default VIEW action
             mIntent = new Intent(Intent.ACTION_VIEW);
-            mIntent.setDataAndType(mDataUri, mimeType);
+            mIntent.setDataAndType(mDataUri, item.getMimeType());
         }
 
         mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
@@ -236,19 +232,6 @@
         mPresence = presence;
     }
 
-    private boolean isProtocolValid(ContentValues entryValues) {
-        final String protocol = entryValues.getAsString(Im.PROTOCOL);
-        if (protocol == null) {
-            return false;
-        }
-        try {
-            Integer.valueOf(protocol);
-        } catch (NumberFormatException e) {
-            return false;
-        }
-        return true;
-    }
-
     @Override
     public CharSequence getSubtitle() {
         return mSubtitle;
diff --git a/src/com/android/contacts/quickcontact/FloatingChildLayout.java b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
index 20a3c1e..555f948 100644
--- a/src/com/android/contacts/quickcontact/FloatingChildLayout.java
+++ b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.quickcontact;
 
-import com.android.contacts.R;
-import com.android.contacts.test.NeededForReflection;
-import com.android.contacts.util.SchedulingUtils;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -36,6 +32,10 @@
 import android.widget.FrameLayout;
 import android.widget.PopupWindow;
 
+import com.android.contacts.R;
+import com.android.contacts.test.NeededForReflection;
+import com.android.contacts.util.SchedulingUtils;
+
 /**
  * Layout containing single child {@link View} which it attempts to center
  * around {@link #setChildTargetScreen(Rect)}.
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 7c93a26..25fb3f4 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -16,29 +16,13 @@
 
 package com.android.contacts.quickcontact;
 
-import com.android.contacts.Collapser;
-import com.android.contacts.ContactLoader;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.util.Constants;
-import com.android.contacts.util.DataStatus;
-import com.android.contacts.util.ImageViewDrawableSetter;
-import com.android.contacts.util.SchedulingUtils;
-import com.android.contacts.util.StopWatch;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ActivityNotFoundException;
 import android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
-import android.content.Entity;
-import android.content.Entity.NamedContentValues;
 import android.content.Intent;
 import android.content.Loader;
 import android.content.pm.PackageManager;
@@ -48,13 +32,11 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Im;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsContract.RawContacts;
 import android.support.v13.app.FragmentPagerAdapter;
@@ -74,6 +56,23 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.contacts.Collapser;
+import com.android.contacts.R;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.ContactLoader;
+import com.android.contacts.model.RawContact;
+import com.android.contacts.model.dataitem.DataItem;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.model.dataitem.EmailDataItem;
+import com.android.contacts.model.dataitem.ImDataItem;
+import com.android.contacts.util.Constants;
+import com.android.contacts.util.DataStatus;
+import com.android.contacts.util.ImageViewDrawableSetter;
+import com.android.contacts.util.SchedulingUtils;
+import com.android.contacts.util.StopWatch;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -330,7 +329,7 @@
     /**
      * Handle the result from the ContactLoader
      */
-    private void bindData(ContactLoader.Result data) {
+    private void bindData(Contact data) {
         final ResolveCache cache = ResolveCache.getInstance(this);
         final Context context = this;
 
@@ -339,42 +338,29 @@
 
         mDefaultsMap.clear();
 
-        mStopWatch.lap("atm"); // AccountTypeManager initialization start
-        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
-                context.getApplicationContext());
-        mStopWatch.lap("fatm"); // AccountTypeManager initialization finished
+        mStopWatch.lap("sph"); // Start photo setting
 
         final ImageView photoView = (ImageView) mPhotoContainer.findViewById(R.id.photo);
         mPhotoSetter.setupContactPhoto(data, photoView);
 
         mStopWatch.lap("ph"); // Photo set
 
-        for (Entity entity : data.getEntities()) {
-            final ContentValues entityValues = entity.getEntityValues();
-            final String accountType = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
-            final String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
-            for (NamedContentValues subValue : entity.getSubValues()) {
-                final ContentValues entryValues = subValue.values;
-                final String mimeType = entryValues.getAsString(Data.MIMETYPE);
+        for (RawContact rawContact : data.getRawContacts()) {
+            for (DataItem dataItem : rawContact.getDataItems()) {
+                final String mimeType = dataItem.getMimeType();
 
                 // Skip this data item if MIME-type excluded
                 if (isMimeExcluded(mimeType)) continue;
 
-                final long dataId = entryValues.getAsLong(Data._ID);
-                final Integer primary = entryValues.getAsInteger(Data.IS_PRIMARY);
-                final boolean isPrimary = primary != null && primary != 0;
-                final Integer superPrimary = entryValues.getAsInteger(Data.IS_SUPER_PRIMARY);
-                final boolean isSuperPrimary = superPrimary != null && superPrimary != 0;
+                final long dataId = dataItem.getId();
+                final boolean isPrimary = dataItem.isPrimary();
+                final boolean isSuperPrimary = dataItem.isSuperPrimary();
 
-                final DataKind kind =
-                        accountTypes.getKindOrFallback(accountType, dataSet, mimeType);
-
-                if (kind != null) {
+                if (dataItem.getDataKind() != null) {
                     // Build an action for this data entry, find a mapping to a UI
                     // element, build its summary from the cursor, and collect it
                     // along with all others of this MIME-type.
-                    final Action action = new DataAction(context, mimeType, kind, dataId,
-                            entryValues);
+                    final Action action = new DataAction(context, dataItem);
                     final boolean wasAdded = considerAdd(action, cache, isSuperPrimary);
                     if (wasAdded) {
                         // Remember the default
@@ -386,12 +372,11 @@
 
                 // Handle Email rows with presence data as Im entry
                 final DataStatus status = data.getStatuses().get(dataId);
-                if (status != null && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    final DataKind imKind = accountTypes.getKindOrFallback(accountType, dataSet,
-                            Im.CONTENT_ITEM_TYPE);
-                    if (imKind != null) {
-                        final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE,
-                                imKind, dataId, entryValues);
+                if (status != null && dataItem instanceof EmailDataItem) {
+                    final EmailDataItem email = (EmailDataItem) dataItem;
+                    final ImDataItem im = ImDataItem.createFromEmail(email);
+                    if (im.getDataKind() != null) {
+                        final DataAction action = new DataAction(context, im);
                         action.setPresence(status.getPresence());
                         considerAdd(action, cache, isSuperPrimary);
                     }
@@ -505,14 +490,14 @@
         listFragment.setListener(mListFragmentListener);
     }
 
-    private LoaderCallbacks<ContactLoader.Result> mLoaderCallbacks =
-            new LoaderCallbacks<ContactLoader.Result>() {
+    private LoaderCallbacks<Contact> mLoaderCallbacks =
+            new LoaderCallbacks<Contact>() {
         @Override
-        public void onLoaderReset(Loader<ContactLoader.Result> loader) {
+        public void onLoaderReset(Loader<Contact> loader) {
         }
 
         @Override
-        public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
+        public void onLoadFinished(Loader<Contact> loader, Contact data) {
             mStopWatch.lap("lf"); // onLoadFinished
             if (isFinishing()) {
                 close(false);
@@ -558,7 +543,7 @@
         }
 
         @Override
-        public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
+        public Loader<Contact> onCreateLoader(int id, Bundle args) {
             if (mLookupUri == null) {
                 Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early");
             }
diff --git a/src/com/android/contacts/quickcontact/QuickContactListFragment.java b/src/com/android/contacts/quickcontact/QuickContactListFragment.java
index 117480a..6fed31d 100644
--- a/src/com/android/contacts/quickcontact/QuickContactListFragment.java
+++ b/src/com/android/contacts/quickcontact/QuickContactListFragment.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.quickcontact;
 
-import com.android.contacts.ContactPresenceIconUtil;
-import com.android.contacts.R;
-
 import android.app.Fragment;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -31,10 +28,13 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
-import android.widget.RelativeLayout;
 import android.widget.ListView;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPresenceIconUtil;
+import com.android.contacts.R;
+
 import java.util.List;
 
 /** A fragment that shows the list of resolve items below a tab */
diff --git a/src/com/android/contacts/quickcontact/ResolveCache.java b/src/com/android/contacts/quickcontact/ResolveCache.java
index 026e0f4..ec59b94 100644
--- a/src/com/android/contacts/quickcontact/ResolveCache.java
+++ b/src/com/android/contacts/quickcontact/ResolveCache.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.quickcontact;
 
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.google.android.collect.Sets;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -30,6 +27,9 @@
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.text.TextUtils;
 
+import com.android.contacts.util.PhoneCapabilityTester;
+import com.google.common.collect.Sets;
+
 import java.lang.ref.SoftReference;
 import java.util.HashMap;
 import java.util.HashSet;
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
index 3283efd..03517d4 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
@@ -16,20 +16,9 @@
 
 package com.android.contacts.socialwidget;
 
-import com.android.contacts.ContactLoader;
-import com.android.contacts.R;
-import com.android.contacts.list.ShortcutIntentBuilder;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.quickcontact.QuickContactBroadcastReceiver;
-import com.android.contacts.util.ContactBadgeUtil;
-import com.android.contacts.util.HtmlUtils;
-import com.android.contacts.util.StreamItemEntry;
-
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProvider;
-import android.content.ComponentName;
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.Intent;
@@ -38,7 +27,6 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Typeface;
 import android.net.Uri;
-import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsContract.StreamItems;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -49,6 +37,16 @@
 import android.view.View;
 import android.widget.RemoteViews;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.ContactLoader;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.quickcontact.QuickContactBroadcastReceiver;
+import com.android.contacts.util.ContactBadgeUtil;
+import com.android.contacts.util.HtmlUtils;
+import com.android.contacts.util.StreamItemEntry;
+
 import java.util.List;
 
 public class SocialWidgetProvider extends AppWidgetProvider {
@@ -118,10 +116,10 @@
         final ContactLoader contactLoader = new ContactLoader(context, contactUri, false, true,
                 false, true);
         contactLoader.registerListener(0,
-                new ContactLoader.OnLoadCompleteListener<ContactLoader.Result>() {
+                new ContactLoader.OnLoadCompleteListener<Contact>() {
                     @Override
-                    public void onLoadComplete(Loader<ContactLoader.Result> loader,
-                            ContactLoader.Result contactData) {
+                    public void onLoadComplete(Loader<Contact> loader,
+                            Contact contactData) {
                         bindRemoteViews(context, widgetId, appWidgetManager, contactData);
                     }
                 });
@@ -130,7 +128,7 @@
     }
 
     private static void bindRemoteViews(final Context context, final int widgetId,
-            final AppWidgetManager widgetManager, ContactLoader.Result contactData) {
+            final AppWidgetManager widgetManager, Contact contactData) {
         Log.d(TAG, "Loaded " + contactData.getLookupKey()
                 + " for widget with id=" + widgetId);
         final RemoteViews views = new RemoteViews(context.getPackageName(),
diff --git a/src/com/android/contacts/test/FragmentTestActivity.java b/src/com/android/contacts/test/FragmentTestActivity.java
index 161ed74..80c6731 100644
--- a/src/com/android/contacts/test/FragmentTestActivity.java
+++ b/src/com/android/contacts/test/FragmentTestActivity.java
@@ -16,11 +16,13 @@
 
 package com.android.contacts.test;
 
+import android.os.Bundle;
+import android.view.Window;
+import android.view.WindowManager;
+
 import com.android.contacts.ContactsActivity;
 import com.android.contacts.R;
 
-import android.os.Bundle;
-
 /**
  * An activity that is used for testing fragments.  A unit test starts this
  * activity, adds a fragment and then tests the fragment.
@@ -30,6 +32,13 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        // Normally fragment/activity onStart() methods will not be called when screen is locked.
+        // Use the following flags to ensure that activities can be show for testing.
+        Window window = getWindow();
+        window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
+                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+
         setContentView(R.layout.fragment_test);
     }
 }
diff --git a/src/com/android/contacts/test/InjectedServices.java b/src/com/android/contacts/test/InjectedServices.java
index 49b88be..4dd955f 100644
--- a/src/com/android/contacts/test/InjectedServices.java
+++ b/src/com/android/contacts/test/InjectedServices.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.test;
 
-import com.google.android.collect.Maps;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.content.ContentResolver;
 import android.content.SharedPreferences;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Maps;
+
 import java.util.HashMap;
 
 /**
diff --git a/src/com/android/contacts/util/AccountFilterUtil.java b/src/com/android/contacts/util/AccountFilterUtil.java
index 3f055d0..b95972c 100644
--- a/src/com/android/contacts/util/AccountFilterUtil.java
+++ b/src/com/android/contacts/util/AccountFilterUtil.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-import com.android.contacts.list.AccountFilterActivity;
-import com.android.contacts.list.ContactListFilter;
-import com.android.contacts.list.ContactListFilterController;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.content.Context;
@@ -29,6 +24,11 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.list.AccountFilterActivity;
+import com.android.contacts.list.ContactListFilter;
+import com.android.contacts.list.ContactListFilterController;
+
 /**
  * Utility class for account filter manipulation.
  */
@@ -163,4 +163,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/util/AccountPromptUtils.java b/src/com/android/contacts/util/AccountPromptUtils.java
index 111c52e..cdefda0 100644
--- a/src/com/android/contacts/util/AccountPromptUtils.java
+++ b/src/com/android/contacts/util/AccountPromptUtils.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-import com.android.contacts.model.GoogleAccountType;
-
 import android.accounts.AccountManager;
 import android.accounts.AccountManagerCallback;
 import android.accounts.AccountManagerFuture;
@@ -32,6 +29,9 @@
 import android.preference.PreferenceManager;
 import android.util.Log;
 
+import com.android.contacts.R;
+import com.android.contacts.model.account.GoogleAccountType;
+
 import java.io.IOException;
 
 /**
diff --git a/src/com/android/contacts/util/AccountSelectionUtil.java b/src/com/android/contacts/util/AccountSelectionUtil.java
index 7317d21..d83cb41 100644
--- a/src/com/android/contacts/util/AccountSelectionUtil.java
+++ b/src/com/android/contacts/util/AccountSelectionUtil.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
@@ -35,6 +30,11 @@
 import android.widget.ArrayAdapter;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/util/AccountsListAdapter.java b/src/com/android/contacts/util/AccountsListAdapter.java
index 058cf84..4355cba 100644
--- a/src/com/android/contacts/util/AccountsListAdapter.java
+++ b/src/com/android/contacts/util/AccountsListAdapter.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-
 import android.content.Context;
 import android.text.TextUtils.TruncateAt;
 import android.view.LayoutInflater;
@@ -30,6 +25,11 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/util/AsyncTaskExecutors.java b/src/com/android/contacts/util/AsyncTaskExecutors.java
index 539dee7..36b05c7 100644
--- a/src/com/android/contacts/util/AsyncTaskExecutors.java
+++ b/src/com/android/contacts/util/AsyncTaskExecutors.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.test.NeededForTesting;
-import com.google.common.base.Preconditions;
-
 import android.os.AsyncTask;
 import android.os.Looper;
 
+import com.android.contacts.test.NeededForTesting;
+import com.google.common.base.Preconditions;
+
 import java.util.concurrent.Executor;
 
 /**
diff --git a/src/com/android/contacts/util/ClipboardUtils.java b/src/com/android/contacts/util/ClipboardUtils.java
index a160668..1d0a3c1 100644
--- a/src/com/android/contacts/util/ClipboardUtils.java
+++ b/src/com/android/contacts/util/ClipboardUtils.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.text.TextUtils;
 import android.widget.Toast;
 
+import com.android.contacts.R;
+
 public class ClipboardUtils {
     private static final String TAG = "ClipboardUtils";
 
diff --git a/src/com/android/contacts/util/ContactBadgeUtil.java b/src/com/android/contacts/util/ContactBadgeUtil.java
index de90c40..5c2cc65 100644
--- a/src/com/android/contacts/util/ContactBadgeUtil.java
+++ b/src/com/android/contacts/util/ContactBadgeUtil.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -29,6 +26,9 @@
 import android.text.format.DateUtils;
 import android.util.Log;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.R;
+
 /**
  * Provides static functions to extract summary information for aggregate contacts
  */
diff --git a/src/com/android/contacts/util/DialogManager.java b/src/com/android/contacts/util/DialogManager.java
index 661c5d3..49796db 100644
--- a/src/com/android/contacts/util/DialogManager.java
+++ b/src/com/android/contacts/util/DialogManager.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-
 import android.app.Activity;
 import android.app.Dialog;
 import android.content.DialogInterface;
@@ -25,6 +23,8 @@
 import android.os.Bundle;
 import android.view.View;
 
+import com.android.contacts.R;
+
 /**
  * Manages creation and destruction of Dialogs that are to be shown by Views. Unlike how Dialogs
  * are regularly used, the Dialogs are not recycled but immediately destroyed after dismissal.
diff --git a/src/com/android/contacts/util/ExpirableCache.java b/src/com/android/contacts/util/ExpirableCache.java
index 196b03a..3f19a26 100644
--- a/src/com/android/contacts/util/ExpirableCache.java
+++ b/src/com/android/contacts/util/ExpirableCache.java
@@ -16,10 +16,10 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.test.NeededForTesting;
-
 import android.util.LruCache;
 
+import com.android.contacts.test.NeededForTesting;
+
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.annotation.concurrent.Immutable;
diff --git a/src/com/android/contacts/util/HtmlUtils.java b/src/com/android/contacts/util/HtmlUtils.java
index a3c9c64..cea300e 100644
--- a/src/com/android/contacts/util/HtmlUtils.java
+++ b/src/com/android/contacts/util/HtmlUtils.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.text.Html;
@@ -30,6 +27,9 @@
 import android.text.style.ImageSpan;
 import android.text.style.QuoteSpan;
 
+import com.android.contacts.R;
+import com.google.common.annotations.VisibleForTesting;
+
 /**
  * Provides static functions to perform custom HTML to text conversions.
  * Specifically, it adjusts the color and padding of the vertical
diff --git a/src/com/android/contacts/util/ImageViewDrawableSetter.java b/src/com/android/contacts/util/ImageViewDrawableSetter.java
index 1d23dd0..b231572 100644
--- a/src/com/android/contacts/util/ImageViewDrawableSetter.java
+++ b/src/com/android/contacts/util/ImageViewDrawableSetter.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.ContactLoader.Result;
-import com.android.contacts.ContactPhotoManager;
-
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
@@ -29,6 +26,9 @@
 import android.util.Log;
 import android.widget.ImageView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.model.Contact;
+
 import java.util.Arrays;
 
 /**
@@ -49,7 +49,7 @@
         mTarget = target;
     }
 
-    public void setupContactPhoto(Result contactData, ImageView photoView) {
+    public void setupContactPhoto(Contact contactData, ImageView photoView) {
         setTarget(photoView);
         setCompressedImage(contactData.getPhotoBinaryData());
     }
diff --git a/src/com/android/contacts/util/LocalizedNameResolver.java b/src/com/android/contacts/util/LocalizedNameResolver.java
index c2ee90a..ec0b812 100644
--- a/src/com/android/contacts/util/LocalizedNameResolver.java
+++ b/src/com/android/contacts/util/LocalizedNameResolver.java
@@ -16,24 +16,24 @@
 
 package com.android.contacts.util;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.accounts.AccountManager;
 import android.accounts.AuthenticatorDescription;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.content.res.Resources.NotFoundException;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 
 /**
diff --git a/src/com/android/contacts/util/PhoneCapabilityTester.java b/src/com/android/contacts/util/PhoneCapabilityTester.java
index ce248bb..421341c 100644
--- a/src/com/android/contacts/util/PhoneCapabilityTester.java
+++ b/src/com/android/contacts/util/PhoneCapabilityTester.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -26,6 +24,8 @@
 import android.net.sip.SipManager;
 import android.telephony.TelephonyManager;
 
+import com.android.contacts.R;
+
 import java.util.List;
 
 /**
diff --git a/src/com/android/contacts/util/PhoneNumberFormatter.java b/src/com/android/contacts/util/PhoneNumberFormatter.java
index 204ac69..7ae28db 100644
--- a/src/com/android/contacts/util/PhoneNumberFormatter.java
+++ b/src/com/android/contacts/util/PhoneNumberFormatter.java
@@ -16,13 +16,13 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.ContactsUtils;
-
 import android.content.Context;
 import android.os.AsyncTask;
 import android.telephony.PhoneNumberFormattingTextWatcher;
 import android.widget.TextView;
 
+import com.android.contacts.ContactsUtils;
+
 public final class PhoneNumberFormatter {
     private PhoneNumberFormatter() {}
 
diff --git a/src/com/android/contacts/util/SchedulingUtils.java b/src/com/android/contacts/util/SchedulingUtils.java
index c55bc16..94294fa 100644
--- a/src/com/android/contacts/util/SchedulingUtils.java
+++ b/src/com/android/contacts/util/SchedulingUtils.java
@@ -17,8 +17,8 @@
 package com.android.contacts.util;
 
 import android.view.View;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.ViewTreeObserver.OnDrawListener;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 
 /** Static methods that are useful for scheduling actions to occur at a later time. */
 public class SchedulingUtils {
diff --git a/src/com/android/contacts/util/StopWatch.java b/src/com/android/contacts/util/StopWatch.java
index 1accfe2..c53f346 100644
--- a/src/com/android/contacts/util/StopWatch.java
+++ b/src/com/android/contacts/util/StopWatch.java
@@ -16,10 +16,10 @@
 
 package com.android.contacts.util;
 
-import com.google.android.collect.Lists;
-
 import android.util.Log;
 
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 
 /**
diff --git a/src/com/android/contacts/util/StreamItemEntry.java b/src/com/android/contacts/util/StreamItemEntry.java
index f9c8700..b15bae9 100644
--- a/src/com/android/contacts/util/StreamItemEntry.java
+++ b/src/com/android/contacts/util/StreamItemEntry.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.detail.ContactDetailDisplayUtils;
-import com.android.contacts.test.NeededForTesting;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.provider.ContactsContract.StreamItems;
 import android.text.Html;
 
+import com.android.contacts.detail.ContactDetailDisplayUtils;
+import com.android.contacts.test.NeededForTesting;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
diff --git a/src/com/android/contacts/vcard/CancelActivity.java b/src/com/android/contacts/vcard/CancelActivity.java
index 5dafa53..ff8512b 100644
--- a/src/com/android/contacts/vcard/CancelActivity.java
+++ b/src/com/android/contacts/vcard/CancelActivity.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.vcard;
 
-import com.android.contacts.R;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -28,11 +26,10 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.contacts.R;
+
 /**
  * The Activity for canceling vCard import/export.
  */
diff --git a/src/com/android/contacts/vcard/ExportProcessor.java b/src/com/android/contacts/vcard/ExportProcessor.java
index b52839b..12f9e24 100644
--- a/src/com/android/contacts/vcard/ExportProcessor.java
+++ b/src/com/android/contacts/vcard/ExportProcessor.java
@@ -15,11 +15,6 @@
  */
 package com.android.contacts.vcard;
 
-import com.android.contacts.R;
-import com.android.contacts.activities.PeopleActivity;
-import com.android.vcard.VCardComposer;
-import com.android.vcard.VCardConfig;
-
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.ContentResolver;
@@ -32,6 +27,11 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.contacts.R;
+import com.android.contacts.activities.PeopleActivity;
+import com.android.vcard.VCardComposer;
+import com.android.vcard.VCardConfig;
+
 import java.io.BufferedWriter;
 import java.io.FileNotFoundException;
 import java.io.IOException;
diff --git a/src/com/android/contacts/vcard/ExportVCardActivity.java b/src/com/android/contacts/vcard/ExportVCardActivity.java
index f38c9df..ac0850f 100644
--- a/src/com/android/contacts/vcard/ExportVCardActivity.java
+++ b/src/com/android/contacts/vcard/ExportVCardActivity.java
@@ -15,9 +15,6 @@
  */
 package com.android.contacts.vcard;
 
-import com.android.contacts.R;
-import com.android.vcard.VCardComposer;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -32,10 +29,11 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Messenger;
-import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.contacts.R;
+
 import java.io.File;
 
 /**
@@ -290,4 +288,4 @@
         }
         finish();
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/vcard/ImportProcessor.java b/src/com/android/contacts/vcard/ImportProcessor.java
index e8a9193..a2e8a48 100644
--- a/src/com/android/contacts/vcard/ImportProcessor.java
+++ b/src/com/android/contacts/vcard/ImportProcessor.java
@@ -15,6 +15,11 @@
  */
 package com.android.contacts.vcard;
 
+import android.accounts.Account;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.util.Log;
+
 import com.android.vcard.VCardEntry;
 import com.android.vcard.VCardEntryCommitter;
 import com.android.vcard.VCardEntryConstructor;
@@ -28,11 +33,6 @@
 import com.android.vcard.exception.VCardNotSupportedException;
 import com.android.vcard.exception.VCardVersionException;
 
-import android.accounts.Account;
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.util.Log;
-
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/src/com/android/contacts/vcard/ImportVCardActivity.java b/src/com/android/contacts/vcard/ImportVCardActivity.java
index 2dc92af..a9566ef 100644
--- a/src/com/android/contacts/vcard/ImportVCardActivity.java
+++ b/src/com/android/contacts/vcard/ImportVCardActivity.java
@@ -16,20 +16,6 @@
 
 package com.android.contacts.vcard;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.util.AccountSelectionUtil;
-import com.android.vcard.VCardEntryCounter;
-import com.android.vcard.VCardParser;
-import com.android.vcard.VCardParser_V21;
-import com.android.vcard.VCardParser_V30;
-import com.android.vcard.VCardSourceDetector;
-import com.android.vcard.exception.VCardException;
-import com.android.vcard.exception.VCardNestedException;
-import com.android.vcard.exception.VCardVersionException;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -60,6 +46,20 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.util.AccountSelectionUtil;
+import com.android.vcard.VCardEntryCounter;
+import com.android.vcard.VCardParser;
+import com.android.vcard.VCardParser_V21;
+import com.android.vcard.VCardParser_V30;
+import com.android.vcard.VCardSourceDetector;
+import com.android.vcard.exception.VCardException;
+import com.android.vcard.exception.VCardNestedException;
+import com.android.vcard.exception.VCardVersionException;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
diff --git a/src/com/android/contacts/vcard/NfcImportVCardActivity.java b/src/com/android/contacts/vcard/NfcImportVCardActivity.java
index c3a55d2..035be60 100644
--- a/src/com/android/contacts/vcard/NfcImportVCardActivity.java
+++ b/src/com/android/contacts/vcard/NfcImportVCardActivity.java
@@ -16,19 +16,6 @@
 
 package com.android.contacts.vcard;
 
-import com.android.contacts.R;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.vcard.VCardEntry;
-import com.android.vcard.VCardEntryCounter;
-import com.android.vcard.VCardParser;
-import com.android.vcard.VCardParser_V21;
-import com.android.vcard.VCardParser_V30;
-import com.android.vcard.VCardSourceDetector;
-import com.android.vcard.exception.VCardException;
-import com.android.vcard.exception.VCardNestedException;
-import com.android.vcard.exception.VCardVersionException;
-
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
@@ -44,9 +31,21 @@
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
 
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.vcard.VCardEntry;
+import com.android.vcard.VCardEntryCounter;
+import com.android.vcard.VCardParser;
+import com.android.vcard.VCardParser_V21;
+import com.android.vcard.VCardParser_V30;
+import com.android.vcard.VCardSourceDetector;
+import com.android.vcard.exception.VCardException;
+import com.android.vcard.exception.VCardNestedException;
+import com.android.vcard.exception.VCardVersionException;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/contacts/vcard/NotificationImportExportListener.java b/src/com/android/contacts/vcard/NotificationImportExportListener.java
index 06cf73f..855f680 100644
--- a/src/com/android/contacts/vcard/NotificationImportExportListener.java
+++ b/src/com/android/contacts/vcard/NotificationImportExportListener.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.vcard;
 
-import com.android.contacts.R;
-import com.android.vcard.VCardEntry;
-
 import android.app.Activity;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -30,9 +27,11 @@
 import android.os.Handler;
 import android.os.Message;
 import android.provider.ContactsContract.RawContacts;
-import android.widget.RemoteViews;
 import android.widget.Toast;
 
+import com.android.contacts.R;
+import com.android.vcard.VCardEntry;
+
 public class NotificationImportExportListener implements VCardImportExportListener,
         Handler.Callback {
     /** The tag used by vCard-related notifications. */
diff --git a/src/com/android/contacts/vcard/SelectAccountActivity.java b/src/com/android/contacts/vcard/SelectAccountActivity.java
index f27331e..0e9c5a8 100644
--- a/src/com/android/contacts/vcard/SelectAccountActivity.java
+++ b/src/com/android/contacts/vcard/SelectAccountActivity.java
@@ -15,18 +15,18 @@
  */
 package com.android.contacts.vcard;
 
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.util.AccountSelectionUtil;
-
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.util.AccountSelectionUtil;
+
 import java.util.List;
 
 public class SelectAccountActivity extends ContactsActivity {
diff --git a/src/com/android/contacts/vcard/VCardImportExportListener.java b/src/com/android/contacts/vcard/VCardImportExportListener.java
index d3ef198..82d7c21 100644
--- a/src/com/android/contacts/vcard/VCardImportExportListener.java
+++ b/src/com/android/contacts/vcard/VCardImportExportListener.java
@@ -16,10 +16,10 @@
 
 package com.android.contacts.vcard;
 
-import com.android.vcard.VCardEntry;
-
 import android.net.Uri;
 
+import com.android.vcard.VCardEntry;
+
 interface VCardImportExportListener {
     void onImportProcessed(ImportRequest request, int jobId, int sequence);
     void onImportParsed(ImportRequest request, int jobId, VCardEntry entry, int currentCount,
diff --git a/src/com/android/contacts/vcard/VCardService.java b/src/com/android/contacts/vcard/VCardService.java
index 34c4acb..4ef1bcb 100644
--- a/src/com/android/contacts/vcard/VCardService.java
+++ b/src/com/android/contacts/vcard/VCardService.java
@@ -36,7 +36,6 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
index 8912a74..5973387 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
@@ -19,14 +19,6 @@
 import static com.android.contacts.CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK;
 import static com.android.contacts.CallDetailActivity.EXTRA_VOICEMAIL_URI;
 
-import com.android.common.io.MoreCloseables;
-import com.android.contacts.ProximitySensorAware;
-import com.android.contacts.R;
-import com.android.contacts.util.AsyncTaskExecutors;
-import com.android.ex.variablespeed.MediaPlayerProxy;
-import com.android.ex.variablespeed.VariableSpeed;
-import com.google.common.base.Preconditions;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.content.ContentResolver;
@@ -47,6 +39,14 @@
 import android.widget.SeekBar;
 import android.widget.TextView;
 
+import com.android.common.io.MoreCloseables;
+import com.android.contacts.ProximitySensorAware;
+import com.android.contacts.R;
+import com.android.contacts.util.AsyncTaskExecutors;
+import com.android.ex.variablespeed.MediaPlayerProxy;
+import com.android.ex.variablespeed.VariableSpeed;
+import com.google.common.base.Preconditions;
+
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
index 7aecf08..2c7ba52 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
@@ -18,13 +18,6 @@
 
 import static android.util.MathUtils.constrain;
 
-import com.android.contacts.R;
-import com.android.contacts.util.AsyncTaskExecutor;
-import com.android.ex.variablespeed.MediaPlayerProxy;
-import com.android.ex.variablespeed.SingleThreadedMediaPlayerProxy;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-
 import android.content.Context;
 import android.database.ContentObserver;
 import android.media.AudioManager;
@@ -37,6 +30,13 @@
 import android.view.View;
 import android.widget.SeekBar;
 
+import com.android.contacts.R;
+import com.android.contacts.util.AsyncTaskExecutor;
+import com.android.ex.variablespeed.MediaPlayerProxy;
+import com.android.ex.variablespeed.SingleThreadedMediaPlayerProxy;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
diff --git a/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
index d88b5d3..c7f9c8f 100644
--- a/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
+++ b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
@@ -24,13 +24,13 @@
 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION;
 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK;
 
-import com.android.contacts.R;
-import com.android.contacts.util.UriUtils;
-
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.VoicemailContract.Status;
 
+import com.android.contacts.R;
+import com.android.contacts.util.UriUtils;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
diff --git a/src/com/android/contacts/widget/AlphaTouchInterceptorOverlay.java b/src/com/android/contacts/widget/AlphaTouchInterceptorOverlay.java
index a7d219c..8779a95 100644
--- a/src/com/android/contacts/widget/AlphaTouchInterceptorOverlay.java
+++ b/src/com/android/contacts/widget/AlphaTouchInterceptorOverlay.java
@@ -16,13 +16,13 @@
 
 package com.android.contacts.widget;
 
-import com.android.contacts.detail.ContactDetailDisplayUtils;
-import com.android.contacts.util.ThemeUtils;
-
 import android.content.Context;
 import android.view.View;
 import android.widget.FrameLayout;
 
+import com.android.contacts.detail.ContactDetailDisplayUtils;
+import com.android.contacts.util.ThemeUtils;
+
 /**
  * A View that other Views can use to create a touch-interceptor layer above
  * their other sub-views. This layer can be enabled and disabled; when enabled,
diff --git a/src/com/android/contacts/widget/CompositeListAdapter.java b/src/com/android/contacts/widget/CompositeListAdapter.java
index 610b97f..34c8fa0 100644
--- a/src/com/android/contacts/widget/CompositeListAdapter.java
+++ b/src/com/android/contacts/widget/CompositeListAdapter.java
@@ -15,15 +15,15 @@
  */
 package com.android.contacts.widget;
 
-import com.android.contacts.test.NeededForTesting;
-import com.google.common.annotations.VisibleForTesting;
-
 import android.database.DataSetObserver;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.ListAdapter;
 
+import com.android.contacts.test.NeededForTesting;
+import com.google.common.annotations.VisibleForTesting;
+
 /**
  * A general purpose adapter that is composed of multiple sub-adapters. It just
  * appends them in the order they are added. It listens to changes from all
diff --git a/src/com/android/contacts/widget/InterpolatingLayout.java b/src/com/android/contacts/widget/InterpolatingLayout.java
index 78785b9..fc3177c 100644
--- a/src/com/android/contacts/widget/InterpolatingLayout.java
+++ b/src/com/android/contacts/widget/InterpolatingLayout.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.widget;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -27,6 +25,8 @@
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
+import com.android.contacts.R;
+
 /**
  * Layout similar to LinearLayout that allows a child to specify examples of
  * desired size depending on the parent size. For example if the widget wants to
diff --git a/src/com/android/contacts/widget/PinnedHeaderListAdapter.java b/src/com/android/contacts/widget/PinnedHeaderListAdapter.java
index a39cfcc..c01e331 100644
--- a/src/com/android/contacts/widget/PinnedHeaderListAdapter.java
+++ b/src/com/android/contacts/widget/PinnedHeaderListAdapter.java
@@ -15,12 +15,12 @@
  */
 package com.android.contacts.widget;
 
-import com.android.common.widget.CompositeCursorAdapter;
-
 import android.content.Context;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.common.widget.CompositeCursorAdapter;
+
 /**
  * A subclass of {@link CompositeCursorAdapter} that manages pinned partition headers.
  */
diff --git a/src/com/android/contacts/widget/PinnedHeaderListDemoActivity.java b/src/com/android/contacts/widget/PinnedHeaderListDemoActivity.java
index b553e3f..4276791 100644
--- a/src/com/android/contacts/widget/PinnedHeaderListDemoActivity.java
+++ b/src/com/android/contacts/widget/PinnedHeaderListDemoActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.widget;
 
-import com.android.contacts.R;
-
 import android.app.ListActivity;
 import android.content.Context;
 import android.database.Cursor;
@@ -29,6 +27,8 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+
 /**
  * An activity that demonstrates various use cases for the {@link PinnedHeaderListView}.
  * If we decide to move PinnedHeaderListView to the framework, this class could go
diff --git a/src/com/android/contacts/widget/ProportionalLayout.java b/src/com/android/contacts/widget/ProportionalLayout.java
index 52a67d4..d069eb7 100644
--- a/src/com/android/contacts/widget/ProportionalLayout.java
+++ b/src/com/android/contacts/widget/ProportionalLayout.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.widget;
 
-import com.android.contacts.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.contacts.R;
+
 /**
  * Layout that calculates its height based on its width, or vice versa (depending on the set
  * {@link #setDirection(Direction)}. The factor is specified in {@link #setRatio(float)}.
diff --git a/src/com/android/contacts/widget/TextHighlightingAnimation.java b/src/com/android/contacts/widget/TextHighlightingAnimation.java
index 882dd48..2924e4e 100644
--- a/src/com/android/contacts/widget/TextHighlightingAnimation.java
+++ b/src/com/android/contacts/widget/TextHighlightingAnimation.java
@@ -15,9 +15,6 @@
  */
 package com.android.contacts.widget;
 
-import com.android.contacts.format.FormatUtils;
-import com.android.internal.R;
-
 import android.database.CharArrayBuffer;
 import android.graphics.Color;
 import android.os.Handler;
@@ -26,6 +23,9 @@
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 
+import com.android.contacts.format.FormatUtils;
+import com.android.internal.R;
+
 /**
  * An animation that alternately dims and brightens the non-highlighted portion of text.
  */
diff --git a/tests/src/com/android/contacts/CallDetailActivityTest.java b/tests/src/com/android/contacts/CallDetailActivityTest.java
index 689f946..ae28929 100644
--- a/tests/src/com/android/contacts/CallDetailActivityTest.java
+++ b/tests/src/com/android/contacts/CallDetailActivityTest.java
@@ -20,13 +20,6 @@
 import static com.android.contacts.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
 import static com.android.contacts.voicemail.VoicemailPlaybackPresenter.Tasks.PREPARE_MEDIA_PLAYER;
 
-import com.android.contacts.util.AsyncTaskExecutors;
-import com.android.contacts.util.FakeAsyncTaskExecutor;
-import com.android.contacts.util.IntegrationTestUtils;
-import com.android.contacts.util.LocaleTestUtils;
-import com.android.internal.view.menu.ContextMenuBuilder;
-import com.google.common.io.Closeables;
-
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -41,6 +34,13 @@
 import android.view.Menu;
 import android.widget.TextView;
 
+import com.android.contacts.util.AsyncTaskExecutors;
+import com.android.contacts.util.FakeAsyncTaskExecutor;
+import com.android.contacts.util.IntegrationTestUtils;
+import com.android.contacts.util.LocaleTestUtils;
+import com.android.internal.view.menu.ContextMenuBuilder;
+import com.google.common.io.Closeables;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
diff --git a/tests/src/com/android/contacts/ContactDetailTest.java b/tests/src/com/android/contacts/ContactDetailTest.java
index b2c19f4..8d91d9e 100644
--- a/tests/src/com/android/contacts/ContactDetailTest.java
+++ b/tests/src/com/android/contacts/ContactDetailTest.java
@@ -16,13 +16,13 @@
 
 package com.android.contacts;
 
+import android.test.ActivityUnitTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
 import com.android.contacts.activities.ContactDetailActivity;
 import com.android.contacts.tests.mocks.ContactsMockContext;
 import com.android.contacts.tests.mocks.MockContentProvider;
 
-import android.test.ActivityUnitTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
 @SmallTest
 public class ContactDetailTest extends ActivityUnitTestCase<ContactDetailActivity> {
     private ContactsMockContext mContext;
diff --git a/tests/src/com/android/contacts/ContactsLaunchPerformance.java b/tests/src/com/android/contacts/ContactsLaunchPerformance.java
index 9177457..5f0336b 100644
--- a/tests/src/com/android/contacts/ContactsLaunchPerformance.java
+++ b/tests/src/com/android/contacts/ContactsLaunchPerformance.java
@@ -19,8 +19,8 @@
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Intent;
-import android.test.LaunchPerformanceBase;
 import android.os.Bundle;
+import android.test.LaunchPerformanceBase;
 
 /**
  * Instrumentation class for Address Book launch performance testing.
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
index c1c3e08..b852b58 100644
--- a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -16,12 +16,6 @@
 
 package com.android.contacts;
 
-import com.android.contacts.calllog.CallTypeHelper;
-import com.android.contacts.calllog.PhoneNumberHelper;
-import com.android.contacts.calllog.TestPhoneNumberHelper;
-import com.android.contacts.util.LocaleTestUtils;
-import com.android.internal.telephony.CallerInfo;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.provider.CallLog.Calls;
@@ -31,6 +25,12 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.contacts.calllog.CallTypeHelper;
+import com.android.contacts.calllog.PhoneNumberHelper;
+import com.android.contacts.calllog.TestPhoneNumberHelper;
+import com.android.contacts.util.LocaleTestUtils;
+import com.android.internal.telephony.CallerInfo;
+
 import java.util.GregorianCalendar;
 import java.util.Locale;
 
diff --git a/tests/src/com/android/contacts/EntityDeltaListTests.java b/tests/src/com/android/contacts/RawContactDeltaListTests.java
similarity index 70%
rename from tests/src/com/android/contacts/EntityDeltaListTests.java
rename to tests/src/com/android/contacts/RawContactDeltaListTests.java
index ee27dd9..165e689 100644
--- a/tests/src/com/android/contacts/EntityDeltaListTests.java
+++ b/tests/src/com/android/contacts/RawContactDeltaListTests.java
@@ -21,37 +21,38 @@
 import static android.content.ContentProviderOperation.TYPE_INSERT;
 import static android.content.ContentProviderOperation.TYPE_UPDATE;
 
-import com.android.contacts.EntityModifierTests.MockContactsSource;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.google.android.collect.Lists;
-
 import android.content.ContentProviderOperation;
 import android.content.ContentValues;
-import android.content.Entity;
+import android.content.Context;
 import android.net.Uri;
 import android.provider.BaseColumns;
 import android.provider.ContactsContract.AggregationExceptions;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
 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.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType;
+import com.google.common.collect.Lists;
+
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 
 /**
- * Tests for {@link EntityDeltaList} which focus on "diff" operations that should
+ * Tests for {@link RawContactDeltaList} which focus on "diff" operations that should
  * create {@link AggregationExceptions} in certain cases.
  */
 @LargeTest
-public class EntityDeltaListTests extends AndroidTestCase {
-    public static final String TAG = "EntityDeltaListTests";
+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;
@@ -71,7 +72,7 @@
     public static final String TEST_PHONE = "555-1212";
     public static final String TEST_ACCOUNT = "org.example.test";
 
-    public EntityDeltaListTests() {
+    public RawContactDeltaListTests() {
         super();
     }
 
@@ -95,47 +96,47 @@
         return (ContentValues) field.get(operation);
     }
 
-    static EntityDelta getUpdate(long rawContactId) {
-        final Entity before = EntityDeltaTests.getEntity(rawContactId,
-                EntityDeltaTests.TEST_PHONE_ID);
-        return EntityDelta.fromBefore(before);
+    static RawContactDelta getUpdate(Context context, long rawContactId) {
+        final RawContact before = RawContactDeltaTests.getRawContact(context, rawContactId,
+                RawContactDeltaTests.TEST_PHONE_ID);
+        return RawContactDelta.fromBefore(before);
     }
 
-    static EntityDelta getInsert() {
+    static RawContactDelta getInsert() {
         final ContentValues after = new ContentValues();
-        after.put(RawContacts.ACCOUNT_NAME, EntityDeltaTests.TEST_ACCOUNT_NAME);
+        after.put(RawContacts.ACCOUNT_NAME, RawContactDeltaTests.TEST_ACCOUNT_NAME);
         after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
 
         final ValuesDelta values = ValuesDelta.fromAfter(after);
-        return new EntityDelta(values);
+        return new RawContactDelta(values);
     }
 
-    static EntityDeltaList buildSet(EntityDelta... deltas) {
-        final EntityDeltaList set = EntityDeltaList.fromSingle(deltas[0]);
+    static RawContactDeltaList buildSet(RawContactDelta... deltas) {
+        final RawContactDeltaList set = RawContactDeltaList.fromSingle(deltas[0]);
         for (int i = 1; i < deltas.length; i++) {
             set.add(deltas[i]);
         }
         return set;
     }
 
-    static EntityDelta buildBeforeEntity(long rawContactId, long version,
+    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 Entity before = new Entity(contact);
+        final RawContact before = new RawContact(context, contact);
         for (ContentValues entry : entries) {
-            before.addSubValue(Data.CONTENT_URI, entry);
+            before.addDataItemValues(entry);
         }
-        return EntityDelta.fromBefore(before);
+        return RawContactDelta.fromBefore(before);
     }
 
-    static EntityDelta buildAfterEntity(ContentValues... entries) {
+    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 EntityDelta after = new EntityDelta(ValuesDelta.fromAfter(contact));
+        final RawContactDelta after = new RawContactDelta(ValuesDelta.fromAfter(contact));
         for (ContentValues entry : entries) {
             after.addEntry(ValuesDelta.fromAfter(entry));
         }
@@ -164,24 +165,24 @@
         return values;
     }
 
-    static void insertPhone(EntityDeltaList set, long rawContactId, ContentValues values) {
-        final EntityDelta match = set.getByRawContactId(rawContactId);
+    static void insertPhone(RawContactDeltaList set, long rawContactId, ContentValues values) {
+        final RawContactDelta match = set.getByRawContactId(rawContactId);
         match.addEntry(ValuesDelta.fromAfter(values));
     }
 
-    static ValuesDelta getPhone(EntityDeltaList set, long rawContactId, long dataId) {
-        final EntityDelta match = set.getByRawContactId(rawContactId);
+    static ValuesDelta getPhone(RawContactDeltaList set, long rawContactId, long dataId) {
+        final RawContactDelta match = set.getByRawContactId(rawContactId);
         return match.getEntry(dataId);
     }
 
-    static void assertDiffPattern(EntityDelta delta, ContentProviderOperation... pattern) {
+    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(EntityDeltaList set, ContentProviderOperation... pattern) {
+    static void assertDiffPattern(RawContactDeltaList set, ContentProviderOperation... pattern) {
         assertDiffPattern(set.buildDiff(), pattern);
     }
 
@@ -281,7 +282,7 @@
         return null;
     }
 
-    static Long getVersion(EntityDeltaList set, Long rawContactId) {
+    static Long getVersion(RawContactDeltaList set, Long rawContactId) {
         return set.getByRawContactId(rawContactId).getValues().getAsLong(RawContacts.VERSION);
     }
 
@@ -301,8 +302,8 @@
     }
 
     public void testInsert() {
-        final EntityDelta insert = getInsert();
-        final EntityDeltaList set = buildSet(insert);
+        final RawContactDelta insert = getInsert();
+        final RawContactDeltaList set = buildSet(insert);
 
         // Inserting single shouldn't create rules
         final ArrayList<ContentProviderOperation> diff = set.buildDiff();
@@ -311,9 +312,9 @@
     }
 
     public void testUpdateUpdate() {
-        final EntityDelta updateFirst = getUpdate(CONTACT_FIRST);
-        final EntityDelta updateSecond = getUpdate(CONTACT_SECOND);
-        final EntityDeltaList set = buildSet(updateFirst, updateSecond);
+        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();
@@ -322,9 +323,9 @@
     }
 
     public void testUpdateInsert() {
-        final EntityDelta update = getUpdate(CONTACT_FIRST);
-        final EntityDelta insert = getInsert();
-        final EntityDeltaList set = buildSet(update, insert);
+        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();
@@ -333,10 +334,10 @@
     }
 
     public void testInsertUpdateInsert() {
-        final EntityDelta insertFirst = getInsert();
-        final EntityDelta update = getUpdate(CONTACT_FIRST);
-        final EntityDelta insertSecond = getInsert();
-        final EntityDeltaList set = buildSet(insertFirst, update, insertSecond);
+        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();
@@ -345,10 +346,10 @@
     }
 
     public void testInsertInsertInsert() {
-        final EntityDelta insertFirst = getInsert();
-        final EntityDelta insertSecond = getInsert();
-        final EntityDelta insertThird = getInsert();
-        final EntityDeltaList set = buildSet(insertFirst, insertSecond, insertThird);
+        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();
@@ -357,21 +358,21 @@
     }
 
     public void testMergeDataRemoteInsert() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildPhone(PHONE_RED), buildPhone(PHONE_GREEN)));
+        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 EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertEquals("Unexpected change when merging", second, merged);
     }
 
     public void testMergeDataLocalUpdateRemoteInsert() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildPhone(PHONE_RED), buildPhone(PHONE_GREEN)));
+        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);
@@ -384,7 +385,7 @@
                 buildUpdateAggregationDefault());
 
         // Merge in the second version, verify diff matches
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged,
                 buildAssertVersion(VER_SECOND),
                 buildUpdateAggregationSuspended(),
@@ -393,10 +394,10 @@
     }
 
     public void testMergeDataLocalUpdateRemoteDelete() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildPhone(PHONE_GREEN)));
+        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);
@@ -410,7 +411,7 @@
 
         // Merge in the second version, verify that our update changed to
         // insert, since RED was deleted on remote side
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged,
                 buildAssertVersion(VER_SECOND),
                 buildUpdateAggregationSuspended(),
@@ -419,10 +420,10 @@
     }
 
     public void testMergeDataLocalDeleteRemoteUpdate() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildPhone(PHONE_RED, TEST_PHONE)));
+        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);
@@ -435,7 +436,7 @@
                 buildUpdateAggregationDefault());
 
         // Merge in the second version, verify that our delete remains
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged,
                 buildAssertVersion(VER_SECOND),
                 buildUpdateAggregationSuspended(),
@@ -444,10 +445,10 @@
     }
 
     public void testMergeDataLocalInsertRemoteInsert() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildPhone(PHONE_RED), buildPhone(PHONE_GREEN)));
+        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));
@@ -459,7 +460,7 @@
                 buildUpdateAggregationDefault());
 
         // Merge in the second version, verify that our insert remains
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged,
                 buildAssertVersion(VER_SECOND),
                 buildUpdateAggregationSuspended(),
@@ -468,15 +469,15 @@
     }
 
     public void testMergeRawContactLocalInsertRemoteInsert() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildPhone(PHONE_RED)), buildBeforeEntity(CONTACT_MARY, VER_SECOND,
-                buildPhone(PHONE_RED)));
+        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 EntityDelta joeContact = buildAfterEntity(joePhoneInsert);
+        final RawContactDelta joeContact = buildAfterEntity(joePhoneInsert);
         final ContentValues joeContactInsert = joeContact.getValues().getCompleteValues();
         joeContactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
         first.add(joeContact);
@@ -488,7 +489,7 @@
                 buildUpdateAggregationKeepTogether(CONTACT_BOB));
 
         // Merge in the second version, verify that our insert remains
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged,
                 buildAssertVersion(VER_SECOND),
                 buildAssertVersion(VER_SECOND),
@@ -499,11 +500,11 @@
     }
 
     public void testMergeRawContactLocalDeleteRemoteDelete() {
-        final EntityDeltaList first = buildSet(
-                buildBeforeEntity(CONTACT_BOB, VER_FIRST, buildPhone(PHONE_RED)),
-                buildBeforeEntity(CONTACT_MARY, VER_FIRST, buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(
-                buildBeforeEntity(CONTACT_BOB, VER_SECOND, buildPhone(PHONE_RED)));
+        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();
@@ -513,16 +514,16 @@
                 buildDelete(RawContacts.CONTENT_URI));
 
         // Merge in the second version, verify that our delete isn't needed
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged);
     }
 
     public void testMergeRawContactLocalUpdateRemoteDelete() {
-        final EntityDeltaList first = buildSet(
-                buildBeforeEntity(CONTACT_BOB, VER_FIRST, buildPhone(PHONE_RED)),
-                buildBeforeEntity(CONTACT_MARY, VER_FIRST, buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(
-                buildBeforeEntity(CONTACT_BOB, VER_SECOND, buildPhone(PHONE_RED)));
+        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);
@@ -540,7 +541,7 @@
         contactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
 
         // Merge and verify that update turned into insert
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged,
                 buildAssertVersion(VER_SECOND),
                 buildOper(RawContacts.CONTENT_URI, TYPE_INSERT, contactInsert),
@@ -550,28 +551,28 @@
     }
 
     public void testMergeUsesNewVersion() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildPhone(PHONE_RED)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildPhone(PHONE_RED)));
+        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 EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertEquals((Long)VER_SECOND, getVersion(merged, CONTACT_BOB));
     }
 
     public void testMergeAfterEnsureAndTrim() {
-        final EntityDeltaList first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
-                buildEmail(EMAIL_YELLOW)));
-        final EntityDeltaList second = buildSet(buildBeforeEntity(CONTACT_BOB, VER_SECOND,
-                buildEmail(EMAIL_YELLOW)));
+        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 EntityDelta bobContact = first.getByRawContactId(CONTACT_BOB);
-        EntityModifier.ensureKindExists(bobContact, source, Phone.CONTENT_ITEM_TYPE);
+        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
@@ -582,11 +583,11 @@
                 buildUpdateAggregationDefault());
 
         // Trim values and ensure that we don't insert things
-        EntityModifier.trimEmpty(bobContact, source);
+        RawContactModifier.trimEmpty(bobContact, source);
         assertDiffPattern(first);
 
         // Now re-parent the change, which should remain no-op
-        final EntityDeltaList merged = EntityDeltaList.mergeAfter(second, first);
+        final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
         assertDiffPattern(merged);
     }
 }
diff --git a/tests/src/com/android/contacts/EntityDeltaTests.java b/tests/src/com/android/contacts/RawContactDeltaTests.java
similarity index 82%
rename from tests/src/com/android/contacts/EntityDeltaTests.java
rename to tests/src/com/android/contacts/RawContactDeltaTests.java
index fa716c7..80e4c20 100644
--- a/tests/src/com/android/contacts/EntityDeltaTests.java
+++ b/tests/src/com/android/contacts/RawContactDeltaTests.java
@@ -16,35 +16,36 @@
 
 package com.android.contacts;
 
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.google.android.collect.Lists;
-
+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 static android.content.ContentProviderOperation.TYPE_DELETE;
-import static android.content.ContentProviderOperation.TYPE_ASSERT;
 
 import android.content.ContentProviderOperation;
-import android.content.ContentValues;
-import android.content.Entity;
 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.provider.ContactsContract.CommonDataKinds.Phone;
 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.model.RawContactDelta.ValuesDelta;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 
 /**
- * Tests for {@link EntityDelta} and {@link ValuesDelta}. These tests
+ * 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 EntityDeltaTests extends AndroidTestCase {
+public class RawContactDeltaTests extends AndroidTestCase {
     public static final String TAG = "EntityDeltaTests";
 
     public static final long TEST_CONTACT_ID = 12;
@@ -55,7 +56,7 @@
 
     public static final String TEST_ACCOUNT_NAME = "TEST";
 
-    public EntityDeltaTests() {
+    public RawContactDeltaTests() {
         super();
     }
 
@@ -64,7 +65,7 @@
         mContext = getContext();
     }
 
-    public static Entity getEntity(long contactId, long phoneId) {
+    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);
@@ -76,31 +77,31 @@
         phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_1);
         phone.put(Phone.TYPE, Phone.TYPE_HOME);
 
-        final Entity before = new Entity(contact);
-        before.addSubValue(Data.CONTENT_URI, phone);
+        final RawContact before = new RawContact(context, contact);
+        before.addDataItemValues(phone);
         return before;
     }
 
     /**
-     * Test that {@link EntityDelta#mergeAfter(EntityDelta)} correctly passes
+     * Test that {@link RawContactDelta#mergeAfter(RawContactDelta)} correctly passes
      * any changes through the {@link Parcel} object. This enforces that
-     * {@link EntityDelta} should be identical when serialized against the same
-     * "before" {@link Entity}.
+     * {@link RawContactDelta} should be identical when serialized against the same
+     * "before" {@link RawContact}.
      */
     public void testParcelChangesNone() {
-        final Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
-        final EntityDelta dest = EntityDelta.fromBefore(before);
+        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 EntityDelta merged = EntityDelta.mergeAfter(dest, source);
+        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
         assertEquals("Unexpected change when merging", source, merged);
     }
 
     public void testParcelChangesInsert() {
-        final Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
-        final EntityDelta dest = EntityDelta.fromBefore(before);
+        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();
@@ -110,35 +111,35 @@
         source.addEntry(ValuesDelta.fromAfter(phone));
 
         // Merge modified values and assert they match
-        final EntityDelta merged = EntityDelta.mergeAfter(dest, source);
+        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 Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
-        final EntityDelta dest = EntityDelta.fromBefore(before);
+        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 EntityDelta merged = EntityDelta.mergeAfter(dest, source);
+        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 Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
-        final EntityDelta dest = EntityDelta.fromBefore(before);
+        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 EntityDelta merged = EntityDelta.mergeAfter(dest, source);
+        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
         assertEquals("Unexpected change when merging", source, merged);
     }
 
@@ -200,13 +201,13 @@
     }
 
     /**
-     * Test that {@link EntityDelta#buildDiff(ArrayList)} is correctly built for
+     * 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 Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
+        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();
@@ -216,8 +217,8 @@
     }
 
     public void testEntityDiffNoneInsert() {
-        final Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
+        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();
@@ -253,8 +254,8 @@
     }
 
     public void testEntityDiffUpdateInsert() {
-        final Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
+        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);
@@ -298,8 +299,8 @@
     }
 
     public void testEntityDiffNoneUpdate() {
-        final Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
+        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);
@@ -332,8 +333,8 @@
     }
 
     public void testEntityDiffDelete() {
-        final Entity before = getEntity(TEST_CONTACT_ID, TEST_PHONE_ID);
-        final EntityDelta source = EntityDelta.fromBefore(before);
+        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
+        final RawContactDelta source = RawContactDelta.fromBefore(before);
 
         // Delete entire entity
         source.getValues().markDeleted();
@@ -361,7 +362,7 @@
         after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
 
         final ValuesDelta values = ValuesDelta.fromAfter(after);
-        final EntityDelta source = new EntityDelta(values);
+        final RawContactDelta source = new RawContactDelta(values);
 
         // Assert two operations: delete Contact and enforce version
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -382,7 +383,7 @@
         after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
 
         final ValuesDelta values = ValuesDelta.fromAfter(after);
-        final EntityDelta source = new EntityDelta(values);
+        final RawContactDelta source = new RawContactDelta(values);
 
         // Insert a new phone number
         final ContentValues phone = new ContentValues();
diff --git a/tests/src/com/android/contacts/EntityModifierTests.java b/tests/src/com/android/contacts/RawContactModifierTests.java
similarity index 80%
rename from tests/src/com/android/contacts/EntityModifierTests.java
rename to tests/src/com/android/contacts/RawContactModifierTests.java
index df4934a..9254a7e 100644
--- a/tests/src/com/android/contacts/EntityModifierTests.java
+++ b/tests/src/com/android/contacts/RawContactModifierTests.java
@@ -20,24 +20,8 @@
 import static android.content.ContentProviderOperation.TYPE_INSERT;
 import static android.content.ContentProviderOperation.TYPE_UPDATE;
 
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.model.EntityDeltaList;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.ExchangeAccountType;
-import com.android.contacts.model.GoogleAccountType;
-import com.android.contacts.tests.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
-import com.google.android.collect.Lists;
-
 import android.content.ContentProviderOperation;
 import android.content.ContentValues;
-import android.content.Entity;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.ContactsContract;
@@ -54,15 +38,31 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.RawContact;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDelta.ValuesDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountType.EditType;
+import com.android.contacts.model.account.ExchangeAccountType;
+import com.android.contacts.model.account.GoogleAccountType;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.android.contacts.tests.mocks.MockContentProvider;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Tests for {@link EntityModifier} to verify that {@link AccountType}
+ * Tests for {@link RawContactModifier} to verify that {@link AccountType}
  * constraints are being enforced correctly.
  */
 @LargeTest
-public class EntityModifierTests extends AndroidTestCase {
+public class RawContactModifierTests extends AndroidTestCase {
     public static final String TAG = "EntityModifierTests";
 
     public static final long VER_FIRST = 100;
@@ -168,9 +168,9 @@
     }
 
     /**
-     * Build an {@link Entity} with the requested set of phone numbers.
+     * Build an {@link RawContact} with the requested set of phone numbers.
      */
-    protected EntityDelta getEntity(Long existingId, ContentValues... entries) {
+    protected RawContactDelta getRawContact(Long existingId, ContentValues... entries) {
         final ContentValues contact = new ContentValues();
         if (existingId != null) {
             contact.put(RawContacts._ID, existingId);
@@ -178,11 +178,11 @@
         contact.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
         contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT_TYPE);
 
-        final Entity before = new Entity(contact);
+        final RawContact before = new RawContact(mContext, contact);
         for (ContentValues values : entries) {
-            before.addSubValue(Data.CONTENT_URI, values);
+            before.addDataItemValues(values);
         }
-        return EntityDelta.fromBefore(before);
+        return RawContactDelta.fromBefore(before);
     }
 
     /**
@@ -201,116 +201,116 @@
 
     /**
      * Insert various rows to test
-     * {@link EntityModifier#getValidTypes(EntityDelta, DataKind, EditType)}
+     * {@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 = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
-        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
-        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
+        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 EntityDelta state = getEntity(TEST_ID);
-        EntityModifier.insertChild(state, kindPhone, typeHome);
-        EntityModifier.insertChild(state, kindPhone, typeWork);
+        final RawContactDelta state = getRawContact(TEST_ID);
+        RawContactModifier.insertChild(state, kindPhone, typeHome);
+        RawContactModifier.insertChild(state, kindPhone, typeWork);
 
         // Expecting home, other
-        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
+        validTypes = RawContactModifier.getValidTypes(state, kindPhone, null);
         assertContains(validTypes, typeHome);
         assertNotContains(validTypes, typeWork);
         assertContains(validTypes, typeOther);
 
         // Add second home
-        EntityModifier.insertChild(state, kindPhone, typeHome);
+        RawContactModifier.insertChild(state, kindPhone, typeHome);
 
         // Expecting other
-        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
+        validTypes = RawContactModifier.getValidTypes(state, kindPhone, null);
         assertNotContains(validTypes, typeHome);
         assertNotContains(validTypes, typeWork);
         assertContains(validTypes, typeOther);
 
         // Add third and fourth home (invalid, but possible)
-        EntityModifier.insertChild(state, kindPhone, typeHome);
-        EntityModifier.insertChild(state, kindPhone, typeHome);
+        RawContactModifier.insertChild(state, kindPhone, typeHome);
+        RawContactModifier.insertChild(state, kindPhone, typeHome);
 
         // Expecting none
-        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
+        validTypes = RawContactModifier.getValidTypes(state, kindPhone, null);
         assertNotContains(validTypes, typeHome);
         assertNotContains(validTypes, typeWork);
         assertNotContains(validTypes, typeOther);
     }
 
     /**
-     * Test {@link EntityModifier#canInsert(EntityDelta, DataKind)} by
+     * 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 = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
-        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
-        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
+        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 EntityDelta state = getEntity(TEST_ID);
-        EntityModifier.insertChild(state, kindPhone, typeHome);
-        EntityModifier.insertChild(state, kindPhone, typeWork);
-        assertTrue("Unable to insert", EntityModifier.canInsert(state, kindPhone));
+        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
-        EntityModifier.insertChild(state, kindPhone, typeOther);
-        EntityModifier.insertChild(state, kindPhone, typeOther);
-        assertTrue("Unable to insert", EntityModifier.canInsert(state, kindPhone));
+        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
-        EntityModifier.insertChild(state, kindPhone, typeHome);
-        assertFalse("Able to insert", EntityModifier.canInsert(state, kindPhone));
+        RawContactModifier.insertChild(state, kindPhone, typeHome);
+        assertFalse("Able to insert", RawContactModifier.canInsert(state, kindPhone));
     }
 
     /**
      * Test
-     * {@link EntityModifier#getBestValidType(EntityDelta, DataKind, boolean, int)}
+     * {@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 = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
-        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
-        final EditType typeFaxWork = EntityModifier.getType(kindPhone, Phone.TYPE_FAX_WORK);
-        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
+        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 EntityDelta state = getEntity(TEST_ID);
-        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
+        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
-        EntityModifier.insertChild(state, kindPhone, typeHome);
-        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
+        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
-        EntityModifier.insertChild(state, kindPhone, typeFaxWork);
-        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
+        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
-        EntityModifier.insertChild(state, kindPhone, typeOther);
-        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
+        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
-        EntityModifier.insertChild(state, kindPhone, typeWork);
-        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
+        RawContactModifier.insertChild(state, kindPhone, typeWork);
+        suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
         assertEquals("Unexpected suggestion", typeOther, suggested);
     }
 
@@ -322,34 +322,34 @@
         final ContentValues after = new ContentValues();
         final ValuesDelta values = ValuesDelta.fromAfter(after);
 
-        assertTrue("Expected empty", EntityModifier.isEmpty(values, kindPhone));
+        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 = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Test row that has type values, but core fields are empty
-        final EntityDelta state = getEntity(TEST_ID);
-        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
+        final RawContactDelta state = getRawContact(TEST_ID);
+        final ValuesDelta values = RawContactModifier.insertChild(state, kindPhone, typeHome);
 
-        assertTrue("Expected empty", EntityModifier.isEmpty(values, kindPhone));
+        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", EntityModifier.isEmpty(values, kindPhone));
+        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 = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Test row that has type values, but core fields are empty
-        final EntityDelta state = getEntity(TEST_ID);
-        EntityModifier.insertChild(state, kindPhone, typeHome);
+        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();
@@ -372,7 +372,7 @@
         }
 
         // Trim empty rows and try again, expecting delete of overall contact
-        EntityModifier.trimEmpty(state, source);
+        RawContactModifier.trimEmpty(state, source);
         diff.clear();
         state.buildDiff(diff);
         assertEquals("Unexpected operations", 1, diff.size());
@@ -386,63 +386,65 @@
     public void testTrimEmptySpaces() {
         final AccountType source = getAccountType();
         final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Test row that has type values, but values are spaces
-        final EntityDelta state = EntityDeltaListTests.buildBeforeEntity(TEST_ID, VER_FIRST);
-        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
+        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
-        EntityDeltaListTests.assertDiffPattern(state,
-                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
-                EntityDeltaListTests.buildUpdateAggregationSuspended(),
-                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
-                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
-                EntityDeltaListTests.buildUpdateAggregationDefault());
+        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
-        EntityModifier.trimEmpty(state, source);
-        EntityDeltaListTests.assertDiffPattern(state,
-                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
-                EntityDeltaListTests.buildDelete(RawContacts.CONTENT_URI));
+        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 = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Test row that has type values with valid number
-        final EntityDelta state = EntityDeltaListTests.buildBeforeEntity(TEST_ID, VER_FIRST);
-        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
+        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
-        EntityDeltaListTests.assertDiffPattern(state,
-                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
-                EntityDeltaListTests.buildUpdateAggregationSuspended(),
-                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
-                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
-                EntityDeltaListTests.buildUpdateAggregationDefault());
+        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
-        EntityModifier.trimEmpty(state, source);
-        EntityDeltaListTests.assertDiffPattern(state,
-                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
-                EntityDeltaListTests.buildUpdateAggregationSuspended(),
-                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
-                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
-                EntityDeltaListTests.buildUpdateAggregationDefault());
+        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);
-        EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Build "before" that has empty row
-        final EntityDelta state = getEntity(TEST_ID);
+        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);
@@ -454,7 +456,7 @@
         assertEquals("Unexpected operations", 0, diff.size());
 
         // Try trimming existing empty, which we shouldn't touch
-        EntityModifier.trimEmpty(state, source);
+        RawContactModifier.trimEmpty(state, source);
         diff.clear();
         state.buildDiff(diff);
         assertEquals("Unexpected operations", 0, diff.size());
@@ -463,7 +465,7 @@
     public void testTrimEmptyAfterUpdate() {
         final AccountType source = getAccountType();
         final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Build "before" that has row with some phone number
         final ContentValues before = new ContentValues();
@@ -471,7 +473,7 @@
         before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
         before.put(kindPhone.typeColumn, typeHome.rawValue);
         before.put(Phone.NUMBER, TEST_PHONE);
-        final EntityDelta state = getEntity(TEST_ID, before);
+        final RawContactDelta state = getRawContact(TEST_ID, before);
 
         // Build diff, expecting no changes
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -501,7 +503,7 @@
         }
 
         // Now run trim, which should turn that update into delete
-        EntityModifier.trimEmpty(state, source);
+        RawContactModifier.trimEmpty(state, source);
         diff.clear();
         state.buildDiff(diff);
         assertEquals("Unexpected operations", 1, diff.size());
@@ -516,11 +518,11 @@
         final AccountType accountType = getAccountType();
         final AccountTypeManager accountTypes = getAccountTypes(accountType);
         final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Try creating a contact without any child entries
-        final EntityDelta state = getEntity(null);
-        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
+        final RawContactDelta state = getRawContact(null);
+        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
 
         // Build diff, expecting single insert
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -533,7 +535,7 @@
         }
 
         // Trim empty rows and try again, expecting no insert
-        EntityModifier.trimEmpty(set, accountTypes);
+        RawContactModifier.trimEmpty(set, accountTypes);
         diff.clear();
         state.buildDiff(diff);
         assertEquals("Unexpected operations", 0, diff.size());
@@ -543,12 +545,12 @@
         final AccountType accountType = getAccountType();
         final AccountTypeManager accountTypes = getAccountTypes(accountType);
         final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Try creating a contact with single empty entry
-        final EntityDelta state = getEntity(null);
-        EntityModifier.insertChild(state, kindPhone, typeHome);
-        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
+        final RawContactDelta state = getRawContact(null);
+        RawContactModifier.insertChild(state, kindPhone, typeHome);
+        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
 
         // Build diff, expecting two insert operations
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -566,7 +568,7 @@
         }
 
         // Trim empty rows and try again, expecting silence
-        EntityModifier.trimEmpty(set, accountTypes);
+        RawContactModifier.trimEmpty(set, accountTypes);
         diff.clear();
         state.buildDiff(diff);
         assertEquals("Unexpected operations", 0, diff.size());
@@ -576,7 +578,7 @@
         final AccountType accountType = getAccountType();
         final AccountTypeManager accountTypes = getAccountTypes(accountType);
         final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Build "before" with two phone numbers
         final ContentValues first = new ContentValues();
@@ -591,8 +593,8 @@
         second.put(kindPhone.typeColumn, typeHome.rawValue);
         second.put(Phone.NUMBER, TEST_PHONE);
 
-        final EntityDelta state = getEntity(TEST_ID, first, second);
-        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
+        final RawContactDelta state = getRawContact(TEST_ID, first, second);
+        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
 
         // Build diff, expecting no changes
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -622,7 +624,7 @@
         }
 
         // Now run trim, which should turn that update into delete
-        EntityModifier.trimEmpty(set, accountTypes);
+        RawContactModifier.trimEmpty(set, accountTypes);
         diff.clear();
         state.buildDiff(diff);
         assertEquals("Unexpected operations", 3, diff.size());
@@ -647,7 +649,7 @@
         final AccountType accountType = getAccountType();
         final AccountTypeManager accountTypes = getAccountTypes(accountType);
         final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
-        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+        final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME);
 
         // Build "before" with two phone numbers
         final ContentValues first = new ContentValues();
@@ -656,8 +658,8 @@
         first.put(kindPhone.typeColumn, typeHome.rawValue);
         first.put(Phone.NUMBER, TEST_PHONE);
 
-        final EntityDelta state = getEntity(TEST_ID, first);
-        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
+        final RawContactDelta state = getRawContact(TEST_ID, first);
+        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
 
         // Build diff, expecting no changes
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -687,7 +689,7 @@
         }
 
         // Now run trim, which should turn into deleting the whole contact
-        EntityModifier.trimEmpty(set, accountTypes);
+        RawContactModifier.trimEmpty(set, accountTypes);
         diff.clear();
         state.buildDiff(diff);
         assertEquals("Unexpected operations", 1, diff.size());
@@ -708,10 +710,10 @@
         first.put(StructuredName.GIVEN_NAME, TEST_NAME);
 
         // Parse extras, making sure we keep single name
-        final EntityDelta state = getEntity(TEST_ID, first);
+        final RawContactDelta state = getRawContact(TEST_ID, first);
         final Bundle extras = new Bundle();
         extras.putString(Insert.NAME, TEST_NAME2);
-        EntityModifier.parseExtras(mContext, accountType, state, extras);
+        RawContactModifier.parseExtras(mContext, accountType, state, extras);
 
         final int nameCount = state.getMimeEntriesCount(StructuredName.CONTENT_ITEM_TYPE, true);
         assertEquals("Unexpected names", 1, nameCount);
@@ -726,7 +728,7 @@
         first.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
         first.put(Im.DATA, TEST_IM);
 
-        final EntityDelta state = getEntity(TEST_ID, first);
+        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
@@ -734,7 +736,7 @@
         final Bundle extras = new Bundle();
         extras.putInt(Insert.IM_PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
         extras.putString(Insert.IM_HANDLE, TEST_IM);
-        EntityModifier.parseExtras(mContext, accountType, state, extras);
+        RawContactModifier.parseExtras(mContext, accountType, state, extras);
 
         final int afterCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size();
         assertEquals("Broke account type rules", beforeCount, afterCount);
@@ -742,12 +744,12 @@
 
     public void testParseExtrasIgnoreUnhandled() {
         final AccountType accountType = getAccountType();
-        final EntityDelta state = getEntity(TEST_ID);
+        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);
-        EntityModifier.parseExtras(mContext, accountType, state, extras);
+        RawContactModifier.parseExtras(mContext, accountType, state, extras);
 
         assertNull("Broke accoun type rules",
                 state.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE));
@@ -755,12 +757,12 @@
 
     public void testParseExtrasJobTitle() {
         final AccountType accountType = getAccountType();
-        final EntityDelta state = getEntity(TEST_ID);
+        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);
-        EntityModifier.parseExtras(mContext, accountType, state, extras);
+        RawContactModifier.parseExtras(mContext, accountType, state, extras);
 
         final int count = state.getMimeEntries(Organization.CONTENT_ITEM_TYPE).size();
         assertEquals("Expected to create organization", 1, count);
@@ -773,7 +775,7 @@
 
         ContactsMockContext context = new ContactsMockContext(getContext());
 
-        EntityDelta oldState = new EntityDelta();
+        RawContactDelta oldState = new RawContactDelta();
         ContentValues mockNameValues = new ContentValues();
         mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
         mockNameValues.put(StructuredName.PREFIX, "prefix");
@@ -786,8 +788,8 @@
         mockNameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "PHONETIC_GIVEN");
         oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateStructuredName(context, oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateStructuredName(context, oldState, newState, kind);
         List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
         assertEquals(1, list.size());
 
@@ -824,14 +826,14 @@
                         StructuredName.MIDDLE_NAME, StructuredName.FAMILY_NAME,
                         StructuredName.SUFFIX);
 
-        EntityDelta oldState = new EntityDelta();
+        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));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateStructuredName(context, oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateStructuredName(context, oldState, newState, kind);
         List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
         assertEquals(1, list.size());
 
@@ -866,7 +868,7 @@
                 .returnRow("prefix given middle family suffix")
                 .withProjection(StructuredName.DISPLAY_NAME);
 
-        EntityDelta oldState = new EntityDelta();
+        RawContactDelta oldState = new RawContactDelta();
         ContentValues mockNameValues = new ContentValues();
         mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
         mockNameValues.put(StructuredName.PREFIX, "prefix");
@@ -876,8 +878,8 @@
         mockNameValues.put(StructuredName.SUFFIX, "suffix");
         oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateStructuredName(context, oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateStructuredName(context, oldState, newState, kind);
 
         List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -892,14 +894,14 @@
         AccountType newAccountType = new ExchangeAccountType(getContext(), "");
         DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
 
-        EntityDelta oldState = new EntityDelta();
+        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));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migratePostal(oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migratePostal(oldState, newState, kind);
 
         List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -915,7 +917,7 @@
         AccountType newAccountType = new GoogleAccountType(getContext(), "");
         DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
 
-        EntityDelta oldState = new EntityDelta();
+        RawContactDelta oldState = new RawContactDelta();
         ContentValues mockNameValues = new ContentValues();
         mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
         mockNameValues.put(StructuredPostal.COUNTRY, "country");
@@ -925,8 +927,8 @@
         mockNameValues.put(StructuredPostal.STREET, "street");
         oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migratePostal(oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migratePostal(oldState, newState, kind);
 
         List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -957,15 +959,15 @@
     private void testMigrateEventCommon(AccountType oldAccountType, AccountType newAccountType) {
         DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
 
-        EntityDelta oldState = new EntityDelta();
+        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));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateEvent(oldState, newState, kind, 1990);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateEvent(oldState, newState, kind, 1990);
 
         List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -981,7 +983,7 @@
         AccountType newAccountType = new ExchangeAccountType(getContext(), "");
         DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
 
-        EntityDelta oldState = new EntityDelta();
+        RawContactDelta oldState = new RawContactDelta();
         ContentValues mockNameValues = new ContentValues();
         mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
         // No year format is not supported by Exchange.
@@ -995,8 +997,8 @@
         mockNameValues.put(Event.TYPE, Event.TYPE_ANNIVERSARY);
         oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateEvent(oldState, newState, kind, 1990);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateEvent(oldState, newState, kind, 1990);
 
         List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -1013,7 +1015,7 @@
         AccountType newAccountType = new ExchangeAccountType(getContext(), "");
         DataKind kind = newAccountType.getKindForMimetype(Email.CONTENT_ITEM_TYPE);
 
-        EntityDelta oldState = new EntityDelta();
+        RawContactDelta oldState = new RawContactDelta();
         ContentValues mockNameValues = new ContentValues();
         mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
         mockNameValues.put(Email.TYPE, Email.TYPE_CUSTOM);
@@ -1037,8 +1039,8 @@
         mockNameValues.put(Email.ADDRESS, "address4");
         oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
 
         List<ValuesDelta> list = newState.getMimeEntries(Email.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -1063,7 +1065,7 @@
         AccountType newAccountType = new ExchangeAccountType(getContext(), "");
         DataKind kind = newAccountType.getKindForMimetype(Im.CONTENT_ITEM_TYPE);
 
-        EntityDelta oldState = new EntityDelta();
+        RawContactDelta oldState = new RawContactDelta();
         ContentValues mockNameValues = new ContentValues();
         mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
         // Exchange doesn't support TYPE_HOME
@@ -1096,8 +1098,8 @@
         mockNameValues.put(Im.DATA, "im4");
         oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
 
         List<ValuesDelta> list = newState.getMimeEntries(Im.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -1149,7 +1151,7 @@
         // - "3" -- MOBILE
         // - "4" -- WORK
 
-        EntityDelta oldState = new EntityDelta();
+        RawContactDelta oldState = new RawContactDelta();
         ContentValues mockNameValues = new ContentValues();
         mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
         mockNameValues.put(Phone.TYPE, Phone.TYPE_HOME);
@@ -1179,8 +1181,8 @@
         mockNameValues.put(Phone.NUMBER, "5");
         oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
 
         List<ValuesDelta> list = newState.getMimeEntries(Phone.CONTENT_ITEM_TYPE);
         assertNotNull(list);
@@ -1208,15 +1210,15 @@
         AccountType newAccountType = new ExchangeAccountType(getContext(), "");
         DataKind kind = newAccountType.getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
 
-        EntityDelta oldState = new EntityDelta();
+        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));
 
-        EntityDelta newState = new EntityDelta();
-        EntityModifier.migrateGenericWithoutTypeColumn(oldState, newState, kind);
+        RawContactDelta newState = new RawContactDelta();
+        RawContactModifier.migrateGenericWithoutTypeColumn(oldState, newState, kind);
 
         List<ValuesDelta> list = newState.getMimeEntries(Organization.CONTENT_ITEM_TYPE);
         assertNotNull(list);
diff --git a/tests/src/com/android/contacts/activities/PeopleActivityTest.java b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
index ea7c3dc..11fccd1 100644
--- a/tests/src/com/android/contacts/activities/PeopleActivityTest.java
+++ b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
@@ -16,25 +16,6 @@
 
 package com.android.contacts.activities;
 
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactsApplication;
-import com.android.contacts.R;
-import com.android.contacts.detail.ContactDetailFragment;
-import com.android.contacts.interactions.TestLoaderManager;
-import com.android.contacts.list.ContactBrowseListFragment;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.BaseAccountType;
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContactPhotoManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
-import com.android.contacts.tests.mocks.MockContentProvider.Query;
-import com.android.contacts.tests.mocks.MockSharedPreferences;
-import com.android.contacts.util.PhoneCapabilityTester;
-
 import android.content.ContentValues;
 import android.content.Intent;
 import android.content.Loader;
@@ -51,6 +32,25 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.widget.TextView;
 
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.ContactsApplication;
+import com.android.contacts.R;
+import com.android.contacts.detail.ContactDetailFragment;
+import com.android.contacts.interactions.TestLoaderManager;
+import com.android.contacts.list.ContactBrowseListFragment;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.account.BaseAccountType;
+import com.android.contacts.test.InjectedServices;
+import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.android.contacts.tests.mocks.MockContactPhotoManager;
+import com.android.contacts.tests.mocks.MockContentProvider;
+import com.android.contacts.tests.mocks.MockContentProvider.Query;
+import com.android.contacts.tests.mocks.MockSharedPreferences;
+import com.android.contacts.util.PhoneCapabilityTester;
+
 /**
  * This test is so outdated that it's disabled temporarily.  TODO Update the test and re-enable it.
  *
diff --git a/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java b/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java
index 8a98018..5bc31f9 100644
--- a/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogAdapterTest.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.calllog;
 
-import com.google.common.collect.Lists;
-
 import android.content.Context;
 import android.database.MatrixCursor;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
 /**
diff --git a/tests/src/com/android/contacts/calllog/CallLogFragmentTest.java b/tests/src/com/android/contacts/calllog/CallLogFragmentTest.java
index 89c0a99..0eaca60 100644
--- a/tests/src/com/android/contacts/calllog/CallLogFragmentTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogFragmentTest.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.CallDetailActivity;
-import com.android.contacts.R;
-import com.android.contacts.test.FragmentTestActivity;
-import com.android.internal.telephony.CallerInfo;
-
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.content.ComponentName;
@@ -42,6 +37,11 @@
 import android.view.View;
 import android.widget.FrameLayout;
 
+import com.android.contacts.CallDetailActivity;
+import com.android.contacts.R;
+import com.android.contacts.test.FragmentTestActivity;
+import com.android.internal.telephony.CallerInfo;
+
 import java.util.Date;
 import java.util.Formatter;
 import java.util.HashMap;
diff --git a/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java b/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java
index 24aa428..de2b292 100644
--- a/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java
@@ -16,7 +16,7 @@
 
 package com.android.contacts.calllog;
 
-import static com.google.android.collect.Lists.newArrayList;
+import static com.google.common.collect.Lists.newArrayList;
 
 import android.database.MatrixCursor;
 import android.provider.CallLog.Calls;
diff --git a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
index 0488044..a184f75 100644
--- a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
@@ -16,16 +16,16 @@
 
 package com.android.contacts.calllog;
 
-import com.android.contacts.PhoneCallDetails;
-import com.android.contacts.PhoneCallDetailsHelper;
-import com.android.internal.telephony.CallerInfo;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.provider.CallLog.Calls;
 import android.test.AndroidTestCase;
 import android.view.View;
 
+import com.android.contacts.PhoneCallDetails;
+import com.android.contacts.PhoneCallDetailsHelper;
+import com.android.internal.telephony.CallerInfo;
+
 /**
  * Unit tests for {@link CallLogListItemHelper}.
  */
diff --git a/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
index 419cac8..07b3691 100644
--- a/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
+++ b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.R;
-import com.android.contacts.util.StreamItemEntry;
-import com.android.contacts.util.StreamItemEntryBuilder;
-
 import android.content.Context;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -29,6 +25,10 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.contacts.R;
+import com.android.contacts.util.StreamItemEntry;
+import com.android.contacts.util.StreamItemEntryBuilder;
+
 /**
  * Unit tests for {@link ContactDetailDisplayUtils}.
  */
diff --git a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
index 02faa24..b1d1daa 100644
--- a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
+++ b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.detail.ContactDetailFragment.DetailViewEntry;
-
 import android.content.ContentValues;
 import android.content.Intent;
 import android.net.Uri;
@@ -26,6 +24,11 @@
 import android.test.AndroidTestCase;
 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;
+
 /**
  * Tests for {@link ContactDetailFragment}.
  */
@@ -41,9 +44,10 @@
         values.put(Im.TYPE, Im.TYPE_HOME);
         values.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
         values.put(Im.DATA, TEST_ADDRESS);
+        ImDataItem im = (ImDataItem) DataItem.createFrom(null, values);
 
         DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
-        ContactDetailFragment.buildImActions(mContext, entry, values);
+        ContactDetailFragment.buildImActions(mContext, entry, im);
         assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
         assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
 
@@ -58,9 +62,10 @@
         values.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
         values.put(Im.DATA, TEST_ADDRESS);
         values.put(Im.CHAT_CAPABILITY, Im.CAPABILITY_HAS_VOICE | Im.CAPABILITY_HAS_VIDEO);
+        ImDataItem im = (ImDataItem) DataItem.createFrom(null, values);
 
         DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
-        ContactDetailFragment.buildImActions(mContext, entry, values);
+        ContactDetailFragment.buildImActions(mContext, entry, im);
         assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
         assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
 
@@ -77,9 +82,10 @@
         values.put(Im.DATA, TEST_ADDRESS);
         values.put(Im.CHAT_CAPABILITY, Im.CAPABILITY_HAS_VOICE | Im.CAPABILITY_HAS_VIDEO |
                 Im.CAPABILITY_HAS_VOICE);
+        ImDataItem im = (ImDataItem) DataItem.createFrom(null, values);
 
         DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
-        ContactDetailFragment.buildImActions(mContext, entry, values);
+        ContactDetailFragment.buildImActions(mContext, entry, im);
         assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
         assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
 
@@ -96,9 +102,10 @@
         values.put(Im.PROTOCOL, Im.PROTOCOL_CUSTOM);
         values.put(Im.CUSTOM_PROTOCOL, TEST_PROTOCOL);
         values.put(Im.DATA, TEST_ADDRESS);
+        ImDataItem im = (ImDataItem) DataItem.createFrom(null, values);
 
         DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
-        ContactDetailFragment.buildImActions(mContext, entry, values);
+        ContactDetailFragment.buildImActions(mContext, entry, im);
         assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
 
         final Uri data = entry.intent.getData();
@@ -119,9 +126,11 @@
         values.put(Email.DATA, TEST_ADDRESS);
         values.put(Email.CHAT_CAPABILITY, Im.CAPABILITY_HAS_VOICE | Im.CAPABILITY_HAS_VIDEO |
                 Im.CAPABILITY_HAS_VOICE);
+        ImDataItem im = ImDataItem.createFromEmail(
+                (EmailDataItem) DataItem.createFrom(null, values));
 
         DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
-        ContactDetailFragment.buildImActions(mContext, entry, values);
+        ContactDetailFragment.buildImActions(mContext, entry, im);
         assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
         assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
 
diff --git a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
index cd2d6bf..7f1ee02 100644
--- a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
+++ b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
@@ -16,14 +16,14 @@
 
 package com.android.contacts.detail;
 
-import com.android.contacts.util.StreamItemEntry;
-import com.android.contacts.util.StreamItemEntryBuilder;
-import com.google.common.collect.Lists;
-
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 
+import com.android.contacts.util.StreamItemEntry;
+import com.android.contacts.util.StreamItemEntryBuilder;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 
 // TODO: We should have tests for action, but that requires a mock sync-adapter that specifies
diff --git a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
index 8007aee..9f2d49b 100644
--- a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
+++ b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
@@ -16,17 +16,15 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.editor.ContactEditorUtils;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.google.android.collect.Sets;
-
-import android.content.Context;
 import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.google.common.collect.Sets;
+
 import java.util.Collection;
 import java.util.Set;
 
diff --git a/tests/src/com/android/contacts/format/TestTextWithHighlightingFactory.java b/tests/src/com/android/contacts/format/TestTextWithHighlightingFactory.java
index 2deaef3..9dbd364 100644
--- a/tests/src/com/android/contacts/format/TestTextWithHighlightingFactory.java
+++ b/tests/src/com/android/contacts/format/TestTextWithHighlightingFactory.java
@@ -16,15 +16,15 @@
 
 package com.android.contacts.format;
 
-import com.android.contacts.widget.TextWithHighlighting;
-import com.android.contacts.widget.TextWithHighlightingFactory;
-
 import android.database.CharArrayBuffer;
 import android.graphics.Typeface;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.SpannableStringBuilder;
 import android.text.style.StyleSpan;
 
+import com.android.contacts.widget.TextWithHighlighting;
+import com.android.contacts.widget.TextWithHighlightingFactory;
+
 /** A factory for {@link TextWithHighlighting} that wraps its parts in italics. */
 @SmallTest
 public final class TestTextWithHighlightingFactory implements TextWithHighlightingFactory {
@@ -46,4 +46,4 @@
     public TextWithHighlighting createTextWithHighlighting() {
         return new TestTextWithHighlighting();
     }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
index b37d24f..fcbd83d 100644
--- a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
+++ b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
@@ -16,19 +16,6 @@
 
 package com.android.contacts.interactions;
 
-import com.android.contacts.ContactsApplication;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.BaseAccountType;
-import com.android.contacts.test.FragmentTestActivity;
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
-import com.android.contacts.tests.mocks.MockContentProvider.Query;
-import com.android.contacts.util.IntegrationTestUtils;
-
 import android.content.ContentUris;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -37,6 +24,19 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.contacts.ContactsApplication;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.BaseAccountType;
+import com.android.contacts.test.FragmentTestActivity;
+import com.android.contacts.test.InjectedServices;
+import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.android.contacts.tests.mocks.MockContentProvider;
+import com.android.contacts.tests.mocks.MockContentProvider.Query;
+import com.android.contacts.util.IntegrationTestUtils;
+
 /**
  * Tests for {@link ContactDeletionInteraction}.
  *
diff --git a/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java b/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
index 2da8859..a82e0f6 100644
--- a/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
+++ b/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
@@ -16,12 +16,6 @@
 
 package com.android.contacts.interactions;
 
-import com.android.contacts.interactions.PhoneNumberInteraction.InteractionType;
-import com.android.contacts.interactions.PhoneNumberInteraction.PhoneItem;
-import com.android.contacts.tests.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockContentProvider;
-import com.android.contacts.tests.mocks.MockContentProvider.Query;
-
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.DialogInterface.OnDismissListener;
@@ -36,6 +30,12 @@
 import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.contacts.interactions.PhoneNumberInteraction.InteractionType;
+import com.android.contacts.interactions.PhoneNumberInteraction.PhoneItem;
+import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.MockContentProvider;
+import com.android.contacts.tests.mocks.MockContentProvider.Query;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/tests/src/com/android/contacts/list/ContactListItemViewTest.java b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
index 82305d5..748876f 100644
--- a/tests/src/com/android/contacts/list/ContactListItemViewTest.java
+++ b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.list;
 
-import com.android.contacts.activities.PeopleActivity;
-import com.android.contacts.format.SpannedTestUtils;
-import com.android.contacts.util.IntegrationTestUtils;
-
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.provider.ContactsContract;
@@ -27,6 +23,10 @@
 import android.test.suitebuilder.annotation.LargeTest;
 import android.widget.TextView;
 
+import com.android.contacts.activities.PeopleActivity;
+import com.android.contacts.format.SpannedTestUtils;
+import com.android.contacts.util.IntegrationTestUtils;
+
 /**
  * Unit tests for {@link ContactListItemView}.
  *
@@ -36,7 +36,7 @@
 @LargeTest
 public class ContactListItemViewTest extends ActivityInstrumentationTestCase2<PeopleActivity> {
     /** The HTML code used to mark the start of the highlighted part. */
-    private static final String START = "<font color =\"#99cc00\">";
+    private static final String START = "<font color =\"#33b5e5\">";
     /** The HTML code used to mark the end of the highlighted part. */
     private static final String END = "</font>";
 
diff --git a/tests/src/com/android/contacts/model/AccountTypeManagerTest.java b/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
index 6f5bbf2..c8db85e 100644
--- a/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
+++ b/tests/src/com/android/contacts/model/AccountTypeManagerTest.java
@@ -16,13 +16,16 @@
 
 package com.android.contacts.model;
 
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
 import android.content.Context;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountTypeWithDataSet;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
diff --git a/tests/src/com/android/contacts/model/AccountWithDataSetTest.java b/tests/src/com/android/contacts/model/AccountWithDataSetTest.java
index 27c106e..1818c38 100644
--- a/tests/src/com/android/contacts/model/AccountWithDataSetTest.java
+++ b/tests/src/com/android/contacts/model/AccountWithDataSetTest.java
@@ -16,13 +16,14 @@
 
 package com.android.contacts.model;
 
-import com.google.common.collect.Lists;
-
 import android.os.Bundle;
 import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
 /**
diff --git a/tests/src/com/android/contacts/ContactLoaderTest.java b/tests/src/com/android/contacts/model/ContactLoaderTest.java
similarity index 92%
rename from tests/src/com/android/contacts/ContactLoaderTest.java
rename to tests/src/com/android/contacts/model/ContactLoaderTest.java
index 5c215f9..54d220f 100644
--- a/tests/src/com/android/contacts/ContactLoaderTest.java
+++ b/tests/src/com/android/contacts/model/ContactLoaderTest.java
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts;
-
-import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountWithDataSet;
-import com.android.contacts.model.BaseAccountType;
-import com.android.contacts.test.InjectedServices;
-import com.android.contacts.tests.mocks.ContactsMockContext;
-import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.android.contacts.tests.mocks.MockContentProvider;
+package com.android.contacts.model;
 
 import android.content.ContentUris;
 import android.net.Uri;
@@ -36,6 +28,15 @@
 import android.test.LoaderTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountWithDataSet;
+import com.android.contacts.model.account.BaseAccountType;
+import com.android.contacts.test.InjectedServices;
+import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.android.contacts.tests.mocks.MockContentProvider;
+
 /**
  * Runs ContactLoader tests for the the contact-detail and editor view.
  */
@@ -74,23 +75,23 @@
         super.tearDown();
     }
 
-    private ContactLoader.Result assertLoadContact(Uri uri) {
+    private Contact assertLoadContact(Uri uri) {
         final ContactLoader loader = new ContactLoader(mMockContext, uri, true);
         return getLoaderResultSynchronously(loader);
     }
 
     public void testNullUri() {
-        ContactLoader.Result result = assertLoadContact(null);
+        Contact result = assertLoadContact(null);
         assertTrue(result.isError());
     }
 
     public void testEmptyUri() {
-        ContactLoader.Result result = assertLoadContact(Uri.EMPTY);
+        Contact result = assertLoadContact(Uri.EMPTY);
         assertTrue(result.isError());
     }
 
     public void testInvalidUri() {
-        ContactLoader.Result result = assertLoadContact(Uri.parse("content://wtf"));
+        Contact result = assertLoadContact(Uri.parse("content://wtf"));
         assertTrue(result.isError());
     }
 
@@ -111,14 +112,14 @@
         mContactsProvider.expectTypeQuery(baseUri, Contacts.CONTENT_ITEM_TYPE);
         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
 
-        ContactLoader.Result contact = assertLoadContact(baseUri);
+        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.getEntities().size());
+        assertEquals(1, contact.getRawContacts().size());
         assertEquals(1, contact.getStatuses().size());
         mContactsProvider.verify();
     }
@@ -143,14 +144,14 @@
         queries.fetchContactIdAndLookupFromRawContactUri(rawContactUri, contactId, lookupKey);
         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
 
-        ContactLoader.Result contact = assertLoadContact(legacyUri);
+        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.getEntities().size());
+        assertEquals(1, contact.getRawContacts().size());
         assertEquals(1, contact.getStatuses().size());
         mContactsProvider.verify();
     }
@@ -174,14 +175,14 @@
         queries.fetchContactIdAndLookupFromRawContactUri(rawContactUri, contactId, lookupKey);
         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
 
-        ContactLoader.Result contact = assertLoadContact(rawContactUri);
+        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.getEntities().size());
+        assertEquals(1, contact.getRawContacts().size());
         assertEquals(1, contact.getStatuses().size());
         mContactsProvider.verify();
     }
@@ -203,14 +204,14 @@
         mContactsProvider.expectTypeQuery(lookupNoIdUri, Contacts.CONTENT_ITEM_TYPE);
         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
 
-        ContactLoader.Result contact = assertLoadContact(lookupNoIdUri);
+        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.getEntities().size());
+        assertEquals(1, contact.getRawContacts().size());
         assertEquals(1, contact.getStatuses().size());
         mContactsProvider.verify();
     }
@@ -232,14 +233,14 @@
         mContactsProvider.expectTypeQuery(lookupUri, Contacts.CONTENT_ITEM_TYPE);
         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
 
-        ContactLoader.Result contact = assertLoadContact(lookupUri);
+        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.getEntities().size());
+        assertEquals(1, contact.getRawContacts().size());
         assertEquals(1, contact.getStatuses().size());
         mContactsProvider.verify();
     }
@@ -271,14 +272,14 @@
         mContactsProvider.expectTypeQuery(lookupWithWrongIdUri, Contacts.CONTENT_ITEM_TYPE);
         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
 
-        ContactLoader.Result contact = assertLoadContact(lookupWithWrongIdUri);
+        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.getEntities().size());
+        assertEquals(1, contact.getRawContacts().size());
         assertEquals(1, contact.getStatuses().size());
 
         mContactsProvider.verify();
diff --git a/tests/src/com/android/contacts/model/AccountTypeTest.java b/tests/src/com/android/contacts/model/account/AccountTypeTest.java
similarity index 97%
rename from tests/src/com/android/contacts/model/AccountTypeTest.java
rename to tests/src/com/android/contacts/model/account/AccountTypeTest.java
index 6d4d6b0..ad111d9 100644
--- a/tests/src/com/android/contacts/model/AccountTypeTest.java
+++ b/tests/src/com/android/contacts/model/account/AccountTypeTest.java
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.tests.R;
+package com.android.contacts.model.account;
 
 import android.content.Context;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.tests.R;
+
 /**
  * Test case for {@link AccountType}.
  *
diff --git a/tests/src/com/android/contacts/model/ExternalAccountTypeTest.java b/tests/src/com/android/contacts/model/account/ExternalAccountTypeTest.java
similarity index 98%
rename from tests/src/com/android/contacts/model/ExternalAccountTypeTest.java
rename to tests/src/com/android/contacts/model/account/ExternalAccountTypeTest.java
index 4c47d68..6eb3bd7 100644
--- a/tests/src/com/android/contacts/model/ExternalAccountTypeTest.java
+++ b/tests/src/com/android/contacts/model/account/ExternalAccountTypeTest.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.model;
-
-import com.android.contacts.tests.R;
+package com.android.contacts.model.account;
 
 import android.content.Context;
 import android.provider.ContactsContract.CommonDataKinds.Email;
@@ -33,9 +31,11 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import java.util.List;
+import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.tests.R;
+import com.google.common.base.Objects;
 
-import libcore.util.Objects;
+import java.util.List;
 
 /**
  * Test case for {@link ExternalAccountType}.
diff --git a/tests/src/com/android/contacts/tests/PhoneNumberTestService.java b/tests/src/com/android/contacts/tests/PhoneNumberTestService.java
index 894e66e..8178985 100644
--- a/tests/src/com/android/contacts/tests/PhoneNumberTestService.java
+++ b/tests/src/com/android/contacts/tests/PhoneNumberTestService.java
@@ -16,11 +16,6 @@
 
 package com.android.contacts.tests;
 
-import com.android.i18n.phonenumbers.NumberParseException;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
-import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
-import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
-
 import android.app.IntentService;
 import android.content.Context;
 import android.content.Intent;
@@ -28,6 +23,11 @@
 import android.telephony.PhoneNumberUtils;
 import android.util.Log;
 
+import com.android.i18n.phonenumbers.NumberParseException;
+import com.android.i18n.phonenumbers.PhoneNumberUtil;
+import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
+import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
 import java.util.LinkedHashSet;
 import java.util.Set;
 
diff --git a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
index c6577b8..252fe24 100644
--- a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
+++ b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.tests.allintents;
 
-import com.android.contacts.tests.R;
-import com.google.android.collect.Lists;
-
 import android.accounts.Account;
 import android.app.ListActivity;
 import android.app.SearchManager;
@@ -48,6 +45,9 @@
 import android.widget.ListView;
 import android.widget.Toast;
 
+import com.android.contacts.tests.R;
+import com.google.common.collect.Lists;
+
 /**
  * An activity that provides access to various modes of the contacts application.
  * Useful for manual and scripted tests.
diff --git a/tests/src/com/android/contacts/tests/allintents/ResultActivity.java b/tests/src/com/android/contacts/tests/allintents/ResultActivity.java
index 562f2ba..214e936 100644
--- a/tests/src/com/android/contacts/tests/allintents/ResultActivity.java
+++ b/tests/src/com/android/contacts/tests/allintents/ResultActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.tests.allintents;
 
-import com.android.contacts.tests.R;
-
 import android.app.Activity;
 import android.content.ContentUris;
 import android.content.Intent;
@@ -28,16 +26,18 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcelable;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.TableLayout;
 import android.widget.TableRow;
 import android.widget.TextView;
-import android.widget.ImageView.ScaleType;
+
+import com.android.contacts.tests.R;
 
 import java.util.Arrays;
 
diff --git a/tests/src/com/android/contacts/tests/calllog/FillCallLogTestActivity.java b/tests/src/com/android/contacts/tests/calllog/FillCallLogTestActivity.java
index 3fc44cb..d04d978 100644
--- a/tests/src/com/android/contacts/tests/calllog/FillCallLogTestActivity.java
+++ b/tests/src/com/android/contacts/tests/calllog/FillCallLogTestActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.tests.calllog;
 
-import com.android.contacts.tests.R;
-
 import android.app.Activity;
 import android.app.LoaderManager;
 import android.content.ContentProviderClient;
@@ -37,6 +35,8 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.contacts.tests.R;
+
 import java.util.Random;
 
 /**
diff --git a/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java b/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
index 2f959f4..a384dea 100644
--- a/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
+++ b/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.tests.mocks;
 
-import com.android.contacts.model.AccountTypeManager;
-
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -28,6 +26,8 @@
 import android.provider.Settings;
 import android.test.mock.MockContentResolver;
 
+import com.android.contacts.model.AccountTypeManager;
+
 /**
  * A mock context for contacts unit tests. Forwards everything to
  * a supplied context, except content resolver operations, which are sent
diff --git a/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java b/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
index 9084ef0..ce16743 100644
--- a/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
+++ b/tests/src/com/android/contacts/tests/mocks/MockAccountTypeManager.java
@@ -15,20 +15,18 @@
  */
 package com.android.contacts.tests.mocks;
 
-import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.AccountTypeWithDataSet;
-import com.android.contacts.model.AccountWithDataSet;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
+import com.android.contacts.model.account.AccountType;
+import com.android.contacts.model.account.AccountTypeWithDataSet;
+import com.android.contacts.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.Collection;
 import java.util.List;
 import java.util.Map;
 
-import libcore.util.Objects;
-
 /**
  * A mock {@link AccountTypeManager} class.
  */
diff --git a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
index 10682c1..efd5ac2 100644
--- a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
+++ b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.tests.mocks;
 
-import com.android.contacts.ContactPhotoManager;
-
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.widget.ImageView;
 
+import com.android.contacts.ContactPhotoManager;
+
 /**
  * A photo preloader that always uses the "no contact" picture and never executes any real
  * db queries
diff --git a/tests/src/com/android/contacts/tests/mocks/MockContentProvider.java b/tests/src/com/android/contacts/tests/mocks/MockContentProvider.java
index 40d5969..71b434d 100644
--- a/tests/src/com/android/contacts/tests/mocks/MockContentProvider.java
+++ b/tests/src/com/android/contacts/tests/mocks/MockContentProvider.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.tests.mocks;
 
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
 import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.database.Cursor;
@@ -26,13 +23,16 @@
 import android.net.Uri;
 import android.text.TextUtils;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import junit.framework.Assert;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 
-import junit.framework.Assert;
-
 /**
  * A programmable mock content provider.
  */
diff --git a/tests/src/com/android/contacts/tests/mocks/MockSharedPreferences.java b/tests/src/com/android/contacts/tests/mocks/MockSharedPreferences.java
index 40fd934..536ba7f 100644
--- a/tests/src/com/android/contacts/tests/mocks/MockSharedPreferences.java
+++ b/tests/src/com/android/contacts/tests/mocks/MockSharedPreferences.java
@@ -16,10 +16,10 @@
 
 package com.android.contacts.tests.mocks;
 
-import com.google.android.collect.Maps;
-
 import android.content.SharedPreferences;
 
+import com.google.common.collect.Maps;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
diff --git a/tests/src/com/android/contacts/tests/quickcontact/QuickContactTestsActivity.java b/tests/src/com/android/contacts/tests/quickcontact/QuickContactTestsActivity.java
index 527d7a3..5092487 100644
--- a/tests/src/com/android/contacts/tests/quickcontact/QuickContactTestsActivity.java
+++ b/tests/src/com/android/contacts/tests/quickcontact/QuickContactTestsActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.tests.quickcontact;
 
-import com.android.contacts.tests.R;
-
 import android.app.Activity;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -32,6 +30,8 @@
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
 
+import com.android.contacts.tests.R;
+
 public class QuickContactTestsActivity extends Activity {
     private static final int REQUEST_CODE_PICK = 1;
     private static final String PREF_NAME = "quick_contact_prefs";
diff --git a/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java b/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java
index d6e95ef..20229d2 100644
--- a/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java
+++ b/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java
@@ -16,10 +16,6 @@
 
 package com.android.contacts.tests.streamitems;
 
-import com.android.contacts.model.GoogleAccountType;
-import com.android.contacts.tests.R;
-import com.google.android.collect.Lists;
-
 import android.app.Activity;
 import android.content.ContentProviderOperation;
 import android.content.ContentUris;
@@ -36,6 +32,10 @@
 import android.widget.Button;
 import android.widget.Toast;
 
+import com.android.contacts.model.account.GoogleAccountType;
+import com.android.contacts.tests.R;
+import com.google.common.collect.Lists;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
diff --git a/tests/src/com/android/contacts/tests/widget/PinnedHeaderUseCaseActivity.java b/tests/src/com/android/contacts/tests/widget/PinnedHeaderUseCaseActivity.java
index b01963f..dd4ac5e 100644
--- a/tests/src/com/android/contacts/tests/widget/PinnedHeaderUseCaseActivity.java
+++ b/tests/src/com/android/contacts/tests/widget/PinnedHeaderUseCaseActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.contacts.tests.widget;
 
-import com.android.contacts.tests.R;
-import com.android.contacts.widget.PinnedHeaderListView;
-
 import android.app.ListActivity;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -27,6 +24,9 @@
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
 
+import com.android.contacts.tests.R;
+import com.android.contacts.widget.PinnedHeaderListView;
+
 /**
  * An activity that demonstrates various use cases for the {@link PinnedHeaderListView}.
  */
diff --git a/tests/src/com/android/contacts/util/ExpirableCacheTest.java b/tests/src/com/android/contacts/util/ExpirableCacheTest.java
index 309cc0e..33e176e 100644
--- a/tests/src/com/android/contacts/util/ExpirableCacheTest.java
+++ b/tests/src/com/android/contacts/util/ExpirableCacheTest.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.util.ExpirableCache.CachedValue;
-
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.LruCache;
 
+import com.android.contacts.util.ExpirableCache.CachedValue;
+
 /**
  * Unit tests for {@link ExpirableCache}.
  */
diff --git a/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java b/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java
index e68c0ec..8c97f21 100644
--- a/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java
+++ b/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java
@@ -16,11 +16,11 @@
 
 package com.android.contacts.util;
 
-import com.google.common.collect.Lists;
-
 import android.app.Instrumentation;
 import android.os.AsyncTask;
 
+import com.google.common.collect.Lists;
+
 import junit.framework.Assert;
 
 import java.util.Iterator;
diff --git a/tests/src/com/android/contacts/util/HtmlUtilsTest.java b/tests/src/com/android/contacts/util/HtmlUtilsTest.java
index 115f289..772e78f 100644
--- a/tests/src/com/android/contacts/util/HtmlUtilsTest.java
+++ b/tests/src/com/android/contacts/util/HtmlUtilsTest.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.util.HtmlUtils.StreamItemQuoteSpan;
-
 import android.graphics.drawable.ColorDrawable;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -27,6 +25,8 @@
 import android.text.style.ImageSpan;
 import android.text.style.QuoteSpan;
 
+import com.android.contacts.util.HtmlUtils.StreamItemQuoteSpan;
+
 /**
  * Tests for {@link HtmlUtils}.
  *
diff --git a/tests/src/com/android/contacts/util/IntegrationTestUtils.java b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
index 66dd4ef..8c9dd6c 100644
--- a/tests/src/com/android/contacts/util/IntegrationTestUtils.java
+++ b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
@@ -20,8 +20,6 @@
 import static android.os.PowerManager.FULL_WAKE_LOCK;
 import static android.os.PowerManager.ON_AFTER_RELEASE;
 
-import com.google.common.base.Preconditions;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
@@ -30,6 +28,8 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.google.common.base.Preconditions;
+
 import junit.framework.Assert;
 
 import java.util.ArrayList;
diff --git a/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java b/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java
index d8d8cf5..9eb550e 100644
--- a/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java
+++ b/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.util.StreamItemEntry;
-
 import android.content.Context;
 
 /**
@@ -68,4 +66,4 @@
         ret.decodeHtml(context);
         return ret;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java b/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
index b1a0175..801c162 100644
--- a/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
+++ b/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
@@ -27,9 +27,6 @@
 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION;
 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK;
 
-import com.android.contacts.R;
-import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
-
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
@@ -37,6 +34,9 @@
 import android.provider.VoicemailContract.Status;
 import android.test.AndroidTestCase;
 
+import com.android.contacts.R;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
+
 import java.util.List;
 
 /**
diff --git a/tests/src/com/android/contacts/widget/CompositeListAdapterTest.java b/tests/src/com/android/contacts/widget/CompositeListAdapterTest.java
index 87d268b..f7dc08e 100644
--- a/tests/src/com/android/contacts/widget/CompositeListAdapterTest.java
+++ b/tests/src/com/android/contacts/widget/CompositeListAdapterTest.java
@@ -15,8 +15,6 @@
  */
 package com.android.contacts.widget;
 
-import com.google.android.collect.Lists;
-
 import android.content.Context;
 import android.database.DataSetObserver;
 import android.test.AndroidTestCase;
@@ -24,6 +22,8 @@
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;